Commit 4d5772c5 authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-7810 Wrong result on execution of a query as a PS (both 1st and further executions)

Alternative fix that doesn't cause view.test crash in --ps:
Remember when Item_ref was fixed right in the constructor
and did not have a full Item_ref::fix_fields() call. Later
in PS/SP, after Item_ref::cleanup, we use this knowledge
to avoid doing full fix_fields() for items that were never
supposed to be fix_field'ed.

Simplify the test case.
parent 2721d69f
...@@ -2150,20 +2150,11 @@ drop database mysqltest4; ...@@ -2150,20 +2150,11 @@ drop database mysqltest4;
# (both 1st and further executions) # (both 1st and further executions)
CREATE TABLE t1 (a INT NOT NULL) ENGINE=MyISAM; CREATE TABLE t1 (a INT NOT NULL) ENGINE=MyISAM;
INSERT INTO t1 VALUES (0),(8); INSERT INTO t1 VALUES (0),(8);
SELECT DISTINCT t9.* FROM t1 AS t9, t1 AS t2; SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2));
a
0
8
SELECT MIN(t3.a) FROM ( t1 AS t3 INNER JOIN t1 AS t4 ON (t3.a = t4.a));
MIN(t3.a)
0
SELECT a FROM ( SELECT DISTINCT t9.* FROM t1 AS t9, t1 AS t2 ) AS sq
WHERE a IN ( SELECT MIN(t3.a) FROM ( t1 AS t3 INNER JOIN t1 AS t4 ON (t3.a = t4.a) ) );
a a
0 0
PREPARE stmt FROM " PREPARE stmt FROM "
SELECT a FROM ( SELECT DISTINCT t9.* FROM t1 AS t9, t1 AS t2 ) AS sq SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2))
WHERE a IN ( SELECT MIN(t3.a) FROM ( t1 AS t3 INNER JOIN t1 AS t4 ON (t3.a = t4.a) ) )
"; ";
execute stmt; execute stmt;
a a
......
...@@ -2190,20 +2190,11 @@ drop database mysqltest4; ...@@ -2190,20 +2190,11 @@ drop database mysqltest4;
# (both 1st and further executions) # (both 1st and further executions)
CREATE TABLE t1 (a INT NOT NULL) ENGINE=MyISAM; CREATE TABLE t1 (a INT NOT NULL) ENGINE=MyISAM;
INSERT INTO t1 VALUES (0),(8); INSERT INTO t1 VALUES (0),(8);
SELECT DISTINCT t9.* FROM t1 AS t9, t1 AS t2; SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2));
a
0
8
SELECT MIN(t3.a) FROM ( t1 AS t3 INNER JOIN t1 AS t4 ON (t3.a = t4.a));
MIN(t3.a)
0
SELECT a FROM ( SELECT DISTINCT t9.* FROM t1 AS t9, t1 AS t2 ) AS sq
WHERE a IN ( SELECT MIN(t3.a) FROM ( t1 AS t3 INNER JOIN t1 AS t4 ON (t3.a = t4.a) ) );
a a
0 0
PREPARE stmt FROM " PREPARE stmt FROM "
SELECT a FROM ( SELECT DISTINCT t9.* FROM t1 AS t9, t1 AS t2 ) AS sq SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2))
WHERE a IN ( SELECT MIN(t3.a) FROM ( t1 AS t3 INNER JOIN t1 AS t4 ON (t3.a = t4.a) ) )
"; ";
execute stmt; execute stmt;
a a
......
...@@ -1848,13 +1848,9 @@ drop database mysqltest4; ...@@ -1848,13 +1848,9 @@ drop database mysqltest4;
CREATE TABLE t1 (a INT NOT NULL) ENGINE=MyISAM; CREATE TABLE t1 (a INT NOT NULL) ENGINE=MyISAM;
INSERT INTO t1 VALUES (0),(8); INSERT INTO t1 VALUES (0),(8);
SELECT DISTINCT t9.* FROM t1 AS t9, t1 AS t2; SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2));
SELECT MIN(t3.a) FROM ( t1 AS t3 INNER JOIN t1 AS t4 ON (t3.a = t4.a));
SELECT a FROM ( SELECT DISTINCT t9.* FROM t1 AS t9, t1 AS t2 ) AS sq
WHERE a IN ( SELECT MIN(t3.a) FROM ( t1 AS t3 INNER JOIN t1 AS t4 ON (t3.a = t4.a) ) );
PREPARE stmt FROM " PREPARE stmt FROM "
SELECT a FROM ( SELECT DISTINCT t9.* FROM t1 AS t9, t1 AS t2 ) AS sq SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2))
WHERE a IN ( SELECT MIN(t3.a) FROM ( t1 AS t3 INNER JOIN t1 AS t4 ON (t3.a = t4.a) ) )
"; ";
execute stmt; execute stmt;
execute stmt; execute stmt;
......
...@@ -6754,7 +6754,7 @@ Item_ref::Item_ref(Name_resolution_context *context_arg, ...@@ -6754,7 +6754,7 @@ Item_ref::Item_ref(Name_resolution_context *context_arg,
/* /*
This constructor used to create some internals references over fixed items This constructor used to create some internals references over fixed items
*/ */
if (ref && *ref && (*ref)->fixed) if ((set_properties_only= (ref && *ref && (*ref)->fixed)))
set_properties(); set_properties();
} }
...@@ -6798,7 +6798,7 @@ Item_ref::Item_ref(TABLE_LIST *view_arg, Item **item, ...@@ -6798,7 +6798,7 @@ Item_ref::Item_ref(TABLE_LIST *view_arg, Item **item,
/* /*
This constructor is used to create some internal references over fixed items This constructor is used to create some internal references over fixed items
*/ */
if (ref && *ref && (*ref)->fixed) if ((set_properties_only= (ref && *ref && (*ref)->fixed)))
set_properties(); set_properties();
} }
...@@ -6873,7 +6873,11 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) ...@@ -6873,7 +6873,11 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
DBUG_ASSERT(fixed == 0); DBUG_ASSERT(fixed == 0);
SELECT_LEX *current_sel= thd->lex->current_select; SELECT_LEX *current_sel= thd->lex->current_select;
if (!ref || ref == not_found_item) if (set_properties_only)
{
/* do nothing */
}
else if (!ref || ref == not_found_item)
{ {
DBUG_ASSERT(reference_trough_name != 0); DBUG_ASSERT(reference_trough_name != 0);
if (!(ref= resolve_ref_in_select_and_group(thd, this, if (!(ref= resolve_ref_in_select_and_group(thd, this,
......
...@@ -2946,6 +2946,7 @@ class Item_ref :public Item_ident ...@@ -2946,6 +2946,7 @@ class Item_ref :public Item_ident
{ {
protected: protected:
void set_properties(); void set_properties();
bool set_properties_only; // the item doesn't need full fix_fields
public: public:
enum Ref_Type { REF, DIRECT_REF, VIEW_REF, OUTER_REF, AGGREGATE_REF }; enum Ref_Type { REF, DIRECT_REF, VIEW_REF, OUTER_REF, AGGREGATE_REF };
Field *result_field; /* Save result here */ Field *result_field; /* Save result here */
...@@ -2955,7 +2956,7 @@ class Item_ref :public Item_ident ...@@ -2955,7 +2956,7 @@ class Item_ref :public Item_ident
const char *db_arg, const char *table_name_arg, const char *db_arg, const char *table_name_arg,
const char *field_name_arg) const char *field_name_arg)
:Item_ident(context_arg, db_arg, table_name_arg, field_name_arg), :Item_ident(context_arg, db_arg, table_name_arg, field_name_arg),
result_field(0), ref(0), reference_trough_name(1) {} set_properties_only(0), result_field(0), ref(0), reference_trough_name(1) {}
/* /*
This constructor is used in two scenarios: This constructor is used in two scenarios:
A) *item = NULL A) *item = NULL
...@@ -2978,7 +2979,7 @@ class Item_ref :public Item_ident ...@@ -2978,7 +2979,7 @@ class Item_ref :public Item_ident
/* Constructor need to process subselect with temporary tables (see Item) */ /* Constructor need to process subselect with temporary tables (see Item) */
Item_ref(THD *thd, Item_ref *item) Item_ref(THD *thd, Item_ref *item)
:Item_ident(thd, item), result_field(item->result_field), ref(item->ref) {} :Item_ident(thd, item), set_properties_only(0), result_field(item->result_field), ref(item->ref) {}
enum Type type() const { return REF_ITEM; } enum Type type() const { return REF_ITEM; }
enum Type real_type() const { return ref ? (*ref)->type() : enum Type real_type() const { return ref ? (*ref)->type() :
REF_ITEM; } REF_ITEM; }
......
...@@ -2007,37 +2007,6 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join, ...@@ -2007,37 +2007,6 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join,
*where_item= NULL; *where_item= NULL;
*having_item= NULL; *having_item= NULL;
/*
For PS we have to do fix_fields(expr) here to ensure that it's
evaluated in the outer context. If not, then fix_having() will do
a fix_fields(expr) in the inner context and mark expr as
'depended', which will cause update_ref_and_keys() to find wrong
keys.
When not running PS, fix_fields(expr) as already been done earlier and
the following test does nothing.
*/
if (expr && !expr->fixed)
{
bool tmp;
SELECT_LEX *save_current_select= thd->lex->current_select;
Item_subselect *save_item;
thd->lex->current_select= thd->lex->current_select->outer_select();
/*
For st_select_lex::mark_as_dependent, who needs to mark
this sub query as correlated.
*/
save_item= thd->lex->current_select->master_unit()->item;
thd->lex->current_select->master_unit()->item= this;
tmp= expr->fix_fields(thd, 0);
thd->lex->current_select->master_unit()->item= save_item;
thd->lex->current_select= save_current_select;
if (tmp)
DBUG_RETURN(true);
}
if (join_having || select_lex->with_sum_func || if (join_having || select_lex->with_sum_func ||
select_lex->group_list.elements) select_lex->group_list.elements)
{ {
......
...@@ -6936,6 +6936,8 @@ find_field_in_tables(THD *thd, Item_ident *item, ...@@ -6936,6 +6936,8 @@ find_field_in_tables(THD *thd, Item_ident *item,
return found; return found;
} }
} }
else
item->can_be_depended= TRUE;
if (db && lower_case_table_names) if (db && lower_case_table_names)
{ {
......
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