diff options
author | Sergey Petrunya <psergey@askmonty.org> | 2011-11-07 23:30:03 +0400 |
---|---|---|
committer | Sergey Petrunya <psergey@askmonty.org> | 2011-11-07 23:30:03 +0400 |
commit | 7c7611d728d393dcc39bfd73ab5b3d56491ff9e7 (patch) | |
tree | 0161559f38c45f22d6043b18e7c7c2668819b7e9 | |
parent | e0500dbc3ac99fc366982f721418fb67c1961cde (diff) | |
download | mariadb-git-7c7611d728d393dcc39bfd73ab5b3d56491ff9e7.tar.gz |
BUG#887026: Wrong result with ICP, outer join, subquery in maria-5.3-icp
- Do not push index condition if we're using a triggered ref access.
-rw-r--r-- | mysql-test/r/myisam_icp.result | 30 | ||||
-rw-r--r-- | mysql-test/t/myisam_icp.test | 30 | ||||
-rw-r--r-- | sql/sql_select.cc | 41 | ||||
-rw-r--r-- | sql/sql_select.h | 1 |
4 files changed, 86 insertions, 16 deletions
diff --git a/mysql-test/r/myisam_icp.result b/mysql-test/r/myisam_icp.result index 01449e4fdb2..6799682c273 100644 --- a/mysql-test/r/myisam_icp.result +++ b/mysql-test/r/myisam_icp.result @@ -727,4 +727,34 @@ SELECT a, MIN(c) FROM t1 WHERE b = 'x' AND c > 'x' GROUP BY a; a MIN(c) 5 y DROP TABLE t1; +# +# BUG#887026: Wrong result with ICP, outer join, subquery in maria-5.3-icp +# +CREATE TABLE t1 (c varchar(1)); +INSERT INTO t1 VALUES ('c'), ('c'); +CREATE TABLE t2 (c varchar(1), b int); +INSERT INTO t2 VALUES ('d', NULL),('d', NULL); +CREATE TABLE t3 (c varchar(1)); +INSERT INTO t3 VALUES ('c'); +INSERT INTO t3 VALUES ('c'); +CREATE TABLE t4 ( b int, c varchar(1), KEY (b)); +INSERT INTO t4 VALUES (7,'c'); +INSERT INTO t4 VALUES (7,'c'); +# Must be t1,t2,t3,t4, with t4 having Full-scan-on-NULL but not Using index condition +explain +SELECT * FROM t1 LEFT JOIN t2 ON t1.c=t2.b +WHERE +t2.b NOT IN (SELECT t4.b FROM t3 STRAIGHT_JOIN t4 WHERE t4.b <= 2 AND t4.c = t3.c); +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 +2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 +2 DEPENDENT SUBQUERY t4 ref_or_null b b 5 func 2 Using where; Full scan on NULL key +SELECT * FROM t1 LEFT JOIN t2 ON t1.c=t2.b +WHERE +t2.b NOT IN (SELECT t4.b FROM t3 STRAIGHT_JOIN t4 WHERE t4.b <= 2 AND t4.c = t3.c); +c c b +c NULL NULL +c NULL NULL +DROP TABLE t1,t2,t3,t4; set optimizer_switch=@myisam_icp_tmp; diff --git a/mysql-test/t/myisam_icp.test b/mysql-test/t/myisam_icp.test index 7e7affb1b8f..bbff6c30e56 100644 --- a/mysql-test/t/myisam_icp.test +++ b/mysql-test/t/myisam_icp.test @@ -227,4 +227,34 @@ SELECT a, MIN(c) FROM t1 WHERE b = 'x' AND c > 'x' GROUP BY a; DROP TABLE t1; +--echo # +--echo # BUG#887026: Wrong result with ICP, outer join, subquery in maria-5.3-icp +--echo # + +CREATE TABLE t1 (c varchar(1)); +INSERT INTO t1 VALUES ('c'), ('c'); + +CREATE TABLE t2 (c varchar(1), b int); +INSERT INTO t2 VALUES ('d', NULL),('d', NULL); + +CREATE TABLE t3 (c varchar(1)); +INSERT INTO t3 VALUES ('c'); +INSERT INTO t3 VALUES ('c'); + +CREATE TABLE t4 ( b int, c varchar(1), KEY (b)); +INSERT INTO t4 VALUES (7,'c'); +INSERT INTO t4 VALUES (7,'c'); + +--echo # Must be t1,t2,t3,t4, with t4 having Full-scan-on-NULL but not Using index condition +explain +SELECT * FROM t1 LEFT JOIN t2 ON t1.c=t2.b +WHERE + t2.b NOT IN (SELECT t4.b FROM t3 STRAIGHT_JOIN t4 WHERE t4.b <= 2 AND t4.c = t3.c); + +SELECT * FROM t1 LEFT JOIN t2 ON t1.c=t2.b +WHERE + t2.b NOT IN (SELECT t4.b FROM t3 STRAIGHT_JOIN t4 WHERE t4.b <= 2 AND t4.c = t3.c); + +DROP TABLE t1,t2,t3,t4; + set optimizer_switch=@myisam_icp_tmp; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 19a29765066..5e1992b8816 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -9101,11 +9101,9 @@ uint check_join_cache_usage(JOIN_TAB *tab, case JT_EQ_REF: if (cache_level <=2 || (no_hashed_cache && no_bka_cache)) goto no_join_cache; - for (uint i= 0; i < tab->ref.key_parts; i++) - { - if (tab->ref.cond_guards[i]) - goto no_join_cache; - } + if (tab->ref.is_access_triggered()) + goto no_join_cache; + if (!tab->is_ref_for_hash_join()) { flags= HA_MRR_NO_NULL_ENDPOINTS | HA_MRR_SINGLE_POINT; @@ -9396,9 +9394,9 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after) table->key_read=1; table->file->extra(HA_EXTRA_KEYREAD); } - else if (!jcl || jcl > 4) + else if ((!jcl || jcl > 4) && !tab->ref.is_access_triggered()) push_index_cond(tab, tab->ref.key); - break; + break; case JT_EQ_REF: tab->read_record.unlock_row= join_read_key_unlock_row; /* fall through */ @@ -9408,7 +9406,7 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after) table->key_read=1; table->file->extra(HA_EXTRA_KEYREAD); } - else if (!jcl || jcl > 4) + else if ((!jcl || jcl > 4) && !tab->ref.is_access_triggered()) push_index_cond(tab, tab->ref.key); break; case JT_REF_OR_NULL: @@ -9423,7 +9421,7 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after) if (table->covering_keys.is_set(tab->ref.key) && !table->no_keyread) table->enable_keyread(); - else if (!jcl || jcl > 4) + else if ((!jcl || jcl > 4) && !tab->ref.is_access_triggered()) push_index_cond(tab, tab->ref.key); break; case JT_ALL: @@ -9780,6 +9778,22 @@ bool TABLE_REF::tmp_table_index_lookup_init(THD *thd, } +/* + Check if ref access uses "Full scan on NULL key" (i.e. it actually alternates + between ref access and full table scan) +*/ + +bool TABLE_REF::is_access_triggered() +{ + for (uint i = 0; i < key_parts; i++) + { + if (cond_guards[i]) + return TRUE; + } + return FALSE; +} + + /** Partially cleanup JOIN after it has executed: close index or rnd read (table cursors), free quick selects. @@ -16656,13 +16670,8 @@ bool test_if_ref(Item *root_cond, Item_field *left_item,Item *right_item) between ref access and full table scan), then no equality can be guaranteed to be true. */ - for (uint i = 0; i < join_tab->ref.key_parts; i++) - { - if (join_tab->ref.cond_guards[i]) - { - return FALSE; - } - } + if (join_tab->ref.is_access_triggered()) + return FALSE; Item *ref_item=part_of_refkey(field->table,field); if (ref_item && (ref_item->eq(right_item,1) || diff --git a/sql/sql_select.h b/sql/sql_select.h index 0a416966995..5476ef9b46c 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -136,6 +136,7 @@ typedef struct st_table_ref bool tmp_table_index_lookup_init(THD *thd, KEY *tmp_key, Item_iterator &it, bool value, uint skip= 0); + bool is_access_triggered(); } TABLE_REF; |