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;
# (both 1st and further executions)
CREATE TABLE t1 (a INT NOT NULL) ENGINE=MyISAM;
INSERT INTO t1 VALUES (0),(8);
SELECT DISTINCT t9.* FROM t1 AS t9, 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) ) );
SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2));
a
0
PREPARE stmt FROM "
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) ) )
SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2))
";
execute stmt;
a
......
......@@ -2190,20 +2190,11 @@ drop database mysqltest4;
# (both 1st and further executions)
CREATE TABLE t1 (a INT NOT NULL) ENGINE=MyISAM;
INSERT INTO t1 VALUES (0),(8);
SELECT DISTINCT t9.* FROM t1 AS t9, 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) ) );
SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2));
a
0
PREPARE stmt FROM "
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) ) )
SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2))
";
execute stmt;
a
......
......@@ -1848,13 +1848,9 @@ drop database mysqltest4;
CREATE TABLE t1 (a INT NOT NULL) ENGINE=MyISAM;
INSERT INTO t1 VALUES (0),(8);
SELECT DISTINCT t9.* FROM t1 AS t9, 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) ) );
SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2));
PREPARE stmt FROM "
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) ) )
SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2))
";
execute stmt;
execute stmt;
......
......@@ -6754,7 +6754,7 @@ Item_ref::Item_ref(Name_resolution_context *context_arg,
/*
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();
}
......@@ -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
*/
if (ref && *ref && (*ref)->fixed)
if ((set_properties_only= (ref && *ref && (*ref)->fixed)))
set_properties();
}
......@@ -6873,7 +6873,11 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
DBUG_ASSERT(fixed == 0);
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);
if (!(ref= resolve_ref_in_select_and_group(thd, this,
......
......@@ -2946,6 +2946,7 @@ class Item_ref :public Item_ident
{
protected:
void set_properties();
bool set_properties_only; // the item doesn't need full fix_fields
public:
enum Ref_Type { REF, DIRECT_REF, VIEW_REF, OUTER_REF, AGGREGATE_REF };
Field *result_field; /* Save result here */
......@@ -2955,7 +2956,7 @@ class Item_ref :public Item_ident
const char *db_arg, const char *table_name_arg,
const char *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:
A) *item = NULL
......@@ -2978,7 +2979,7 @@ class Item_ref :public Item_ident
/* Constructor need to process subselect with temporary tables (see 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 real_type() const { return ref ? (*ref)->type() :
REF_ITEM; }
......
......@@ -2007,37 +2007,6 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join,
*where_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 ||
select_lex->group_list.elements)
{
......
......@@ -6936,6 +6936,8 @@ find_field_in_tables(THD *thd, Item_ident *item,
return found;
}
}
else
item->can_be_depended= TRUE;
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