summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Petrunya <psergey@askmonty.org>2011-11-07 23:30:03 +0400
committerSergey Petrunya <psergey@askmonty.org>2011-11-07 23:30:03 +0400
commit7c7611d728d393dcc39bfd73ab5b3d56491ff9e7 (patch)
tree0161559f38c45f22d6043b18e7c7c2668819b7e9
parente0500dbc3ac99fc366982f721418fb67c1961cde (diff)
downloadmariadb-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.result30
-rw-r--r--mysql-test/t/myisam_icp.test30
-rw-r--r--sql/sql_select.cc41
-rw-r--r--sql/sql_select.h1
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;