List:Commits« Previous MessageNext Message »
From:Evgeny Potemkin Date:July 28 2009 11:37am
Subject:bzr commit into mysql-5.4 branch (epotemkin:2825) Bug#43600
View as plain text  
#At file:///work/bzrroot/43600-bug-azalea/ based on revid:alik@stripped

 2825 Evgeny Potemkin	2009-07-28
      Bug#43600: Incorrect type conversion caused wrong result.
      
      The index_cond_func_xxx function is used to evaluate pushed index condition or
      return an error if the tuple being checked is out of range.
      And there are two bugs in it:
      1) The function result type is my_bool, but actually it can return 3
         values - TRUE/FALSE/OUT OF RANGE.
      2) The type of the pushed condition evaluation is converted to my_bool, but
      since the evaluation result isn't checked it's possible to return values
      other that 0/1, thus falsely returning OUT OF RANGE.
      
      The fix for this bug introduces the enum for the index_cond_func_xxx's
      result called ICP_RESULT. It has three values:
      
      0=ICP_NO_MATCH  - index tuple doesn't satisfy the pushed index condition (the 
                    engine should discard the tuple and go to the next one)
      1=ICP_MATCH     - index tuple satisfies the pushed index condition (the engine
                    should fetch and return the record)
      2=ICP_OUT_OF_RANGE - index tuple is out range that we're scanning, e.g. this 
                       if we're scanning "t.key BETWEEN 10 AND 20" and got a 
                       "t.key=21" tuple (the engine should stop scanning and return 
                       HA_ERR_END_OF_FILE right away).
      
      The index_cond_func_myisam and index_cond_func_innodb functions now checking
      the pushed condition evaluation result, and making sure that only 0/1 are
      returned.
     @ include/my_handler.h
        Bug#43600: Incorrect type conversion caused wrong result.
        The enum for the index_cond_func_xxx's result is introduced.
        It's called ICP_RESULT.
     @ mysql-test/include/mix1.inc
        A test case added for the bug#43600.
     @ mysql-test/r/innodb_mysql.result
        A test case added for the bug#43600.
     @ mysql-test/r/myisam.result
        A test case added for the bug#43600.
     @ mysql-test/t/myisam.test
        A test case added for the bug#43600.
     @ storage/innobase/handler/ha_innodb.cc
        Bug#43600: Incorrect type conversion caused wrong result.
        The result type of the index_cond_func_innodb function
        is changed to uint and the result of the pushed condition
        evaluation now is checked to make sure that only 0/1 are returned.
     @ storage/innobase/include/row0mysql.h
        Bug#43600: Incorrect type conversion caused wrong result.
        The result type of the index_cond_func_innodb function
        is changed to uint.
     @ storage/myisam/ha_myisam.cc
        Bug#43600: Incorrect type conversion caused wrong result.
        The index_cond_func_myisam function now checks the pushed
        condition evaluation result, and makes sure that only 0/1 are
        returned.
     @ storage/myisam/ha_myisam.h
        Bug#43600: Incorrect type conversion caused wrong result.
        Result type of the index_cond_func_xxx function is changed to the
        ICP_RESULT enum.
     @ storage/myisam/myisamdef.h
        Bug#43600: Incorrect type conversion caused wrong result.
        Result type of the index_cond_func_xxx function is changed to the
        ICP_RESULT enum.

    modified:
      include/my_handler.h
      mysql-test/include/mix1.inc
      mysql-test/r/innodb_mysql.result
      mysql-test/r/myisam.result
      mysql-test/t/myisam.test
      storage/innobase/handler/ha_innodb.cc
      storage/innobase/include/row0mysql.h
      storage/myisam/ha_myisam.cc
      storage/myisam/ha_myisam.h
      storage/myisam/myisamdef.h
