From 39afdcddd12858619b648ffaa670021356c3d0c2 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 10 Apr 2014 12:14:18 +0300 Subject: [PATCH] MDEV-5401: Wrong result (missing row) on a 2nd execution of PS with exists_to_in=on, MERGE view or a SELECT SQ The problem was that the view substitute its fields (on prepare) with reverting the change after execution. After prepare on optimization exists2in convertion substituted arguments of '=' with constsnt '1', but then one of the arguments of '=' was reverted to the view field reference.This lead to incorrect WHERE condition on the second execution. To fix the problem we replace whole '=' with '1' permannently. --- mysql-test/r/subselect_exists2in.result | 23 +++++++++++++++++++++++ mysql-test/t/subselect_exists2in.test | 25 +++++++++++++++++++++++++ sql/item_subselect.cc | 14 +++++--------- 3 files changed, 53 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/subselect_exists2in.result b/mysql-test/r/subselect_exists2in.result index efbbe08cede..1d0732060b7 100644 --- a/mysql-test/r/subselect_exists2in.result +++ b/mysql-test/r/subselect_exists2in.result @@ -862,4 +862,27 @@ i c1 c2 t1_field t2_field drop table t1,t2,t3; set optimizer_switch=default; set optimizer_switch='exists_to_in=on'; +# +#MDEV-5401: Wrong result (missing row) on a 2nd execution of PS with +#exists_to_in=on, MERGE view or a SELECT SQ +# +CREATE TABLE t1 (a INT) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1),(2); +CREATE ALGORITHM=MERGE VIEW v1 AS SELECT * FROM t1; +CREATE TABLE t2 (b INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (2),(3); +SELECT * FROM v1 WHERE EXISTS ( SELECT * FROM t2 t2x, t2 t2y WHERE t2y.b = a ); +a +2 +PREPARE stmt FROM "SELECT * FROM v1 WHERE EXISTS ( SELECT * FROM t2 t2x, t2 t2y WHERE t2y.b = a )"; +EXECUTE stmt; +a +2 +EXECUTE stmt; +a +2 +deallocate prepare stmt; +drop view v1; +drop table t1,t2; +# End of 10.0 tests set optimizer_switch=default; diff --git a/mysql-test/t/subselect_exists2in.test b/mysql-test/t/subselect_exists2in.test index 94e7109e9d2..9450ef71494 100644 --- a/mysql-test/t/subselect_exists2in.test +++ b/mysql-test/t/subselect_exists2in.test @@ -735,5 +735,30 @@ drop table t1,t2,t3; set optimizer_switch=default; set optimizer_switch='exists_to_in=on'; +--echo # +--echo #MDEV-5401: Wrong result (missing row) on a 2nd execution of PS with +--echo #exists_to_in=on, MERGE view or a SELECT SQ +--echo # +CREATE TABLE t1 (a INT) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1),(2); + +CREATE ALGORITHM=MERGE VIEW v1 AS SELECT * FROM t1; + +CREATE TABLE t2 (b INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (2),(3); + +SELECT * FROM v1 WHERE EXISTS ( SELECT * FROM t2 t2x, t2 t2y WHERE t2y.b = a ); + +PREPARE stmt FROM "SELECT * FROM v1 WHERE EXISTS ( SELECT * FROM t2 t2x, t2 t2y WHERE t2y.b = a )"; +EXECUTE stmt; +EXECUTE stmt; + +deallocate prepare stmt; + +drop view v1; +drop table t1,t2; + +--echo # End of 10.0 tests + #restore defaults set optimizer_switch=default; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 67af49c4f9f..38bb3121ed8 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -2626,7 +2626,7 @@ static bool check_equality_for_exist2in(Item_func *func, typedef struct st_eq_field_outer { - Item_func **eq_ref; + Item **eq_ref; Item_ident *local_field; Item *outer_exp; } EQ_FIELD_OUTER; @@ -2665,7 +2665,7 @@ static bool find_inner_outer_equalities(Item **conds, &element.outer_exp)) { found= TRUE; - element.eq_ref= (Item_func **)li.ref(); + element.eq_ref= li.ref(); if (result.append(element)) goto alloc_err; } @@ -2677,7 +2677,7 @@ static bool find_inner_outer_equalities(Item **conds, &element.outer_exp)) { found= TRUE; - element.eq_ref= (Item_func **)conds; + element.eq_ref= conds; if (result.append(element)) goto alloc_err; } @@ -2700,7 +2700,7 @@ bool Item_exists_subselect::exists2in_processor(uchar *opt_arg) THD *thd= (THD *)opt_arg; SELECT_LEX *first_select=unit->first_select(), *save_select; JOIN *join= first_select->join; - Item_func *eq= NULL, **eq_ref= NULL; + Item **eq_ref= NULL; Item_ident *local_field= NULL; Item *outer_exp= NULL; Item *left_exp= NULL; Item_in_subselect *in_subs; @@ -2774,7 +2774,6 @@ bool Item_exists_subselect::exists2in_processor(uchar *opt_arg) { Item *item= it++; eq_ref= eqs.at(i).eq_ref; - eq= *eq_ref; local_field= eqs.at(i).local_field; outer_exp= eqs.at(i).outer_exp; /* Add the field to the SELECT_LIST */ @@ -2789,10 +2788,7 @@ bool Item_exists_subselect::exists2in_processor(uchar *opt_arg) /* remove the parts from condition */ if (!upper_not || !local_field->maybe_null) - { - eq->arguments()[0]= new Item_int(1); - eq->arguments()[1]= new Item_int(1); - } + *eq_ref= new Item_int(1); else { *eq_ref= new Item_func_isnotnull(