summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <bell@book.sanja.is.com.ua>2005-05-03 18:47:53 +0300
committerunknown <bell@book.sanja.is.com.ua>2005-05-03 18:47:53 +0300
commit7b4374f6f7b2ee440e28c317794ba5bc81ddc7c0 (patch)
treea90cea629d23dd63b90ef3b266056720f47d4537 /sql
parent9724795fd68149c2a780de1cdcb194c8a7b17597 (diff)
parent371b26e11c2a982dc3025481f743bd7d4c636f0a (diff)
downloadmariadb-git-7b4374f6f7b2ee440e28c317794ba5bc81ddc7c0.tar.gz
Merge book.sanja.is.com.ua:/Users/bell/mysql/bk/mysql-5.0
into book.sanja.is.com.ua:/Users/bell/mysql/bk/work-test-5.0 BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted
Diffstat (limited to 'sql')
-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.cc11
4 files changed, 87 insertions, 1 deletions
diff --git a/sql/item.cc b/sql/item.cc
index 7264f8b2d68..a2649d7506f 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
+ last_select - select where resolved_item was resolved
+ current_sel - current select (select where resolved_item was placed)
+ 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 *last_select,
+ SELECT_LEX *current_sel,
+ 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 850a2d6636d..f762896ba34 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1800,6 +1800,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 *last_select,
+ st_select_lex *current_sel,
+ 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..30780eb1802 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -2689,6 +2689,17 @@ 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;
+ /*
+ If the field was an outer referencee, mark all selects using this
+ sub query as dependent of the outer query
+ */
+ if (current_sel != last_select)
+ mark_select_range_as_dependent(thd, last_select, current_sel,
+ found, *ref, item);
+ }
return found;
}
}