Commit 7c7611d7 authored by Sergey Petrunya's avatar Sergey Petrunya

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.
parent e0500dbc
......@@ -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;
......@@ -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;
......@@ -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) ||
......
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment