From edd980225a9895f46754d54677bd76327152c78b Mon Sep 17 00:00:00 2001 From: Sergey Petrunya Date: Mon, 26 Aug 2013 21:38:04 +0400 Subject: [PATCH] Fix for MDEV-4836 fix: take into account situation where "notnull_col IS NULL" is not a direct child of the WHERE clause item, but rather is embedded inside Item_cond_and or Item_cond_or. --- mysql-test/r/join_outer.result | 8 ++++++++ mysql-test/r/join_outer_jcl6.result | 8 ++++++++ mysql-test/t/join_outer.test | 11 +++++++++++ sql/item_cmpfunc.cc | 4 ++-- sql/sql_select.cc | 22 ++++++++++++++++++++++ sql/sql_select.h | 1 + 6 files changed, 52 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result index 3cfe2b20a1a..d77f3df1cdf 100644 --- a/mysql-test/r/join_outer.result +++ b/mysql-test/r/join_outer.result @@ -2150,6 +2150,14 @@ id d i 1 0000-00-00 NULL 2 0000-00-00 NULL DROP TABLE t1,t2; +CREATE TABLE t1 (i1 INT, d1 DATE NOT NULL); +INSERT INTO t1 VALUES (1,'2012-12-21'),(2,'0000-00-00'); +CREATE TABLE t2 (i2 INT, j2 INT); +INSERT INTO t2 VALUES (1,10),(2,20); +SELECT * FROM t1 LEFT JOIN t2 ON i1 = j2 WHERE d1 IS NULL AND 1 OR i1 = i2; +i1 d1 i2 j2 +2 0000-00-00 NULL NULL +DROP TABLE t1,t2; # # Bug mdev-4942: LEFT JOIN with conjunctive # IS NULL in WHERE diff --git a/mysql-test/r/join_outer_jcl6.result b/mysql-test/r/join_outer_jcl6.result index 5c20a87f10c..59760470176 100644 --- a/mysql-test/r/join_outer_jcl6.result +++ b/mysql-test/r/join_outer_jcl6.result @@ -2161,6 +2161,14 @@ id d i 1 0000-00-00 NULL 2 0000-00-00 NULL DROP TABLE t1,t2; +CREATE TABLE t1 (i1 INT, d1 DATE NOT NULL); +INSERT INTO t1 VALUES (1,'2012-12-21'),(2,'0000-00-00'); +CREATE TABLE t2 (i2 INT, j2 INT); +INSERT INTO t2 VALUES (1,10),(2,20); +SELECT * FROM t1 LEFT JOIN t2 ON i1 = j2 WHERE d1 IS NULL AND 1 OR i1 = i2; +i1 d1 i2 j2 +2 0000-00-00 NULL NULL +DROP TABLE t1,t2; # # Bug mdev-4942: LEFT JOIN with conjunctive # IS NULL in WHERE diff --git a/mysql-test/t/join_outer.test b/mysql-test/t/join_outer.test index 0ef1ea593a2..f85feb70ccb 100644 --- a/mysql-test/t/join_outer.test +++ b/mysql-test/t/join_outer.test @@ -1696,6 +1696,17 @@ CREATE TABLE t2 (i INT); SELECT * FROM t1 LEFT JOIN t2 ON (id=i) WHERE NULL OR d IS NULL; DROP TABLE t1,t2; + +CREATE TABLE t1 (i1 INT, d1 DATE NOT NULL); +INSERT INTO t1 VALUES (1,'2012-12-21'),(2,'0000-00-00'); + +CREATE TABLE t2 (i2 INT, j2 INT); +INSERT INTO t2 VALUES (1,10),(2,20); + +SELECT * FROM t1 LEFT JOIN t2 ON i1 = j2 WHERE d1 IS NULL AND 1 OR i1 = i2; +DROP TABLE t1,t2; + + --echo # --echo # Bug mdev-4942: LEFT JOIN with conjunctive --echo # IS NULL in WHERE diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 6f181c39b67..cd1881e2970 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -4302,7 +4302,7 @@ Item_cond::fix_fields(THD *thd, Item **ref) used_tables_cache|= item->used_tables(); if (item->const_item()) { - if (!item->is_expensive() && !cond_is_datetime_is_null(item) && + if (!item->is_expensive() && !cond_has_datetime_is_null(item) && item->val_int() == 0) { /* @@ -4355,7 +4355,7 @@ Item_cond::eval_not_null_tables(uchar *opt_arg) table_map tmp_table_map; if (item->const_item()) { - if (!item->is_expensive() && !cond_is_datetime_is_null(item) && + if (!item->is_expensive() && !cond_has_datetime_is_null(item) && item->val_int() == 0) { /* diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 51ce9bccf6c..ba0b41fc5df 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -13526,6 +13526,28 @@ void propagate_new_equalities(THD *thd, Item *cond, } } +/* + Check if cond_is_datetime_is_null() is true for the condition cond, or + for any of its AND/OR-children +*/ +bool cond_has_datetime_is_null(Item *cond) +{ + if (cond_is_datetime_is_null(cond)) + return true; + + if (cond->type() == Item::COND_ITEM) + { + List *cond_arg_list= ((Item_cond*) cond)->argument_list(); + List_iterator li(*cond_arg_list); + Item *item; + while ((item= li++)) + { + if (cond_has_datetime_is_null(item)) + return true; + } + } + return false; +} /* Check if passed condtition has for of diff --git a/sql/sql_select.h b/sql/sql_select.h index fd12cfae335..b4709f85560 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1796,6 +1796,7 @@ bool const_expression_in_where(COND *cond, Item *comp_item, Field *comp_field= NULL, Item **const_item= NULL); bool cond_is_datetime_is_null(Item *cond); +bool cond_has_datetime_is_null(Item *cond); /* Table elimination entry point function */ void eliminate_tables(JOIN *join);