diff options
author | unknown <bell@sanja.is.com.ua> | 2005-04-30 01:43:35 +0300 |
---|---|---|
committer | unknown <bell@sanja.is.com.ua> | 2005-04-30 01:43:35 +0300 |
commit | b2689e33b9d1f81e810f0d6c9db1fff544c891f7 (patch) | |
tree | 76e9a2b38996ffe678e6d7f6f52a06dc680dc52e | |
parent | 7b980938b4b37d0503facfb672e606f0f51510d5 (diff) | |
parent | 90eada084e026716abc1a6f6485e6d1376875abe (diff) | |
download | mariadb-git-b2689e33b9d1f81e810f0d6c9db1fff544c891f7.tar.gz |
Merge sanja.is.com.ua:/home/bell/mysql/bk/mysql-5.0
into sanja.is.com.ua:/home/bell/mysql/bk/work-test-5.0
sql/item.cc:
Auto merged
sql/sql_base.cc:
Auto merged
-rw-r--r-- | sql/item.cc | 68 | ||||
-rw-r--r-- | sql/item.h | 6 | ||||
-rw-r--r-- | sql/item_subselect.h | 3 | ||||
-rw-r--r-- | sql/sql_base.cc | 8 |
4 files changed, 84 insertions, 1 deletions
diff --git a/sql/item.cc b/sql/item.cc index 7264f8b2d68..9902b14ece5 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -454,6 +454,7 @@ void Item_ident::cleanup() db_name= orig_db_name; table_name= orig_table_name; field_name= orig_field_name; + depended_from= 0; DBUG_VOID_RETURN; } @@ -2334,7 +2335,7 @@ bool Item_ref_null_helper::get_date(TIME *ltime, uint fuzzydate) */ static void mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current, - Item_ident *resolved_item, + Item_ident *resolved_item, Item_ident *mark_item) { const char *db_name= (resolved_item->db_name ? @@ -2359,6 +2360,71 @@ static void mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current, } +/* + Mark range of selects and resolved identifier (field/reference) item as + dependent + + SYNOPSIS + mark_select_range_as_dependent() + thd - thread handler + current_sel - current select (select where resolved_item was placed) + last_select - select where resolved_item was resolved + found_field - field which was found during resolving + found_item - Item which was found during resolving (if resolved + identifier belongs to VIEW) + resolved_item - Identifier which was resolved + + NOTE: + We have to mark all items between current_sel (including) and + last_select (excluding) as dependend (select before last_select should + be marked with actual table mask used by resolved item, all other with + OUTER_REF_TABLE_BIT) and also write dependence information to Item of + resolved identifier. +*/ + +void mark_select_range_as_dependent(THD *thd, + SELECT_LEX *current_sel, + SELECT_LEX *last_select, + Field *found_field, Item *found_item, + Item_ident *resolved_item) +{ + /* + Go from current SELECT to SELECT where field was resolved (it + have to be reachable from current SELECT, because it was already + done once when we resolved this field and cached result of + resolving) + */ + SELECT_LEX *previous_select= current_sel; + for(; + previous_select->outer_select() != last_select; + previous_select= previous_select->outer_select()) + { + Item_subselect *prev_subselect_item= + previous_select->master_unit()->item; + prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT; + prev_subselect_item->const_item_cache= 0; + } + { + Item_subselect *prev_subselect_item= + previous_select->master_unit()->item; + Item_ident *dependent= resolved_item; + if (found_field == view_ref_found) + { + Item::Type type= found_item->type(); + prev_subselect_item->used_tables_cache|= + found_item->used_tables(); + dependent= ((type == Item::REF_ITEM || type == Item::FIELD_ITEM) ? + (Item_ident*) found_item : + 0); + } + else + prev_subselect_item->used_tables_cache|= + found_field->table->map; + prev_subselect_item->const_item_cache= 0; + mark_as_dependent(thd, last_select, current_sel, resolved_item, + dependent); + } +} /* diff --git a/sql/item.h b/sql/item.h index e86c66ca6f3..9a00b2f0d82 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1795,6 +1795,12 @@ public: static enum_field_types get_real_type(Item *); }; +class st_select_lex; +void mark_select_range_as_dependent(THD *thd, + st_select_lex *current_sel, + st_select_lex *last_select, + Field *found_field, Item *found_item, + Item_ident *resolved_item); extern Item_buff *new_Item_buff(Item *item); extern Item_result item_cmp_type(Item_result a,Item_result b); diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 1a407c695b2..bdea5c5efee 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -122,6 +122,9 @@ public: friend bool Item_field::fix_fields(THD *, TABLE_LIST *, Item **); friend bool Item_ref::fix_fields(THD *, TABLE_LIST *, Item **); friend bool Item_param::fix_fields(THD *, TABLE_LIST *, Item **); + friend void mark_select_range_as_dependent(THD*, + st_select_lex*, st_select_lex*, + Field*, Item*, Item_ident*); }; /* single value subselect */ diff --git a/sql/sql_base.cc b/sql/sql_base.cc index ade1fb96b96..f6147080b9c 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2689,6 +2689,14 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, { if (found == WRONG_GRANT) return (Field*) 0; + { + SELECT_LEX *current_sel= thd->lex->current_select; + SELECT_LEX *last_select= item->cached_table->select_lex; + /* check that field was resolved in outer query */ + if (current_sel != last_select) + mark_select_range_as_dependent(thd, current_sel, last_select, + found, *ref, item); + } return found; } } |