List:Commits« Previous MessageNext Message »
From:Gleb Shchepa Date:September 19 2009 3:54pm
Subject:bzr commit into mysql-5.1-bugteam branch (gshchepa:3117) Bug#44139
View as plain text  
#At file:///work/44139-5.1/ based on revid:joro@stripped

 3117 Gleb Shchepa	2009-09-19
      Bug #44139: Table scan when NULL appears in IN clause
      
      SELECT ... WHERE ... IN (NULL, ...) does full table scan,
      even if the same query without the NULL uses efficient range scan.
      
      1. The collect_cmp_types() function has been modified to
         heading NULLs in the IN list.
      2. NULL-skipping code of the Item_func_in::fix_length_and_dec()
         function has been updated to prevent SEGVs.
     @ mysql-test/r/func_in.result
        Added test case for the bug #44139.
     @ mysql-test/t/func_in.test
        Added test case for the bug #44139.
     @ sql/item_cmpfunc.cc
        Bug #44139: Table scan when NULL appears in IN clause
        
        1. The collect_cmp_types() function has been modified to
           heading NULLs in the IN list.
        2. NULL-skipping code of the Item_func_in::fix_length_and_dec()
           function has been updated to prevent SEGVs.

    modified:
      mysql-test/r/func_in.result
      mysql-test/t/func_in.test
      sql/item_cmpfunc.cc
=== modified file 'mysql-test/r/func_in.result'
--- a/mysql-test/r/func_in.result	2009-05-25 08:00:40 +0000
+++ b/mysql-test/r/func_in.result	2009-09-19 15:54:44 +0000
@@ -608,4 +608,19 @@ SELECT SUM( DISTINCT e ) FROM t1 GROUP B
 ((AVG( 1 ), 1 + c, 1 + d), (AVG( 1 ), 2 + c, 2 + d));
 SUM( DISTINCT e )
 DROP TABLE t1;
+#
+# Bug #44139: Table scan when NULL appears in IN clause
+#
+CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, b INT);
+INSERT INTO t1 (b) VALUES (1),(1),(1),(1),(1);
+INSERT INTO t1 (b) SELECT b FROM t1;
+INSERT INTO t1 (b) SELECT b FROM t1;
+EXPLAIN SELECT * FROM t1 WHERE a IN (160000, 160001, 160002);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	3	Using where
+EXPLAIN SELECT * FROM t1 WHERE a IN (NULL, 160000, 160001, 160002);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	3	Using where
+DROP TABLE t1;
+#
 End of 5.1 tests

=== modified file 'mysql-test/t/func_in.test'
--- a/mysql-test/t/func_in.test	2009-05-25 08:00:40 +0000
+++ b/mysql-test/t/func_in.test	2009-09-19 15:54:44 +0000
@@ -456,4 +456,21 @@ SELECT SUM( DISTINCT e ) FROM t1 GROUP B
   ((AVG( 1 ), 1 + c, 1 + d), (AVG( 1 ), 2 + c, 2 + d));
 DROP TABLE t1;
 
+--echo #
+--echo # Bug #44139: Table scan when NULL appears in IN clause
+--echo #
+
+CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, b INT);
+
+INSERT INTO t1 (b) VALUES (1),(1),(1),(1),(1);
+INSERT INTO t1 (b) SELECT b FROM t1;
+INSERT INTO t1 (b) SELECT b FROM t1;
+
+EXPLAIN SELECT * FROM t1 WHERE a IN (160000, 160001, 160002);
+EXPLAIN SELECT * FROM t1 WHERE a IN (NULL, 160000, 160001, 160002);
+
+DROP TABLE t1;
+
+--echo #
+
 --echo End of 5.1 tests

=== modified file 'sql/item_cmpfunc.cc'
--- a/sql/item_cmpfunc.cc	2009-08-28 16:21:54 +0000
+++ b/sql/item_cmpfunc.cc	2009-09-19 15:54:44 +0000
@@ -199,7 +199,7 @@ enum_field_types agg_field_type(Item **i
     Bitmap of collected types - otherwise
 */
 
-static uint collect_cmp_types(Item **items, uint nitems)
+static uint collect_cmp_types(Item **items, uint nitems, bool skip_nulls= false)
 {
   uint i;
   uint found_types;
@@ -208,6 +208,8 @@ static uint collect_cmp_types(Item **ite
   found_types= 0;
   for (i= 1; i < nitems ; i++)
   {
+    if (skip_nulls && items[i]->type() == Item::NULL_ITEM)
+      continue;
     if ((left_result == ROW_RESULT || 
          items[i]->result_type() == ROW_RESULT) &&
         cmp_row_type(items[0], items[i]))
@@ -215,6 +217,8 @@ static uint collect_cmp_types(Item **ite
     found_types|= 1<< (uint)item_cmp_type(left_result,
                                            items[i]->result_type());
   }
+  if (skip_nulls && !found_types && nitems >= 1)
+    found_types= 1 << (uint)item_cmp_type(left_result, items[1]->result_type());
   return found_types;
 }
 
@@ -3515,7 +3519,7 @@ void Item_func_in::fix_length_and_dec()
   uint type_cnt= 0, i;
   Item_result cmp_type= STRING_RESULT;
   left_result_type= args[0]->result_type();
-  if (!(found_types= collect_cmp_types(args, arg_count)))
+  if (!(found_types= collect_cmp_types(args, arg_count, true)))
     return;
   
   for (arg= args + 1, arg_end= args + arg_count; arg != arg_end ; arg++)
@@ -3693,9 +3697,11 @@ void Item_func_in::fix_length_and_dec()
       uint j=0;
       for (uint i=1 ; i < arg_count ; i++)
       {
-	array->set(j,args[i]);
 	if (!args[i]->null_value)			// Skip NULL values
+        {
+          array->set(j,args[i]);
 	  j++;
+        }
 	else
 	  have_null= 1;
       }


Attachment: [text/bzr-bundle] bzr/gshchepa@mysql.com-20090919155444-0mlo4n450zee9fl7.bundle
Thread
bzr commit into mysql-5.1-bugteam branch (gshchepa:3117) Bug#44139Gleb Shchepa19 Sep