List:Commits« Previous MessageNext Message »
From:Jorgen Loland Date:May 18 2011 11:25am
Subject:bzr commit into mysql-trunk branch (jorgen.loland:3308) Bug#12430646
View as plain text  
#At file:///export/home/jl208045/mysql/wl4800/mysql-next-mr-opt-backporting-wl4800-12430646/ based on revid:jorgen.loland@stripped

 3308 Jorgen Loland	2011-05-18
      BUG#12430646 - SEL_ARG::LEFT AND RIGHT POINTERS INCORRECTLY USED.
                     CRASHES OPTIMIZER TRACING
      
      SEL_ARGs are the building blocks of range conditions. Multiple
      conditions are stored as SEL_ARGs in a RedBlack tree, in which 
      left and right points to children SEL_ARGs. 
      
      When a SEL_ARG does not have a left or right child, left/right 
      normally points to null_element. This is, however, not the case
      with a special SEL_ARG of type MAYBE_KEY. For this type, the
      left and right pointers are required to be NULL pointers. This 
      is inconsistent, but many functions rely on this fact 
      (e.g. eq_tree(), SEL_ARG::first()). 
      
      Two bugs are fixed by this changeset: 
       1) One of the SEL_ARG constructors did not initialize
          prev, next, left and right pointers.
       2) and_all_keys() sets left and right pointers to 
          &null_element for SEL_ARG::MAYBE_KEY even though it is 
          explicitly stated that these shall be NULL.
     @ mysql-test/r/optimizer_trace_bugs.result
        New regression test result file for statements that failed with 
        optimizer tracing enabled.
        Added test for BUG#12430646
     @ mysql-test/t/optimizer_trace_bugs.test
        New regression test file for statements that failed with 
        optimizer tracing enabled.
        Added test for BUG#12430646
     @ sql/opt_range.cc
        * One of the SEL_ARG constructors did not initialize prev,
          next, left and right pointers.
        * and_all_keys() sets left and right pointers to &null_element
          for SEL_ARG::MAYBE_KEY even though it is explicitly stated
          that these shall be NULL.

    added:
      mysql-test/r/optimizer_trace_bugs.result
      mysql-test/t/optimizer_trace_bugs.test
    modified:
      sql/opt_range.cc
=== added file 'mysql-test/r/optimizer_trace_bugs.result'
--- a/mysql-test/r/optimizer_trace_bugs.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/optimizer_trace_bugs.result	2011-05-18 11:25:27 +0000
@@ -0,0 +1,33 @@
+SET optimizer_trace="enabled=on,end_marker=on,one_line=off";
+#
+# BUG#12430646 - SEL_ARG::LEFT AND RIGHT POINTERS INCORRECTLY 
+#                USED. CRASHES OPTIMIZER TRACING
+#
+CREATE TABLE t1 (
+a INT,
+b CHAR(2),
+c INT,
+d INT,
+KEY (c),
+KEY (d,a,b(2)),
+KEY (b(1))
+);
+INSERT INTO t1 VALUES (NULL, 'a', 1, 2), (NULL, 'a', 1, 2),
+(1,    'a', 1, 2), (1,    'a', 1, 2);
+CREATE TABLE t2 (
+a INT,
+c INT,
+e INT,
+KEY (e)
+);
+INSERT INTO t2 VALUES (1, 1, NULL), (1, 1, NULL);
+SELECT 1
+FROM t1, t2
+WHERE t1.d <> '1' AND t1.b > '1'
+AND t1.a = t2.a AND t1.c = t2.c;
+1
+1
+1
+1
+1
+DROP TABLE t1, t2;

=== added file 'mysql-test/t/optimizer_trace_bugs.test'
--- a/mysql-test/t/optimizer_trace_bugs.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/optimizer_trace_bugs.test	2011-05-18 11:25:27 +0000
@@ -0,0 +1,38 @@
+# Regressiontest for statements that failed with optimizer tracing enabled.
+
+--source include/have_optimizer_trace.inc
+SET optimizer_trace="enabled=on,end_marker=on,one_line=off";
+
+--echo #
+--echo # BUG#12430646 - SEL_ARG::LEFT AND RIGHT POINTERS INCORRECTLY 
+--echo #                USED. CRASHES OPTIMIZER TRACING
+--echo #
+
+CREATE TABLE t1 (
+  a INT,
+  b CHAR(2),
+  c INT,
+  d INT,
+  KEY (c),
+  KEY (d,a,b(2)),
+  KEY (b(1))
+);
+
+INSERT INTO t1 VALUES (NULL, 'a', 1, 2), (NULL, 'a', 1, 2),
+                      (1,    'a', 1, 2), (1,    'a', 1, 2);
+
+CREATE TABLE t2 (
+  a INT,
+  c INT,
+  e INT,
+  KEY (e)
+);
+
+INSERT INTO t2 VALUES (1, 1, NULL), (1, 1, NULL);
+
+SELECT 1
+FROM t1, t2
+WHERE t1.d <> '1' AND t1.b > '1'
+AND t1.a = t2.a AND t1.c = t2.c;
+
+DROP TABLE t1, t2;

