diff options
author | unknown <dlenev@brandersnatch.localdomain> | 2004-09-30 16:28:17 +0400 |
---|---|---|
committer | unknown <dlenev@brandersnatch.localdomain> | 2004-09-30 16:28:17 +0400 |
commit | 53edc92cd01c292ebe536070f11c311542c7bb95 (patch) | |
tree | 869403a16f8b3c117fed13dae2bac7e2f7ab89b6 /sql/sql_base.cc | |
parent | ccf52b4fd5bd7ae0a418d22f2758cef345b6afa6 (diff) | |
download | mariadb-git-53edc92cd01c292ebe536070f11c311542c7bb95.tar.gz |
Final solution for bug# 4302 "Ambiguos order by when renamed column is
identical to another in result"
According to SQL standard queries like
"select t1.a as col from t1, t2 order by a" should return an error if
both tables contain field a.
mysql-test/r/order_by.result:
Updated test to conform SQL-standard.
mysql-test/t/order_by.test:
Updated test to conform SQL-standard.
sql/item.cc:
find_item_in_list() has now one more out parameter which is not used
in item.cc functions.
sql/mysql_priv.h:
find_item_in_list(): Added boolean out parameter "unaliased" which
indicates that we have found field by its original name and not by
its alias in item (select) list.
sql/sql_base.cc:
find_item_in_list(): Added boolean out parameter "unaliased" which
indicates that we have found field by its original name and not by
its alias in item (select) list. This means that additional check is
required to ensure there will be no ambiguity if we would search for this
field in all tables.
sql/sql_select.cc:
find_order_in_list(): If we have found field in select list by its
original name and not by its alias then we should perform additional
check to ensure that there will be no ambiguity if we will search for
this field in all tables. Also small cleanup.
Diffstat (limited to 'sql/sql_base.cc')
-rw-r--r-- | sql/sql_base.cc | 43 |
1 files changed, 28 insertions, 15 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 75eb5753e1e..7464523aad4 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2082,14 +2082,17 @@ 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, error message is reported not_found_item Function was called with report_error == REPORT_EXCEPT_NOT_FOUND and item was not found. No error message was reported - found field + found field */ // Special Item pointer for find_item_in_list returning @@ -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; @@ -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; @@ -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, @@ -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 } @@ -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) |