From 86c5cad4e0165a5cdf7b5615a66f5dac8c5c01aa Mon Sep 17 00:00:00 2001 From: "sergefp@mysql.com" <> Date: Tue, 15 Aug 2006 20:33:14 +0400 Subject: [PATCH 1/3] BUG#21077: Possible crash caused by invalid sequence of handler::* calls: The crash was caused by invalid sequence of handler::** calls: ha_smth->index_init(); ha_smth->index_next_same(); (2) (2) is an invalid call as it was not preceeded by any 'scan setup' call like index_first() or index_read(). The cause was that QUICK_SELECT::reset() didn't "fully reset" the quick select- current QUICK_RANGE wasn't forgotten, and quick select might attempt to continue reading the range, which would result in the above mentioned invalid sequence of handler calls. 5.x versions are not affected by the bug - they already have the missing "range=NULL" clause. --- mysql-test/r/innodb_mysql.result | 21 +++++++++++++++++++++ mysql-test/t/innodb_mysql.test | 27 +++++++++++++++++++++++++++ sql/opt_range.h | 2 +- 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 920d7aa42ce..ee4c114087d 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -83,3 +83,24 @@ b a 3 3 3 3 DROP TABLE t1, t2, t3; +CREATE TABLE `t1` (`id1` INT) ; +INSERT INTO `t1` (`id1`) VALUES (1),(5),(2); +CREATE TABLE `t2` ( +`id1` INT, +`id2` INT NOT NULL, +`id3` INT, +`id4` INT NOT NULL, +UNIQUE (`id2`,`id4`), +KEY (`id1`) +) ENGINE=InnoDB; +INSERT INTO `t2`(`id1`,`id2`,`id3`,`id4`) VALUES +(1,1,1,0), +(1,1,2,1), +(5,1,2,2), +(6,1,2,3), +(1,2,2,2), +(1,2,1,1); +SELECT `id1` FROM `t1` WHERE `id1` NOT IN (SELECT `id1` FROM `t2` WHERE `id2` = 1 AND `id3` = 2); +id1 +2 +DROP TABLE t1, t2; diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index 0b789e1a6d5..a5fe248604f 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -90,3 +90,30 @@ SELECT STRAIGHT_JOIN SQL_NO_CACHE t1.b, t1.a FROM t1, t3, t2 WHERE t3.a = t2.a AND t2.b = t1.a AND t3.b = 1 AND t3.c IN (1, 2) ORDER BY t1.b LIMIT 5; DROP TABLE t1, t2, t3; + + +# BUG#21077 (The testcase is not deterministic so correct execution doesn't +# prove anything) For proof one should track if sequence of ha_innodb::* func +# calls is correct. +CREATE TABLE `t1` (`id1` INT) ; +INSERT INTO `t1` (`id1`) VALUES (1),(5),(2); + +CREATE TABLE `t2` ( + `id1` INT, + `id2` INT NOT NULL, + `id3` INT, + `id4` INT NOT NULL, + UNIQUE (`id2`,`id4`), + KEY (`id1`) +) ENGINE=InnoDB; + +INSERT INTO `t2`(`id1`,`id2`,`id3`,`id4`) VALUES +(1,1,1,0), +(1,1,2,1), +(5,1,2,2), +(6,1,2,3), +(1,2,2,2), +(1,2,1,1); + +SELECT `id1` FROM `t1` WHERE `id1` NOT IN (SELECT `id1` FROM `t2` WHERE `id2` = 1 AND `id3` = 2); +DROP TABLE t1, t2; diff --git a/sql/opt_range.h b/sql/opt_range.h index 15f0bf02b34..d2f4452a762 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -86,7 +86,7 @@ public: QUICK_SELECT(THD *thd, TABLE *table,uint index_arg,bool no_alloc=0); virtual ~QUICK_SELECT(); - void reset(void) { next=0; it.rewind(); } + void reset(void) { next=0; it.rewind(); range= NULL;} int init() { key_part_info= head->key_info[index].key_part; From d4cacdb5ccc191c8d41103e1cc310d9dc2832314 Mon Sep 17 00:00:00 2001 From: "sergefp@mysql.com" <> Date: Thu, 24 Aug 2006 19:14:36 +0400 Subject: [PATCH 2/3] Bug #16255: Subquery in WHERE (the cset by Georgi Kodinov) Must not use Item_direct_ref in HAVING because it points to the new value (witch is not yet calculated for the first row). --- mysql-test/r/subselect.result | 11 +++++++++++ mysql-test/t/subselect.test | 12 ++++++++++++ sql/item_subselect.cc | 10 +++++----- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 983ad628425..e84c3957760 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -2895,3 +2895,14 @@ select * from t1 where NOT(s1 = ALL (select s1/s1 from t1)); s1 2 drop table t1; +CREATE TABLE t1 (a INT, b INT, PRIMARY KEY (a,b)); +INSERT INTO t1 VALUES(26, 1), (48, 2); +SELECT * FROM t1 r WHERE (r.a,r.b) IN (SELECT a,MAX(b) FROM t1 GROUP BY a); +a b +26 1 +48 2 +SELECT * FROM t1 r WHERE (r.a,r.b) IN (SELECT a + 0,MAX(b) FROM t1 GROUP BY a); +a b +26 1 +48 2 +DROP TABLE t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index fc97d22cbb1..780a4f3a002 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1861,4 +1861,16 @@ select * from t1 where NOT(s1+1 = ANY (select s1 from t1)); select * from t1 where (s1 = ALL (select s1/s1 from t1)); select * from t1 where NOT(s1 = ALL (select s1/s1 from t1)); drop table t1; + +# +# Bug #16255: Subquery in where +# +CREATE TABLE t1 (a INT, b INT, PRIMARY KEY (a,b)); + +INSERT INTO t1 VALUES(26, 1), (48, 2); + +SELECT * FROM t1 r WHERE (r.a,r.b) IN (SELECT a,MAX(b) FROM t1 GROUP BY a); +SELECT * FROM t1 r WHERE (r.a,r.b) IN (SELECT a + 0,MAX(b) FROM t1 GROUP BY a); + +DROP TABLE t1; # End of 4.1 tests diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index c95a91de13e..13beb022c9d 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -976,18 +976,18 @@ Item_in_subselect::row_value_transformer(JOIN *join) DBUG_RETURN(RES_ERROR); Item *item_eq= new Item_func_eq(new - Item_direct_ref((*optimizer->get_cache())-> + Item_ref((*optimizer->get_cache())-> addr(i), (char *)"", (char *)in_left_expr_name), new - Item_direct_ref(select_lex->ref_pointer_array + i, + Item_ref(select_lex->ref_pointer_array + i, (char *)"", (char *)"") ); Item *item_isnull= new Item_func_isnull(new - Item_direct_ref( select_lex-> + Item_ref( select_lex-> ref_pointer_array+i, (char *)"", (char *)"") @@ -1000,7 +1000,7 @@ Item_in_subselect::row_value_transformer(JOIN *join) new Item_is_not_null_test(this, new - Item_direct_ref(select_lex-> + Item_ref(select_lex-> ref_pointer_array + i, (char *)"", (char *)"") @@ -1057,7 +1057,7 @@ Item_in_subselect::row_value_transformer(JOIN *join) new Item_is_not_null_test(this, new - Item_direct_ref(select_lex-> + Item_ref(select_lex-> ref_pointer_array + i, (char *)"", (char *)"") From 848548e16f940e117bfde69613314307f441d995 Mon Sep 17 00:00:00 2001 From: "sergefp@mysql.com" <> Date: Thu, 24 Aug 2006 19:16:27 +0400 Subject: [PATCH 3/3] BUG#16255: Post-review fixes: adjust the testcase. --- mysql-test/r/subselect.result | 33 ++++++++++++++++++++++----------- mysql-test/t/subselect.test | 22 +++++++++++++++++----- 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index e84c3957760..f5abc4ed42a 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -2895,14 +2895,25 @@ select * from t1 where NOT(s1 = ALL (select s1/s1 from t1)); s1 2 drop table t1; -CREATE TABLE t1 (a INT, b INT, PRIMARY KEY (a,b)); -INSERT INTO t1 VALUES(26, 1), (48, 2); -SELECT * FROM t1 r WHERE (r.a,r.b) IN (SELECT a,MAX(b) FROM t1 GROUP BY a); -a b -26 1 -48 2 -SELECT * FROM t1 r WHERE (r.a,r.b) IN (SELECT a + 0,MAX(b) FROM t1 GROUP BY a); -a b -26 1 -48 2 -DROP TABLE t1; +create table t1 ( +retailerID varchar(8) NOT NULL, +statusID int(10) unsigned NOT NULL, +changed datetime NOT NULL, +UNIQUE KEY retailerID (retailerID, statusID, changed) +); +INSERT INTO t1 VALUES("0026", "1", "2005-12-06 12:18:56"); +INSERT INTO t1 VALUES("0026", "2", "2006-01-06 12:25:53"); +INSERT INTO t1 VALUES("0037", "1", "2005-12-06 12:18:56"); +INSERT INTO t1 VALUES("0037", "2", "2006-01-06 12:25:53"); +INSERT INTO t1 VALUES("0048", "1", "2006-01-06 12:37:50"); +INSERT INTO t1 VALUES("0059", "1", "2006-01-06 12:37:50"); +select * from t1 r1 +where (r1.retailerID,(r1.changed)) in +(SELECT r2.retailerId,(max(changed)) from t1 r2 +group by r2.retailerId); +retailerID statusID changed +0026 2 2006-01-06 12:25:53 +0037 2 2006-01-06 12:25:53 +0048 1 2006-01-06 12:37:50 +0059 1 2006-01-06 12:37:50 +drop table t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 780a4f3a002..10dfb788c10 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1865,12 +1865,24 @@ drop table t1; # # Bug #16255: Subquery in where # -CREATE TABLE t1 (a INT, b INT, PRIMARY KEY (a,b)); +create table t1 ( + retailerID varchar(8) NOT NULL, + statusID int(10) unsigned NOT NULL, + changed datetime NOT NULL, + UNIQUE KEY retailerID (retailerID, statusID, changed) +); -INSERT INTO t1 VALUES(26, 1), (48, 2); +INSERT INTO t1 VALUES("0026", "1", "2005-12-06 12:18:56"); +INSERT INTO t1 VALUES("0026", "2", "2006-01-06 12:25:53"); +INSERT INTO t1 VALUES("0037", "1", "2005-12-06 12:18:56"); +INSERT INTO t1 VALUES("0037", "2", "2006-01-06 12:25:53"); +INSERT INTO t1 VALUES("0048", "1", "2006-01-06 12:37:50"); +INSERT INTO t1 VALUES("0059", "1", "2006-01-06 12:37:50"); -SELECT * FROM t1 r WHERE (r.a,r.b) IN (SELECT a,MAX(b) FROM t1 GROUP BY a); -SELECT * FROM t1 r WHERE (r.a,r.b) IN (SELECT a + 0,MAX(b) FROM t1 GROUP BY a); +select * from t1 r1 + where (r1.retailerID,(r1.changed)) in + (SELECT r2.retailerId,(max(changed)) from t1 r2 + group by r2.retailerId); +drop table t1; -DROP TABLE t1; # End of 4.1 tests