List:Commits« Previous MessageNext Message »
From:Roy Lyseng Date:November 5 2009 10:16am
Subject:bzr commit into mysql-6.0-codebase-bugfixing branch (roy.lyseng:3699)
Bug#45863 WL#4389
View as plain text  
#At file:///home/rl136806/mysql/repo/mysql-6.0-linux/ based on revid:holyfoot@stripped

 3699 Roy Lyseng	2009-11-05
      BUG#45863: Assertion failed: (fixed == 0)...
      The problem in JOIN::prepare() is that fix_fields() is called prematurely
      from subquery_types_allow_materialization().
      The call to fix_fields() observed the unknown column name and set error
      status accordingly.
      But JOIN::prepare() failed to notice the error and attempted to call
      fix_fields() again, now with a half-way resolved expression, and we have
      an assert().
      The fix is mostly taken from the committed but unpushed work in WL#4389,
      which is about applying semijoin transformation to EXISTS queries,
      but also consolidates some of the semantic checking on subqueries.
      The call to fix_fields() inside JOIN::prepare() is moved so that it is
      always executed before subquery_types_allow_materialization().
      Hence, the latter no longer needs to call fix_fields() and we can remove
      the thd argument (and also let both return values become output arguments).
      I also removed one of the "psergey-todo" comments, because the subselect
      cardinality check is now always performed in the early stages of
      JOIN::prepare(). But eliminating all the comments would be beyond the scope
      of this bugfix.
      Noticed another problem during development as well: One query was optimized
      differently in regular and prepared mode, and this happened because the
      is_correlated flag was set differently in the two modes. Had to make sure
      that this flag is set consistently, by calling fix_fields() from
      JOIN::prepare() also for the first execution of a prepared statement.
      Otherwise, is_correlated would be set inconsistently by the fix_fields()
      call in convert_subq_to_sj().
      
        mysql-test/r/subselect4.result
          Added test results for bug
      
        mysql-test/t/subselect4.test
          Added tests for bug
      
        sql/sql_select.cc
          Modified JOIN::prepare() and subquery_types_allow_materialization
          according to above description.

    modified:
      mysql-test/r/subselect4.result
      mysql-test/t/subselect4.test
      sql/sql_select.cc
=== modified file 'mysql-test/r/subselect4.result'
--- a/mysql-test/r/subselect4.result	2009-10-25 13:41:27 +0000
+++ b/mysql-test/r/subselect4.result	2009-11-05 10:13:23 +0000
@@ -131,3 +131,299 @@ set @@session.optimizer_switch          
 @@session.optimizer_use_mrr         = @old_optimizer_use_mrr,
 @@session.engine_condition_pushdown = @old_engine_condition_pushdown;
 DROP TABLE t1;
