diff options
author | unknown <dlenev@brandersnatch.localdomain> | 2004-08-20 19:30:45 +0400 |
---|---|---|
committer | unknown <dlenev@brandersnatch.localdomain> | 2004-08-20 19:30:45 +0400 |
commit | 764dd4918cb1a099348a47639ac5223aca8c3ee3 (patch) | |
tree | ef5a56fdd09959b03ed0bd03c6e5ce93ba678d14 | |
parent | 03990ba490fbab94115d003a8d9186bdc0bbafcb (diff) | |
parent | f9c3cb5f2e764955890c9a4db8d791a47561d130 (diff) | |
download | mariadb-git-764dd4918cb1a099348a47639ac5223aca8c3ee3.tar.gz |
Merge bk-internal.mysql.com:/home/bk/mysql-4.1
into brandersnatch.localdomain:/home/dlenev/src/mysql-4.1-bg4302
sql/sql_select.cc:
Auto merged
-rw-r--r-- | mysql-test/r/order_by.result | 73 | ||||
-rw-r--r-- | mysql-test/t/order_by.test | 45 | ||||
-rw-r--r-- | sql/sql_base.cc | 123 | ||||
-rw-r--r-- | sql/sql_select.cc | 9 |
4 files changed, 211 insertions, 39 deletions
diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result index 694dc26bcde..b3bc4a18a40 100644 --- a/mysql-test/r/order_by.result +++ b/mysql-test/r/order_by.result @@ -116,7 +116,7 @@ col1 2 3 2 -select col1 as id from t1 order by t1.id; +select col1 as id from t1 order by id; id 1 1 @@ -126,16 +126,16 @@ id 2 2 3 -select concat(col1) as id from t1 order by t1.id; +select concat(col1) as id from t1 order by id; id -2 -2 1 1 1 2 -3 2 +2 +2 +3 drop table t1; CREATE TABLE t1 (id int auto_increment primary key,aika varchar(40),aikakentta timestamp); insert into t1 (aika) values ('Keskiviikko'); @@ -660,3 +660,66 @@ a b c d 1 1 12 -1 1 1 2 0 drop table t1, t2; +create table t1 (col1 int, col int); +create table t2 (col2 int, col int); +insert into t1 values (1,1),(2,2),(3,3); +insert into t2 values (1,3),(2,2),(3,1); +select t1.* , t2.col as t2_col from t1 left join t2 on (t1.col1=t2.col2) +order by col; +col1 col t2_col +1 1 3 +2 2 2 +3 3 1 +select col1 as col, col from t1 order by col; +ERROR 23000: Column 'col' in order clause is ambiguous +select t1.col as c1, t2.col as c2 from t1, t2 where t1.col1=t2.col2 +order by col; +ERROR 23000: Column 'col' in order clause is ambiguous +select t1.col as c1, t2.col as c2 from t1, t2 where t1.col1=t2.col2 +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.col from t1, t2 where t1.col1=t2.col2 +order by col; +t1_col col +3 1 +2 2 +1 3 +select col2 as c, col as c from t2 order by col; +c c +3 1 +2 2 +1 3 +select col2 as col, col as col2 from t2 order by col; +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 +2 2 2 +1 3 3 +select t2.col2 as col from t2 order by t2.col; +col +3 +2 +1 +select t2.col2 as col, t2.col from t2 order by t2.col; +col col +3 1 +2 2 +1 3 +select t2.col2, t2.col, t2.col from t2 order by t2.col; +col2 col col +3 1 1 +2 2 2 +1 3 3 +drop table t1, t2; diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test index 465920deaed..5131bb8c8b8 100644 --- a/mysql-test/t/order_by.test +++ b/mysql-test/t/order_by.test @@ -97,8 +97,8 @@ create table t1 (id int not null,col1 int not null,col2 int not null,index(col1) insert into t1 values(1,2,2),(2,2,1),(3,1,2),(4,1,1),(5,1,4),(6,2,3),(7,3,1),(8,2,4); select * from t1 order by col1,col2; select col1 from t1 order by id; -select col1 as id from t1 order by t1.id; -select concat(col1) as id from t1 order by t1.id; +select col1 as id from t1 order by id; +select concat(col1) as id from t1 order by id; drop table t1; # @@ -445,3 +445,44 @@ insert into t1 select 1, b, c + (@row:=@row - 1) * 10, d - @row from t2 limit 10 select * from t1 where a=1 and b in (1) order by c, b, a; select * from t1 where a=1 and b in (1); drop table t1, t2; + +# +# Bug #4302 +# Ambiguos order by when renamed column is identical to another in result. +# Should not fail and prefer column from t1 for sorting. +# +create table t1 (col1 int, col int); +create table t2 (col2 int, col int); +insert into t1 values (1,1),(2,2),(3,3); +insert into t2 values (1,3),(2,2),(3,1); +select t1.* , t2.col as t2_col from t1 left join t2 on (t1.col1=t2.col2) + order by col; + +# +# Let us also test various ambiguos and potentially ambiguos cases +# related to aliases +# +--error 1052 +select col1 as col, col from t1 order by col; +--error 1052 +select t1.col as c1, t2.col as c2 from t1, t2 where t1.col1=t2.col2 + order by col; +--error 1052 +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; + +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; +select t2.col2 as col, t2.col from t2 order by t2.col; +select t2.col2, t2.col, t2.col from t2 order by t2.col; + +drop table t1, t2; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 4efdd3edbcd..3513e9f1c92 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2101,10 +2101,12 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter, find_item_error_report_type report_error) { List_iterator<Item> li(items); - Item **found=0,*item; + Item **found=0, **found_unaliased= 0, *item; const char *db_name=0; const char *field_name=0; const char *table_name=0; + bool found_unaliased_non_uniq= 0; + uint unaliased_counter; if (find->type() == Item::FIELD_ITEM || find->type() == Item::REF_ITEM) { field_name= ((Item_ident*) find)->field_name; @@ -2117,42 +2119,88 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter, if (field_name && item->type() == Item::FIELD_ITEM) { Item_field *item_field= (Item_field*) item; + /* In case of group_concat() with ORDER BY condition in the QUERY item_field can be field of temporary table without item name (if this field created from expression argument of group_concat()), => we have to check presence of name before compare */ - if (item_field->name && - (!my_strcasecmp(system_charset_info, item_field->name, field_name) || - !my_strcasecmp(system_charset_info, - item_field->field_name, field_name))) + if (!item_field->name) + continue; + + if (table_name) { - if (!table_name) - { - if (found) - { - if ((*found)->eq(item,0)) - continue; // Same field twice (Access?) - 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; - } - else - { - if (!strcmp(item_field->table_name,table_name) && - (!db_name || (db_name && item_field->db_name && - !strcmp(item_field->db_name, db_name)))) - { - found= li.ref(); - *counter= i; - break; - } - } + /* + 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. + + QQ: Why do we use simple strcmp for table name comparison here ? + */ + if (!my_strcasecmp(system_charset_info, item_field->field_name, + field_name) && + !strcmp(item_field->table_name, table_name) && + (!db_name || (item_field->db_name && + !strcmp(item_field->db_name, db_name)))) + { + if (found) + { + if ((*found)->eq(item, 0)) + continue; // Same field twice + 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; + } + } + 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_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; + } + else if (!my_strcasecmp(system_charset_info, item_field->field_name, + field_name)) + { + /* + 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) + { + if ((*found_unaliased)->eq(item, 0)) + continue; // Same field twice + found_unaliased_non_uniq= 1; + } + else + { + found_unaliased= li.ref(); + unaliased_counter= i; + } } } else if (!table_name && (item->eq(find,0) || @@ -2165,6 +2213,21 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter, break; } } + if (!found) + { + if (found_unaliased_non_uniq) + { + 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; + } + if (found_unaliased) + { + found= found_unaliased; + *counter= unaliased_counter; + } + } if (found) return found; else if (report_error != REPORT_EXCEPT_NOT_FOUND) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 3a0ae219e81..908b28155c7 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7994,13 +7994,18 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, return 0; } uint counter; - Item **item= find_item_in_list(itemptr, fields, &counter, IGNORE_ERRORS); - if (item) + Item **item= find_item_in_list(itemptr, fields, &counter, + REPORT_EXCEPT_NOT_FOUND); + if (!item) + return 1; + + if (item != not_found_item) { order->item= ref_pointer_array + counter; order->in_field_list=1; return 0; } + order->in_field_list=0; Item *it= *order->item; /* |