diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 43247b56096..1bf6d6c7716 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -3033,6 +3033,19 @@ t3 CREATE TABLE `t3` ( `a` datetime default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t1,t2,t3; +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES (1), (2); +SELECT a FROM t1 WHERE (SELECT 1 FROM DUAL WHERE 1=0) > 0; +a +SELECT a FROM t1 WHERE (SELECT 1 FROM DUAL WHERE 1=0) IS NULL; +a +1 +2 +EXPLAIN SELECT a FROM t1 WHERE (SELECT 1 FROM DUAL WHERE 1=0) IS NULL; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +DROP TABLE t1; create table t1 (df decimal(5,1)); insert into t1 values(1.1); insert into t1 values(2.2); diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 0bbbc5a793e..0b658f746a4 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1988,6 +1988,18 @@ SHOW CREATE TABLE t3; DROP TABLE t1,t2,t3; +# +# Bug 24670: subquery witout tables but with a WHERE clause +# + +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES (1), (2); + +SELECT a FROM t1 WHERE (SELECT 1 FROM DUAL WHERE 1=0) > 0; +SELECT a FROM t1 WHERE (SELECT 1 FROM DUAL WHERE 1=0) IS NULL; +EXPLAIN SELECT a FROM t1 WHERE (SELECT 1 FROM DUAL WHERE 1=0) IS NULL; + +DROP TABLE t1; # End of 4.1 tests # diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index bffecb3c84c..4910fff4c4e 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -349,6 +349,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join) */ !(select_lex->item_list.head()->type() == FIELD_ITEM || select_lex->item_list.head()->type() == REF_ITEM) && + !join->conds && !join->having && /* switch off this optimization for prepare statement, because we do not rollback this changes @@ -373,8 +374,6 @@ Item_singlerow_subselect::select_transformer(JOIN *join) */ substitution->walk(&Item::remove_dependence_processor, (byte *) select_lex->outer_select()); - /* SELECT without FROM clause can't have WHERE or HAVING clause */ - DBUG_ASSERT(join->conds == 0 && join->having == 0); return RES_REDUCE; } return RES_OK; @@ -2277,6 +2276,22 @@ bool subselect_single_select_engine::no_tables() } +/* + Check statically whether the subquery can return NULL + + SINOPSYS + subselect_single_select_engine::may_be_null() + + RETURN + FALSE can guarantee that the subquery never return NULL + TRUE otherwise +*/ +bool subselect_single_select_engine::may_be_null() +{ + return ((no_tables() && !join->conds && !join->having) ? maybe_null : 1); +} + + /* Report about presence of tables in subquery diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 35ded79b75d..e9edb157f54 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -363,7 +363,7 @@ public: enum Item_result type() { return res_type; } enum_field_types field_type() { return res_field_type; } virtual void exclude()= 0; - bool may_be_null() { return maybe_null; }; + virtual bool may_be_null() { return maybe_null; }; virtual table_map upper_select_const_tables()= 0; static table_map calc_const_tables(TABLE_LIST *); virtual void print(String *str)= 0; @@ -400,6 +400,7 @@ public: void print (String *str); bool change_result(Item_subselect *si, select_subselect *result); bool no_tables(); + bool may_be_null(); bool is_executed() const { return executed; } bool no_rows(); };