mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
Merge
sql/item.cc: Auto merged sql/item.h: Auto merged mysql-test/t/disabled.def: SCCS merged
This commit is contained in:
@@ -11,5 +11,4 @@
|
|||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
sp-goto : GOTO is currently is disabled - will be fixed in the future
|
sp-goto : GOTO is currently is disabled - will be fixed in the future
|
||||||
subselect : Bug#15706
|
|
||||||
ndb_load : Bug#17233
|
ndb_load : Bug#17233
|
||||||
|
477
sql/item.cc
477
sql/item.cc
@@ -3210,6 +3210,252 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Resolve the name of an outer select column reference.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
Item_field::fix_outer_field()
|
||||||
|
thd [in] current thread
|
||||||
|
from_field [in/out] found field reference or (Field*)not_found_field
|
||||||
|
reference [in/out] view column if this item was resolved to a view column
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
The method resolves the column reference represented by 'this' as a column
|
||||||
|
present in outer selects that contain current select.
|
||||||
|
|
||||||
|
NOTES
|
||||||
|
This is the inner loop of Item_field::fix_fields:
|
||||||
|
|
||||||
|
for each outer query Q_k beginning from the inner-most one
|
||||||
|
{
|
||||||
|
search for a column or derived column named col_ref_i
|
||||||
|
[in table T_j] in the FROM clause of Q_k;
|
||||||
|
|
||||||
|
if such a column is not found
|
||||||
|
Search for a column or derived column named col_ref_i
|
||||||
|
[in table T_j] in the SELECT and GROUP clauses of Q_k.
|
||||||
|
}
|
||||||
|
|
||||||
|
IMPLEMENTATION
|
||||||
|
In prepared statements, because of cache, find_field_in_tables()
|
||||||
|
can resolve fields even if they don't belong to current context.
|
||||||
|
In this case this method only finds appropriate context and marks
|
||||||
|
current select as dependent. The found reference of field should be
|
||||||
|
provided in 'from_field'.
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
1 - column succefully resolved and fix_fields() should continue.
|
||||||
|
0 - column fully fixed and fix_fields() should return FALSE
|
||||||
|
-1 - error occured
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
|
||||||
|
{
|
||||||
|
enum_parsing_place place= NO_MATTER;
|
||||||
|
bool field_found= (*from_field != not_found_field);
|
||||||
|
bool upward_lookup= FALSE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
If there are outer contexts (outer selects, but current select is
|
||||||
|
not derived table or view) try to resolve this reference in the
|
||||||
|
outer contexts.
|
||||||
|
|
||||||
|
We treat each subselect as a separate namespace, so that different
|
||||||
|
subselects may contain columns with the same names. The subselects
|
||||||
|
are searched starting from the innermost.
|
||||||
|
*/
|
||||||
|
Name_resolution_context *last_checked_context= context;
|
||||||
|
Item **ref= (Item **) not_found_item;
|
||||||
|
Name_resolution_context *outer_context= context->outer_context;
|
||||||
|
for (;
|
||||||
|
outer_context;
|
||||||
|
outer_context= outer_context->outer_context)
|
||||||
|
{
|
||||||
|
SELECT_LEX *select= outer_context->select_lex;
|
||||||
|
Item_subselect *prev_subselect_item=
|
||||||
|
last_checked_context->select_lex->master_unit()->item;
|
||||||
|
last_checked_context= outer_context;
|
||||||
|
upward_lookup= TRUE;
|
||||||
|
|
||||||
|
place= prev_subselect_item->parsing_place;
|
||||||
|
/*
|
||||||
|
If outer_field is set, field was already found by first call
|
||||||
|
to find_field_in_tables(). Only need to find appropriate context.
|
||||||
|
*/
|
||||||
|
if (field_found && outer_context->select_lex !=
|
||||||
|
cached_table->select_lex)
|
||||||
|
continue;
|
||||||
|
/*
|
||||||
|
In case of a view, find_field_in_tables() writes the pointer to
|
||||||
|
the found view field into '*reference', in other words, it
|
||||||
|
substitutes this Item_field with the found expression.
|
||||||
|
*/
|
||||||
|
if (field_found || (*from_field= find_field_in_tables(thd, this,
|
||||||
|
outer_context->
|
||||||
|
first_name_resolution_table,
|
||||||
|
outer_context->
|
||||||
|
last_name_resolution_table,
|
||||||
|
reference,
|
||||||
|
IGNORE_EXCEPT_NON_UNIQUE,
|
||||||
|
TRUE, TRUE)) !=
|
||||||
|
not_found_field)
|
||||||
|
{
|
||||||
|
if (*from_field)
|
||||||
|
{
|
||||||
|
if (*from_field != view_ref_found)
|
||||||
|
{
|
||||||
|
prev_subselect_item->used_tables_cache|= (*from_field)->table->map;
|
||||||
|
prev_subselect_item->const_item_cache= 0;
|
||||||
|
if (thd->lex->in_sum_func &&
|
||||||
|
thd->lex->in_sum_func->nest_level ==
|
||||||
|
thd->lex->current_select->nest_level)
|
||||||
|
{
|
||||||
|
Item::Type type= (*reference)->type();
|
||||||
|
set_if_bigger(thd->lex->in_sum_func->max_arg_level,
|
||||||
|
select->nest_level);
|
||||||
|
set_field(*from_field);
|
||||||
|
fixed= 1;
|
||||||
|
mark_as_dependent(thd, last_checked_context->select_lex,
|
||||||
|
context->select_lex, this,
|
||||||
|
((type == REF_ITEM || type == FIELD_ITEM) ?
|
||||||
|
(Item_ident*) (*reference) : 0));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Item::Type type= (*reference)->type();
|
||||||
|
prev_subselect_item->used_tables_cache|=
|
||||||
|
(*reference)->used_tables();
|
||||||
|
prev_subselect_item->const_item_cache&=
|
||||||
|
(*reference)->const_item();
|
||||||
|
mark_as_dependent(thd, last_checked_context->select_lex,
|
||||||
|
context->select_lex, this,
|
||||||
|
((type == REF_ITEM || type == FIELD_ITEM) ?
|
||||||
|
(Item_ident*) (*reference) :
|
||||||
|
0));
|
||||||
|
/*
|
||||||
|
A reference to a view field had been found and we
|
||||||
|
substituted it instead of this Item (find_field_in_tables
|
||||||
|
does it by assigning the new value to *reference), so now
|
||||||
|
we can return from this function.
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Search in SELECT and GROUP lists of the outer select. */
|
||||||
|
if (outer_context->resolve_in_select_list)
|
||||||
|
{
|
||||||
|
if (!(ref= resolve_ref_in_select_and_group(thd, this, select)))
|
||||||
|
return -1; /* Some error occurred (e.g. ambiguous names). */
|
||||||
|
if (ref != not_found_item)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(*ref && (*ref)->fixed);
|
||||||
|
prev_subselect_item->used_tables_cache|= (*ref)->used_tables();
|
||||||
|
prev_subselect_item->const_item_cache&= (*ref)->const_item();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Reference is not found in this select => this subquery depend on
|
||||||
|
outer select (or we just trying to find wrong identifier, in this
|
||||||
|
case it does not matter which used tables bits we set)
|
||||||
|
*/
|
||||||
|
prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT;
|
||||||
|
prev_subselect_item->const_item_cache= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DBUG_ASSERT(ref != 0);
|
||||||
|
if (!*from_field)
|
||||||
|
return -1;
|
||||||
|
if (ref == not_found_item && *from_field == not_found_field)
|
||||||
|
{
|
||||||
|
if (upward_lookup)
|
||||||
|
{
|
||||||
|
// We can't say exactly what absent table or field
|
||||||
|
my_error(ER_BAD_FIELD_ERROR, MYF(0), full_name(), thd->where);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Call find_field_in_tables only to report the error */
|
||||||
|
find_field_in_tables(thd, this,
|
||||||
|
context->first_name_resolution_table,
|
||||||
|
context->last_name_resolution_table,
|
||||||
|
reference, REPORT_ALL_ERRORS,
|
||||||
|
!any_privileges &&
|
||||||
|
TRUE, TRUE);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (ref != not_found_item)
|
||||||
|
{
|
||||||
|
Item *save;
|
||||||
|
Item_ref *rf;
|
||||||
|
|
||||||
|
/* Should have been checked in resolve_ref_in_select_and_group(). */
|
||||||
|
DBUG_ASSERT(*ref && (*ref)->fixed);
|
||||||
|
/*
|
||||||
|
Here, a subset of actions performed by Item_ref::set_properties
|
||||||
|
is not enough. So we pass ptr to NULL into Item_[direct]_ref
|
||||||
|
constructor, so no initialization is performed, and call
|
||||||
|
fix_fields() below.
|
||||||
|
*/
|
||||||
|
save= *ref;
|
||||||
|
*ref= NULL; // Don't call set_properties()
|
||||||
|
rf= (place == IN_HAVING ?
|
||||||
|
new Item_ref(context, ref, (char*) table_name,
|
||||||
|
(char*) field_name) :
|
||||||
|
new Item_direct_ref(context, ref, (char*) table_name,
|
||||||
|
(char*) field_name));
|
||||||
|
*ref= save;
|
||||||
|
if (!rf)
|
||||||
|
return -1;
|
||||||
|
thd->change_item_tree(reference, rf);
|
||||||
|
/*
|
||||||
|
rf is Item_ref => never substitute other items (in this case)
|
||||||
|
during fix_fields() => we can use rf after fix_fields()
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(!rf->fixed); // Assured by Item_ref()
|
||||||
|
if (rf->fix_fields(thd, reference) || rf->check_cols(1))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
mark_as_dependent(thd, last_checked_context->select_lex,
|
||||||
|
context->select_lex, this,
|
||||||
|
rf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mark_as_dependent(thd, last_checked_context->select_lex,
|
||||||
|
context->select_lex,
|
||||||
|
this, this);
|
||||||
|
if (last_checked_context->select_lex->having_fix_field)
|
||||||
|
{
|
||||||
|
Item_ref *rf;
|
||||||
|
rf= new Item_ref(context,
|
||||||
|
(cached_table->db[0] ? cached_table->db : 0),
|
||||||
|
(char*) cached_table->alias, (char*) field_name);
|
||||||
|
if (!rf)
|
||||||
|
return -1;
|
||||||
|
thd->change_item_tree(reference, rf);
|
||||||
|
/*
|
||||||
|
rf is Item_ref => never substitute other items (in this case)
|
||||||
|
during fix_fields() => we can use rf after fix_fields()
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(!rf->fixed); // Assured by Item_ref()
|
||||||
|
if (rf->fix_fields(thd, reference) || rf->check_cols(1))
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Resolve the name of a column reference.
|
Resolve the name of a column reference.
|
||||||
|
|
||||||
@@ -3257,12 +3503,11 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select)
|
|||||||
|
|
||||||
bool Item_field::fix_fields(THD *thd, Item **reference)
|
bool Item_field::fix_fields(THD *thd, Item **reference)
|
||||||
{
|
{
|
||||||
enum_parsing_place place= NO_MATTER;
|
|
||||||
DBUG_ASSERT(fixed == 0);
|
DBUG_ASSERT(fixed == 0);
|
||||||
if (!field) // If field is not checked
|
if (!field) // If field is not checked
|
||||||
{
|
{
|
||||||
bool upward_lookup= FALSE;
|
|
||||||
Field *from_field= (Field *)not_found_field;
|
Field *from_field= (Field *)not_found_field;
|
||||||
|
bool outer_fixed= false;
|
||||||
/*
|
/*
|
||||||
In case of view, find_field_in_tables() write pointer to view field
|
In case of view, find_field_in_tables() write pointer to view field
|
||||||
expression to 'reference', i.e. it substitute that expression instead
|
expression to 'reference', i.e. it substitute that expression instead
|
||||||
@@ -3277,7 +3522,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
|
|||||||
TRUE)) ==
|
TRUE)) ==
|
||||||
not_found_field)
|
not_found_field)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
/* Look up in current select's item_list to find aliased fields */
|
/* Look up in current select's item_list to find aliased fields */
|
||||||
if (thd->lex->current_select->is_item_list_lookup)
|
if (thd->lex->current_select->is_item_list_lookup)
|
||||||
{
|
{
|
||||||
@@ -3292,197 +3537,11 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ((ret= fix_outer_field(thd, &from_field, reference)) < 0)
|
||||||
/*
|
goto error;
|
||||||
If there are outer contexts (outer selects, but current select is
|
else if (!ret)
|
||||||
not derived table or view) try to resolve this reference in the
|
return FALSE;
|
||||||
outer contexts.
|
outer_fixed= TRUE;
|
||||||
|
|
||||||
We treat each subselect as a separate namespace, so that different
|
|
||||||
subselects may contain columns with the same names. The subselects
|
|
||||||
are searched starting from the innermost.
|
|
||||||
*/
|
|
||||||
Name_resolution_context *last_checked_context= context;
|
|
||||||
Item **ref= (Item **) not_found_item;
|
|
||||||
Name_resolution_context *outer_context= context->outer_context;
|
|
||||||
for (;
|
|
||||||
outer_context;
|
|
||||||
outer_context= outer_context->outer_context)
|
|
||||||
{
|
|
||||||
SELECT_LEX *select= outer_context->select_lex;
|
|
||||||
Item_subselect *prev_subselect_item=
|
|
||||||
last_checked_context->select_lex->master_unit()->item;
|
|
||||||
last_checked_context= outer_context;
|
|
||||||
upward_lookup= TRUE;
|
|
||||||
|
|
||||||
place= prev_subselect_item->parsing_place;
|
|
||||||
/*
|
|
||||||
In case of a view, find_field_in_tables() writes the pointer to
|
|
||||||
the found view field into '*reference', in other words, it
|
|
||||||
substitutes this Item_field with the found expression.
|
|
||||||
*/
|
|
||||||
if ((from_field= find_field_in_tables(thd, this,
|
|
||||||
outer_context->
|
|
||||||
first_name_resolution_table,
|
|
||||||
outer_context->
|
|
||||||
last_name_resolution_table,
|
|
||||||
reference,
|
|
||||||
IGNORE_EXCEPT_NON_UNIQUE,
|
|
||||||
TRUE, TRUE)) !=
|
|
||||||
not_found_field)
|
|
||||||
{
|
|
||||||
if (from_field)
|
|
||||||
{
|
|
||||||
if (from_field != view_ref_found)
|
|
||||||
{
|
|
||||||
prev_subselect_item->used_tables_cache|= from_field->table->map;
|
|
||||||
prev_subselect_item->const_item_cache= 0;
|
|
||||||
if (thd->lex->in_sum_func &&
|
|
||||||
thd->lex->in_sum_func->nest_level ==
|
|
||||||
thd->lex->current_select->nest_level)
|
|
||||||
{
|
|
||||||
Item::Type type= (*reference)->type();
|
|
||||||
set_if_bigger(thd->lex->in_sum_func->max_arg_level,
|
|
||||||
select->nest_level);
|
|
||||||
set_field(from_field);
|
|
||||||
fixed= 1;
|
|
||||||
mark_as_dependent(thd, last_checked_context->select_lex,
|
|
||||||
context->select_lex, this,
|
|
||||||
((type == REF_ITEM || type == FIELD_ITEM) ?
|
|
||||||
(Item_ident*) (*reference) : 0));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Item::Type type= (*reference)->type();
|
|
||||||
prev_subselect_item->used_tables_cache|=
|
|
||||||
(*reference)->used_tables();
|
|
||||||
prev_subselect_item->const_item_cache&=
|
|
||||||
(*reference)->const_item();
|
|
||||||
mark_as_dependent(thd, last_checked_context->select_lex,
|
|
||||||
context->select_lex, this,
|
|
||||||
((type == REF_ITEM || type == FIELD_ITEM) ?
|
|
||||||
(Item_ident*) (*reference) :
|
|
||||||
0));
|
|
||||||
/*
|
|
||||||
A reference to a view field had been found and we
|
|
||||||
substituted it instead of this Item (find_field_in_tables
|
|
||||||
does it by assigning the new value to *reference), so now
|
|
||||||
we can return from this function.
|
|
||||||
*/
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Search in SELECT and GROUP lists of the outer select. */
|
|
||||||
if (outer_context->resolve_in_select_list)
|
|
||||||
{
|
|
||||||
if (!(ref= resolve_ref_in_select_and_group(thd, this, select)))
|
|
||||||
goto error; /* Some error occurred (e.g. ambiguous names). */
|
|
||||||
if (ref != not_found_item)
|
|
||||||
{
|
|
||||||
DBUG_ASSERT(*ref && (*ref)->fixed);
|
|
||||||
prev_subselect_item->used_tables_cache|= (*ref)->used_tables();
|
|
||||||
prev_subselect_item->const_item_cache&= (*ref)->const_item();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Reference is not found in this select => this subquery depend on
|
|
||||||
outer select (or we just trying to find wrong identifier, in this
|
|
||||||
case it does not matter which used tables bits we set)
|
|
||||||
*/
|
|
||||||
prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT;
|
|
||||||
prev_subselect_item->const_item_cache= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBUG_ASSERT(ref != 0);
|
|
||||||
if (!from_field)
|
|
||||||
goto error;
|
|
||||||
if (ref == not_found_item && from_field == not_found_field)
|
|
||||||
{
|
|
||||||
if (upward_lookup)
|
|
||||||
{
|
|
||||||
// We can't say exactly what absent table or field
|
|
||||||
my_error(ER_BAD_FIELD_ERROR, MYF(0), full_name(), thd->where);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Call find_field_in_tables only to report the error */
|
|
||||||
find_field_in_tables(thd, this,
|
|
||||||
context->first_name_resolution_table,
|
|
||||||
context->last_name_resolution_table,
|
|
||||||
reference, REPORT_ALL_ERRORS,
|
|
||||||
!any_privileges &&
|
|
||||||
TRUE, TRUE);
|
|
||||||
}
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
else if (ref != not_found_item)
|
|
||||||
{
|
|
||||||
Item *save;
|
|
||||||
Item_ref *rf;
|
|
||||||
|
|
||||||
/* Should have been checked in resolve_ref_in_select_and_group(). */
|
|
||||||
DBUG_ASSERT(*ref && (*ref)->fixed);
|
|
||||||
/*
|
|
||||||
Here, a subset of actions performed by Item_ref::set_properties
|
|
||||||
is not enough. So we pass ptr to NULL into Item_[direct]_ref
|
|
||||||
constructor, so no initialization is performed, and call
|
|
||||||
fix_fields() below.
|
|
||||||
*/
|
|
||||||
save= *ref;
|
|
||||||
*ref= NULL; // Don't call set_properties()
|
|
||||||
rf= (place == IN_HAVING ?
|
|
||||||
new Item_ref(context, ref, (char*) table_name,
|
|
||||||
(char*) field_name) :
|
|
||||||
new Item_direct_ref(context, ref, (char*) table_name,
|
|
||||||
(char*) field_name));
|
|
||||||
*ref= save;
|
|
||||||
if (!rf)
|
|
||||||
goto error;
|
|
||||||
thd->change_item_tree(reference, rf);
|
|
||||||
/*
|
|
||||||
rf is Item_ref => never substitute other items (in this case)
|
|
||||||
during fix_fields() => we can use rf after fix_fields()
|
|
||||||
*/
|
|
||||||
DBUG_ASSERT(!rf->fixed); // Assured by Item_ref()
|
|
||||||
if (rf->fix_fields(thd, reference) || rf->check_cols(1))
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
mark_as_dependent(thd, last_checked_context->select_lex,
|
|
||||||
context->select_lex, this,
|
|
||||||
rf);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mark_as_dependent(thd, last_checked_context->select_lex,
|
|
||||||
context->select_lex,
|
|
||||||
this, this);
|
|
||||||
if (last_checked_context->select_lex->having_fix_field)
|
|
||||||
{
|
|
||||||
Item_ref *rf;
|
|
||||||
rf= new Item_ref(context,
|
|
||||||
(cached_table->db[0] ? cached_table->db : 0),
|
|
||||||
(char*) cached_table->alias, (char*) field_name);
|
|
||||||
if (!rf)
|
|
||||||
goto error;
|
|
||||||
thd->change_item_tree(reference, rf);
|
|
||||||
/*
|
|
||||||
rf is Item_ref => never substitute other items (in this case)
|
|
||||||
during fix_fields() => we can use rf after fix_fields()
|
|
||||||
*/
|
|
||||||
DBUG_ASSERT(!rf->fixed); // Assured by Item_ref()
|
|
||||||
if (rf->fix_fields(thd, reference) || rf->check_cols(1))
|
|
||||||
goto error;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (!from_field)
|
else if (!from_field)
|
||||||
goto error;
|
goto error;
|
||||||
@@ -3502,6 +3561,17 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
|
|||||||
if (from_field == view_ref_found)
|
if (from_field == view_ref_found)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
if (!outer_fixed && cached_table && cached_table->select_lex &&
|
||||||
|
context->select_lex &&
|
||||||
|
cached_table->select_lex != context->select_lex)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
if ((ret= fix_outer_field(thd, &from_field, reference)) < 0)
|
||||||
|
goto error;
|
||||||
|
else if (!ret)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
set_field(from_field);
|
set_field(from_field);
|
||||||
if (thd->lex->in_sum_func &&
|
if (thd->lex->in_sum_func &&
|
||||||
thd->lex->in_sum_func->nest_level ==
|
thd->lex->in_sum_func->nest_level ==
|
||||||
@@ -4620,6 +4690,25 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
|
|||||||
}
|
}
|
||||||
if (from_field != not_found_field)
|
if (from_field != not_found_field)
|
||||||
{
|
{
|
||||||
|
if (cached_table && cached_table->select_lex &&
|
||||||
|
outer_context->select_lex &&
|
||||||
|
cached_table->select_lex != outer_context->select_lex)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Due to cache, find_field_in_tables() can return field which
|
||||||
|
doesn't belong to provided outer_context. In this case we have
|
||||||
|
to find proper field context in order to fix field correcly.
|
||||||
|
*/
|
||||||
|
do
|
||||||
|
{
|
||||||
|
outer_context= outer_context->outer_context;
|
||||||
|
select= outer_context->select_lex;
|
||||||
|
prev_subselect_item=
|
||||||
|
last_checked_context->select_lex->master_unit()->item;
|
||||||
|
last_checked_context= outer_context;
|
||||||
|
} while (outer_context && outer_context->select_lex &&
|
||||||
|
cached_table->select_lex != outer_context->select_lex);
|
||||||
|
}
|
||||||
prev_subselect_item->used_tables_cache|= from_field->table->map;
|
prev_subselect_item->used_tables_cache|= from_field->table->map;
|
||||||
prev_subselect_item->const_item_cache= 0;
|
prev_subselect_item->const_item_cache= 0;
|
||||||
break;
|
break;
|
||||||
|
@@ -1161,6 +1161,7 @@ public:
|
|||||||
inline uint32 max_disp_length() { return field->max_length(); }
|
inline uint32 max_disp_length() { return field->max_length(); }
|
||||||
Item_field *filed_for_view_update() { return this; }
|
Item_field *filed_for_view_update() { return this; }
|
||||||
Item *safe_charset_converter(CHARSET_INFO *tocs);
|
Item *safe_charset_converter(CHARSET_INFO *tocs);
|
||||||
|
int fix_outer_field(THD *thd, Field **field, Item **reference);
|
||||||
friend class Item_default_value;
|
friend class Item_default_value;
|
||||||
friend class Item_insert_value;
|
friend class Item_insert_value;
|
||||||
friend class st_select_lex_unit;
|
friend class st_select_lex_unit;
|
||||||
|
@@ -125,6 +125,7 @@ public:
|
|||||||
friend class select_subselect;
|
friend class select_subselect;
|
||||||
friend class Item_in_optimizer;
|
friend class Item_in_optimizer;
|
||||||
friend bool Item_field::fix_fields(THD *, Item **);
|
friend bool Item_field::fix_fields(THD *, Item **);
|
||||||
|
friend int Item_field::fix_outer_field(THD *, Field **, Item **);
|
||||||
friend bool Item_ref::fix_fields(THD *, Item **);
|
friend bool Item_ref::fix_fields(THD *, Item **);
|
||||||
friend void mark_select_range_as_dependent(THD*,
|
friend void mark_select_range_as_dependent(THD*,
|
||||||
st_select_lex*, st_select_lex*,
|
st_select_lex*, st_select_lex*,
|
||||||
|
Reference in New Issue
Block a user