mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
if outer refernce (identifier) was resolved with help of cache all subqueries and resolved item itseld have to be correctly marked as dependent
(BUG#10041) sql/item.cc: depended_from shoudl be cleaned layout fixed function to mark range of SELECTs as dependent (used if item was resolved with PS cache of resolving identifiers) sql/item.h: function to mark range of SELECTs as dependent (used if item was resolved with PS cache of resolving identifiers) sql/item_subselect.h: function to mark range of SELECTs as dependent (used if item was resolved with PS cache of resolving identifiers) sql/sql_base.cc: if outer refernce (identifier) was resolved with help of cache all subqueries and resolved item itseld have to be correctly marked as dependent
This commit is contained in:
68
sql/item.cc
68
sql/item.cc
@@ -454,6 +454,7 @@ void Item_ident::cleanup()
|
|||||||
db_name= orig_db_name;
|
db_name= orig_db_name;
|
||||||
table_name= orig_table_name;
|
table_name= orig_table_name;
|
||||||
field_name= orig_field_name;
|
field_name= orig_field_name;
|
||||||
|
depended_from= 0;
|
||||||
DBUG_VOID_RETURN;
|
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,
|
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)
|
Item_ident *mark_item)
|
||||||
{
|
{
|
||||||
const char *db_name= (resolved_item->db_name ?
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -1795,6 +1795,12 @@ public:
|
|||||||
static enum_field_types get_real_type(Item *);
|
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_buff *new_Item_buff(Item *item);
|
||||||
extern Item_result item_cmp_type(Item_result a,Item_result b);
|
extern Item_result item_cmp_type(Item_result a,Item_result b);
|
||||||
|
@@ -122,6 +122,9 @@ public:
|
|||||||
friend bool Item_field::fix_fields(THD *, TABLE_LIST *, Item **);
|
friend bool Item_field::fix_fields(THD *, TABLE_LIST *, Item **);
|
||||||
friend bool Item_ref::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 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 */
|
/* single value subselect */
|
||||||
|
@@ -2689,6 +2689,14 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
|
|||||||
{
|
{
|
||||||
if (found == WRONG_GRANT)
|
if (found == WRONG_GRANT)
|
||||||
return (Field*) 0;
|
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;
|
return found;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user