summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <evgen@moonbone.local>2006-05-30 18:57:08 +0400
committerunknown <evgen@moonbone.local>2006-05-30 18:57:08 +0400
commita9824f263dcaedaabfbbc9e398eb55117f19a41f (patch)
tree20b81b6ecc616520415d9e5ec251ac8f3fb2a194
parent2264b644735e869fdbb16397c75170d86e2de127 (diff)
parentc007dabaf62b7ac7eb41e2460b12d652b132bb7f (diff)
downloadmariadb-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.result21
-rw-r--r--mysql-test/t/func_in.test12
-rw-r--r--sql/item_cmpfunc.cc37
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,