Commit c22d307a authored by Igor Babaev's avatar Igor Babaev

Fixed bug mdev-10785.

The condition pushed into WHERE/HAVING of a materialized
view/derived table may differ for different executions of
the same prepared statement. That's why the should be
ANDed with the existing WHERE/HAVING conditions only after all
permanent transformations of these conditions has been
performed.
parent 61d46e04
......@@ -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;
......@@ -908,3 +908,18 @@ SELECT * FROM t1 WHERE 1 IN ( SELECT * FROM v );
DROP VIEW v;
DROP TABLE t1;
--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;
......@@ -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;
sl->cond_pushed_into_where= extracted_cond_copy;
}
continue;
......@@ -1236,18 +1226,8 @@ 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;
......
......@@ -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;
......
......@@ -765,6 +765,8 @@ class st_select_lex: public st_select_lex_node
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 */
......
......@@ -1249,6 +1249,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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment