From 9e6f484788db461b46a365d415ee7043cab65f1e Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Thu, 13 Oct 2011 22:39:00 -0700 Subject: [PATCH] Fixed LP bug #872735. This bug happened because the maps of covering keys for mergeable derived tables/views was not recalculated after the derived tables/vies had been merged into the main query. --- mysql-test/r/derived_view.result | 38 ++++++++++++++++++++++++++++++++ mysql-test/t/derived_view.test | 33 +++++++++++++++++++++++++++ sql/item.h | 5 +++++ sql/sql_lex.cc | 15 +++++++++++++ 4 files changed, 91 insertions(+) diff --git a/mysql-test/r/derived_view.result b/mysql-test/r/derived_view.result index b79485d94e0..ceb63ddc967 100644 --- a/mysql-test/r/derived_view.result +++ b/mysql-test/r/derived_view.result @@ -1424,4 +1424,42 @@ a a c a a c b a d 6 23 -1 NULL NULL NULL NULL NULL 5 DROP VIEW v2,v3; DROP TABLE t1,t2,t3,t4,t5; +# +# LP bug #872735: derived used in a NOT IN subquery +# +CREATE TABLE t1 (b int NOT NULL); +INSERT INTO t1 VALUES (9), (7); +CREATE TABLE t2 (a int NOT NULL) ; +INSERT INTO t2 VALUES (1), (2); +CREATE TABLE t3 ( +a int NOT NULL , c int NOT NULL, d varchar(1) NOT NULL, +KEY (c,a) , PRIMARY KEY (a) +); +INSERT INTO t3 VALUES +(14,4,'a'), (15,7,'b'), (16,4,'c'), (17,1,'d'), (18,9,'e'), +(19,4,'f'), (20,8,'g'); +SET SESSION optimizer_switch='derived_merge=on,subquery_cache=off'; +# The following two EXPLAINs must return the same execution plan +EXPLAIN +SELECT * FROM t1 , t2 +WHERE (t2.a ,t1.b) NOT IN (SELECT DISTINCT c,a FROM t3 t); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 +1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY t ref PRIMARY,c c 4 func 2 Using where; Using index +EXPLAIN +SELECT * FROM t1 , t2 +WHERE (t2.a ,t1.b) NOT IN (SELECT DISTINCT c,a FROM (SELECT * FROM t3) t); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 +1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY t3 ref PRIMARY,c c 4 func 2 Using where; Using index +SELECT * FROM t1 , t2 +WHERE (t2.a ,t1.b) NOT IN (SELECT DISTINCT c,a FROM (SELECT * FROM t3) t); +b a +9 1 +7 1 +9 2 +7 2 +DROP TABLE t1,t2,t3; set optimizer_switch=@exit_optimizer_switch; diff --git a/mysql-test/t/derived_view.test b/mysql-test/t/derived_view.test index 1c8cbec8a3e..9f7e24481a0 100644 --- a/mysql-test/t/derived_view.test +++ b/mysql-test/t/derived_view.test @@ -877,5 +877,38 @@ SELECT STRAIGHT_JOIN * DROP VIEW v2,v3; DROP TABLE t1,t2,t3,t4,t5; +--echo # +--echo # LP bug #872735: derived used in a NOT IN subquery +--echo # + +CREATE TABLE t1 (b int NOT NULL); +INSERT INTO t1 VALUES (9), (7); + +CREATE TABLE t2 (a int NOT NULL) ; +INSERT INTO t2 VALUES (1), (2); + +CREATE TABLE t3 ( + a int NOT NULL , c int NOT NULL, d varchar(1) NOT NULL, + KEY (c,a) , PRIMARY KEY (a) +); +INSERT INTO t3 VALUES + (14,4,'a'), (15,7,'b'), (16,4,'c'), (17,1,'d'), (18,9,'e'), + (19,4,'f'), (20,8,'g'); + +SET SESSION optimizer_switch='derived_merge=on,subquery_cache=off'; + +--echo # The following two EXPLAINs must return the same execution plan +EXPLAIN +SELECT * FROM t1 , t2 + WHERE (t2.a ,t1.b) NOT IN (SELECT DISTINCT c,a FROM t3 t); +EXPLAIN +SELECT * FROM t1 , t2 + WHERE (t2.a ,t1.b) NOT IN (SELECT DISTINCT c,a FROM (SELECT * FROM t3) t); + +SELECT * FROM t1 , t2 + WHERE (t2.a ,t1.b) NOT IN (SELECT DISTINCT c,a FROM (SELECT * FROM t3) t); + +DROP TABLE t1,t2,t3; + # The following command must be the last one the file set optimizer_switch=@exit_optimizer_switch; diff --git a/sql/item.h b/sql/item.h index 8cacd231fbf..efd358db874 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1816,6 +1816,11 @@ public: bool get_date_result(MYSQL_TIME *ltime,uint fuzzydate); bool is_null() { return field->is_null(); } void update_null_value(); + void update_used_tables() + { + if (field && field->table) + field->table->covering_keys.intersect(field->part_of_key); + } Item *get_tmp_table_item(THD *thd); bool collect_item_field_processor(uchar * arg); bool add_field_to_set_processor(uchar * arg); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 7f39d4ad7f3..64e295d82ea 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -3411,6 +3411,21 @@ void SELECT_LEX::update_used_tables() while ((tl= ti++)) { TABLE_LIST *embedding; + if (tl->table) + { + embedding= tl->embedding; + for (embedding= tl->embedding; embedding; embedding=embedding->embedding) + { + if (embedding->is_view_or_derived()) + { + DBUG_ASSERT(embedding->is_merged_derived()); + TABLE *tab= tl->table; + tab->covering_keys= tab->s->keys_for_keyread; + tab->covering_keys.intersect(tab->keys_in_use_for_query); + break; + } + } + } embedding= tl; do {