summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Babaev <igor@askmonty.org>2018-07-25 11:57:57 -0700
committerIgor Babaev <igor@askmonty.org>2018-07-25 11:58:19 -0700
commitaad70e9b4cdd719c3f7a559764e37ba7eea7bc3e (patch)
tree9335217f794275a03101aeedf668044c5599a0c6
parentde85355436e483902e0fff432348bc16f9ec1557 (diff)
downloadmariadb-git-aad70e9b4cdd719c3f7a559764e37ba7eea7bc3e.tar.gz
MDEV-16820 Lost 'Impossible where' from query with inexpensive subquery
This patch fixes another problem introduced by the patch for mdev-4817. The latter changed Item_cond::fix_fields() in such a way that it could call the virtual method is_expensive(). With the first its call the method saves the result in Item::is_expensive_cache. For all next calls the method returns the result from this cache. So if the item once was determined as expensive the method always returns true. For subqueries it's not good, because non-optimized subqueries always is considered as expensive. It means that the cache should be invalidated after the call of optimize_constant_subqueries().
-rw-r--r--mysql-test/r/subselect.result16
-rw-r--r--mysql-test/r/subselect_no_exists_to_in.result16
-rw-r--r--mysql-test/r/subselect_no_mat.result16
-rw-r--r--mysql-test/r/subselect_no_opts.result16
-rw-r--r--mysql-test/r/subselect_no_scache.result16
-rw-r--r--mysql-test/r/subselect_no_semijoin.result16
-rw-r--r--mysql-test/t/subselect.test15
-rw-r--r--sql/item.h5
-rw-r--r--sql/sql_select.cc7
9 files changed, 123 insertions, 0 deletions
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index e2ed43158f1..1c75aa66287 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -7240,6 +7240,22 @@ a
5
SET @@optimizer_switch= @optimiser_switch_save;
DROP TABLE t1, t2, t3;
+#
+# MDEV-16820: impossible where with inexpensive subquery
+#
+create table t1 (a int) engine=myisam;
+insert into t1 values (3), (1), (7);
+create table t2 (b int, index idx(b));
+insert into t2 values (2), (5), (3), (2);
+explain select * from t1 where (select max(b) from t2) = 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
+2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+explain select * from t1 where (select max(b) from t2) = 10 and t1.a > 3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
+2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+drop table t1,t2;
End of 5.5 tests
# End of 10.0 tests
#
diff --git a/mysql-test/r/subselect_no_exists_to_in.result b/mysql-test/r/subselect_no_exists_to_in.result
index 6306cfff89d..0bd14a535e0 100644
--- a/mysql-test/r/subselect_no_exists_to_in.result
+++ b/mysql-test/r/subselect_no_exists_to_in.result
@@ -7240,6 +7240,22 @@ a
5
SET @@optimizer_switch= @optimiser_switch_save;
DROP TABLE t1, t2, t3;
+#
+# MDEV-16820: impossible where with inexpensive subquery
+#
+create table t1 (a int) engine=myisam;
+insert into t1 values (3), (1), (7);
+create table t2 (b int, index idx(b));
+insert into t2 values (2), (5), (3), (2);
+explain select * from t1 where (select max(b) from t2) = 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
+2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+explain select * from t1 where (select max(b) from t2) = 10 and t1.a > 3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
+2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+drop table t1,t2;
End of 5.5 tests
# End of 10.0 tests
#
diff --git a/mysql-test/r/subselect_no_mat.result b/mysql-test/r/subselect_no_mat.result
index 0db1b031133..a3b7871bb7e 100644
--- a/mysql-test/r/subselect_no_mat.result
+++ b/mysql-test/r/subselect_no_mat.result
@@ -7233,6 +7233,22 @@ a
5
SET @@optimizer_switch= @optimiser_switch_save;
DROP TABLE t1, t2, t3;
+#
+# MDEV-16820: impossible where with inexpensive subquery
+#
+create table t1 (a int) engine=myisam;
+insert into t1 values (3), (1), (7);
+create table t2 (b int, index idx(b));
+insert into t2 values (2), (5), (3), (2);
+explain select * from t1 where (select max(b) from t2) = 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
+2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+explain select * from t1 where (select max(b) from t2) = 10 and t1.a > 3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
+2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+drop table t1,t2;
End of 5.5 tests
# End of 10.0 tests
#
diff --git a/mysql-test/r/subselect_no_opts.result b/mysql-test/r/subselect_no_opts.result
index 1fa6f385b2b..9dcc690448f 100644
--- a/mysql-test/r/subselect_no_opts.result
+++ b/mysql-test/r/subselect_no_opts.result
@@ -7231,6 +7231,22 @@ a
5
SET @@optimizer_switch= @optimiser_switch_save;
DROP TABLE t1, t2, t3;
+#
+# MDEV-16820: impossible where with inexpensive subquery
+#
+create table t1 (a int) engine=myisam;
+insert into t1 values (3), (1), (7);
+create table t2 (b int, index idx(b));
+insert into t2 values (2), (5), (3), (2);
+explain select * from t1 where (select max(b) from t2) = 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
+2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+explain select * from t1 where (select max(b) from t2) = 10 and t1.a > 3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
+2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+drop table t1,t2;
End of 5.5 tests
# End of 10.0 tests
#
diff --git a/mysql-test/r/subselect_no_scache.result b/mysql-test/r/subselect_no_scache.result
index 986542bd0bf..7b3c001f6b3 100644
--- a/mysql-test/r/subselect_no_scache.result
+++ b/mysql-test/r/subselect_no_scache.result
@@ -7246,6 +7246,22 @@ a
5
SET @@optimizer_switch= @optimiser_switch_save;
DROP TABLE t1, t2, t3;
+#
+# MDEV-16820: impossible where with inexpensive subquery
+#
+create table t1 (a int) engine=myisam;
+insert into t1 values (3), (1), (7);
+create table t2 (b int, index idx(b));
+insert into t2 values (2), (5), (3), (2);
+explain select * from t1 where (select max(b) from t2) = 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
+2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+explain select * from t1 where (select max(b) from t2) = 10 and t1.a > 3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
+2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+drop table t1,t2;
End of 5.5 tests
# End of 10.0 tests
#
diff --git a/mysql-test/r/subselect_no_semijoin.result b/mysql-test/r/subselect_no_semijoin.result
index d5fcc17f08c..a0625246e2b 100644
--- a/mysql-test/r/subselect_no_semijoin.result
+++ b/mysql-test/r/subselect_no_semijoin.result
@@ -7231,6 +7231,22 @@ a
5
SET @@optimizer_switch= @optimiser_switch_save;
DROP TABLE t1, t2, t3;
+#
+# MDEV-16820: impossible where with inexpensive subquery
+#
+create table t1 (a int) engine=myisam;
+insert into t1 values (3), (1), (7);
+create table t2 (b int, index idx(b));
+insert into t2 values (2), (5), (3), (2);
+explain select * from t1 where (select max(b) from t2) = 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
+2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+explain select * from t1 where (select max(b) from t2) = 10 and t1.a > 3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
+2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+drop table t1,t2;
End of 5.5 tests
# End of 10.0 tests
#
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 7e9e5a731bc..1048e5a5a27 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -6102,6 +6102,21 @@ and t1.a in (select `test`.`t3`.`c` from `test`.`t3`);
SET @@optimizer_switch= @optimiser_switch_save;
DROP TABLE t1, t2, t3;
+--echo #
+--echo # MDEV-16820: impossible where with inexpensive subquery
+--echo #
+
+create table t1 (a int) engine=myisam;
+insert into t1 values (3), (1), (7);
+
+create table t2 (b int, index idx(b));
+insert into t2 values (2), (5), (3), (2);
+
+explain select * from t1 where (select max(b) from t2) = 10;
+explain select * from t1 where (select max(b) from t2) = 10 and t1.a > 3;
+
+drop table t1,t2;
+
--echo End of 5.5 tests
--echo # End of 10.0 tests
diff --git a/sql/item.h b/sql/item.h
index ce07f993dc4..8fad8dadf22 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1614,6 +1614,11 @@ public:
virtual bool limit_index_condition_pushdown_processor(void *arg) { return 0; }
virtual bool exists2in_processor(void *arg) { return 0; }
virtual bool find_selective_predicates_list_processor(void *arg) { return 0; }
+ bool cleanup_is_expensive_cache_processor(void *arg)
+ {
+ is_expensive_cache= (int8)(-1);
+ return 0;
+ }
/*
TRUE if the expression depends only on the table indicated by tab_map
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 1fa21437266..4cabf5c1b40 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1335,6 +1335,13 @@ JOIN::optimize_inner()
if (optimize_constant_subqueries())
DBUG_RETURN(1);
+ if (conds && conds->has_subquery())
+ (void) conds->walk(&Item::cleanup_is_expensive_cache_processor,
+ 0, (void *) 0);
+ if (having && having->has_subquery())
+ (void) having->walk(&Item::cleanup_is_expensive_cache_processor,
+ 0, (void *) 0);
+
if (setup_jtbm_semi_joins(this, join_list, &conds))
DBUG_RETURN(1);