diff options
author | unknown <bell@sanja.is.com.ua> | 2003-10-23 21:09:40 +0300 |
---|---|---|
committer | unknown <bell@sanja.is.com.ua> | 2003-10-23 21:09:40 +0300 |
commit | e94666f8e79c01b6ed3d7b0da482cd0a461e4092 (patch) | |
tree | 5492ee0331057192a6ffbf9b6deac98f943df4bf /sql | |
parent | 9a4aa99769b29cb4084b3b16d2bfb7067d817d2c (diff) | |
parent | d3d001fd022ca69ba2310dce4c932fcea2b330a8 (diff) | |
download | mariadb-git-e94666f8e79c01b6ed3d7b0da482cd0a461e4092.tar.gz |
Merge
sql/item.cc:
Auto merged
mysql-test/r/subselect.result:
SCCS merged
mysql-test/t/subselect.test:
SCCS merged
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item.cc | 47 | ||||
-rw-r--r-- | sql/item_subselect.cc | 54 | ||||
-rw-r--r-- | sql/item_subselect.h | 15 |
3 files changed, 107 insertions, 9 deletions
diff --git a/sql/item.cc b/sql/item.cc index ea1eaf29373..0462a78376f 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -819,9 +819,11 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) // Prevent using outer fields in subselects, that is not supported now SELECT_LEX *cursel=(SELECT_LEX *) thd->lex.current_select; if (cursel->master_unit()->first_select()->linkage != DERIVED_TABLE_TYPE) - for (SELECT_LEX *sl= cursel->outer_select(); + { + SELECT_LEX_UNIT *prev_unit= cursel->master_unit(); + for (SELECT_LEX *sl= prev_unit->outer_select(); sl; - sl= sl->outer_select()) + sl= (prev_unit= sl->master_unit())->outer_select()) { table_list= (last= sl)->get_table_list(); if (sl->resolve_mode == SELECT_LEX::INSERT_MODE && table_list) @@ -829,19 +831,38 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) // it is primary INSERT st_select_lex => skip first table resolving table_list= table_list->next; } + + Item_subselect *prev_subselect_item= prev_unit->item; if ((tmp= find_field_in_tables(thd, this, table_list, &where, 0)) != not_found_field) + { + prev_subselect_item->used_tables_cache|= tmp->table->map; + prev_subselect_item->const_item_cache= 0; break; + } if (sl->resolve_mode == SELECT_LEX::SELECT_MODE && (refer= find_item_in_list(this, sl->item_list, &counter, REPORT_EXCEPT_NOT_FOUND)) != (Item **) not_found_item) + { + if (*refer && (*refer)->fixed) // Avoid crash in case of error + { + prev_subselect_item->used_tables_cache|= (*refer)->used_tables(); + prev_subselect_item->const_item_cache&= (*refer)->const_item(); + } break; + } + + // Reference is not found => depend from outer (or just error) + prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT; + prev_subselect_item->const_item_cache= 0; + if (sl->master_unit()->first_select()->linkage == DERIVED_TABLE_TYPE) break; // do not look over derived table } + } if (!tmp) return -1; else if (!refer) @@ -1360,7 +1381,8 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) if (!ref) { TABLE_LIST *where= 0, *table_list; - SELECT_LEX *sl= thd->lex.current_select->outer_select(); + SELECT_LEX_UNIT *prev_unit= thd->lex.current_select->master_unit(); + SELECT_LEX *sl= prev_unit->outer_select(); /* Finding only in current select will be performed for selects that have not outer one and for derived tables (which not support using outer @@ -1388,15 +1410,23 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) cause error ER_NON_UNIQ_ERROR in find_item_in_list. */ SELECT_LEX *last=0; - for ( ; sl ; sl= sl->outer_select()) + for ( ; sl ; sl= (prev_unit= sl->master_unit())->outer_select()) { last= sl; + Item_subselect *prev_subselect_item= prev_unit->item; if (sl->resolve_mode == SELECT_LEX::SELECT_MODE && (ref= find_item_in_list(this, sl->item_list, &counter, REPORT_EXCEPT_NOT_FOUND)) != (Item **)not_found_item) + { + if (*ref && (*ref)->fixed) // Avoid crash in case of error + { + prev_subselect_item->used_tables_cache|= (*ref)->used_tables(); + prev_subselect_item->const_item_cache&= (*ref)->const_item(); + } break; + } table_list= sl->get_table_list(); if (sl->resolve_mode == SELECT_LEX::INSERT_MODE && table_list) { @@ -1406,7 +1436,16 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) if ((tmp= find_field_in_tables(thd, this, table_list, &where, 0)) != not_found_field) + { + prev_subselect_item->used_tables_cache|= tmp->table->map; + prev_subselect_item->const_item_cache= 0; break; + } + + // Reference is not found => depend from outer (or just error) + prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT; + prev_subselect_item->const_item_cache= 0; + if (sl->master_unit()->first_select()->linkage == DERIVED_TABLE_TYPE) break; // do not look over derived table diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 5e0221ad6c7..704681dd511 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -36,7 +36,8 @@ inline Item * and_items(Item* cond, Item *item) Item_subselect::Item_subselect(): Item_result_field(), engine_owner(1), value_assigned(0), substitution(0), - engine(0), have_to_be_excluded(0), engine_changed(0) + engine(0), used_tables_cache(0), have_to_be_excluded(0), + const_item_cache(1), engine_changed(0) { reset(); /* @@ -111,6 +112,11 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref) } fix_length_and_dec(); } + if (engine->uncacheable()) + { + const_item_cache= 0; + used_tables_cache|= RAND_TABLE_BIT; + } fixed= 1; thd->where= save_where; return res; @@ -146,10 +152,24 @@ void Item_subselect::fix_length_and_dec() engine->fix_length_and_dec(0); } -inline table_map Item_subselect::used_tables() const +table_map Item_subselect::used_tables() const +{ + return (table_map) (engine->dependent() ? used_tables_cache : 0L); +} + +bool Item_subselect::const_item() const +{ + return const_item_cache; +} + +void Item_subselect::update_used_tables() { - return (table_map) (engine->dependent() ? 1L : - (engine->uncacheable() ? RAND_TABLE_BIT : 0L)); + if (!engine->uncacheable()) + { + // did all used tables become ststic? + if ((used_tables_cache & ~engine->upper_select_const_tables())) + const_item_cache= 1; + } } Item_singlerow_subselect::Item_singlerow_subselect(st_select_lex *select_lex) @@ -1138,3 +1158,29 @@ void subselect_uniquesubquery_engine::exclude() //this never should be called DBUG_ASSERT(0); } + + +table_map subselect_engine::calc_const_tables(TABLE_LIST *table) +{ + table_map map= 0; + for(; table; table= table->next) + { + TABLE *tbl= table->table; + if (tbl && tbl->const_table) + map|= tbl->map; + } + return map; +} + + +table_map subselect_single_select_engine::upper_select_const_tables() +{ + return calc_const_tables((TABLE_LIST *) select_lex->outer_select()-> + table_list.first); +} + +table_map subselect_union_engine::upper_select_const_tables() +{ + return calc_const_tables((TABLE_LIST *) unit->outer_select()-> + table_list.first); +} diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 312b453a5a2..3a543ff288c 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -41,11 +41,15 @@ protected: /* substitution instead of subselect in case of optimization */ Item *substitution; /* engine that perform execution of subselect (single select or union) */ - subselect_engine *engine; + subselect_engine *engine; + /* cache of used external tables */ + table_map used_tables_cache; /* allowed number of columns (1 for single value subqueries) */ uint max_columns; /* work with 'substitution' */ bool have_to_be_excluded; + /* cache of constante state */ + bool const_item_cache; public: /* changed engine indicator */ @@ -85,6 +89,8 @@ public: bool exec(); virtual void fix_length_and_dec(); table_map used_tables() const; + bool const_item() const; + void update_used_tables(); void print(String *str) { if (name) @@ -101,6 +107,8 @@ public: friend class select_subselect; friend class Item_in_optimizer; + friend bool Item_field::fix_fields(THD *, TABLE_LIST *, Item **); + friend bool Item_ref::fix_fields(THD *, TABLE_LIST *, Item **); }; /* single value subselect */ @@ -264,6 +272,8 @@ public: enum Item_result type() { return res_type; } virtual void exclude()= 0; bool may_be_null() { return maybe_null; }; + virtual table_map upper_select_const_tables()= 0; + static table_map calc_const_tables(TABLE_LIST *); }; @@ -285,6 +295,7 @@ public: bool dependent(); bool uncacheable(); void exclude(); + table_map upper_select_const_tables(); }; @@ -302,6 +313,7 @@ public: bool dependent(); bool uncacheable(); void exclude(); + table_map upper_select_const_tables(); }; @@ -328,6 +340,7 @@ public: bool dependent() { return 1; } bool uncacheable() { return 1; } void exclude(); + table_map upper_select_const_tables() { return 0; } }; |