From 5b441013e1975741512fbb6f1f1ff34d336cfcc1 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Wed, 5 Feb 2014 17:47:38 -0800 Subject: [PATCH 1/3] Fixed bug mdev-5468. The field JOIN::select_lex->where should be updated after the call of remove_eq_conds() in the function make_join_statistics(). This matters for subselects. --- mysql-test/r/subselect4.result | 27 +++++++++++++++++++++++++++ mysql-test/t/subselect4.test | 34 ++++++++++++++++++++++++++++++++++ sql/sql_select.cc | 1 + 3 files changed, 62 insertions(+) diff --git a/mysql-test/r/subselect4.result b/mysql-test/r/subselect4.result index 20cb28c3ffb..6c314c448cb 100644 --- a/mysql-test/r/subselect4.result +++ b/mysql-test/r/subselect4.result @@ -2348,5 +2348,32 @@ SELECT * FROM t1 AS t WHERE a='r' AND (c,b) NOT IN (SELECT c,b FROM t2 WHERE (c,b)=(t.c,t.b)); a b c d DROP TABLE t1, t2; +# +# MDEV-5468: assertion failure with a simplified condition in subselect +# +CREATE TABLE t1 (a int, b int) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1); +CREATE TABLE t2 ( pk int PRIMARY KEY, c INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (1,4), (2,6); +SELECT ( SELECT MAX(b) FROM t1, t2 WHERE pk = a AND b < from_sq.c ) AS select_sq, +COUNT( DISTINCT from_sq.c ) +FROM ( SELECT DISTINCT t2_1.* FROM t2 AS t2_1, t2 AS t2_2 ) AS from_sq +GROUP BY select_sq ; +select_sq COUNT( DISTINCT from_sq.c ) +1 2 +DROP TABLE t1,t2; +CREATE TABLE t1 (id int, a2 char(2), a3 char(3)) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,'BE','BEL'); +CREATE TABLE t2 (id int, a2 char(2), a3 char(3)) ENGINE=MyISAM; +INSERT INTO t2 VALUES (1,'BE','BEL'), (2,'MX','MEX'); +CREATE VIEW v2 AS SELECT DISTINCT * FROM t2; +SELECT * FROM t1 AS outer_t1, v2 +WHERE v2.a3 = outer_t1.a3 +AND EXISTS ( SELECT * FROM t1 WHERE a2 < v2.a2 AND id = outer_t1.id ) +AND outer_t1.a3 < 'J' +ORDER BY v2.id; +id a2 a3 id a2 a3 +DROP VIEW v2; +DROP TABLE t1,t2; SET optimizer_switch= @@global.optimizer_switch; set @@tmp_table_size= @@global.tmp_table_size; diff --git a/mysql-test/t/subselect4.test b/mysql-test/t/subselect4.test index ad0e135f37e..6aa1fd51859 100644 --- a/mysql-test/t/subselect4.test +++ b/mysql-test/t/subselect4.test @@ -1936,5 +1936,39 @@ SELECT * FROM t1 AS t DROP TABLE t1, t2; +--echo # +--echo # MDEV-5468: assertion failure with a simplified condition in subselect +--echo # + +CREATE TABLE t1 (a int, b int) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1); + +CREATE TABLE t2 ( pk int PRIMARY KEY, c INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (1,4), (2,6); + +SELECT ( SELECT MAX(b) FROM t1, t2 WHERE pk = a AND b < from_sq.c ) AS select_sq, + COUNT( DISTINCT from_sq.c ) +FROM ( SELECT DISTINCT t2_1.* FROM t2 AS t2_1, t2 AS t2_2 ) AS from_sq +GROUP BY select_sq ; + +DROP TABLE t1,t2; + + +CREATE TABLE t1 (id int, a2 char(2), a3 char(3)) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,'BE','BEL'); + +CREATE TABLE t2 (id int, a2 char(2), a3 char(3)) ENGINE=MyISAM; +INSERT INTO t2 VALUES (1,'BE','BEL'), (2,'MX','MEX'); +CREATE VIEW v2 AS SELECT DISTINCT * FROM t2; + +SELECT * FROM t1 AS outer_t1, v2 +WHERE v2.a3 = outer_t1.a3 + AND EXISTS ( SELECT * FROM t1 WHERE a2 < v2.a2 AND id = outer_t1.id ) + AND outer_t1.a3 < 'J' +ORDER BY v2.id; + +DROP VIEW v2; +DROP TABLE t1,t2; + SET optimizer_switch= @@global.optimizer_switch; set @@tmp_table_size= @@global.tmp_table_size; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 3e5652f2a16..611b786a257 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3535,6 +3535,7 @@ make_join_statistics(JOIN *join, List &tables_list, if (conds && const_count) { conds= remove_eq_conds(join->thd, conds, &join->cond_value); + join->select_lex->where= conds; if (join->cond_value == Item::COND_FALSE) { join->impossible_where= true; From 34b6f51dab7a2710b1bba816dde486a9c9c6c9c2 Mon Sep 17 00:00:00 2001 From: Sergey Petrunya Date: Fri, 7 Feb 2014 20:51:31 +0400 Subject: [PATCH 2/3] MDEV-5582: Plugin 'MEMORY' has ref_count=1 after shutdown with materialization+semijoin - Let cleanup_empty_jtbm_semi_joins() walk into semi-join nests. --- mysql-test/r/subselect_sj2.result | 17 +++++++++++++++++ mysql-test/r/subselect_sj2_jcl6.result | 17 +++++++++++++++++ mysql-test/r/subselect_sj2_mat.result | 17 +++++++++++++++++ mysql-test/t/subselect_sj2.test | 19 +++++++++++++++++++ sql/opt_subselect.cc | 8 ++++++-- sql/opt_subselect.h | 2 +- sql/sql_select.cc | 2 +- 7 files changed, 78 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/subselect_sj2.result b/mysql-test/r/subselect_sj2.result index cfbec56427f..b7509c1cda3 100644 --- a/mysql-test/r/subselect_sj2.result +++ b/mysql-test/r/subselect_sj2.result @@ -1112,5 +1112,22 @@ t3 AS t3a INNER JOIN t3 AS t3b ON ( t3a.i3 = t3b.i3 ) ); i1 DROP TABLE t1,t2,t3; +# +# MDEV-5582: Plugin 'MEMORY' has ref_count=1 after shutdown with materialization+semijoin +# +CREATE TABLE t1 (a INT) engine=innodb; +INSERT INTO t1 VALUES (8),(9); +CREATE TABLE t2 (b INT) engine=innodb; +INSERT INTO t2 VALUES (2),(3); +CREATE TABLE t3 (c INT, INDEX(c)) engine=innodb; +INSERT INTO t2 VALUES (4),(5); +explain +SELECT * FROM t1 WHERE 9 IN ( SELECT b FROM t2 WHERE 1 IN ( SELECT MIN(c) FROM t3 ) ); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +3 MATERIALIZED NULL NULL NULL NULL NULL NULL NULL No matching min/max row +SELECT * FROM t1 WHERE 9 IN ( SELECT b FROM t2 WHERE 1 IN ( SELECT MIN(c) FROM t3 ) ); +a +DROP TABLE t1,t2,t3; # This must be the last in the file: set optimizer_switch=@subselect_sj2_tmp; diff --git a/mysql-test/r/subselect_sj2_jcl6.result b/mysql-test/r/subselect_sj2_jcl6.result index 4f1beb6cac1..b0f508abab6 100644 --- a/mysql-test/r/subselect_sj2_jcl6.result +++ b/mysql-test/r/subselect_sj2_jcl6.result @@ -1127,6 +1127,23 @@ t3 AS t3a INNER JOIN t3 AS t3b ON ( t3a.i3 = t3b.i3 ) ); i1 DROP TABLE t1,t2,t3; +# +# MDEV-5582: Plugin 'MEMORY' has ref_count=1 after shutdown with materialization+semijoin +# +CREATE TABLE t1 (a INT) engine=innodb; +INSERT INTO t1 VALUES (8),(9); +CREATE TABLE t2 (b INT) engine=innodb; +INSERT INTO t2 VALUES (2),(3); +CREATE TABLE t3 (c INT, INDEX(c)) engine=innodb; +INSERT INTO t2 VALUES (4),(5); +explain +SELECT * FROM t1 WHERE 9 IN ( SELECT b FROM t2 WHERE 1 IN ( SELECT MIN(c) FROM t3 ) ); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +3 MATERIALIZED NULL NULL NULL NULL NULL NULL NULL No matching min/max row +SELECT * FROM t1 WHERE 9 IN ( SELECT b FROM t2 WHERE 1 IN ( SELECT MIN(c) FROM t3 ) ); +a +DROP TABLE t1,t2,t3; # This must be the last in the file: set optimizer_switch=@subselect_sj2_tmp; # diff --git a/mysql-test/r/subselect_sj2_mat.result b/mysql-test/r/subselect_sj2_mat.result index d3cc8d08be2..bd0afd5a730 100644 --- a/mysql-test/r/subselect_sj2_mat.result +++ b/mysql-test/r/subselect_sj2_mat.result @@ -1114,6 +1114,23 @@ t3 AS t3a INNER JOIN t3 AS t3b ON ( t3a.i3 = t3b.i3 ) ); i1 DROP TABLE t1,t2,t3; +# +# MDEV-5582: Plugin 'MEMORY' has ref_count=1 after shutdown with materialization+semijoin +# +CREATE TABLE t1 (a INT) engine=innodb; +INSERT INTO t1 VALUES (8),(9); +CREATE TABLE t2 (b INT) engine=innodb; +INSERT INTO t2 VALUES (2),(3); +CREATE TABLE t3 (c INT, INDEX(c)) engine=innodb; +INSERT INTO t2 VALUES (4),(5); +explain +SELECT * FROM t1 WHERE 9 IN ( SELECT b FROM t2 WHERE 1 IN ( SELECT MIN(c) FROM t3 ) ); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +3 MATERIALIZED NULL NULL NULL NULL NULL NULL NULL No matching min/max row +SELECT * FROM t1 WHERE 9 IN ( SELECT b FROM t2 WHERE 1 IN ( SELECT MIN(c) FROM t3 ) ); +a +DROP TABLE t1,t2,t3; # This must be the last in the file: set optimizer_switch=@subselect_sj2_tmp; set optimizer_switch=default; diff --git a/mysql-test/t/subselect_sj2.test b/mysql-test/t/subselect_sj2.test index 91db113d35a..bf7e0d4d3af 100644 --- a/mysql-test/t/subselect_sj2.test +++ b/mysql-test/t/subselect_sj2.test @@ -1249,5 +1249,24 @@ SELECT * FROM t1 WHERE ( 1, 1 ) IN ( DROP TABLE t1,t2,t3; +--echo # +--echo # MDEV-5582: Plugin 'MEMORY' has ref_count=1 after shutdown with materialization+semijoin +--echo # +CREATE TABLE t1 (a INT) engine=innodb; +INSERT INTO t1 VALUES (8),(9); + +CREATE TABLE t2 (b INT) engine=innodb; +INSERT INTO t2 VALUES (2),(3); + +CREATE TABLE t3 (c INT, INDEX(c)) engine=innodb; +INSERT INTO t2 VALUES (4),(5); + +explain +SELECT * FROM t1 WHERE 9 IN ( SELECT b FROM t2 WHERE 1 IN ( SELECT MIN(c) FROM t3 ) ); +SELECT * FROM t1 WHERE 9 IN ( SELECT b FROM t2 WHERE 1 IN ( SELECT MIN(c) FROM t3 ) ); + +DROP TABLE t1,t2,t3; + + --echo # This must be the last in the file: set optimizer_switch=@subselect_sj2_tmp; diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 07dbb3991b0..60eee3fd48f 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -5234,9 +5234,9 @@ bool setup_jtbm_semi_joins(JOIN *join, List *join_list, through Item::cleanup() calls). */ -void cleanup_empty_jtbm_semi_joins(JOIN *join) +void cleanup_empty_jtbm_semi_joins(JOIN *join, List *join_list) { - List_iterator li(*join->join_list); + List_iterator li(*join_list); TABLE_LIST *table; while ((table= li++)) { @@ -5248,6 +5248,10 @@ void cleanup_empty_jtbm_semi_joins(JOIN *join) table->table= NULL; } } + else if (table->nested_join && table->sj_subq_pred) + { + cleanup_empty_jtbm_semi_joins(join, &table->nested_join->join_list); + } } } diff --git a/sql/opt_subselect.h b/sql/opt_subselect.h index 88ecc6cb405..444b3840950 100644 --- a/sql/opt_subselect.h +++ b/sql/opt_subselect.h @@ -12,7 +12,7 @@ int pull_out_semijoin_tables(JOIN *join); bool optimize_semijoin_nests(JOIN *join, table_map all_table_map); bool setup_jtbm_semi_joins(JOIN *join, List *join_list, Item **join_where); -void cleanup_empty_jtbm_semi_joins(JOIN *join); +void cleanup_empty_jtbm_semi_joins(JOIN *join, List *join_list); // used by Loose_scan_opt ulonglong get_bound_sj_equalities(TABLE_LIST *sj_nest, diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 3e5652f2a16..e5fa81c1457 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -10549,7 +10549,7 @@ void JOIN::cleanup(bool full) } if (full) { - cleanup_empty_jtbm_semi_joins(this); + cleanup_empty_jtbm_semi_joins(this, join_list); /* Ensure that the following delete_elements() would not be called twice for the same list. From 50b9e30b7270095c6b151a993d3231d546f491ca Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Fri, 7 Feb 2014 15:50:36 -0800 Subject: [PATCH 3/3] Fixed bug mdev-5611. The method Item_field::update_table_bitmaps() should not try to mark the bit for a self-referencing virtual column. --- mysql-test/suite/vcol/r/vcol_misc.result | 5 +++++ mysql-test/suite/vcol/t/vcol_misc.test | 7 +++++++ sql/item.h | 6 +++++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/vcol/r/vcol_misc.result b/mysql-test/suite/vcol/r/vcol_misc.result index 4514928e592..8631789f15f 100644 --- a/mysql-test/suite/vcol/r/vcol_misc.result +++ b/mysql-test/suite/vcol/r/vcol_misc.result @@ -316,4 +316,9 @@ ERROR HY000: The value specified for computed column 'd' in table 't1' ignored INSERT INTO `test`.`t1`(`a`,`b`,`c`,`d`) VALUES ( '1','a',NULL,'a'); ERROR HY000: The value specified for computed column 'd' in table 't1' ignored drop table t1; +# +# MDEV-5611: self-referencing virtual column +# +create table t1 (a int, b int as (b is null) virtual); +ERROR HY000: A computed column cannot be based on a computed column # end of 5.3 tests diff --git a/mysql-test/suite/vcol/t/vcol_misc.test b/mysql-test/suite/vcol/t/vcol_misc.test index 9c8443218fa..a4c1fc06ce9 100644 --- a/mysql-test/suite/vcol/t/vcol_misc.test +++ b/mysql-test/suite/vcol/t/vcol_misc.test @@ -275,4 +275,11 @@ UPDATE `test`.`t1` SET `d`='b' WHERE `a`='1' AND `b`='a' AND `c`='1' AND `d`='a INSERT INTO `test`.`t1`(`a`,`b`,`c`,`d`) VALUES ( '1','a',NULL,'a'); drop table t1; +--echo # +--echo # MDEV-5611: self-referencing virtual column +--echo # + +--error ER_VCOL_BASED_ON_VCOL +create table t1 (a int, b int as (b is null) virtual); + --echo # end of 5.3 tests diff --git a/sql/item.h b/sql/item.h index 5e8e4dfc892..58abc42dd80 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1877,7 +1877,11 @@ public: tab->merge_keys.merge(field->part_of_key); if (tab->read_set) bitmap_fast_test_and_set(tab->read_set, field->field_index); - if (field->vcol_info) + /* + Do not mark a self-referecing virtual column. + Such virtual columns are reported as invalid. + */ + if (field->vcol_info && tab->vcol_set) tab->mark_virtual_col(field); } }