+#
+# BUG#45863 "Assertion failed: (fixed == 0), function fix_fields(),
+#            file item.cc, line 4448"
+#
+DROP TABLE IF EXISTS C, BB;
+CREATE TABLE `C` (
+`varchar_key` varchar(1) NOT NULL,
+`varchar_nokey` varchar(1) NOT NULL,
+KEY `varchar_key` (`varchar_key`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+INSERT INTO `C` VALUES
+('k','k'),('a','a'),('',''),('u','u'),('e','e'),('v','v'),('i','i'),
+('t','t'),('u','u'),('f','f'),('u','u'),('m','m'),('j','j'),('f','f'),
+('v','v'),('j','j'),('g','g'),('e','e'),('h','h'),('z','z');
+CREATE TABLE `BB` (
+`varchar_key` varchar(1) NOT NULL,
+`varchar_nokey` varchar(1) NOT NULL,
+KEY `varchar_key` (`varchar_key`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+INSERT INTO `BB` VALUES ('i','i'),('t','t');
+SELECT `varchar_nokey` FROM C
+WHERE (`varchar_nokey`, OUTR) IN (SELECT `varchar_key`
+                                  FROM BB);
+ERROR 42S22: Unknown column 'OUTR' in 'IN/ALL/ANY subquery'
+DROP TABLE C,BB;
+#
+# During work with BUG#45863 I had problems with a query that was
+# optimized differently in regular and prepared mode.
+# Because there was a bug in one of the selected strategies, I became
+# aware of the problem. Adding an EXPLAIN query to catch this.
+# (we obviously need to run with and without --ps-protocol to catch it)
+DROP TABLE IF EXISTS t1, t2, t3;
+CREATE TABLE t1
+(EMPNUM   CHAR(3) NOT NULL,
+EMPNAME  CHAR(20),
+GRADE    DECIMAL(4),
+CITY     CHAR(15));
+CREATE TABLE t2
+(PNUM     CHAR(3) NOT NULL,
+PNAME    CHAR(20),
+PTYPE    CHAR(6),
+BUDGET   DECIMAL(9),
+CITY     CHAR(15));
+CREATE TABLE t3
+(EMPNUM   CHAR(3) NOT NULL,
+PNUM     CHAR(3) NOT NULL,
+HOURS    DECIMAL(5));
+INSERT INTO t1 VALUES ('E1','Alice',12,'Deale');
+INSERT INTO t1 VALUES ('E2','Betty',10,'Vienna');
+INSERT INTO t1 VALUES ('E3','Carmen',13,'Vienna');
+INSERT INTO t1 VALUES ('E4','Don',12,'Deale');
+INSERT INTO t1 VALUES ('E5','Ed',13,'Akron');
+INSERT INTO t2 VALUES ('P1','MXSS','Design',10000,'Deale');
+INSERT INTO t2 VALUES ('P2','CALM','Code',30000,'Vienna');
+INSERT INTO t2 VALUES ('P3','SDP','Test',30000,'Tampa');
+INSERT INTO t2 VALUES ('P4','SDP','Design',20000,'Deale');
+INSERT INTO t2 VALUES ('P5','IRM','Test',10000,'Vienna');
+INSERT INTO t2 VALUES ('P6','PAYR','Design',50000,'Deale');
+INSERT INTO t3 VALUES  ('E1','P1',40);
+INSERT INTO t3 VALUES  ('E1','P2',20);
+INSERT INTO t3 VALUES  ('E1','P3',80);
+INSERT INTO t3 VALUES  ('E1','P4',20);
+INSERT INTO t3 VALUES  ('E1','P5',12);
+INSERT INTO t3 VALUES  ('E1','P6',12);
+INSERT INTO t3 VALUES  ('E2','P1',40);
+INSERT INTO t3 VALUES  ('E2','P2',80);
+INSERT INTO t3 VALUES  ('E3','P2',20);
+INSERT INTO t3 VALUES  ('E4','P2',20);
+INSERT INTO t3 VALUES  ('E4','P4',40);
+INSERT INTO t3 VALUES  ('E4','P5',80);
+SET @old_optimizer_switch = @@session.optimizer_switch;
+SET @old_join_cache_level = @@session.join_cache_level;
+SET SESSION optimizer_switch = 'firstmatch=on,loosescan=on,materialization=on,semijoin=on';
+SET SESSION join_cache_level = 1;
+CREATE UNIQUE INDEX t1_IDX ON t1(EMPNUM);
+EXPLAIN SELECT EMPNAME
+FROM t1
+WHERE EMPNUM IN
+(SELECT EMPNUM
+FROM t3
+WHERE PNUM IN
+(SELECT PNUM
+FROM t2
+WHERE PTYPE = 'Design'));
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	t1	ALL	t1_IDX	NULL	NULL	NULL	5	
+1	PRIMARY	t2	ALL	NULL	NULL	NULL	NULL	6	Using where; Start materialize
+1	PRIMARY	t3	ALL	NULL	NULL	NULL	NULL	12	Using where; End materialize; Using join buffer
+DROP INDEX t1_IDX ON t1;
+CREATE INDEX t1_IDX ON t1(EMPNUM);
+EXPLAIN SELECT EMPNAME
+FROM t1
+WHERE EMPNUM IN
+(SELECT EMPNUM
+FROM t3
+WHERE PNUM IN
+(SELECT PNUM
+FROM t2
+WHERE PTYPE = 'Design'));
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	t1	ALL	t1_IDX	NULL	NULL	NULL	5	
+1	PRIMARY	t2	ALL	NULL	NULL	NULL	NULL	6	Using where; Start materialize
+1	PRIMARY	t3	ALL	NULL	NULL	NULL	NULL	12	Using where; End materialize; Using join buffer
+DROP INDEX t1_IDX ON t1;
+EXPLAIN SELECT EMPNAME
+FROM t1
+WHERE EMPNUM IN
+(SELECT EMPNUM
+FROM t3
+WHERE PNUM IN
+(SELECT PNUM
+FROM t2
+WHERE PTYPE = 'Design'));
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	5	
+1	PRIMARY	t2	ALL	NULL	NULL	NULL	NULL	6	Using where; Start materialize
+1	PRIMARY	t3	ALL	NULL	NULL	NULL	NULL	12	Using where; End materialize; Using join buffer
+SET SESSION optimizer_switch = @old_optimizer_switch;
+SET SESSION join_cache_level = @old_join_cache_level;
+DROP TABLE t1, t2, t3;
+#
+# BUG#46631 "Crash with unknown column name in an IN subquery with
+#            loosescan=on"
+#           (Duplicate of BUG#45863)
+#
+DROP TABLE /*! IF EXISTS */ CC;
+DROP TABLE /*! IF EXISTS */ C;
+DROP TABLE /*! IF EXISTS */ D;
+DROP TABLE /*! IF EXISTS */ BB;
+CREATE TABLE `CC` (
+`pk` int(11) NOT NULL AUTO_INCREMENT,
+`int_nokey` int(11) DEFAULT NULL,
+`int_key` int(11) DEFAULT NULL,
+`datetime_key` datetime DEFAULT NULL,
+`varchar_key` varchar(1) DEFAULT NULL,
+`varchar_nokey` varchar(1) DEFAULT NULL,
+PRIMARY KEY (`pk`),
+KEY `int_key` (`int_key`),
+KEY `datetime_key` (`datetime_key`),
+KEY `varchar_key` (`varchar_key`,`int_key`)
+) ENGINE=MyISAM AUTO_INCREMENT=30 DEFAULT CHARSET=latin1;
+CREATE TABLE `C` (
+`pk` int(11) NOT NULL AUTO_INCREMENT,
+`int_nokey` int(11) DEFAULT NULL,
+`int_key` int(11) DEFAULT NULL,
+`datetime_key` datetime DEFAULT NULL,
+`varchar_key` varchar(1) DEFAULT NULL,
+`varchar_nokey` varchar(1) DEFAULT NULL,
+PRIMARY KEY (`pk`),
+KEY `int_key` (`int_key`),
+KEY `datetime_key` (`datetime_key`),
+KEY `varchar_key` (`varchar_key`,`int_key`)
+) ENGINE=MyISAM AUTO_INCREMENT=21 DEFAULT CHARSET=latin1;
+CREATE TABLE `D` (
+`pk` int(11) NOT NULL AUTO_INCREMENT,
+`int_nokey` int(11) DEFAULT NULL,
+`int_key` int(11) DEFAULT NULL,
+`datetime_key` datetime DEFAULT NULL,
+`varchar_key` varchar(1) DEFAULT NULL,
+`varchar_nokey` varchar(1) DEFAULT NULL,
+PRIMARY KEY (`pk`),
+KEY `int_key` (`int_key`),
+KEY `datetime_key` (`datetime_key`),
+KEY `varchar_key` (`varchar_key`,`int_key`)
+) ENGINE=MyISAM AUTO_INCREMENT=101 DEFAULT CHARSET=latin1;
+CREATE TABLE `BB` (
+`pk` int(11) NOT NULL AUTO_INCREMENT,
+`int_nokey` int(11) DEFAULT NULL,
+`int_key` int(11) DEFAULT NULL,
+`datetime_key` datetime DEFAULT NULL,
+`varchar_key` varchar(1) DEFAULT NULL,
+`varchar_nokey` varchar(1) DEFAULT NULL,
+PRIMARY KEY (`pk`),
+KEY `int_key` (`int_key`),
+KEY `datetime_key` (`datetime_key`),
+KEY `varchar_key` (`varchar_key`,`int_key`)
+) ENGINE=MyISAM AUTO_INCREMENT=12 DEFAULT CHARSET=latin1;
+SET @old_optimizer_switch = @@session.optimizer_switch;
+SET SESSION optimizer_switch = 'firstmatch=on,loosescan=on,materialization=on,semijoin=on';
+SELECT MAX(table1.`varchar_key`) field1  
+FROM BB table1
+STRAIGHT_JOIN
+(D table2 JOIN
+CC table3
+ON table2.`varchar_key`)
+ON table2 .`datetime_key`  
+WHERE ('q', 'a') IN (SELECT `varchar_key`, `varchar_nokey`
+                     FROM C)
+AND ( (SELECT SUBQUERY2_t1.`varchar_nokey`
+         FROM CC SUBQUERY2_t1
+STRAIGHT_JOIN
+(C SUBQUERY2_t2
+JOIN BB SUBQUERY2_t3
+ON SUBQUERY2_t3 .`int_nokey` = SUBQUERY2_t2.`int_key`)
+ON SUBQUERY2_t3.`int_key` = SUBQUERY2_t2.`pk`)
+OR (table3.`pk`, table3) IN (SELECT SUBQUERY3_t1.`int_nokey`,
+SUBQUERY3_t1.`int_key`
+                                  FROM (D AS SUBQUERY3_t1)
+)
+)  
+HAVING field1 != 3  
+ORDER BY table1.`varchar_key`,
+CONCAT(table1.`varchar_nokey`, table1.`varchar_nokey`),
+CONCAT(table3.`varchar_nokey`, table3.`varchar_nokey`);
+ERROR 42S22: Unknown column 'table3' in 'IN/ALL/ANY subquery'
+SET SESSION optimizer_switch = @old_optimizer_switch;
+DROP TABLE CC;
+DROP TABLE C;
+DROP TABLE D;
+DROP TABLE BB;
+DROP TABLE /*! IF EXISTS */ CC;
+DROP TABLE /*! IF EXISTS */ C;
+DROP TABLE /*! IF EXISTS */ D;
+DROP TABLE /*! IF EXISTS */ BB;
+CREATE TABLE `CC` (
+`pk` int(11) NOT NULL AUTO_INCREMENT,
+`int_nokey` int(11) DEFAULT NULL,
+`int_key` int(11) DEFAULT NULL,
+`datetime_key` datetime DEFAULT NULL,
+`varchar_key` varchar(1) DEFAULT NULL,
+`varchar_nokey` varchar(1) DEFAULT NULL,
+PRIMARY KEY (`pk`),
+KEY `int_key` (`int_key`),
+KEY `datetime_key` (`datetime_key`),
+KEY `varchar_key` (`varchar_key`,`int_key`)
+) ENGINE=MyISAM AUTO_INCREMENT=30 DEFAULT CHARSET=latin1;
+CREATE TABLE `C` (
+`pk` int(11) NOT NULL AUTO_INCREMENT,
+`int_nokey` int(11) DEFAULT NULL,
+`int_key` int(11) DEFAULT NULL,
+`datetime_key` datetime DEFAULT NULL,
+`varchar_key` varchar(1) DEFAULT NULL,
+`varchar_nokey` varchar(1) DEFAULT NULL,
+PRIMARY KEY (`pk`),
+KEY `int_key` (`int_key`),
+KEY `datetime_key` (`datetime_key`),
+KEY `varchar_key` (`varchar_key`,`int_key`)
+) ENGINE=MyISAM AUTO_INCREMENT=21 DEFAULT CHARSET=latin1;
+CREATE TABLE `D` (
+`pk` int(11) NOT NULL AUTO_INCREMENT,
+`int_nokey` int(11) DEFAULT NULL,
+`int_key` int(11) DEFAULT NULL,
+`datetime_key` datetime DEFAULT NULL,
+`varchar_key` varchar(1) DEFAULT NULL,
+`varchar_nokey` varchar(1) DEFAULT NULL,
+PRIMARY KEY (`pk`),
+KEY `int_key` (`int_key`),
+KEY `datetime_key` (`datetime_key`),
+KEY `varchar_key` (`varchar_key`,`int_key`)
+) ENGINE=MyISAM AUTO_INCREMENT=101 DEFAULT CHARSET=latin1;
+CREATE TABLE `BB` (
+`pk` int(11) NOT NULL AUTO_INCREMENT,
+`int_nokey` int(11) DEFAULT NULL,
+`int_key` int(11) DEFAULT NULL,
+`datetime_key` datetime DEFAULT NULL,
+`varchar_key` varchar(1) DEFAULT NULL,
+`varchar_nokey` varchar(1) DEFAULT NULL,
+PRIMARY KEY (`pk`),
+KEY `int_key` (`int_key`),
+KEY `datetime_key` (`datetime_key`),
+KEY `varchar_key` (`varchar_key`,`int_key`)
+) ENGINE=MyISAM AUTO_INCREMENT=12 DEFAULT CHARSET=latin1;
+SET @old_optimizer_switch = @@session.optimizer_switch;
+SET SESSION optimizer_switch = 'firstmatch=on,loosescan=on,materialization=on,semijoin=on';
+SELECT MAX(table1 .`varchar_key`) field1  
+FROM BB table1
+STRAIGHT_JOIN
+(D table2
+JOIN CC table3
+ON table2.`varchar_key`)
+ON table2.`datetime_key`  
+WHERE ('q' , 'a') IN (SELECT `varchar_key`, `varchar_nokey`  
+FROM C)
+AND ( (SELECT SUBQUERY2_t1.`varchar_nokey`
+         FROM CC SUBQUERY2_t1
+STRAIGHT_JOIN
+(C SUBQUERY2_t2
+JOIN
+BB SUBQUERY2_t3
+ON SUBQUERY2_t3.`int_nokey` = SUBQUERY2_t2.`int_key`)
+ON SUBQUERY2_t3.`int_key` = SUBQUERY2_t2 .`pk`)
+OR (table3 .`pk`, table3) IN (SELECT SUBQUERY3_t1.`int_nokey`,
+SUBQUERY3_t1 .`int_key`  
+FROM (D AS SUBQUERY3_t1)
+)
+)  
+HAVING field1 != 3
+ORDER BY table1.`varchar_key` ,
+CONCAT(table1.`varchar_nokey`, table1.`varchar_nokey`),
+CONCAT(table3.`varchar_nokey`, table3.`varchar_nokey`);
+ERROR 42S22: Unknown column 'table3' in 'IN/ALL/ANY subquery'
+SET SESSION optimizer_switch = @old_optimizer_switch;
+DROP TABLE CC;
+DROP TABLE C;
+DROP TABLE D;
+DROP TABLE BB;

=== modified file 'mysql-test/t/subselect4.test'
--- a/mysql-test/t/subselect4.test	2009-10-25 13:41:27 +0000
+++ b/mysql-test/t/subselect4.test	2009-11-05 10:13:23 +0000
@@ -121,3 +121,325 @@ set @@session.optimizer_switch          
     @@session.engine_condition_pushdown = @old_engine_condition_pushdown;
 
 DROP TABLE t1;
+
+--echo #
+--echo # BUG#45863 "Assertion failed: (fixed == 0), function fix_fields(),
+--echo #            file item.cc, line 4448"
+--echo #
+--disable_warnings
+DROP TABLE IF EXISTS C, BB;
+--enable_warnings
+
+CREATE TABLE `C` (
+  `varchar_key` varchar(1) NOT NULL,
+  `varchar_nokey` varchar(1) NOT NULL,
+  KEY `varchar_key` (`varchar_key`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+INSERT INTO `C` VALUES
+  ('k','k'),('a','a'),('',''),('u','u'),('e','e'),('v','v'),('i','i'),
+  ('t','t'),('u','u'),('f','f'),('u','u'),('m','m'),('j','j'),('f','f'),
+  ('v','v'),('j','j'),('g','g'),('e','e'),('h','h'),('z','z');
+CREATE TABLE `BB` (
+  `varchar_key` varchar(1) NOT NULL,
+  `varchar_nokey` varchar(1) NOT NULL,
+  KEY `varchar_key` (`varchar_key`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+INSERT INTO `BB` VALUES ('i','i'),('t','t');
+-- error ER_BAD_FIELD_ERROR
+SELECT `varchar_nokey` FROM C
+WHERE (`varchar_nokey`, OUTR) IN (SELECT `varchar_key`
+                                  FROM BB);
+DROP TABLE C,BB;
+
+--echo #
+--echo # During work with BUG#45863 I had problems with a query that was
+--echo # optimized differently in regular and prepared mode.
+--echo # Because there was a bug in one of the selected strategies, I became
+--echo # aware of the problem. Adding an EXPLAIN query to catch this.
+--echo # (we obviously need to run with and without --ps-protocol to catch it)
+
+--disable_warnings
+DROP TABLE IF EXISTS t1, t2, t3;
+--enable_warnings
+
+CREATE TABLE t1
+ (EMPNUM   CHAR(3) NOT NULL,
+  EMPNAME  CHAR(20),
+  GRADE    DECIMAL(4),
+  CITY     CHAR(15));
+
+CREATE TABLE t2
+ (PNUM     CHAR(3) NOT NULL,
+  PNAME    CHAR(20),
+  PTYPE    CHAR(6),
+  BUDGET   DECIMAL(9),
+  CITY     CHAR(15));
+
+CREATE TABLE t3
+ (EMPNUM   CHAR(3) NOT NULL,
+  PNUM     CHAR(3) NOT NULL,
+  HOURS    DECIMAL(5));
+
+INSERT INTO t1 VALUES ('E1','Alice',12,'Deale');
+INSERT INTO t1 VALUES ('E2','Betty',10,'Vienna');
+INSERT INTO t1 VALUES ('E3','Carmen',13,'Vienna');
+INSERT INTO t1 VALUES ('E4','Don',12,'Deale');
+INSERT INTO t1 VALUES ('E5','Ed',13,'Akron');
+
+INSERT INTO t2 VALUES ('P1','MXSS','Design',10000,'Deale');
+INSERT INTO t2 VALUES ('P2','CALM','Code',30000,'Vienna');
+INSERT INTO t2 VALUES ('P3','SDP','Test',30000,'Tampa');
+INSERT INTO t2 VALUES ('P4','SDP','Design',20000,'Deale');
+INSERT INTO t2 VALUES ('P5','IRM','Test',10000,'Vienna');
+INSERT INTO t2 VALUES ('P6','PAYR','Design',50000,'Deale');
+
+INSERT INTO t3 VALUES  ('E1','P1',40);
+INSERT INTO t3 VALUES  ('E1','P2',20);
+INSERT INTO t3 VALUES  ('E1','P3',80);
+INSERT INTO t3 VALUES  ('E1','P4',20);
+INSERT INTO t3 VALUES  ('E1','P5',12);
+INSERT INTO t3 VALUES  ('E1','P6',12);
+INSERT INTO t3 VALUES  ('E2','P1',40);
+INSERT INTO t3 VALUES  ('E2','P2',80);
+INSERT INTO t3 VALUES  ('E3','P2',20);
+INSERT INTO t3 VALUES  ('E4','P2',20);
+INSERT INTO t3 VALUES  ('E4','P4',40);
+INSERT INTO t3 VALUES  ('E4','P5',80);
+
+SET @old_optimizer_switch = @@session.optimizer_switch;
+SET @old_join_cache_level = @@session.join_cache_level;
+SET SESSION optimizer_switch = 'firstmatch=on,loosescan=on,materialization=on,semijoin=on';
+SET SESSION join_cache_level = 1;
+
+CREATE UNIQUE INDEX t1_IDX ON t1(EMPNUM);
+
+EXPLAIN SELECT EMPNAME
+FROM t1
+WHERE EMPNUM IN
+   (SELECT EMPNUM
+    FROM t3
+    WHERE PNUM IN
+       (SELECT PNUM
+        FROM t2
+        WHERE PTYPE = 'Design'));
+
+DROP INDEX t1_IDX ON t1;
+CREATE INDEX t1_IDX ON t1(EMPNUM);
+
+EXPLAIN SELECT EMPNAME
+FROM t1
+WHERE EMPNUM IN
+   (SELECT EMPNUM
+    FROM t3
+    WHERE PNUM IN
+       (SELECT PNUM
+        FROM t2
+        WHERE PTYPE = 'Design'));
+
+DROP INDEX t1_IDX ON t1;
+
+EXPLAIN SELECT EMPNAME
+FROM t1
+WHERE EMPNUM IN
+   (SELECT EMPNUM
+    FROM t3
+    WHERE PNUM IN
+       (SELECT PNUM
+        FROM t2
+        WHERE PTYPE = 'Design'));
+
+SET SESSION optimizer_switch = @old_optimizer_switch;
+SET SESSION join_cache_level = @old_join_cache_level;
+
+DROP TABLE t1, t2, t3;
+
+--echo #
+--echo # BUG#46631 "Crash with unknown column name in an IN subquery with
+--echo #            loosescan=on"
+--echo #           (Duplicate of BUG#45863)
+--echo #
+
+--disable_warnings
+DROP TABLE /*! IF EXISTS */ CC;
+DROP TABLE /*! IF EXISTS */ C;
+DROP TABLE /*! IF EXISTS */ D;
+DROP TABLE /*! IF EXISTS */ BB;
+--enable_warnings
+CREATE TABLE `CC` (
+  `pk` int(11) NOT NULL AUTO_INCREMENT,
+  `int_nokey` int(11) DEFAULT NULL,
+  `int_key` int(11) DEFAULT NULL,
+  `datetime_key` datetime DEFAULT NULL,
+  `varchar_key` varchar(1) DEFAULT NULL,
+  `varchar_nokey` varchar(1) DEFAULT NULL,
+  PRIMARY KEY (`pk`),
+  KEY `int_key` (`int_key`),
+  KEY `datetime_key` (`datetime_key`),
+  KEY `varchar_key` (`varchar_key`,`int_key`)
+) ENGINE=MyISAM AUTO_INCREMENT=30 DEFAULT CHARSET=latin1;
+CREATE TABLE `C` (
+  `pk` int(11) NOT NULL AUTO_INCREMENT,
+  `int_nokey` int(11) DEFAULT NULL,
+  `int_key` int(11) DEFAULT NULL,
+  `datetime_key` datetime DEFAULT NULL,
+  `varchar_key` varchar(1) DEFAULT NULL,
+  `varchar_nokey` varchar(1) DEFAULT NULL,
+  PRIMARY KEY (`pk`),
+  KEY `int_key` (`int_key`),
+  KEY `datetime_key` (`datetime_key`),
+  KEY `varchar_key` (`varchar_key`,`int_key`)
+) ENGINE=MyISAM AUTO_INCREMENT=21 DEFAULT CHARSET=latin1;
+CREATE TABLE `D` (
+  `pk` int(11) NOT NULL AUTO_INCREMENT,
+  `int_nokey` int(11) DEFAULT NULL,
+  `int_key` int(11) DEFAULT NULL,
+  `datetime_key` datetime DEFAULT NULL,
+  `varchar_key` varchar(1) DEFAULT NULL,
+  `varchar_nokey` varchar(1) DEFAULT NULL,
+  PRIMARY KEY (`pk`),
+  KEY `int_key` (`int_key`),
+  KEY `datetime_key` (`datetime_key`),
+  KEY `varchar_key` (`varchar_key`,`int_key`)
+) ENGINE=MyISAM AUTO_INCREMENT=101 DEFAULT CHARSET=latin1;
+CREATE TABLE `BB` (
+  `pk` int(11) NOT NULL AUTO_INCREMENT,
+  `int_nokey` int(11) DEFAULT NULL,
+  `int_key` int(11) DEFAULT NULL,
+  `datetime_key` datetime DEFAULT NULL,
+  `varchar_key` varchar(1) DEFAULT NULL,
+  `varchar_nokey` varchar(1) DEFAULT NULL,
+  PRIMARY KEY (`pk`),
+  KEY `int_key` (`int_key`),
+  KEY `datetime_key` (`datetime_key`),
+  KEY `varchar_key` (`varchar_key`,`int_key`)
+) ENGINE=MyISAM AUTO_INCREMENT=12 DEFAULT CHARSET=latin1;
+
+SET @old_optimizer_switch = @@session.optimizer_switch;
+SET SESSION optimizer_switch = 'firstmatch=on,loosescan=on,materialization=on,semijoin=on';
+
+-- error ER_BAD_FIELD_ERROR
+SELECT MAX(table1.`varchar_key`) field1  
+FROM BB table1
+     STRAIGHT_JOIN
+       (D table2 JOIN
+        CC table3
+        ON table2.`varchar_key`)
+     ON table2 .`datetime_key`  
+WHERE ('q', 'a') IN (SELECT `varchar_key`, `varchar_nokey`
+                     FROM C)
+  AND ( (SELECT SUBQUERY2_t1.`varchar_nokey`
+         FROM CC SUBQUERY2_t1
+              STRAIGHT_JOIN
+                (C SUBQUERY2_t2
+                 JOIN BB SUBQUERY2_t3
+                 ON SUBQUERY2_t3 .`int_nokey` = SUBQUERY2_t2.`int_key`)
+              ON SUBQUERY2_t3.`int_key` = SUBQUERY2_t2.`pk`)
+     OR (table3.`pk`, table3) IN (SELECT SUBQUERY3_t1.`int_nokey`,
+                                         SUBQUERY3_t1.`int_key`
+                                  FROM (D AS SUBQUERY3_t1)
+     )
+  )  
+HAVING field1 != 3  
+ORDER BY table1.`varchar_key`,
+         CONCAT(table1.`varchar_nokey`, table1.`varchar_nokey`),
+         CONCAT(table3.`varchar_nokey`, table3.`varchar_nokey`);
+
+SET SESSION optimizer_switch = @old_optimizer_switch;
+
+DROP TABLE CC;
+DROP TABLE C;
+DROP TABLE D;
+DROP TABLE BB;
+
+--disable_warnings
+DROP TABLE /*! IF EXISTS */ CC;
+DROP TABLE /*! IF EXISTS */ C;
+DROP TABLE /*! IF EXISTS */ D;
+DROP TABLE /*! IF EXISTS */ BB;
+--enable_warnings
+CREATE TABLE `CC` (
+  `pk` int(11) NOT NULL AUTO_INCREMENT,
+  `int_nokey` int(11) DEFAULT NULL,
+  `int_key` int(11) DEFAULT NULL,
+  `datetime_key` datetime DEFAULT NULL,
+  `varchar_key` varchar(1) DEFAULT NULL,
+  `varchar_nokey` varchar(1) DEFAULT NULL,
+  PRIMARY KEY (`pk`),
+  KEY `int_key` (`int_key`),
+  KEY `datetime_key` (`datetime_key`),
+  KEY `varchar_key` (`varchar_key`,`int_key`)
+) ENGINE=MyISAM AUTO_INCREMENT=30 DEFAULT CHARSET=latin1;
+CREATE TABLE `C` (
+  `pk` int(11) NOT NULL AUTO_INCREMENT,
+  `int_nokey` int(11) DEFAULT NULL,
+  `int_key` int(11) DEFAULT NULL,
+  `datetime_key` datetime DEFAULT NULL,
+  `varchar_key` varchar(1) DEFAULT NULL,
+  `varchar_nokey` varchar(1) DEFAULT NULL,
+  PRIMARY KEY (`pk`),
+  KEY `int_key` (`int_key`),
+  KEY `datetime_key` (`datetime_key`),
+  KEY `varchar_key` (`varchar_key`,`int_key`)
+) ENGINE=MyISAM AUTO_INCREMENT=21 DEFAULT CHARSET=latin1;
+CREATE TABLE `D` (
+  `pk` int(11) NOT NULL AUTO_INCREMENT,
+  `int_nokey` int(11) DEFAULT NULL,
+  `int_key` int(11) DEFAULT NULL,
+  `datetime_key` datetime DEFAULT NULL,
+  `varchar_key` varchar(1) DEFAULT NULL,
+  `varchar_nokey` varchar(1) DEFAULT NULL,
+  PRIMARY KEY (`pk`),
+  KEY `int_key` (`int_key`),
+  KEY `datetime_key` (`datetime_key`),
+  KEY `varchar_key` (`varchar_key`,`int_key`)
+) ENGINE=MyISAM AUTO_INCREMENT=101 DEFAULT CHARSET=latin1;
+CREATE TABLE `BB` (
+  `pk` int(11) NOT NULL AUTO_INCREMENT,
+  `int_nokey` int(11) DEFAULT NULL,
+  `int_key` int(11) DEFAULT NULL,
+  `datetime_key` datetime DEFAULT NULL,
+  `varchar_key` varchar(1) DEFAULT NULL,
+  `varchar_nokey` varchar(1) DEFAULT NULL,
+  PRIMARY KEY (`pk`),
+  KEY `int_key` (`int_key`),
+  KEY `datetime_key` (`datetime_key`),
+  KEY `varchar_key` (`varchar_key`,`int_key`)
+) ENGINE=MyISAM AUTO_INCREMENT=12 DEFAULT CHARSET=latin1;
+
+SET @old_optimizer_switch = @@session.optimizer_switch;
+SET SESSION optimizer_switch = 'firstmatch=on,loosescan=on,materialization=on,semijoin=on';
+
+-- error ER_BAD_FIELD_ERROR
+SELECT MAX(table1 .`varchar_key`) field1  
+FROM BB table1
+     STRAIGHT_JOIN
+       (D table2
+        JOIN CC table3
+        ON table2.`varchar_key`)
+     ON table2.`datetime_key`  
+WHERE ('q' , 'a') IN (SELECT `varchar_key`, `varchar_nokey`  
+                      FROM C)
+  AND ( (SELECT SUBQUERY2_t1.`varchar_nokey`
+         FROM CC SUBQUERY2_t1
+              STRAIGHT_JOIN
+               (C SUBQUERY2_t2
+                JOIN
+                BB SUBQUERY2_t3
+                ON SUBQUERY2_t3.`int_nokey` = SUBQUERY2_t2.`int_key`)
+              ON SUBQUERY2_t3.`int_key` = SUBQUERY2_t2 .`pk`)
+      OR (table3 .`pk`, table3) IN (SELECT SUBQUERY3_t1.`int_nokey`,
+                                           SUBQUERY3_t1 .`int_key`  
+                                    FROM (D AS SUBQUERY3_t1)
+       )
+  )  
+HAVING field1 != 3
+ORDER BY table1.`varchar_key` ,
+         CONCAT(table1.`varchar_nokey`, table1.`varchar_nokey`),
+         CONCAT(table3.`varchar_nokey`, table3.`varchar_nokey`);
+
+SET SESSION optimizer_switch = @old_optimizer_switch;
+
+DROP TABLE CC;
+DROP TABLE C;
+DROP TABLE D;
+DROP TABLE BB;

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2009-11-04 08:53:57 +0000
+++ b/sql/sql_select.cc	2009-11-05 10:13:23 +0000
@@ -257,8 +257,8 @@ static uint make_join_orderinfo(JOIN *jo
 static int
 join_read_record_no_init(JOIN_TAB *tab);
 static
-bool subquery_types_allow_materialization(THD *thd, 
-                                          Item_in_subselect *in_subs,
+void subquery_types_allow_materialization(Item_in_subselect *in_subs,
+                                          bool *mat_allowed,
                                           bool *scan_allowed);
 int do_sj_reset(SJ_TMP_TABLE *sj_tbl);
 TABLE *create_duplicate_weedout_tmp_table(THD *thd, uint uniq_tuple_length_arg,
@@ -581,6 +581,58 @@ JOIN::prepare(Item ***rref_pointer_array
     Item_in_subselect *in_subs= NULL;
     if (subselect->substype() == Item_subselect::IN_SUBS)
       in_subs= (Item_in_subselect*)subselect;
+
+    /* Resolve expressions and perform semantic analysis for IN query */
+    if (in_subs != NULL)
+      /*
+        TODO: Add the condition below to this if statement when we have proper
+        support for is_correlated handling for materialized semijoins.
+        If we were to add this condition now, the fix_fields() call in
+        convert_subq_to_sj() would force the flag is_correlated to be set
+        erroneously for prepared queries.
+        See decorrelate_subquery_search_cond() in tree mysql-6.0-exists2in
+        for (hopefully) proper correlation handling.
+
+        thd->stmt_arena->state != Query_arena::PREPARED)
+      */
+    {
+      SELECT_LEX *current= thd->lex->current_select;
+      thd->lex->current_select= current->return_after_parsing();
+      char const *save_where= thd->where;
+      thd->where= "IN/ALL/ANY subquery";
+        
+      bool failure= !in_subs->left_expr->fixed &&
+                     in_subs->left_expr->fix_fields(thd, &in_subs->left_expr);
+      thd->lex->current_select= current;
+      thd->where= save_where;
+      if (failure)
+        DBUG_RETURN(-1); /* purecov: deadcode */
+      /*
+        Check if the left and right expressions have the same # of
+        columns, i.e. we don't have a case like 
+          (oe1, oe2) IN (SELECT ie1, ie2, ie3 ...)
+
+        TODO why do we have this duplicated in IN->EXISTS transformers?
+        psergey-todo: fix these: grep for duplicated_subselect_card_check
+      */
+      if (select_lex->item_list.elements != in_subs->left_expr->cols())
+      {
+        my_error(ER_OPERAND_COLUMNS, MYF(0), in_subs->left_expr->cols());
+        DBUG_RETURN(-1);
+      }
+    }
+    /*
+      The below test might seem redundant, but this code block may also be
+      executed for EXISTS queries as soon as WL#4389 has been integrated
+      in the codebase.
+    */
+    if (in_subs != NULL &&
+        thd->stmt_arena->state != Query_arena::PREPARED)
+    {
+      subquery_types_allow_materialization(in_subs,
+                                      &in_subs->types_allow_materialization,
+                                      &in_subs->sjm_scan_allowed);
+    }
     DBUG_PRINT("info", ("Checking if subq can be converted to semi-join"));
     /*
       Check if we're in subquery that is a candidate for flattening into a
@@ -613,39 +665,8 @@ JOIN::prepare(Item ***rref_pointer_array
           & SELECT_STRAIGHT_JOIN))                                    // 10
     {
       DBUG_PRINT("info", ("Subquery is semi-join conversion candidate"));
-      in_subs->types_allow_materialization= 
-        subquery_types_allow_materialization(thd, in_subs,
-                                             &in_subs->sjm_scan_allowed);
-
-      if (thd->stmt_arena->state != Query_arena::PREPARED)
-      {
-        SELECT_LEX *current= thd->lex->current_select;
-        thd->lex->current_select= current->return_after_parsing();
-        char const *save_where= thd->where;
-        thd->where= "IN/ALL/ANY subquery";
-        
-        bool failure= !in_subs->left_expr->fixed &&
-                       in_subs->left_expr->fix_fields(thd, 
-                                                      &in_subs->left_expr);
-        thd->lex->current_select= current;
-        thd->where= save_where;
-        in_subs->emb_on_expr_nest= thd->thd_marker.emb_on_expr_nest;
-        if (failure)
-          DBUG_RETURN(-1); /* purecov: deadcode */
-        /*
-          Check if the left and right expressions have the same # of
-          columns, i.e. we don't have a case like 
-            (oe1, oe2) IN (SELECT ie1, ie2, ie3 ...)
 
-          TODO why do we have this duplicated in IN->EXISTS transformers?
-          psergey-todo: fix these: grep for duplicated_subselect_card_check
-        */
-        if (select_lex->item_list.elements != in_subs->left_expr->cols())
-        {
-          my_error(ER_OPERAND_COLUMNS, MYF(0), in_subs->left_expr->cols());
-          DBUG_RETURN(-1);
-        }
-      }
+      in_subs->emb_on_expr_nest= thd->thd_marker.emb_on_expr_nest;
 
       /* Register the subquery for further processing */
       select_lex->outer_select()->join->sj_subselects.append(thd->mem_root, in_subs);
@@ -694,9 +715,8 @@ JOIN::prepare(Item ***rref_pointer_array
           select_lex->master_unit()->first_select()->leaf_tables &&     // 3
           thd->lex->sql_command == SQLCOM_SELECT &&                     // *
           select_lex->outer_select()->leaf_tables &&                    // 3A
-          subquery_types_allow_materialization(thd, in_subs, NULL))
+          in_subs->types_allow_materialization)
       {
-        // psergey-todo: duplicated_subselect_card_check: where it's done?
         if (in_subs->is_top_level_item() &&                             // 4
             !in_subs->is_correlated &&                                  // 5
             in_subs->exec_method == Item_in_subselect::NOT_TRANSFORMED) // 6
@@ -854,7 +874,8 @@ err:
     subquery_types_allow_materialization()
       thd               Thread handle
       in_subs           Subquery predicate
-      scan_allowed  OUT If the return value is TRUE: 
+      mat_allowed   OUT If TRUE, subquery materialization is allowed
+      scan_allowed  OUT If *mat_allowed is TRUE: 
                           indicates whether it is possible to use subquery
                           materialization and scan the materialized table
                         Else
@@ -895,39 +916,23 @@ err:
           details)
         * require that compared columns have exactly the same type. This is
           a temporary measure to avoid BUG#36752-type problems.
-
-  RETURN 
-    TRUE   Yes, subquery types allow materialization
-    FALSE  No, or this is an invalid subquery
 */
 
 static 
-bool subquery_types_allow_materialization(THD *thd,  
-                                          Item_in_subselect *in_subs,
+void subquery_types_allow_materialization(Item_in_subselect *in_subs,
+                                          bool *mat_allowed,
                                           bool *scan_allowed)
 {
   DBUG_ENTER("subquery_types_allow_materialization");
   
-  /* Fix the left expression if it is not yet fixed */
-  if (!in_subs->left_expr->fixed)
-  {
-    SELECT_LEX *save_lex= thd->lex->current_select;
-    thd->lex->current_select= save_lex->outer_select();
-    char const *save_where= thd->where;
-    thd->where= "IN/ALL/ANY subquery";
-    bool res= in_subs->left_expr->fix_fields(thd, &in_subs->left_expr);
-    thd->where= save_where;
-    thd->lex->current_select=save_lex;
-    if (res)
-      DBUG_RETURN(FALSE);
-  }
-
   List_iterator<Item> it(in_subs->unit->first_select()->item_list);
   uint elements= in_subs->unit->first_select()->item_list.elements;
-  // psergey: duplicated_subselect_card_check
-  if (in_subs->left_expr->cols() != elements)
-    DBUG_RETURN(FALSE);
-  
+
+  *mat_allowed= FALSE;        // Assign default return value
+
+  /* Left expression should be fixed when we reach here */
+  DBUG_ASSERT(in_subs->left_expr->fixed);
+
   bool all_are_fields= TRUE;
   for (uint i= 0; i < elements; i++)
   {
@@ -936,26 +941,27 @@ bool subquery_types_allow_materializatio
     all_are_fields &= (outer->real_item()->type() == Item::FIELD_ITEM && 
                        inner->real_item()->type() == Item::FIELD_ITEM);
     if (outer->result_type() != inner->result_type())
-      DBUG_RETURN(FALSE);
+      DBUG_VOID_RETURN;
     switch (outer->result_type()) {
     case STRING_RESULT:
       if (outer->is_datetime() != inner->is_datetime())
-        DBUG_RETURN(FALSE);
+        DBUG_VOID_RETURN;
 
       if (!(outer->collation.collation == inner->collation.collation 
           /*&& outer->max_length <= inner->max_length */))
-        DBUG_RETURN(FALSE);
+        DBUG_VOID_RETURN;
     /*case INT_RESULT:
       if (!(outer->unsigned_flag ^ inner->unsigned_flag))
-        DBUG_RETURN(FALSE); */
+        DBUG_VOID_RETURN; */
     default:
       ;/* suitable for materialization */
     }
   }
+  *mat_allowed= TRUE;
   if (scan_allowed)
     *scan_allowed= all_are_fields;
   DBUG_PRINT("info",("subquery_types_allow_materialization: ok, allowed"));
-  DBUG_RETURN(TRUE);
+  DBUG_VOID_RETURN;
 }
 
 


Attachment: [text/bzr-bundle] bzr/roy.lyseng@sun.com-20091105101323-288p72pykuo1h5f0.bundle
Thread
bzr commit into mysql-6.0-codebase-bugfixing branch (roy.lyseng:3699)Bug#45863 WL#4389Roy Lyseng5 Nov
  • Re: bzr commit into mysql-6.0-codebase-bugfixing branch(roy.lyseng:3699) Bug#45863 WL#4389Evgeny Potemkin25 Nov
    • Re: bzr commit into mysql-6.0-codebase-bugfixing branch(roy.lyseng:3699) Bug#45863 WL#4389Roy Lyseng30 Nov