summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <bell@sanja.is.com.ua>2005-04-30 01:43:35 +0300
committerunknown <bell@sanja.is.com.ua>2005-04-30 01:43:35 +0300
commitb2689e33b9d1f81e810f0d6c9db1fff544c891f7 (patch)
tree76e9a2b38996ffe678e6d7f6f52a06dc680dc52e
parent7b980938b4b37d0503facfb672e606f0f51510d5 (diff)
parent90eada084e026716abc1a6f6485e6d1376875abe (diff)
downloadmariadb-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.cc68
-rw-r--r--sql/item.h6
-rw-r--r--sql/item_subselect.h3
-rw-r--r--sql/sql_base.cc8
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;
}
}