diff options
author | unknown <evgen@moonbone.local> | 2006-05-30 18:57:08 +0400 |
---|---|---|
committer | unknown <evgen@moonbone.local> | 2006-05-30 18:57:08 +0400 |
commit | a9824f263dcaedaabfbbc9e398eb55117f19a41f (patch) | |
tree | 20b81b6ecc616520415d9e5ec251ac8f3fb2a194 | |
parent | 2264b644735e869fdbb16397c75170d86e2de127 (diff) | |
parent | c007dabaf62b7ac7eb41e2460b12d652b132bb7f (diff) | |
download | mariadb-git-a9824f263dcaedaabfbbc9e398eb55117f19a41f.tar.gz |
Merge moonbone.local:/work/18630-bug-4.1-mysql
into moonbone.local:/work/18360-bug-4.1-mysql-opt
-rw-r--r-- | mysql-test/r/func_in.result | 21 | ||||
-rw-r--r-- | mysql-test/t/func_in.test | 12 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 37 |
3 files changed, 68 insertions, 2 deletions
diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result index 3cf2afc83d1..0632dddb87e 100644 --- a/mysql-test/r/func_in.result +++ b/mysql-test/r/func_in.result @@ -202,3 +202,24 @@ select count(*) from t1 where id not in (1,2); count(*) 1 drop table t1; +create table t1 (f1 char(1), f2 int); +insert into t1 values (1,0),('a',1),('z',2); +select f1 from t1 where f1 in (1,'z'); +f1 +1 +z +select f2 from t1 where f2 in (1,'z'); +f2 +0 +1 +select f1 from t1 where 'z' in (1,f1); +f1 +z +select * from t1 where 'z' in (f2,f1); +f1 f2 +z 2 +select * from t1 where 1 in (f2,f1); +f1 f2 +1 0 +a 1 +drop table t1; diff --git a/mysql-test/t/func_in.test b/mysql-test/t/func_in.test index 2ffe5a2d5f7..3481f2c7b11 100644 --- a/mysql-test/t/func_in.test +++ b/mysql-test/t/func_in.test @@ -109,4 +109,16 @@ select count(*) from t1 where id not in (1); select count(*) from t1 where id not in (1,2); drop table t1; +# +# Bug#18360 Incorrect type coercion in IN() results in false comparison +# +create table t1 (f1 char(1), f2 int); +insert into t1 values (1,0),('a',1),('z',2); +select f1 from t1 where f1 in (1,'z'); +select f2 from t1 where f2 in (1,'z'); +select f1 from t1 where 'z' in (1,f1); +select * from t1 where 'z' in (f2,f1); +select * from t1 where 1 in (f2,f1); +drop table t1; + # End of 4.1 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 3c41fb56d89..bfbb3355004 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -58,12 +58,45 @@ static void agg_result_type(Item_result *type, Item **items, uint nitems) } } + +/* + Aggregates result types from the array of items. + + SYNOPSIS: + agg_cmp_type() + type [out] the aggregated type + items array of items to aggregate the type from + nitems number of items in the array + + DESCRIPTION + This function aggregates result types from the array of items. Found type + supposed to be used later for comparison of values of these items. + Aggregation itself is performed by the item_cmp_type() function. + + NOTES + Aggregation rules: + If all items are constants the type will be aggregated from all items. + If there are some non-constant items then only types of non-constant + items will be used for aggregation. +*/ static void agg_cmp_type(Item_result *type, Item **items, uint nitems) { uint i; type[0]= items[0]->result_type(); - for (i=1 ; i < nitems ; i++) - type[0]= item_cmp_type(type[0], items[i]->result_type()); + /* Reset to 0 on first occurence of non-const item. 1 otherwise */ + bool is_const= items[0]->const_item(); + + for (i= 1 ; i < nitems ; i++) + { + if (!items[i]->const_item()) + { + type[0]= is_const ? items[i]->result_type() : + item_cmp_type(type[0], items[i]->result_type()); + is_const= 0; + } + else if (is_const) + type[0]= item_cmp_type(type[0], items[i]->result_type()); + } } static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, |