summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/derived_cond_pushdown.result16
-rw-r--r--mysql-test/t/derived_cond_pushdown.test17
-rw-r--r--sql/sql_derived.cc38
-rw-r--r--sql/sql_lex.cc1
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_select.cc18
6 files changed, 59 insertions, 33 deletions
diff --git a/mysql-test/r/derived_cond_pushdown.result b/mysql-test/r/derived_cond_pushdown.result
index 9401a035d55..91c6e629821 100644
--- a/mysql-test/r/derived_cond_pushdown.result
+++ b/mysql-test/r/derived_cond_pushdown.result
@@ -7016,3 +7016,19 @@ SELECT * FROM t1 WHERE 1 IN ( SELECT * FROM v );
i
DROP VIEW v;
DROP TABLE t1;
+#
+# MDEV-10785: second execution of a query with condition
+# pushed into view
+#
+CREATE TABLE t1 (i int);
+CREATE VIEW v1 AS SELECT i FROM t1 WHERE i < 5;
+CREATE FUNCTION f (in1 int) RETURNS int RETURN in1;
+CREATE VIEW v2 AS SELECT * FROM v1 GROUP BY i;
+PREPARE stmt FROM "SELECT * FROM v2 WHERE f(0) <> 2";
+EXECUTE stmt;
+i
+EXECUTE stmt;
+i
+DROP FUNCTION f;
+DROP VIEW v2,v1;
+DROP TABLE t1;
diff --git a/mysql-test/t/derived_cond_pushdown.test b/mysql-test/t/derived_cond_pushdown.test
index cfd73bd145b..141c705aa18 100644
--- a/mysql-test/t/derived_cond_pushdown.test
+++ b/mysql-test/t/derived_cond_pushdown.test
@@ -907,4 +907,19 @@ CREATE VIEW v AS SELECT 5;
SELECT * FROM t1 WHERE 1 IN ( SELECT * FROM v );
DROP VIEW v;
DROP TABLE t1;
- \ No newline at end of file
+
+--echo #
+--echo # MDEV-10785: second execution of a query with condition
+--echo # pushed into view
+--echo #
+
+CREATE TABLE t1 (i int);
+CREATE VIEW v1 AS SELECT i FROM t1 WHERE i < 5;
+CREATE FUNCTION f (in1 int) RETURNS int RETURN in1;
+CREATE VIEW v2 AS SELECT * FROM v1 GROUP BY i;
+PREPARE stmt FROM "SELECT * FROM v2 WHERE f(0) <> 2";
+EXECUTE stmt;
+EXECUTE stmt;
+DROP FUNCTION f;
+DROP VIEW v2,v1;
+DROP TABLE t1;
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index a7435117e69..677a4c4d91a 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -1145,7 +1145,7 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
return false;
/* Do not push conditions into constant derived */
- if (derived->fill_me)
+ if (unit->executed)
return false;
/* Do not push conditions into recursive with tables */
@@ -1191,18 +1191,8 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
(uchar*) sl);
if (extracted_cond_copy)
{
- /*
- Create the conjunction of the existing where condition of sl
- and the pushed condition, take it as the new where condition of sl
- and fix this new condition
- */
- extracted_cond_copy->walk(&Item::cleanup_processor, 0, 0);
- thd->change_item_tree(&sl->join->conds,
- and_conds(thd, sl->join->conds,
- extracted_cond_copy));
-
- if (sl->join->conds->fix_fields(thd, &sl->join->conds))
- goto err;
+ extracted_cond_copy->walk(&Item::cleanup_processor, 0, 0);
+ sl->cond_pushed_into_where= extracted_cond_copy;
}
continue;
@@ -1236,19 +1226,9 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
*/
extracted_cond_copy= remove_pushed_top_conjuncts(thd, extracted_cond_copy);
- /*
- Create the conjunction of the existing where condition of sl
- and the pushed condition, take it as the new where condition of sl
- and fix this new condition
- */
cond_over_grouping_fields->walk(&Item::cleanup_processor, 0, 0);
- thd->change_item_tree(&sl->join->conds,
- and_conds(thd, sl->join->conds,
- cond_over_grouping_fields));
-
- if (sl->join->conds->fix_fields(thd, &sl->join->conds))
- goto err;
-
+ sl->cond_pushed_into_where= cond_over_grouping_fields;
+
if (!extracted_cond_copy)
continue;
}
@@ -1268,13 +1248,7 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
and fix this new condition
*/
extracted_cond_copy->walk(&Item::cleanup_processor, 0, 0);
- thd->change_item_tree(&sl->join->having,
- and_conds(thd, sl->join->having,
- extracted_cond_copy));
- sl->having_fix_field= 1;
- if (sl->join->having->fix_fields(thd, &sl->join->having))
- return true;
- sl->having_fix_field= 0;
+ sl->cond_pushed_into_having= extracted_cond_copy;
}
thd->lex->current_select= save_curr_select;
return false;
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 5c2b004a471..592de98ca0f 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -2093,6 +2093,7 @@ void st_select_lex::init_query()
item_list.empty();
join= 0;
having= prep_having= where= prep_where= 0;
+ cond_pushed_into_where= cond_pushed_into_having= 0;
olap= UNSPECIFIED_OLAP_TYPE;
having_fix_field= 0;
context.select_lex= this;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 881116192fd..e499cc794a1 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -765,6 +765,8 @@ public:
Item *where, *having; /* WHERE & HAVING clauses */
Item *prep_where; /* saved WHERE clause for prepared statement processing */
Item *prep_having;/* saved HAVING clause for prepared statement processing */
+ Item *cond_pushed_into_where; /* condition pushed into the select's WHERE */
+ Item *cond_pushed_into_having; /* condition pushed into the select's HAVING */
/* Saved values of the WHERE and HAVING clauses*/
Item::cond_result cond_value, having_value;
/* point on lex in which it was created, used in view subquery detection */
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 49bc6199d4b..aa08420931f 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1248,6 +1248,24 @@ JOIN::optimize_inner()
if (setup_jtbm_semi_joins(this, join_list, &conds))
DBUG_RETURN(1);
+
+ if (select_lex->cond_pushed_into_where)
+ {
+ conds= and_conds(thd, conds, select_lex->cond_pushed_into_where);
+ if (conds && conds->fix_fields(thd, &conds))
+ DBUG_RETURN(1);
+ }
+ if (select_lex->cond_pushed_into_having)
+ {
+ having= and_conds(thd, having, select_lex->cond_pushed_into_having);
+ if (having)
+ {
+ select_lex->having_fix_field= 1;
+ if (having->fix_fields(thd, &having))
+ DBUG_RETURN(1);
+ select_lex->having_fix_field= 0;
+ }
+ }
conds= optimize_cond(this, conds, join_list, FALSE,
&cond_value, &cond_equal, OPT_LINK_EQUAL_FIELDS);