=== modified file 'include/my_handler.h'
--- a/include/my_handler.h	2008-11-12 15:23:22 +0000
+++ b/include/my_handler.h	2009-07-28 11:37:42 +0000
@@ -123,8 +123,29 @@ extern void my_handler_error_unregister(
   this amount of bytes.
 */
 #define portable_sizeof_char_ptr 8
+
+/*
+  Return values of index_cond_func_xxx functions.
+
+  0=ICP_NO_MATCH  - index tuple doesn't satisfy the pushed index condition (the
+                engine should discard the tuple and go to the next one)
+  1=ICP_MATCH     - index tuple satisfies the pushed index condition (the engine
+                should fetch and return the record)
+  2=ICP_OUT_OF_RANGE - index tuple is out range that we're scanning, e.g. this
+                   if we're scanning "t.key BETWEEN 10 AND 20" and got a
+                   "t.key=21" tuple (the engine should stop scanning and return
+                   HA_ERR_END_OF_FILE right away).
+*/
+
+typedef enum icp_result {
+  ICP_NO_MATCH,
+  ICP_MATCH,
+  ICP_OUT_OF_RANGE
+} ICP_RESULT;
+
 #ifdef	__cplusplus
 }
 #endif
 
+
 #endif /* _my_handler_h */

=== modified file 'mysql-test/include/mix1.inc'
--- a/mysql-test/include/mix1.inc	2009-07-09 16:11:01 +0000
+++ b/mysql-test/include/mix1.inc	2009-07-28 11:37:42 +0000
@@ -1585,3 +1585,27 @@ SELECT 1 FROM (SELECT COUNT(DISTINCT c1)
 DROP TABLE t1;
 
 --echo End of 5.1 tests
+
+--echo #
+--echo # Bug#43600: Incorrect type conversion caused wrong result.
+--echo #
+CREATE TABLE t1 (
+  a int NOT NULL
+) engine= innodb;
+
+CREATE TABLE t2 (
+  a int NOT NULL,
+  b int NOT NULL,
+  filler char(100) DEFAULT NULL,
+  KEY a (a,b)
+) engine= innodb;
+
+insert into t1 values (0),(1),(2),(3),(4);
+insert into t2 select A.a + 10 *B.a, 1, 'filler' from t1 A, t1 B;
+
+explain select * from t1, t2 where t2.a=t1.a and t2.b + 1;
+select * from t1, t2 where t2.a=t1.a and t2.b + 1;
+
+drop table t1,t2;
+--echo # End of test case for the bug#43600
+

=== modified file 'mysql-test/r/innodb_mysql.result'
--- a/mysql-test/r/innodb_mysql.result	2009-07-09 16:11:01 +0000
+++ b/mysql-test/r/innodb_mysql.result	2009-07-28 11:37:42 +0000
@@ -1764,6 +1764,33 @@ id	select_type	table	type	possible_keys	
 2	DERIVED	t1	index	c3,c2	c2	14	NULL	5	
 DROP TABLE t1;
 End of 5.1 tests
+#
+# Bug#43600: Incorrect type conversion caused wrong result.
+#
+CREATE TABLE t1 (
+a int NOT NULL
+) engine= innodb;
+CREATE TABLE t2 (
+a int NOT NULL,
+b int NOT NULL,
+filler char(100) DEFAULT NULL,
+KEY a (a,b)
+) engine= innodb;
+insert into t1 values (0),(1),(2),(3),(4);
+insert into t2 select A.a + 10 *B.a, 1, 'filler' from t1 A, t1 B;
+explain select * from t1, t2 where t2.a=t1.a and t2.b + 1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	5	
+1	SIMPLE	t2	ref	a	a	4	test.t1.a	1	Using where
+select * from t1, t2 where t2.a=t1.a and t2.b + 1;
+a	a	b	filler
+0	0	1	filler
+1	1	1	filler
+2	2	1	filler
+3	3	1	filler
+4	4	1	filler
+drop table t1,t2;
+# End of test case for the bug#43600
 drop table if exists t1, t2, t3;
 create table t1(a int);
 insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);

