Loading mysql-test/r/order_by.result +3 −6 Original line number Diff line number Diff line Loading @@ -680,6 +680,9 @@ order by col; ERROR 23000: Column 'col' in order clause is ambiguous select col1 from t1, t2 where t1.col1=t2.col2 order by col; ERROR 23000: Column 'col' in order clause is ambiguous select t1.col as t1_col, t2.col2 from t1, t2 where t1.col1=t2.col2 order by col; ERROR 23000: Column 'col' in order clause is ambiguous select t1.col as t1_col, t2.col from t1, t2 where t1.col1=t2.col2 order by col; t1_col col Loading @@ -696,12 +699,6 @@ col col2 1 3 2 2 3 1 select t1.col as t1_col, t2.col2 from t1, t2 where t1.col1=t2.col2 order by col; t1_col col2 1 1 2 2 3 3 select t2.col2, t2.col, t2.col from t2 order by col; col2 col col 3 1 1 Loading mysql-test/t/order_by.test +3 −2 Original line number Diff line number Diff line Loading @@ -472,13 +472,14 @@ select t1.col as c1, t2.col as c2 from t1, t2 where t1.col1=t2.col2 order by col; --error 1052 select col1 from t1, t2 where t1.col1=t2.col2 order by col; --error 1052 select t1.col as t1_col, t2.col2 from t1, t2 where t1.col1=t2.col2 order by col; select t1.col as t1_col, t2.col from t1, t2 where t1.col1=t2.col2 order by col; select col2 as c, col as c from t2 order by col; select col2 as col, col as col2 from t2 order by col; select t1.col as t1_col, t2.col2 from t1, t2 where t1.col1=t2.col2 order by col; select t2.col2, t2.col, t2.col from t2 order by col; select t2.col2 as col from t2 order by t2.col; Loading sql/item.cc +9 −7 Original line number Diff line number Diff line Loading @@ -1246,6 +1246,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) TABLE_LIST *table_list; Item **refer= (Item **)not_found_item; uint counter; bool not_used; // Prevent using outer fields in subselects, that is not supported now SELECT_LEX *cursel= (SELECT_LEX *) thd->lex->current_select; if (cursel->master_unit()->first_select()->linkage != DERIVED_TABLE_TYPE) Loading Loading @@ -1288,7 +1289,8 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) } if (sl->resolve_mode == SELECT_LEX::SELECT_MODE && (refer= find_item_in_list(this, sl->item_list, &counter, REPORT_EXCEPT_NOT_FOUND)) != REPORT_EXCEPT_NOT_FOUND, ¬_used)) != (Item **) not_found_item) { if (*refer && (*refer)->fixed) // Avoid crash in case of error Loading Loading @@ -1889,6 +1891,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) { DBUG_ASSERT(fixed == 0); uint counter; bool not_used; if (!ref) { TABLE_LIST *where= 0, *table_list; Loading @@ -1908,13 +1911,13 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) first_select()->linkage != DERIVED_TABLE_TYPE) ? REPORT_EXCEPT_NOT_FOUND : REPORT_ALL_ERRORS))) == REPORT_ALL_ERRORS ), ¬_used)) == (Item **)not_found_item) { upward_lookup= 1; Field *tmp= (Field*) not_found_field; /* We can't find table field in table list of current select, We can't find table field in select list of current select, consequently we have to find it in outer subselect(s). We can't join lists of outer & current select, because of scope of view rules. For example if both tables (outer & current) have Loading @@ -1929,8 +1932,8 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) Item_subselect *prev_subselect_item= prev_unit->item; if (sl->resolve_mode == SELECT_LEX::SELECT_MODE && (ref= find_item_in_list(this, sl->item_list, &counter, REPORT_EXCEPT_NOT_FOUND)) != &counter, REPORT_EXCEPT_NOT_FOUND, ¬_used)) != (Item **)not_found_item) { if (*ref && (*ref)->fixed) // Avoid crash in case of error Loading Loading @@ -1989,8 +1992,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) // Call to report error find_item_in_list(this, *(thd->lex->current_select->get_item_list()), &counter, REPORT_ALL_ERRORS); &counter, REPORT_ALL_ERRORS, ¬_used); } ref= 0; return 1; Loading sql/mysql_priv.h +2 −1 Original line number Diff line number Diff line Loading @@ -705,7 +705,8 @@ enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND, IGNORE_ERRORS}; extern const Item **not_found_item; Item ** find_item_in_list(Item *item, List<Item> &items, uint *counter, find_item_error_report_type report_error); find_item_error_report_type report_error, bool *unaliased); bool get_key_map_from_key_list(key_map *map, TABLE *table, List<String> *index_list); bool insert_fields(THD *thd,TABLE_LIST *tables, Loading sql/sql_base.cc +28 −15 Original line number Diff line number Diff line Loading @@ -2082,6 +2082,9 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, 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. RETURN VALUES 0 Item is not found or item is not unique, Loading @@ -2098,7 +2101,7 @@ const Item **not_found_item= (const Item**) 0x1; Item ** find_item_in_list(Item *find, List<Item> &items, uint *counter, find_item_error_report_type report_error) find_item_error_report_type report_error, bool *unaliased) { List_iterator<Item> li(items); Item **found=0, **found_unaliased= 0, *item; Loading @@ -2107,6 +2110,9 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter, const char *table_name=0; bool found_unaliased_non_uniq= 0; uint unaliased_counter; *unaliased= FALSE; if (find->type() == Item::FIELD_ITEM || find->type() == Item::REF_ITEM) { field_name= ((Item_ident*) find)->field_name; Loading Loading @@ -2134,17 +2140,18 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter, /* If table name is specified we should find field 'field_name' in table 'table_name'. According to SQL-standard we should ignore aliases in this case. Note that we should prefer fields from the select list over other fields from the tables participating in this select in case of ambiguity. aliases in this case. Since we should NOT prefer fields from the select list over other fields from the tables participating in this select in case of ambiguity we have to do extra check outside this function. We use strcmp for table names and database names as these may be case sensitive. In cases where they are not case sensitive, they are always in lower case. case sensitive. In cases where they are not case sensitive, they are always in lower case. item_field->field_name and item_field->table_name can be 0x0 if item is not fix fielded yet. item is not fix_field()'ed yet. */ if (item_field->field_name && item_field->table_name && !my_strcasecmp(system_charset_info, item_field->field_name, Loading @@ -2153,17 +2160,22 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter, (!db_name || (item_field->db_name && !strcmp(item_field->db_name, db_name)))) { if (found) if (found_unaliased) { if ((*found)->eq(item, 0)) continue; // Same field twice if ((*found_unaliased)->eq(item, 0)) continue; /* Two matching fields in select list. We already can bail out because we are searching through unaliased names only and will have duplicate error anyway. */ if (report_error != IGNORE_ERRORS) my_printf_error(ER_NON_UNIQ_ERROR, ER(ER_NON_UNIQ_ERROR), MYF(0), find->full_name(), current_thd->where); return (Item**) 0; } found= li.ref(); *counter= i; found_unaliased= li.ref(); unaliased_counter= i; if (db_name) break; // Perfect match } Loading Loading @@ -2235,6 +2247,7 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter, { found= found_unaliased; *counter= unaliased_counter; *unaliased= TRUE; } } if (found) Loading Loading
mysql-test/r/order_by.result +3 −6 Original line number Diff line number Diff line Loading @@ -680,6 +680,9 @@ order by col; ERROR 23000: Column 'col' in order clause is ambiguous select col1 from t1, t2 where t1.col1=t2.col2 order by col; ERROR 23000: Column 'col' in order clause is ambiguous select t1.col as t1_col, t2.col2 from t1, t2 where t1.col1=t2.col2 order by col; ERROR 23000: Column 'col' in order clause is ambiguous select t1.col as t1_col, t2.col from t1, t2 where t1.col1=t2.col2 order by col; t1_col col Loading @@ -696,12 +699,6 @@ col col2 1 3 2 2 3 1 select t1.col as t1_col, t2.col2 from t1, t2 where t1.col1=t2.col2 order by col; t1_col col2 1 1 2 2 3 3 select t2.col2, t2.col, t2.col from t2 order by col; col2 col col 3 1 1 Loading
mysql-test/t/order_by.test +3 −2 Original line number Diff line number Diff line Loading @@ -472,13 +472,14 @@ select t1.col as c1, t2.col as c2 from t1, t2 where t1.col1=t2.col2 order by col; --error 1052 select col1 from t1, t2 where t1.col1=t2.col2 order by col; --error 1052 select t1.col as t1_col, t2.col2 from t1, t2 where t1.col1=t2.col2 order by col; select t1.col as t1_col, t2.col from t1, t2 where t1.col1=t2.col2 order by col; select col2 as c, col as c from t2 order by col; select col2 as col, col as col2 from t2 order by col; select t1.col as t1_col, t2.col2 from t1, t2 where t1.col1=t2.col2 order by col; select t2.col2, t2.col, t2.col from t2 order by col; select t2.col2 as col from t2 order by t2.col; Loading
sql/item.cc +9 −7 Original line number Diff line number Diff line Loading @@ -1246,6 +1246,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) TABLE_LIST *table_list; Item **refer= (Item **)not_found_item; uint counter; bool not_used; // Prevent using outer fields in subselects, that is not supported now SELECT_LEX *cursel= (SELECT_LEX *) thd->lex->current_select; if (cursel->master_unit()->first_select()->linkage != DERIVED_TABLE_TYPE) Loading Loading @@ -1288,7 +1289,8 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) } if (sl->resolve_mode == SELECT_LEX::SELECT_MODE && (refer= find_item_in_list(this, sl->item_list, &counter, REPORT_EXCEPT_NOT_FOUND)) != REPORT_EXCEPT_NOT_FOUND, ¬_used)) != (Item **) not_found_item) { if (*refer && (*refer)->fixed) // Avoid crash in case of error Loading Loading @@ -1889,6 +1891,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) { DBUG_ASSERT(fixed == 0); uint counter; bool not_used; if (!ref) { TABLE_LIST *where= 0, *table_list; Loading @@ -1908,13 +1911,13 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) first_select()->linkage != DERIVED_TABLE_TYPE) ? REPORT_EXCEPT_NOT_FOUND : REPORT_ALL_ERRORS))) == REPORT_ALL_ERRORS ), ¬_used)) == (Item **)not_found_item) { upward_lookup= 1; Field *tmp= (Field*) not_found_field; /* We can't find table field in table list of current select, We can't find table field in select list of current select, consequently we have to find it in outer subselect(s). We can't join lists of outer & current select, because of scope of view rules. For example if both tables (outer & current) have Loading @@ -1929,8 +1932,8 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) Item_subselect *prev_subselect_item= prev_unit->item; if (sl->resolve_mode == SELECT_LEX::SELECT_MODE && (ref= find_item_in_list(this, sl->item_list, &counter, REPORT_EXCEPT_NOT_FOUND)) != &counter, REPORT_EXCEPT_NOT_FOUND, ¬_used)) != (Item **)not_found_item) { if (*ref && (*ref)->fixed) // Avoid crash in case of error Loading Loading @@ -1989,8 +1992,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) // Call to report error find_item_in_list(this, *(thd->lex->current_select->get_item_list()), &counter, REPORT_ALL_ERRORS); &counter, REPORT_ALL_ERRORS, ¬_used); } ref= 0; return 1; Loading
sql/mysql_priv.h +2 −1 Original line number Diff line number Diff line Loading @@ -705,7 +705,8 @@ enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND, IGNORE_ERRORS}; extern const Item **not_found_item; Item ** find_item_in_list(Item *item, List<Item> &items, uint *counter, find_item_error_report_type report_error); find_item_error_report_type report_error, bool *unaliased); bool get_key_map_from_key_list(key_map *map, TABLE *table, List<String> *index_list); bool insert_fields(THD *thd,TABLE_LIST *tables, Loading
sql/sql_base.cc +28 −15 Original line number Diff line number Diff line Loading @@ -2082,6 +2082,9 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, 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. RETURN VALUES 0 Item is not found or item is not unique, Loading @@ -2098,7 +2101,7 @@ const Item **not_found_item= (const Item**) 0x1; Item ** find_item_in_list(Item *find, List<Item> &items, uint *counter, find_item_error_report_type report_error) find_item_error_report_type report_error, bool *unaliased) { List_iterator<Item> li(items); Item **found=0, **found_unaliased= 0, *item; Loading @@ -2107,6 +2110,9 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter, const char *table_name=0; bool found_unaliased_non_uniq= 0; uint unaliased_counter; *unaliased= FALSE; if (find->type() == Item::FIELD_ITEM || find->type() == Item::REF_ITEM) { field_name= ((Item_ident*) find)->field_name; Loading Loading @@ -2134,17 +2140,18 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter, /* If table name is specified we should find field 'field_name' in table 'table_name'. According to SQL-standard we should ignore aliases in this case. Note that we should prefer fields from the select list over other fields from the tables participating in this select in case of ambiguity. aliases in this case. Since we should NOT prefer fields from the select list over other fields from the tables participating in this select in case of ambiguity we have to do extra check outside this function. We use strcmp for table names and database names as these may be case sensitive. In cases where they are not case sensitive, they are always in lower case. case sensitive. In cases where they are not case sensitive, they are always in lower case. item_field->field_name and item_field->table_name can be 0x0 if item is not fix fielded yet. item is not fix_field()'ed yet. */ if (item_field->field_name && item_field->table_name && !my_strcasecmp(system_charset_info, item_field->field_name, Loading @@ -2153,17 +2160,22 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter, (!db_name || (item_field->db_name && !strcmp(item_field->db_name, db_name)))) { if (found) if (found_unaliased) { if ((*found)->eq(item, 0)) continue; // Same field twice if ((*found_unaliased)->eq(item, 0)) continue; /* Two matching fields in select list. We already can bail out because we are searching through unaliased names only and will have duplicate error anyway. */ if (report_error != IGNORE_ERRORS) my_printf_error(ER_NON_UNIQ_ERROR, ER(ER_NON_UNIQ_ERROR), MYF(0), find->full_name(), current_thd->where); return (Item**) 0; } found= li.ref(); *counter= i; found_unaliased= li.ref(); unaliased_counter= i; if (db_name) break; // Perfect match } Loading Loading @@ -2235,6 +2247,7 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter, { found= found_unaliased; *counter= unaliased_counter; *unaliased= TRUE; } } if (found) Loading