List:Commits« Previous MessageNext Message »
From:Evgeny Potemkin Date:May 28 2011 8:40am
Subject:bzr commit into mysql-trunk branch (evgeny.potemkin:3002) Bug#11791677
Bug#11791705
View as plain text  
#At file:///work/bzrroot/11791677-bug/ based on revid:epotemkin@stripped

 3002 Evgeny Potemkin	2011-05-28
      Bug#11791677: ASSERTION FAILED IN JOIN_MATERIALIZE_TABLE IN SQL_SELECT.CC ON 
      NESTED SUBQUERY
      Derived tables materialization mechanism substitutes table's read_first_record
      with the join_materialize_table function to materialize table on the first read,
      after this is done the original read_first_record is restored and called.
      Subqueries in WHERE clause could reinitialize join and restore
      join_materialize_table as the read_first_record function. Assertion is thrown
      on attempt to materialize a derived table second time.
      To avoid this a new materialization callback is added to the JOIN_TAB structure.
      It is called when it's non zero and the table haven't been materialized yet.
      This also fixes the bug#11791705.
     @ mysql-test/r/derived.result
        Added test cases for bugs #11791677 and #11791705.
     @ mysql-test/t/derived.test
        Added test cases for bugs #11791677 and #11791705.
     @ sql/sql_join_cache.cc
        Bug#11791677: ASSERTION FAILED IN JOIN_MATERIALIZE_TABLE IN SQL_SELECT.CC ON 
        NESTED SUBQUERY
        Now JOIN_TAB::materialize_table callback function is called for materializable
        derived tables/views prior to reading them.
     @ sql/sql_select.cc
        Bug#11791677: ASSERTION FAILED IN JOIN_MATERIALIZE_TABLE IN SQL_SELECT.CC ON 
        NESTED SUBQUERY
        Now JOIN_TAB::materialize_table callback is used to call materializing function
        instead of flipping JOIN_TAB::read_first_record.
     @ sql/sql_select.h
        Bug#11791677: ASSERTION FAILED IN JOIN_MATERIALIZE_TABLE IN SQL_SELECT.CC ON 
        NESTED SUBQUERY
        Added materialize_table callback hook to the JOIN_TAB struct.

    modified:
      mysql-test/r/derived.result
      mysql-test/t/derived.test
      sql/sql_join_cache.cc
      sql/sql_select.cc
      sql/sql_select.h
=== modified file 'mysql-test/r/derived.result'
--- a/mysql-test/r/derived.result	2011-02-17 12:14:26 +0000
+++ b/mysql-test/r/derived.result	2011-05-28 08:39:37 +0000
@@ -1328,3 +1328,56 @@ f1	f11	f2	f22	f3	f33
 DROP TABLE t1,t2,t3;
 DROP VIEW v1,v2,v3,v4,v6,v7;
 #
+#
+# Bug#11791677 - ASSERTION FAILED IN JOIN_MATERIALIZE_TABLE IN
+#                SQL_SELECT.CC ON NESTED SUBQUERY 
+#
+CREATE TABLE t1 (
+pk int(11) NOT NULL AUTO_INCREMENT,
+col_int_key int(11) DEFAULT NULL,
+col_varchar_key varchar(1) DEFAULT NULL,
+PRIMARY KEY (pk),
+KEY col_varchar_key (col_varchar_key,col_int_key)
+);
+INSERT INTO t1 VALUES (10,8,'v'), (29,4,'c');
+CREATE TABLE t2 (  
+pk int(11) NOT NULL AUTO_INCREMENT,
+col_int_nokey int(11) DEFAULT NULL,
+col_varchar_key varchar(1) DEFAULT NULL,
+PRIMARY KEY (pk)
+);
+INSERT INTO t2 VALUES (16,1,'c'), (20,4,'d');
+CREATE TABLE t3 (
+`field1` varchar(1) DEFAULT NULL,
+`field2` int(11) DEFAULT NULL
+);
+INSERT INTO t3 VALUES ('m',6),('c',4);
+SELECT *
+FROM t3
+WHERE (field1, field2) IN (
+SELECT t1.col_varchar_key AS field1,
+t1.col_int_key AS field2
+FROM ( t1 INNER JOIN (
+SELECT t2.*
+FROM t2
+WHERE t2.col_int_nokey < t2.pk ) AS alias2
+ON (alias2.col_varchar_key = t1.col_varchar_key ) )
+GROUP BY field1, field2
+ORDER BY t1.col_int_key, t1 .pk DESC )
+;
+field1	field2
+c	4
+DROP TABLE t1,t2,t3;
+#
+#
+# Bug#11791705 - CRASH IN JOIN_MATERIALIZE_TABLE OR ASSERTION FAIL:
+#                !TAB->SAVE_READ_FIRST_RECORD
+#
+CREATE TABLE t1 (a INTEGER);
+INSERT INTO t1 VALUES (NULL),(NULL);
+SELECT * FROM t1
+WHERE (a, a) NOT IN
+(SELECT * FROM (SELECT 8, 4 UNION SELECT 2, 3) tt) ;
+a
+DROP TABLE t1;
+#