=== modified file 'sql/opt_range.cc'
--- a/sql/opt_range.cc	2011-05-18 10:37:05 +0000
+++ b/sql/opt_range.cc	2011-05-18 11:25:27 +0000
@@ -376,7 +376,9 @@ public:
   uchar *min_value,*max_value;			// Pointer to range
 
   /*
-    eq_tree() requires that left == right == 0 if the type is MAYBE_KEY.
+    eq_tree(), first(), last() etc require that left == right == NULL
+    if the type is MAYBE_KEY. Todo: fix this so SEL_ARGs without R-B
+    children are handled consistently. See related WL#5894.
    */
   SEL_ARG *left,*right;   /* R-B tree children */
   SEL_ARG *next,*prev;    /* Links for bi-directional interval list */
@@ -396,10 +398,17 @@ public:
   SEL_ARG(Field *,const uchar *, const uchar *);
   SEL_ARG(Field *field, uint8 part, uchar *min_value, uchar *max_value,
 	  uint8 min_flag, uint8 max_flag, uint8 maybe_flag);
+  /*
+    Used to construct MAYBE_KEY and IMPOSSIBLE SEL_ARGs. left and
+    right is NULL, so this ctor must not be used to create other
+    SEL_ARG types. See todo for left/right pointers.
+  */
   SEL_ARG(enum Type type_arg)
-    :min_flag(0),elements(1),use_count(1),left(0),right(0),next_key_part(0),
-    color(BLACK), type(type_arg)
-  {}
+    :min_flag(0),elements(1),use_count(1),left(NULL),right(NULL),
+     next_key_part(0), color(BLACK), type(type_arg)
+  {
+    DBUG_ASSERT(type_arg == MAYBE_KEY || type_arg == IMPOSSIBLE);
+  }
   inline bool is_same(SEL_ARG *arg)
   {
     if (type != arg->type || part != arg->part)
@@ -1797,6 +1806,9 @@ QUICK_RANGE::QUICK_RANGE()
 
 SEL_ARG::SEL_ARG(SEL_ARG &arg) :Sql_alloc()
 {
+  DBUG_ASSERT(arg.type != MAYBE_KEY);  // Would need left=right=NULL
+  left=right= &null_element;
+  prev=next= NULL;
   type=arg.type;
   min_flag=arg.min_flag;
   max_flag=arg.max_flag;
@@ -1815,7 +1827,7 @@ inline void SEL_ARG::make_root()
 {
   left=right= &null_element;
   color=BLACK;
-  next=prev=0;
+  next=prev= NULL;
   use_count=0; elements=1;
 }
 
@@ -1823,8 +1835,8 @@ SEL_ARG::SEL_ARG(Field *f,const uchar *m
                  const uchar *max_value_arg)
   :min_flag(0), max_flag(0), maybe_flag(0), maybe_null(f->real_maybe_null()),
    elements(1), use_count(1), field(f), min_value((uchar*) min_value_arg),
-   max_value((uchar*) max_value_arg), next(0),prev(0),
-   next_key_part(0),color(BLACK),type(KEY_RANGE)
+   max_value((uchar*) max_value_arg), next(NULL), prev(NULL),
+   next_key_part(0), color(BLACK), type(KEY_RANGE)
 {
   left=right= &null_element;
 }
@@ -1835,7 +1847,7 @@ SEL_ARG::SEL_ARG(Field *field_,uint8 par
   :min_flag(min_flag_),max_flag(max_flag_),maybe_flag(maybe_flag_),
    part(part_),maybe_null(field_->real_maybe_null()), elements(1),use_count(1),
    field(field_), min_value(min_value_), max_value(max_value_),
-   next(0),prev(0),next_key_part(0),color(BLACK),type(KEY_RANGE)
+   next(NULL), prev(NULL), next_key_part(0), color(BLACK), type(KEY_RANGE)
 {
   left=right= &null_element;
 }
@@ -6972,7 +6984,9 @@ and_all_keys(RANGE_OPT_PARAM *param, SEL
   }
   if (key1->type == SEL_ARG::MAYBE_KEY)
   {
-    key1->right= key1->left= &null_element;
+    // See todo for left/right pointers
+    DBUG_ASSERT(!key1->left);
+    DBUG_ASSERT(!key1->right);
     key1->next= key1->prev= 0;
   }
   for (next=key1->first(); next ; next=next->next)


Attachment: [text/bzr-bundle] bzr/jorgen.loland@oracle.com-20110518112527-2df6qg7h9ymrj17c.bundle
Thread
bzr commit into mysql-trunk branch (jorgen.loland:3308) Bug#12430646Jorgen Loland19 May