=== modified file 'mysql-test/r/myisam.result'
--- a/mysql-test/r/myisam.result	2009-06-02 13:04:43 +0000
+++ b/mysql-test/r/myisam.result	2009-07-28 11:37:42 +0000
@@ -2295,3 +2295,30 @@ h+0	d + 0	e	g + 0
 1	1	4	0
 DROP TABLE t1;
 End of 5.1 tests
+#
+# Bug#43600: Incorrect type conversion caused wrong result.
+#
+CREATE TABLE t1 (
+a int NOT NULL
+) engine= myisam;
+CREATE TABLE t2 (
+a int NOT NULL,
+b int NOT NULL,
+filler char(100) DEFAULT NULL,
+KEY a (a,b)
+) engine= myisam;
+insert into t1 values (0),(1),(2),(3),(4);
+insert into t2 select A.a + 10 *B.a, 1, 'filler' from t1 A, t1 B;
+explain select * from t1, t2 where t2.a=t1.a and t2.b + 1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	5	
+1	SIMPLE	t2	ref	a	a	4	test.t1.a	1	Using index condition
+select * from t1, t2 where t2.a=t1.a and t2.b + 1;
+a	a	b	filler
+0	0	1	filler
+1	1	1	filler
+2	2	1	filler
+3	3	1	filler
+4	4	1	filler
+drop table t1,t2;
+# End of test case for the bug#43600

=== modified file 'mysql-test/t/myisam.test'
--- a/mysql-test/t/myisam.test	2009-04-30 10:27:29 +0000
+++ b/mysql-test/t/myisam.test	2009-07-28 11:37:42 +0000
@@ -1542,3 +1542,27 @@ SELECT h+0, d + 0, e, g + 0 FROM t1;
 DROP TABLE t1;
 
 --echo End of 5.1 tests
+
+--echo #
+--echo # Bug#43600: Incorrect type conversion caused wrong result.
+--echo #
+CREATE TABLE t1 (
+  a int NOT NULL
+) engine= myisam;
+
+CREATE TABLE t2 (
+  a int NOT NULL,
+  b int NOT NULL,
+  filler char(100) DEFAULT NULL,
+  KEY a (a,b)
+) engine= myisam;
+
+insert into t1 values (0),(1),(2),(3),(4);
+insert into t2 select A.a + 10 *B.a, 1, 'filler' from t1 A, t1 B;
+
+explain select * from t1, t2 where t2.a=t1.a and t2.b + 1;
+select * from t1, t2 where t2.a=t1.a and t2.b + 1;
+
+drop table t1,t2;
+--echo # End of test case for the bug#43600
+

=== modified file 'storage/innobase/handler/ha_innodb.cc'
--- a/storage/innobase/handler/ha_innodb.cc	2009-06-25 09:55:58 +0000
+++ b/storage/innobase/handler/ha_innodb.cc	2009-07-28 11:37:42 +0000
@@ -63,7 +63,7 @@ static bool innodb_inited = 0;
 static handlerton *innodb_hton_ptr;
 
 C_MODE_START
-static my_bool index_cond_func_innodb(void *arg);
+static uint index_cond_func_innodb(void *arg);
 C_MODE_END
 
 
@@ -8573,9 +8573,12 @@ ha_rows ha_innobase::multi_range_read_in
 
 C_MODE_START
 
-/* Index condition check function to be called from within Innobase */
+/*
+  Index condition check function to be called from within Innobase.
+  See note on ICP_RESULT for return values description.
+*/
 
-static my_bool index_cond_func_innodb(void *arg)
+static uint index_cond_func_innodb(void *arg)
 {
   ha_innobase *h= (ha_innobase*)arg;
   if (h->end_range)
@@ -8583,7 +8586,7 @@ static my_bool index_cond_func_innodb(vo
     if (h->compare_key2(h->end_range) > 0)
       return 2; /* caller should return HA_ERR_END_OF_FILE already */
   }
-  return (my_bool)h->pushed_idx_cond->val_int();
+  return test(h->pushed_idx_cond->val_int());
 }
 
 C_MODE_END

