summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <dlenev@brandersnatch.localdomain>2004-08-20 19:30:45 +0400
committerunknown <dlenev@brandersnatch.localdomain>2004-08-20 19:30:45 +0400
commit764dd4918cb1a099348a47639ac5223aca8c3ee3 (patch)
treeef5a56fdd09959b03ed0bd03c6e5ce93ba678d14
parent03990ba490fbab94115d003a8d9186bdc0bbafcb (diff)
parentf9c3cb5f2e764955890c9a4db8d791a47561d130 (diff)
downloadmariadb-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.result73
-rw-r--r--mysql-test/t/order_by.test45
-rw-r--r--sql/sql_base.cc123
-rw-r--r--sql/sql_select.cc9
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;
/*