From 8e6440df0b8b08a67829932d62d354f83d29becc Mon Sep 17 00:00:00 2001 From: Sergey Petrunya Date: Wed, 26 Oct 2011 02:38:49 +0400 Subject: [PATCH] BUG#877288: Wrong result with semijoin + materialization + multipart key - when create_ref_for_key() is constructing a ref access for a table that's inside a SJ-Materialization nest, it may not use references to fields of tables that are unside the nest (because these fields will not yet have values when ref access will be used) The check was performed in the first of create_ref_for_key's loops (the one which counts how many key parts are usable) but not in the second (the one which actually fills the TABLE_REF structure). --- mysql-test/r/subselect_sj.result | 31 +++++++++++++++++++++++++++ mysql-test/r/subselect_sj_jcl6.result | 31 +++++++++++++++++++++++++++ mysql-test/t/subselect_sj.test | 19 ++++++++++++++++ sql/sql_select.cc | 3 ++- 4 files changed, 83 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/subselect_sj.result b/mysql-test/r/subselect_sj.result index 2c39e9e5472..351515f8d40 100644 --- a/mysql-test/r/subselect_sj.result +++ b/mysql-test/r/subselect_sj.result @@ -1963,4 +1963,35 @@ ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your W set max_join_size= @tmp_mjs_861147; set optimizer_switch= @tmp_os_861147; DROP TABLE t1,t2,t3,t4,t5,t6; +# +# BUG#877288: Wrong result with semijoin + materialization + multipart key +# +set @tmp_877288=@@optimizer_switch; +set optimizer_switch='semijoin=ON,materialization=ON'; +CREATE TABLE t1 ( a int) ; +INSERT INTO t1 VALUES (19),(19),(19),(20),(20),(20),(20),(20),(20); +CREATE TABLE t2 ( b int NOT NULL , c int NOT NULL , KEY (b,c)) ; +INSERT INTO t2 VALUES (14,1),(15,1),(16,1),(17,1),(18,1),(19,1),(20,1); +CREATE TABLE t3 ( a int, d int) ; +INSERT INTO t3 VALUES (19,1),(7,1),(3,1),(3,1),(20,1),(3,1),(16,1),(17,1),(9,1),(4,1),(6,1),(15,1),(17,1); +explain +SELECT * FROM t1 WHERE (a) IN (SELECT a FROM t2 JOIN t3 ON b = a); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 9 +1 PRIMARY eq_ref distinct_key distinct_key 5 func 1 +2 SUBQUERY t3 ALL NULL NULL NULL NULL 13 Using where +2 SUBQUERY t2 ref b b 4 test.t3.a 1 Using index +SELECT * FROM t1 WHERE (a) IN (SELECT a FROM t2 JOIN t3 ON b = a); +a +19 +19 +19 +20 +20 +20 +20 +20 +20 +DROP TABLE t1,t2,t3; +set optimizer_switch=@tmp_877288; set optimizer_switch=@subselect_sj_tmp; diff --git a/mysql-test/r/subselect_sj_jcl6.result b/mysql-test/r/subselect_sj_jcl6.result index de8277343d7..0931a4d743a 100644 --- a/mysql-test/r/subselect_sj_jcl6.result +++ b/mysql-test/r/subselect_sj_jcl6.result @@ -1974,6 +1974,37 @@ ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your W set max_join_size= @tmp_mjs_861147; set optimizer_switch= @tmp_os_861147; DROP TABLE t1,t2,t3,t4,t5,t6; +# +# BUG#877288: Wrong result with semijoin + materialization + multipart key +# +set @tmp_877288=@@optimizer_switch; +set optimizer_switch='semijoin=ON,materialization=ON'; +CREATE TABLE t1 ( a int) ; +INSERT INTO t1 VALUES (19),(19),(19),(20),(20),(20),(20),(20),(20); +CREATE TABLE t2 ( b int NOT NULL , c int NOT NULL , KEY (b,c)) ; +INSERT INTO t2 VALUES (14,1),(15,1),(16,1),(17,1),(18,1),(19,1),(20,1); +CREATE TABLE t3 ( a int, d int) ; +INSERT INTO t3 VALUES (19,1),(7,1),(3,1),(3,1),(20,1),(3,1),(16,1),(17,1),(9,1),(4,1),(6,1),(15,1),(17,1); +explain +SELECT * FROM t1 WHERE (a) IN (SELECT a FROM t2 JOIN t3 ON b = a); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 9 +1 PRIMARY eq_ref distinct_key distinct_key 5 func 1 +2 SUBQUERY t3 ALL NULL NULL NULL NULL 13 Using where +2 SUBQUERY t2 ref b b 4 test.t3.a 1 Using index +SELECT * FROM t1 WHERE (a) IN (SELECT a FROM t2 JOIN t3 ON b = a); +a +19 +19 +19 +20 +20 +20 +20 +20 +20 +DROP TABLE t1,t2,t3; +set optimizer_switch=@tmp_877288; set optimizer_switch=@subselect_sj_tmp; # # BUG#49129: Wrong result with IN-subquery with join_cache_level=6 and firstmatch=off diff --git a/mysql-test/t/subselect_sj.test b/mysql-test/t/subselect_sj.test index f5c943e44c1..385bf35753a 100644 --- a/mysql-test/t/subselect_sj.test +++ b/mysql-test/t/subselect_sj.test @@ -1807,6 +1807,25 @@ set optimizer_switch= @tmp_os_861147; DROP TABLE t1,t2,t3,t4,t5,t6; +--echo # +--echo # BUG#877288: Wrong result with semijoin + materialization + multipart key +--echo # +set @tmp_877288=@@optimizer_switch; +set optimizer_switch='semijoin=ON,materialization=ON'; +CREATE TABLE t1 ( a int) ; +INSERT INTO t1 VALUES (19),(19),(19),(20),(20),(20),(20),(20),(20); + +CREATE TABLE t2 ( b int NOT NULL , c int NOT NULL , KEY (b,c)) ; +INSERT INTO t2 VALUES (14,1),(15,1),(16,1),(17,1),(18,1),(19,1),(20,1); + +CREATE TABLE t3 ( a int, d int) ; +INSERT INTO t3 VALUES (19,1),(7,1),(3,1),(3,1),(20,1),(3,1),(16,1),(17,1),(9,1),(4,1),(6,1),(15,1),(17,1); + +explain +SELECT * FROM t1 WHERE (a) IN (SELECT a FROM t2 JOIN t3 ON b = a); +SELECT * FROM t1 WHERE (a) IN (SELECT a FROM t2 JOIN t3 ON b = a); +DROP TABLE t1,t2,t3; +set optimizer_switch=@tmp_877288; # The following command must be the last one the file set optimizer_switch=@subselect_sj_tmp; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 29db90452a2..71d3137f1c0 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7360,7 +7360,8 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, while (((~used_tables) & keyuse->used_tables) || (keyuse->keypart != (is_hash_join_key_no(key) ? - keyinfo->key_part[i].field->field_index : i))) + keyinfo->key_part[i].field->field_index : i)) || + !are_tables_local(j, keyuse->val->used_tables())) keyuse++; /* Skip other parts */ uint maybe_null= test(keyinfo->key_part[i].null_bit);