=== modified file 'storage/innobase/include/row0mysql.h'
--- a/storage/innobase/include/row0mysql.h	2009-06-25 09:55:58 +0000
+++ b/storage/innobase/include/row0mysql.h	2009-07-28 11:37:42 +0000
@@ -524,7 +524,7 @@ struct mysql_row_templ_struct {
 #define ROW_PREBUILT_ALLOCATED	78540783
 #define ROW_PREBUILT_FREED	26423527
 
-typedef my_bool (*index_cond_func_t)(void *param);
+typedef uint (*index_cond_func_t)(void *param);
 
 /* A struct for (sometimes lazily) prebuilt structures in an Innobase table
 handle used within MySQL; these are used to save CPU time. */

=== modified file 'storage/myisam/ha_myisam.cc'
--- a/storage/myisam/ha_myisam.cc	2009-07-08 12:46:36 +0000
+++ b/storage/myisam/ha_myisam.cc	2009-07-28 11:37:42 +0000
@@ -1522,15 +1522,15 @@ int ha_myisam::delete_row(const uchar *b
 
 C_MODE_START
 
-my_bool index_cond_func_myisam(void *arg)
+ICP_RESULT index_cond_func_myisam(void *arg)
 {
   ha_myisam *h= (ha_myisam*)arg;
   if (h->end_range)
   {
     if (h->compare_key2(h->end_range) > 0)
-      return 2; /* caller should return HA_ERR_END_OF_FILE already */
+      return ICP_OUT_OF_RANGE; /* caller should return HA_ERR_END_OF_FILE already */
   }
-  return (my_bool)h->pushed_idx_cond->val_int();
+  return (ICP_RESULT) test(h->pushed_idx_cond->val_int());
 }
 
 C_MODE_END

=== modified file 'storage/myisam/ha_myisam.h'
--- a/storage/myisam/ha_myisam.h	2009-07-08 12:46:36 +0000
+++ b/storage/myisam/ha_myisam.h	2009-07-28 11:37:42 +0000
@@ -35,7 +35,7 @@ extern TYPELIB myisam_recover_typelib;
 extern ulong myisam_recover_options;
 
 C_MODE_START
-my_bool index_cond_func_myisam(void *arg);
+ICP_RESULT index_cond_func_myisam(void *arg);
 C_MODE_END
 
 class ha_myisam: public handler
@@ -168,7 +168,7 @@ public:
   Item *idx_cond_push(uint keyno, Item* idx_cond);
 private:
   DsMrr_impl ds_mrr;
-  friend my_bool index_cond_func_myisam(void *arg);
+  friend ICP_RESULT index_cond_func_myisam(void *arg);
 };
 
 #if !defined(EMBEDDED_LIBRARY) && defined(HAVE_MYISAM_PHYSICAL_LOGGING)

=== modified file 'storage/myisam/myisamdef.h'
--- a/storage/myisam/myisamdef.h	2009-04-01 21:36:07 +0000
+++ b/storage/myisam/myisamdef.h	2009-07-28 11:37:42 +0000
@@ -256,8 +256,7 @@ typedef struct st_mi_isam_share
   my_bool MI_LOG_OPEN_stored_in_physical_log;
 } MYISAM_SHARE;
 
-
-typedef my_bool (*index_cond_func_t)(void *param);
+typedef ICP_RESULT (*index_cond_func_t)(void *param);
 
 /** Information local to the table's instance */
 struct st_myisam_info


Attachment: [text/bzr-bundle] bzr/epotemkin@mysql.com-20090728113742-llw1j8l8h66k36xu.bundle
Thread
bzr commit into mysql-5.4 branch (epotemkin:2825) Bug#43600Evgeny Potemkin28 Jul
  • Re: bzr commit into mysql-5.4 branch (epotemkin:2825) Bug#43600Guilhem Bichot29 Jul
    • Re: bzr commit into mysql-5.4 branch (epotemkin:2825) Bug#43600Evgeny Potemkin30 Jul
Re: bzr commit into mysql-5.4 branch (epotemkin:2825) Bug#43600Guilhem Bichot29 Jul