diff options
-rw-r--r-- | sql/item_row.cc | 23 | ||||
-rw-r--r-- | sql/item_row.h | 12 | ||||
-rw-r--r-- | sql/sql_select.cc | 10 |
3 files changed, 39 insertions, 6 deletions
diff --git a/sql/item_row.cc b/sql/item_row.cc index 464a8fd0ec5..e073f8e24e7 100644 --- a/sql/item_row.cc +++ b/sql/item_row.cc @@ -18,8 +18,10 @@ #include "assert.h" Item_row::Item_row(List<Item> &arg): - Item(), array_holder(1) + Item(), array_holder(1), used_tables_cache(0), const_item_cache(1) { + + //TODO: think placing 2-3 component items in item (as it done for function) if ((arg_count= arg.elements)) items= (Item**) sql_alloc(sizeof(Item*)*arg_count); else @@ -45,16 +47,31 @@ void Item_row::illegal_method_call(const char *method) bool Item_row::fix_fields(THD *thd, TABLE_LIST *tabl, Item **ref) { - tables= 0; + null_value= 0; + maybe_null= 0; for (uint i= 0; i < arg_count; i++) { if (items[i]->fix_fields(thd, tabl, items+i)) return 1; - tables |= items[i]->used_tables(); + used_tables_cache |= items[i]->used_tables(); + const_item_cache&= items[i]->const_item(); + maybe_null|= items[i]->maybe_null; } return 0; } +void Item_row::update_used_tables() +{ + used_tables_cache= 0; + const_item_cache= 1; + for (uint i= 0; i < arg_count; i++) + { + items[i]->update_used_tables(); + used_tables_cache|= items[i]->used_tables(); + const_item_cache&= items[i]->const_item(); + } +} + bool Item_row::check_cols(uint c) { if (c != arg_count) diff --git a/sql/item_row.h b/sql/item_row.h index 5580250b4fb..d097fca8f1d 100644 --- a/sql/item_row.h +++ b/sql/item_row.h @@ -17,13 +17,17 @@ class Item_row: public Item { bool array_holder; - table_map tables; + table_map used_tables_cache; + bool const_item_cache; uint arg_count; Item **items; public: Item_row(List<Item> &); Item_row(Item_row *item): - Item(), array_holder(0), tables(item->tables), arg_count(item->arg_count), + Item(), array_holder(0), + used_tables_cache(item->used_tables_cache), + const_item_cache(item->const_item_cache), + arg_count(item->arg_count), items(item->items) {} @@ -56,8 +60,10 @@ public: return 0; }; bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref); - table_map used_tables() const { return tables; }; + table_map used_tables() const { return used_tables_cache; }; + bool const_item() const { return const_item_cache; }; enum Item_result result_type() const { return ROW_RESULT; } + void update_used_tables(); virtual uint cols() { return arg_count; } virtual Item* el(uint i) { return items[i]; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 50820b931b6..4e9f8cf9383 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -763,6 +763,16 @@ JOIN::exec() select_options, unit))) DBUG_VOID_RETURN; + /* + We don't have to store rows in temp table that doesn't match HAVING if: + - we are sorting the table and writing complete group rows to the + temp table. + - We are using DISTINCT without resolving the distinct as a GROUP BY + on all columns. + + If having is not handled here, it will be checked before the row + is sent to the client. + */ if (having_list && (sort_and_group || (exec_tmp_table->distinct && !group_list))) having=having_list; |