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.cc140
1 files changed, 86 insertions, 54 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 6f114165fa6..77bb1d9642b 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -849,6 +849,7 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table,
thd thread handle
table table which should be checked
table_list list of tables
+ check_alias whether to check tables' aliases
NOTE: to exclude derived tables from check we use following mechanism:
a) during derived table processing set THD::derived_tables_processing
@@ -876,10 +877,11 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table,
0 if table is unique
*/
-TABLE_LIST* unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list)
+TABLE_LIST* unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list,
+ bool check_alias)
{
TABLE_LIST *res;
- const char *d_name, *t_name;
+ const char *d_name, *t_name, *t_alias;
DBUG_ENTER("unique_table");
DBUG_PRINT("enter", ("table alias: %s", table->alias));
@@ -907,6 +909,7 @@ TABLE_LIST* unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list)
}
d_name= table->db;
t_name= table->table_name;
+ t_alias= table->alias;
DBUG_PRINT("info", ("real table: %s.%s", d_name, t_name));
for (;;)
@@ -914,6 +917,9 @@ TABLE_LIST* unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list)
if (((! (res= find_table_in_global_list(table_list, d_name, t_name))) &&
(! (res= mysql_lock_have_duplicate(thd, table, table_list)))) ||
((!res->table || res->table != table->table) &&
+ (!check_alias || !(lower_case_table_names ?
+ my_strcasecmp(files_charset_info, t_alias, res->alias) :
+ strcmp(t_alias, res->alias))) &&
res->select_lex && !res->select_lex->exclude_from_table_unique_test &&
!res->prelocking_placeholder))
break;
@@ -3654,10 +3660,13 @@ find_field_in_tables(THD *thd, Item_ident *item,
return not_found_item, report other errors,
return 0
IGNORE_ERRORS Do not report errors, return 0 if error
- unaliased Set to true if item is field which was found
- by original field name and not by its alias
- in item list. Set to false otherwise.
-
+ resolution Set to the resolution type if the item is found
+ (it says whether the item is resolved
+ against an alias name,
+ or as a field name without alias,
+ or as a field hidden by alias,
+ or ignoring alias)
+
RETURN VALUES
0 Item is not found or item is not unique,
error message is reported
@@ -3673,7 +3682,8 @@ Item **not_found_item= (Item**) 0x1;
Item **
find_item_in_list(Item *find, List<Item> &items, uint *counter,
- find_item_error_report_type report_error, bool *unaliased)
+ find_item_error_report_type report_error,
+ enum_resolution_type *resolution)
{
List_iterator<Item> li(items);
Item **found=0, **found_unaliased= 0, *item;
@@ -3687,10 +3697,9 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
*/
bool is_ref_by_name= 0;
uint unaliased_counter;
-
LINT_INIT(unaliased_counter); // Dependent on found_unaliased
- *unaliased= FALSE;
+ *resolution= NOT_RESOLVED;
is_ref_by_name= (find->type() == Item::FIELD_ITEM ||
find->type() == Item::REF_ITEM);
@@ -3757,63 +3766,77 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
}
found_unaliased= li.ref();
unaliased_counter= i;
+ *resolution= RESOLVED_IGNORING_ALIAS;
if (db_name)
break; // Perfect match
}
}
- else if (!my_strcasecmp(system_charset_info, item_field->name,
- field_name))
- {
- /*
- If table name was not given we should scan through aliases
- (or non-aliased fields) first. We are also checking unaliased
- name of the field in then next else-if, to be able to find
- instantly field (hidden by alias) if no suitable alias (or
- non-aliased field) was found.
- */
- if (found)
- {
- if ((*found)->eq(item, 0))
- continue; // Same field twice
- if (report_error != IGNORE_ERRORS)
- my_error(ER_NON_UNIQ_ERROR, MYF(0),
- find->full_name(), current_thd->where);
- return (Item**) 0;
- }
- found= li.ref();
- *counter= i;
- }
- else if (!my_strcasecmp(system_charset_info, item_field->field_name,
- field_name))
+ else
{
- /*
- We will use un-aliased field or react on such ambiguities only if
- we won't be able to find aliased field.
- Again if we have ambiguity with field outside of select list
- we should prefer fields from select list.
- */
- if (found_unaliased)
+ int fname_cmp= my_strcasecmp(system_charset_info,
+ item_field->field_name,
+ field_name);
+ if (!my_strcasecmp(system_charset_info,
+ item_field->name,field_name))
{
- if ((*found_unaliased)->eq(item, 0))
- continue; // Same field twice
- found_unaliased_non_uniq= 1;
+ /*
+ If table name was not given we should scan through aliases
+ and non-aliased fields first. We are also checking unaliased
+ name of the field in then next else-if, to be able to find
+ instantly field (hidden by alias) if no suitable alias or
+ non-aliased field was found.
+ */
+ if (found)
+ {
+ if ((*found)->eq(item, 0))
+ continue; // Same field twice
+ if (report_error != IGNORE_ERRORS)
+ my_error(ER_NON_UNIQ_ERROR, MYF(0),
+ find->full_name(), current_thd->where);
+ return (Item**) 0;
+ }
+ found= li.ref();
+ *counter= i;
+ *resolution= fname_cmp ? RESOLVED_AGAINST_ALIAS:
+ RESOLVED_WITH_NO_ALIAS;
}
- else
+ else if (!fname_cmp)
{
+ /*
+ We will use non-aliased field or react on such ambiguities only if
+ we won't be able to find aliased field.
+ Again if we have ambiguity with field outside of select list
+ we should prefer fields from select list.
+ */
+ if (found_unaliased)
+ {
+ if ((*found_unaliased)->eq(item, 0))
+ continue; // Same field twice
+ found_unaliased_non_uniq= 1;
+ }
found_unaliased= li.ref();
unaliased_counter= i;
}
}
}
- else if (!table_name && (find->eq(item,0) ||
- is_ref_by_name && find->name && item->name &&
- !my_strcasecmp(system_charset_info,
- item->name,find->name)))
- {
- found= li.ref();
- *counter= i;
- break;
- }
+ else if (!table_name)
+ {
+ if (is_ref_by_name && find->name && item->name &&
+ !my_strcasecmp(system_charset_info,item->name,find->name))
+ {
+ found= li.ref();
+ *counter= i;
+ *resolution= RESOLVED_AGAINST_ALIAS;
+ break;
+ }
+ else if (find->eq(item,0))
+ {
+ found= li.ref();
+ *counter= i;
+ *resolution= RESOLVED_IGNORING_ALIAS;
+ break;
+ }
+ }
}
if (!found)
{
@@ -3828,7 +3851,7 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
{
found= found_unaliased;
*counter= unaliased_counter;
- *unaliased= TRUE;
+ *resolution= RESOLVED_BEHIND_ALIAS;
}
}
if (found)
@@ -4606,12 +4629,15 @@ bool setup_fields(THD *thd, Item **ref_pointer_array,
bool save_set_query_id= thd->set_query_id;
nesting_map save_allow_sum_func= thd->lex->allow_sum_func;
List_iterator<Item> it(fields);
+ bool save_is_item_list_lookup;
DBUG_ENTER("setup_fields");
thd->set_query_id=set_query_id;
if (allow_sum_func)
thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level;
thd->where= THD::DEFAULT_WHERE;
+ save_is_item_list_lookup= thd->lex->current_select->is_item_list_lookup;
+ thd->lex->current_select->is_item_list_lookup= 0;
/*
To prevent fail on forward lookup we fill it with zerows,
@@ -4634,6 +4660,7 @@ bool setup_fields(THD *thd, Item **ref_pointer_array,
if (!item->fixed && item->fix_fields(thd, it.ref()) ||
(item= *(it.ref()))->check_cols(1))
{
+ thd->lex->current_select->is_item_list_lookup= save_is_item_list_lookup;
thd->lex->allow_sum_func= save_allow_sum_func;
thd->set_query_id= save_set_query_id;
DBUG_RETURN(TRUE); /* purecov: inspected */
@@ -4646,6 +4673,7 @@ bool setup_fields(THD *thd, Item **ref_pointer_array,
thd->used_tables|= item->used_tables();
thd->lex->current_select->cur_pos_in_select_list++;
}
+ thd->lex->current_select->is_item_list_lookup= save_is_item_list_lookup;
thd->lex->current_select->cur_pos_in_select_list= UNDEF_POS;
thd->lex->allow_sum_func= save_allow_sum_func;
@@ -5142,6 +5170,8 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
*/
bool it_is_update= (select_lex == &thd->lex->select_lex) &&
thd->lex->which_check_option_applicable();
+ bool save_is_item_list_lookup= select_lex->is_item_list_lookup;
+ select_lex->is_item_list_lookup= 0;
DBUG_ENTER("setup_conds");
if (select_lex->conds_processed_with_permanent_arena ||
@@ -5216,9 +5246,11 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
select_lex->where= *conds;
select_lex->conds_processed_with_permanent_arena= 1;
}
+ thd->lex->current_select->is_item_list_lookup= save_is_item_list_lookup;
DBUG_RETURN(test(thd->net.report_error));
err_no_arena:
+ select_lex->is_item_list_lookup= save_is_item_list_lookup;
DBUG_RETURN(1);
}