Commit e000e4a2 authored by Gleb Shchepa's avatar Gleb Shchepa

Bug #37761: IN handles NULL differently for table-subquery

            and value-list

The server returns unexpected results if a right side of the 
NOT IN clause consists of NULL value and some constants of
the same type, for example:

  SELECT * FROM t WHERE NOT t.id IN (NULL, 1, 2) 
  
may return 3, 4, 5 etc if a table contains these values.


The Item_func_in::val_int method has been modified:
unnecessary resets of an Item_func_case::has_null field 
value has been moved outside of an argument comparison
loop. (Also unnecessary re-initialization of the null_value
field has been moved).


mysql-test/r/func_in.result:
  Added test case for bug #37761.
mysql-test/t/func_in.test:
  Added test case for bug #37761.
sql/item_cmpfunc.cc:
  Bug #37761: IN handles NULL differently for table-subquery 
              and value-list
  
  The Item_func_in::val_int method has been modified:
  unnecessary resets of an Item_func_case::has_null field 
  value has been moved outside of an argument comparison
  loop. (Also unnecessary re-initialization of the null_value
  field has been moved).
parent 75518d01
...@@ -569,4 +569,10 @@ insert into t1 values (),(),(),(),(),(),(),(),(),(); ...@@ -569,4 +569,10 @@ insert into t1 values (),(),(),(),(),(),(),(),(),();
select a from t1 where a not in (a,a,a) group by a; select a from t1 where a not in (a,a,a) group by a;
a a
drop table t1; drop table t1;
create table t1 (id int);
select * from t1 where NOT id in (select null union all select 1);
id
select * from t1 where NOT id in (null, 1);
id
drop table t1;
End of 5.1 tests End of 5.1 tests
...@@ -417,4 +417,13 @@ insert into t1 values (),(),(),(),(),(),(),(),(),(); ...@@ -417,4 +417,13 @@ insert into t1 values (),(),(),(),(),(),(),(),(),();
select a from t1 where a not in (a,a,a) group by a; select a from t1 where a not in (a,a,a) group by a;
drop table t1; drop table t1;
#
# Bug #37761: IN handles NULL differently for table-subquery and value-list
#
create table t1 (id int);
select * from t1 where NOT id in (select null union all select 1);
select * from t1 where NOT id in (null, 1);
drop table t1;
--echo End of 5.1 tests --echo End of 5.1 tests
...@@ -3758,6 +3758,9 @@ longlong Item_func_in::val_int() ...@@ -3758,6 +3758,9 @@ longlong Item_func_in::val_int()
return (longlong) (!null_value && tmp != negated); return (longlong) (!null_value && tmp != negated);
} }
if ((null_value= args[0]->null_value))
return 0;
have_null= 0;
for (uint i= 1 ; i < arg_count ; i++) for (uint i= 1 ; i < arg_count ; i++)
{ {
Item_result cmp_type= item_cmp_type(left_result_type, args[i]->result_type()); Item_result cmp_type= item_cmp_type(left_result_type, args[i]->result_type());
...@@ -3766,9 +3769,6 @@ longlong Item_func_in::val_int() ...@@ -3766,9 +3769,6 @@ longlong Item_func_in::val_int()
if (!(value_added_map & (1 << (uint)cmp_type))) if (!(value_added_map & (1 << (uint)cmp_type)))
{ {
in_item->store_value(args[0]); in_item->store_value(args[0]);
if ((null_value=args[0]->null_value))
return 0;
have_null= 0;
value_added_map|= 1 << (uint)cmp_type; value_added_map|= 1 << (uint)cmp_type;
} }
if (!in_item->cmp(args[i]) && !args[i]->null_value) if (!in_item->cmp(args[i]) && !args[i]->null_value)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment