diff --git a/mysql-test/r/derived_cond_pushdown.result b/mysql-test/r/derived_cond_pushdown.result index c2bc5daeb4d..813c3aab83d 100644 --- a/mysql-test/r/derived_cond_pushdown.result +++ b/mysql-test/r/derived_cond_pushdown.result @@ -8178,3 +8178,66 @@ EXPLAIN } DROP VIEW v1; DROP TABLE t1; +# +# MDEV-11608: pushdown of the predicate with cached null value +# +CREATE TABLE t1 (c VARCHAR(3)); +CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 VALUES ('foo'),('bar'); +CREATE TABLE t2 (c VARCHAR(3)); +INSERT INTO t2 VALUES ('foo'),('xyz'); +SELECT * FROM v1 WHERE v1.c IN ( SELECT MIN(c) FROM t2 WHERE 0 ); +c +EXPLAIN FORMAT=JSON +SELECT * FROM v1 WHERE v1.c IN ( SELECT MIN(c) FROM t2 WHERE 0 ); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "", + "access_type": "system", + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "table": { + "message": "Impossible WHERE" + } + } + } + }, + "table": { + "table_name": "", + "access_type": "ALL", + "rows": 2, + "filtered": 100, + "attached_condition": "v1.c = NULL", + "materialized": { + "query_block": { + "select_id": 3, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 2, + "filtered": 100, + "attached_condition": "t1.c = NULL" + } + } + } + } + } +} +DROP VIEW v1; +DROP TABLE t1,t2; +CREATE TABLE t1 (d DECIMAL(10,2)); +CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 VALUES (5.37),(1.1); +CREATE TABLE t2 (d DECIMAL(10,2)); +INSERT INTO t2 VALUES ('1.1'),('2.23'); +SELECT * FROM v1 WHERE v1.d IN ( SELECT MIN(d) FROM t2 WHERE 0 ); +d +DROP VIEW v1; +DROP TABLE t1,t2; diff --git a/mysql-test/t/derived_cond_pushdown.test b/mysql-test/t/derived_cond_pushdown.test index 68117c71db6..e43751472db 100644 --- a/mysql-test/t/derived_cond_pushdown.test +++ b/mysql-test/t/derived_cond_pushdown.test @@ -1289,3 +1289,33 @@ SELECT * FROM v1 WHERE NULLIF(1, i); DROP VIEW v1; DROP TABLE t1; + +--echo # +--echo # MDEV-11608: pushdown of the predicate with cached null value +--echo # + +CREATE TABLE t1 (c VARCHAR(3)); +CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 VALUES ('foo'),('bar'); + +CREATE TABLE t2 (c VARCHAR(3)); +INSERT INTO t2 VALUES ('foo'),('xyz'); + +SELECT * FROM v1 WHERE v1.c IN ( SELECT MIN(c) FROM t2 WHERE 0 ); +EXPLAIN FORMAT=JSON +SELECT * FROM v1 WHERE v1.c IN ( SELECT MIN(c) FROM t2 WHERE 0 ); + +DROP VIEW v1; +DROP TABLE t1,t2; + +CREATE TABLE t1 (d DECIMAL(10,2)); +CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 VALUES (5.37),(1.1); + +CREATE TABLE t2 (d DECIMAL(10,2)); +INSERT INTO t2 VALUES ('1.1'),('2.23'); + +SELECT * FROM v1 WHERE v1.d IN ( SELECT MIN(d) FROM t2 WHERE 0 ); + +DROP VIEW v1; +DROP TABLE t1,t2; diff --git a/sql/item.cc b/sql/item.cc index ead45f84305..6d9274759e4 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -9703,12 +9703,15 @@ my_decimal *Item_cache_decimal::val_decimal(my_decimal *val) Item *Item_cache_decimal::convert_to_basic_const_item(THD *thd) { Item *new_item; - my_decimal decimal_value; - my_decimal *result= val_decimal(&decimal_value); DBUG_ASSERT(value_cached || example != 0); - new_item= null_value ? - (Item*) new (thd->mem_root) Item_null(thd) : - (Item*) new (thd->mem_root) Item_decimal(thd, result); + if (null_value) + new_item= (Item*) new (thd->mem_root) Item_null(thd); + else + { + my_decimal decimal_value; + my_decimal *result= val_decimal(&decimal_value); + new_item= (Item*) new (thd->mem_root) Item_decimal(thd, result); + } return new_item; } @@ -9795,14 +9798,14 @@ bool Item_cache_row::allocate(THD *thd, uint num) Item *Item_cache_str::convert_to_basic_const_item(THD *thd) { Item *new_item; - char buff[MAX_FIELD_WIDTH]; - String tmp(buff, sizeof(buff), value->charset()); - String *result= val_str(&tmp); DBUG_ASSERT(value_cached || example != 0); if (null_value) new_item= (Item*) new (thd->mem_root) Item_null(thd); else { + char buff[MAX_FIELD_WIDTH]; + String tmp(buff, sizeof(buff), value->charset()); + String *result= val_str(&tmp); uint length= result->length(); char *tmp_str= thd->strmake(result->ptr(), length); new_item= new (thd->mem_root) Item_string(thd, tmp_str, length,