MDEV-17411 Wrong WHERE optimization with simple CASE and searched CASE

This commit is contained in:
Alexander Barkov 2018-10-11 13:39:53 +04:00
parent 30629e196d
commit 4de0d920be
7 changed files with 66 additions and 9 deletions

View file

@ -546,5 +546,32 @@ Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 'a'
DROP TABLE t1;
#
# MDEV-17411 Wrong WHERE optimization with simple CASE and searched CASE
#
CREATE TABLE t1 (a INT, b INT, KEY(a));
INSERT INTO t1 VALUES (1,1),(2,2),(3,3);
SELECT * FROM t1 WHERE CASE a WHEN b THEN 1 END=1;
a b
1 1
2 2
3 3
SELECT * FROM t1 WHERE CASE WHEN a THEN b ELSE 1 END=3;
a b
3 3
SELECT * FROM t1 WHERE
CASE a WHEN b THEN 1 END=1 AND
CASE WHEN a THEN b ELSE 1 END=3;
a b
3 3
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE
CASE a WHEN b THEN 1 END=1 AND
CASE WHEN a THEN b ELSE 1 END=3;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where (case `test`.`t1`.`a` when `test`.`t1`.`b` then 1 end) = 1 and (case when `test`.`t1`.`a` then `test`.`t1`.`b` else 1 end) = 3
DROP TABLE t1;
#
# End of 10.3 test
#

View file

@ -390,6 +390,28 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='a' AND CASE 'a' WHEN 'a' THEN 'a' ELS
DROP TABLE t1;
--echo #
--echo # MDEV-17411 Wrong WHERE optimization with simple CASE and searched CASE
--echo #
CREATE TABLE t1 (a INT, b INT, KEY(a));
INSERT INTO t1 VALUES (1,1),(2,2),(3,3);
SELECT * FROM t1 WHERE CASE a WHEN b THEN 1 END=1;
SELECT * FROM t1 WHERE CASE WHEN a THEN b ELSE 1 END=3;
SELECT * FROM t1 WHERE
CASE a WHEN b THEN 1 END=1 AND
CASE WHEN a THEN b ELSE 1 END=3;
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE
CASE a WHEN b THEN 1 END=1 AND
CASE WHEN a THEN b ELSE 1 END=3;
DROP TABLE t1;
--echo #
--echo # End of 10.3 test
--echo #

View file

@ -2211,6 +2211,15 @@ protected:
}
return true;
}
bool eq(const Item_args *other, bool binary_cmp) const
{
for (uint i= 0; i < arg_count ; i++)
{
if (!args[i]->eq(other->args[i], binary_cmp))
return false;
}
return true;
}
public:
Item_args(void)
:args(NULL), arg_count(0)

View file

@ -1813,10 +1813,7 @@ bool Item_func_opt_neg::eq(const Item *item, bool binary_cmp) const
return 0;
if (negated != ((Item_func_opt_neg *) item_func)->negated)
return 0;
for (uint i=0; i < arg_count ; i++)
if (!args[i]->eq(item_func->arguments()[i], binary_cmp))
return 0;
return 1;
return Item_args::eq(item_func, binary_cmp);
}

View file

@ -2154,6 +2154,7 @@ public:
DBUG_ASSERT(arg_count >= 2);
reorder_args(0);
}
enum Functype functype() const { return CASE_SEARCHED_FUNC; }
void print(String *str, enum_query_type query_type);
bool fix_length_and_dec();
Item *propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
@ -2206,6 +2207,7 @@ public:
Predicant_to_list_comparator::cleanup();
DBUG_VOID_RETURN;
}
enum Functype functype() const { return CASE_SIMPLE_FUNC; }
void print(String *str, enum_query_type query_type);
bool fix_length_and_dec();
Item *propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond);

View file

@ -647,10 +647,7 @@ bool Item_func::eq(const Item *item, bool binary_cmp) const
(func_type == Item_func::FUNC_SP &&
my_strcasecmp(system_charset_info, func_name(), item_func->func_name())))
return 0;
for (uint i=0; i < arg_count ; i++)
if (!args[i]->eq(item_func->args[i], binary_cmp))
return 0;
return 1;
return Item_args::eq(item_func, binary_cmp);
}

View file

@ -76,7 +76,10 @@ public:
SUSERVAR_FUNC, GUSERVAR_FUNC, COLLATE_FUNC,
EXTRACT_FUNC, CHAR_TYPECAST_FUNC, FUNC_SP, UDF_FUNC,
NEG_FUNC, GSYSVAR_FUNC, IN_OPTIMIZER_FUNC, DYNCOL_FUNC,
JSON_EXTRACT_FUNC };
JSON_EXTRACT_FUNC,
CASE_SEARCHED_FUNC, // Used by ColumnStore/Spider
CASE_SIMPLE_FUNC // Used by ColumnStore/spider
};
enum Type type() const { return FUNC_ITEM; }
virtual enum Functype functype() const { return UNKNOWN_FUNC; }
Item_func(THD *thd): Item_func_or_sum(thd)