=== modified file 'mysql-test/t/derived.test'
--- a/mysql-test/t/derived.test	2011-02-17 12:14:26 +0000
+++ b/mysql-test/t/derived.test	2011-05-28 08:39:37 +0000
@@ -693,3 +693,64 @@ DROP VIEW v1,v2,v3,v4,v6,v7;
 
 --echo #
 
+--echo #
+--echo # Bug#11791677 - ASSERTION FAILED IN JOIN_MATERIALIZE_TABLE IN
+--echo #                SQL_SELECT.CC ON NESTED SUBQUERY 
+--echo #
+CREATE TABLE t1 (
+  pk int(11) NOT NULL AUTO_INCREMENT,
+  col_int_key int(11) DEFAULT NULL,
+  col_varchar_key varchar(1) DEFAULT NULL,
+  PRIMARY KEY (pk),
+  KEY col_varchar_key (col_varchar_key,col_int_key)
+);
+
+INSERT INTO t1 VALUES (10,8,'v'), (29,4,'c');
+  
+CREATE TABLE t2 (  
+  pk int(11) NOT NULL AUTO_INCREMENT,
+  col_int_nokey int(11) DEFAULT NULL,
+  col_varchar_key varchar(1) DEFAULT NULL,
+  PRIMARY KEY (pk)
+);
+
+INSERT INTO t2 VALUES (16,1,'c'), (20,4,'d');
+
+CREATE TABLE t3 (
+  `field1` varchar(1) DEFAULT NULL,
+  `field2` int(11) DEFAULT NULL
+);
+
+INSERT INTO t3 VALUES ('m',6),('c',4);
+
+SELECT *
+FROM t3
+WHERE (field1, field2) IN (
+  SELECT t1.col_varchar_key AS field1,
+         t1.col_int_key AS field2
+  FROM ( t1 INNER JOIN (
+      SELECT t2.*
+      FROM t2
+      WHERE t2.col_int_nokey < t2.pk ) AS alias2
+    ON (alias2.col_varchar_key = t1.col_varchar_key ) )
+  GROUP BY field1, field2
+  ORDER BY t1.col_int_key, t1 .pk DESC )
+;
+
+DROP TABLE t1,t2,t3;
+--echo #
+
+--echo #
+--echo # Bug#11791705 - CRASH IN JOIN_MATERIALIZE_TABLE OR ASSERTION FAIL:
+--echo #                !TAB->SAVE_READ_FIRST_RECORD
+--echo #
+CREATE TABLE t1 (a INTEGER);
+INSERT INTO t1 VALUES (NULL),(NULL);
+
+SELECT * FROM t1
+WHERE (a, a) NOT IN
+  (SELECT * FROM (SELECT 8, 4 UNION SELECT 2, 3) tt) ;
+
+DROP TABLE t1; 
+--echo #
+

=== modified file 'sql/sql_join_cache.cc'
--- a/sql/sql_join_cache.cc	2011-02-18 10:46:59 +0000
+++ b/sql/sql_join_cache.cc	2011-05-28 08:39:37 +0000
@@ -1794,6 +1794,12 @@ enum_nested_loop_state JOIN_CACHE_BNL::j
     tab->table->status= 0;
   }
 
