summaryrefslogtreecommitdiff
path: root/sql/sql_base.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_base.cc')
-rw-r--r--sql/sql_base.cc45
1 files changed, 38 insertions, 7 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index b7831a2a5b5..f578876bc5e 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -2617,6 +2617,8 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list,
table_list->alias, name, item_name, (ulong) ref));
Field_iterator_view field_it;
field_it.set(table_list);
+ Query_arena *arena, backup;
+
DBUG_ASSERT(table_list->schema_table_reformed ||
(ref != 0 && table_list->view != 0));
for (; !field_it.end_of_fields(); field_it.next())
@@ -2638,7 +2640,13 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list,
name, length))
DBUG_RETURN(WRONG_GRANT);
#endif
+ // in PS use own arena or data will be freed after prepare
+ if (register_tree_change)
+ arena= thd->activate_stmt_arena_if_needed(&backup);
Item *item= field_it.create_item(thd);
+ if (register_tree_change && arena)
+ thd->restore_active_arena(arena, &backup);
+
if (!item)
DBUG_RETURN(0);
/*
@@ -2700,6 +2708,8 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name,
field_it(*(table_ref->join_columns));
Natural_join_column *nj_col;
Field *found_field;
+ Query_arena *arena, backup;
+
DBUG_ENTER("find_field_in_natural_join");
DBUG_PRINT("enter", ("field name: '%s', ref 0x%lx",
name, (ulong) ref));
@@ -2728,7 +2738,14 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name,
The found field is a view field, we do as in find_field_in_view()
and return a pointer to pointer to the Item of that field.
*/
+ if (register_tree_change)
+ arena= thd->activate_stmt_arena_if_needed(&backup);
+
Item *item= nj_col->create_item(thd);
+
+ if (register_tree_change && arena)
+ thd->restore_active_arena(arena, &backup);
+
if (!item)
DBUG_RETURN(NULL);
DBUG_ASSERT(nj_col->table_field == NULL);
@@ -2882,14 +2899,15 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
/*
Check that the table and database that qualify the current field name
are the same as the table we are going to search for the field.
- This is done differently for NATURAL/USING joins because there we can't
- simply compare the qualifying table and database names with the ones of
+ This is done differently for NATURAL/USING joins or nested joins that
+ are operands of NATURAL/USING joins because there we can't simply
+ compare the qualifying table and database names with the ones of
'table_list' because each field in such a join may originate from a
different table.
TODO: Ensure that table_name, db_name and tables->db always points to
something !
*/
- if (!table_list->is_natural_join &&
+ if (!(table_list->nested_join && table_list->join_columns) &&
table_name && table_name[0] &&
(my_strcasecmp(table_alias_charset, table_list->alias, table_name) ||
(db_name && db_name[0] && table_list->db && table_list->db[0] &&
@@ -2904,8 +2922,13 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
register_tree_change)))
*actual_table= table_list;
}
- else if (table_list->is_natural_join)
+ else if (table_list->nested_join && table_list->join_columns)
{
+ /*
+ If this is a NATURAL/USING join, or an operand of such join which is a
+ join itself, and the field name is qualified, then search for the field
+ in the operands of the join.
+ */
if (table_name && table_name[0])
{
/*
@@ -2927,7 +2950,9 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
}
/*
Non-qualified field, search directly in the result columns of the
- natural join.
+ natural join. The condition of the outer IF is true for the top-most
+ natural join, thus if the field is not qualified, we will search
+ directly the top-most NATURAL/USING join.
*/
fld= find_field_in_natural_join(thd, table_list, name, length, ref,
/* TIMOUR_TODO: check this with Sanja */
@@ -3569,10 +3594,16 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2,
if (add_columns && is_created_2)
table_ref_2->join_columns->push_back(cur_nj_col_2);
- /* Compare the two columns and check for duplicate common fields. */
+ /*
+ Compare the two columns and check for duplicate common fields.
+ A common field is duplicate either if it was already found in
+ table_ref_2 (then found == TRUE), or if a field in table_ref_2
+ was already matched by some previous field in table_ref_1
+ (then cur_nj_col_2->is_common == TRUE).
+ */
if (!my_strcasecmp(system_charset_info, field_name_1, cur_field_name_2))
{
- if (found)
+ if (found || cur_nj_col_2->is_common)
{
my_error(ER_NON_UNIQ_ERROR, MYF(0), field_name_1, thd->where);
goto err;