Fix LP BUG#719198
Analysis: The assert failed because the execution code for partial matching is designed with the assumption that NULLs on the left side are detected as early as possible, and a NULL result is returned before any lookups are performed at all. However, in the case of an Item_cache object on the left side, null was not detected properly, because detection was done via Item::is_null(), which is not implemented at all for Item_cache, and resolved to the default Item::is_null() which always returns FALSE. Solution: Use the property Item::null_value instead of is_null(), which is properly updated for Item_cache objects as well.
This commit is contained in:
parent
0d5d68f684
commit
546a166b4e
@ -1371,3 +1371,41 @@ SELECT pk FROM t1 WHERE (b,c,d) IN (SELECT b,c,d FROM t2 WHERE pk > 0);
|
|||||||
pk
|
pk
|
||||||
2
|
2
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
|
#
|
||||||
|
# LPBUG#719198 Ordered_key::cmp_key_with_search_key(rownum_t): Assertion `!compare_pred[i]->null_value'
|
||||||
|
# failed with subquery on both sides of NOT IN and materialization
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (f1a int, f1b int) ;
|
||||||
|
INSERT IGNORE INTO t1 VALUES (1,1),(2,2);
|
||||||
|
CREATE TABLE t2 ( f2 int);
|
||||||
|
INSERT IGNORE INTO t2 VALUES (3),(4);
|
||||||
|
CREATE TABLE t3 (f3a int, f3b int);
|
||||||
|
set session optimizer_switch='materialization=on,partial_match_rowid_merge=on,partial_match_table_scan=off';
|
||||||
|
EXPLAIN
|
||||||
|
SELECT * FROM t2 WHERE (SELECT f3a FROM t3) NOT IN (SELECT f1a FROM t1);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where
|
||||||
|
3 SUBQUERY t1 ALL NULL NULL NULL NULL 2
|
||||||
|
2 SUBQUERY t3 system NULL NULL NULL NULL 0 const row not found
|
||||||
|
SELECT * FROM t2 WHERE (SELECT f3a FROM t3) NOT IN (SELECT f1a FROM t1);
|
||||||
|
f2
|
||||||
|
EXPLAIN
|
||||||
|
SELECT * FROM t2 WHERE (SELECT f3a, f3b FROM t3) NOT IN (SELECT f1a, f1b FROM t1);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where
|
||||||
|
3 SUBQUERY t1 ALL NULL NULL NULL NULL 2
|
||||||
|
2 SUBQUERY t3 system NULL NULL NULL NULL 0 const row not found
|
||||||
|
SELECT * FROM t2 WHERE (SELECT f3a, f3b FROM t3) NOT IN (SELECT f1a, f1b FROM t1);
|
||||||
|
f2
|
||||||
|
insert into t3 values (1,1),(2,2);
|
||||||
|
EXPLAIN
|
||||||
|
SELECT * FROM t2 WHERE (SELECT f3a FROM t3 where f3a > 3) NOT IN (SELECT f1a FROM t1);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where
|
||||||
|
3 SUBQUERY t1 ALL NULL NULL NULL NULL 2
|
||||||
|
2 SUBQUERY t3 ALL NULL NULL NULL NULL 2 Using where
|
||||||
|
SELECT * FROM t2 WHERE (SELECT f3a FROM t3 where f3a > 3) NOT IN (SELECT f1a FROM t1);
|
||||||
|
f2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
drop table t1, t2, t3;
|
||||||
|
@ -1011,3 +1011,31 @@ SELECT pk FROM t1 WHERE (a) IN (SELECT a FROM t2 WHERE pk > 0);
|
|||||||
SELECT pk FROM t1 WHERE (b,c,d) IN (SELECT b,c,d FROM t2 WHERE pk > 0);
|
SELECT pk FROM t1 WHERE (b,c,d) IN (SELECT b,c,d FROM t2 WHERE pk > 0);
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # LPBUG#719198 Ordered_key::cmp_key_with_search_key(rownum_t): Assertion `!compare_pred[i]->null_value'
|
||||||
|
--echo # failed with subquery on both sides of NOT IN and materialization
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1 (f1a int, f1b int) ;
|
||||||
|
INSERT IGNORE INTO t1 VALUES (1,1),(2,2);
|
||||||
|
CREATE TABLE t2 ( f2 int);
|
||||||
|
INSERT IGNORE INTO t2 VALUES (3),(4);
|
||||||
|
CREATE TABLE t3 (f3a int, f3b int);
|
||||||
|
|
||||||
|
set session optimizer_switch='materialization=on,partial_match_rowid_merge=on,partial_match_table_scan=off';
|
||||||
|
|
||||||
|
EXPLAIN
|
||||||
|
SELECT * FROM t2 WHERE (SELECT f3a FROM t3) NOT IN (SELECT f1a FROM t1);
|
||||||
|
SELECT * FROM t2 WHERE (SELECT f3a FROM t3) NOT IN (SELECT f1a FROM t1);
|
||||||
|
|
||||||
|
EXPLAIN
|
||||||
|
SELECT * FROM t2 WHERE (SELECT f3a, f3b FROM t3) NOT IN (SELECT f1a, f1b FROM t1);
|
||||||
|
SELECT * FROM t2 WHERE (SELECT f3a, f3b FROM t3) NOT IN (SELECT f1a, f1b FROM t1);
|
||||||
|
|
||||||
|
insert into t3 values (1,1),(2,2);
|
||||||
|
|
||||||
|
EXPLAIN
|
||||||
|
SELECT * FROM t2 WHERE (SELECT f3a FROM t3 where f3a > 3) NOT IN (SELECT f1a FROM t1);
|
||||||
|
SELECT * FROM t2 WHERE (SELECT f3a FROM t3 where f3a > 3) NOT IN (SELECT f1a FROM t1);
|
||||||
|
|
||||||
|
drop table t1, t2, t3;
|
||||||
|
@ -3342,6 +3342,13 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@todo
|
||||||
|
Implement the is_null() method for this class. Currently calling is_null()
|
||||||
|
on any Item_cache object resolves to Item::is_null(), which reutns FALSE
|
||||||
|
for any value.
|
||||||
|
*/
|
||||||
|
|
||||||
class Item_cache: public Item_basic_constant
|
class Item_cache: public Item_basic_constant
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
@ -5069,7 +5069,7 @@ bool subselect_rowid_merge_engine::partial_match()
|
|||||||
for (uint i= test(non_null_key); i < keys_count; i++)
|
for (uint i= test(non_null_key); i < keys_count; i++)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(merge_keys[i]->get_column_count() == 1);
|
DBUG_ASSERT(merge_keys[i]->get_column_count() == 1);
|
||||||
if (merge_keys[i]->get_search_key(0)->is_null())
|
if (merge_keys[i]->get_search_key(0)->null_value)
|
||||||
{
|
{
|
||||||
++count_nulls_in_search_key;
|
++count_nulls_in_search_key;
|
||||||
bitmap_set_bit(&matching_outer_cols, merge_keys[i]->get_keyid());
|
bitmap_set_bit(&matching_outer_cols, merge_keys[i]->get_keyid());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user