+  /* Materialize table prior reading it */
+  if (join_tab->materialize_table &&
+      !join_tab->table->pos_in_table_list->materialized &&
+      (error= (*join_tab->materialize_table)(join_tab)))
+    goto finish;
+
   /* Start retrieving all records of the joined table */
   if ((error= (*join_tab->read_first_record)(join_tab)))
   {
@@ -2297,6 +2303,12 @@ enum_nested_loop_state JOIN_CACHE_BKA::j
   if (!records)
     return NESTED_LOOP_OK;  
                    
+  /* Materialize table prior reading it */
+  if (join_tab->materialize_table &&
+      !join_tab->table->pos_in_table_list->materialized &&
+      (error= (*join_tab->materialize_table)(join_tab)))
+    goto finish;
+
   rc= init_join_matching_records(&seq_funcs, records);
   if (rc != NESTED_LOOP_OK)
     goto finish;

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2011-02-17 12:14:26 +0000
+++ b/sql/sql_select.cc	2011-05-28 08:39:37 +0000
@@ -11414,10 +11414,7 @@ make_join_readinfo(JOIN *join, ulonglong
     // Materialize derived tables prior to accessing them.
     if (tab->table->pos_in_table_list->uses_materialization() &&
         !tab->table->pos_in_table_list->materialized)
-    {
-      tab->save_read_first_record= tab->read_first_record;
-      tab->read_first_record= join_materialize_table;
-    }
+      tab->materialize_table= join_materialize_table;
   }
   join->join_tab[join->tables-1].next_select=0; /* Set by do_select */
 
@@ -17551,7 +17548,7 @@ sub_select(JOIN *join,JOIN_TAB *join_tab
       (*join_tab->next_select)(join,join_tab+1,end_of_records);
     DBUG_RETURN(nls);
   }
-  int error;
+  int error= 0;
   enum_nested_loop_state rc;
   READ_RECORD *info= &join_tab->read_record;
 
@@ -17575,7 +17572,13 @@ sub_select(JOIN *join,JOIN_TAB *join_tab
   }
   join->thd->warning_info->reset_current_row_for_warning();
 
-  error= (*join_tab->read_first_record)(join_tab);
+  /* Materialize table prior reading it */
+  if (join_tab->materialize_table &&
+      !join_tab->table->pos_in_table_list->materialized)
+    error= (*join_tab->materialize_table)(join_tab);
+
+  if (!error)
+    error= (*join_tab->read_first_record)(join_tab);
 
   if (join_tab->keep_current_rowid)
     join_tab->table->file->position(join_tab->table->record[0]);
@@ -18515,11 +18518,7 @@ join_materialize_table(JOIN_TAB *tab)
                                         derived, &mysql_derived_materialize);
   mysql_handle_single_derived(tab->table->in_use->lex,
                               derived, &mysql_derived_cleanup);
-  if (res)
-    return -1;
-  tab->read_first_record= tab->save_read_first_record;
-  tab->save_read_first_record= NULL;
-  return (*tab->read_first_record)(tab);
+  return res ? NESTED_LOOP_ERROR : NESTED_LOOP_OK;
 }
 
 

=== modified file 'sql/sql_select.h'
--- a/sql/sql_select.h	2011-02-18 10:46:59 +0000
+++ b/sql/sql_select.h	2011-05-28 08:39:37 +0000
@@ -264,6 +264,7 @@ typedef struct st_join_table : public Sq
   */
   uint          packed_info;
 
+  READ_RECORD::Setup_func materialize_table;
   READ_RECORD::Setup_func read_first_record;
   Next_select_func next_select;
   READ_RECORD	read_record;
@@ -271,7 +272,6 @@ typedef struct st_join_table : public Sq
     The following two fields are used for a [NOT] IN subquery if it is
     executed by an alternative full table scan when the left operand of
     the subquery predicate is evaluated to NULL.
-    save_read_first_record is also used during derived tables materialization.
   */
   READ_RECORD::Setup_func save_read_first_record;/* to save read_first_record */
   READ_RECORD::Read_func save_read_record;/* to save read_record.read_record */
@@ -453,6 +453,7 @@ st_join_table::st_join_table()
     pre_idx_push_select_cond(NULL),
     info(NULL),
     packed_info(0),
+    materialize_table(NULL),
     read_first_record(NULL),
     next_select(NULL),
     read_record(),


Attachment: [text/bzr-bundle] bzr/evgeny.potemkin@oracle.com-20110528083937-iycjtv2z79559hec.bundle
Thread
bzr commit into mysql-trunk branch (evgeny.potemkin:3002) Bug#11791677Bug#11791705Evgeny Potemkin31 May