maria-developers team mailing list archive
-
maria-developers team
-
Mailing list archive
-
Message #00505
Rev 2818: BUG#31480: Incorrect result for nested subquery when executed via semi join in file:///home/psergey/dev/mysql-next-fix-subq/
At file:///home/psergey/dev/mysql-next-fix-subq/
------------------------------------------------------------
revno: 2818
revision-id: psergey@xxxxxxxxxxxx-20090708095341-9i08n2r8igulpxzz
parent: psergey@xxxxxxxxxxxx-20090706143329-72s3e73rov2f5tml
committer: Sergey Petrunya <psergey@xxxxxxxxxxxx>
branch nick: mysql-next-fix-subq
timestamp: Wed 2009-07-08 13:53:41 +0400
message:
BUG#31480: Incorrect result for nested subquery when executed via semi join
Make the fix work with prepared statements:
- collect/save ancestor_used_tables and furthest_correlated_ancestor only at
PREPARE phase (at execute() we are unable to tell what table_map the outer
reference would tell. since it would be the same anyway, we save it at
PREPARE phase)
=== modified file 'sql/item_subselect.cc'
--- a/sql/item_subselect.cc 2009-07-06 14:26:03 +0000
+++ b/sql/item_subselect.cc 2009-07-08 09:53:41 +0000
@@ -39,8 +39,8 @@
Item_subselect::Item_subselect():
Item_result_field(), value_assigned(0), thd(0), substitution(0),
engine(0), old_engine(0), used_tables_cache(0), have_to_be_excluded(0),
- const_item_cache(1), inside_fix_fields(0), engine_changed(0), changed(0),
- is_correlated(FALSE)
+ const_item_cache(1), inside_first_fix_fields(0), ancestor_used_tables(0),
+ engine_changed(0), changed(0), is_correlated(FALSE)
{
with_subselect= 1;
reset();
@@ -158,6 +158,7 @@
DBUG_RETURN(RES_OK);
}
+
void Item_subselect::set_depth()
{
uint n= 0;
@@ -166,6 +167,7 @@
this->depth= n - 1;
}
+
bool Item_subselect::fix_fields(THD *thd_param, Item **ref)
{
char const *save_where= thd_param->where;
@@ -175,23 +177,25 @@
DBUG_ASSERT(fixed == 0);
engine->set_thd((thd= thd_param));
- if (!inside_fix_fields)
+ if (!ancestor_used_tables)
{
set_depth();
- if (!(ancestor_used_tables= (table_map*)thd->calloc((1+depth) *
- sizeof(table_map))))
+ if (!(ancestor_used_tables=
+ (table_map*)alloc_root(thd->stmt_arena->mem_root,
+ (1+depth)*sizeof(table_map))))
return TRUE;
furthest_correlated_ancestor= 0;
+ inside_first_fix_fields= TRUE;
}
if (check_stack_overrun(thd, STACK_MIN_SIZE, (uchar*)&res))
return TRUE;
- inside_fix_fields++;
res= engine->prepare();
-
+
// all transformation is done (used by prepared statements)
changed= 1;
+ inside_first_fix_fields= FALSE;
if (!res)
{
@@ -220,14 +224,12 @@
if (!(*ref)->fixed)
ret= (*ref)->fix_fields(thd, ref);
thd->where= save_where;
- inside_fix_fields--;
return ret;
}
// Is it one field subselect?
if (engine->cols() > max_columns)
{
my_error(ER_OPERAND_COLUMNS, MYF(0), 1);
- inside_fix_fields--;
return TRUE;
}
fix_length_and_dec();
@@ -244,12 +246,23 @@
fixed= 1;
err:
- inside_fix_fields--;
thd->where= save_where;
return res;
}
+void Item_subselect::mark_as_dependent(uint n_levels, table_map dep_map)
+{
+ if (inside_first_fix_fields)
+ {
+ is_correlated= TRUE;
+ furthest_correlated_ancestor= max(furthest_correlated_ancestor, n_levels);
+ if (n_levels > 1)
+ ancestor_used_tables[n_levels - 2]= dep_map;
+ }
+}
+
+
/*
Adjust attributes after our parent select has been merged into grandparent
=== modified file 'sql/item_subselect.h'
--- a/sql/item_subselect.h 2009-07-06 07:57:39 +0000
+++ b/sql/item_subselect.h 2009-07-08 09:53:41 +0000
@@ -68,7 +68,7 @@
/* cache of constant state */
bool const_item_cache;
- int inside_fix_fields;
+ int inside_first_fix_fields;
public:
/*
Depth of the subquery predicate.
@@ -140,6 +140,7 @@
return null_value;
}
bool fix_fields(THD *thd, Item **ref);
+ void mark_as_dependent(uint n_levels, table_map dep_map);
void fix_after_pullout(st_select_lex *new_parent, uint parent_tables,
Item **ref);
virtual bool exec();
=== modified file 'sql/sql_lex.cc'
--- a/sql/sql_lex.cc 2009-07-06 07:57:39 +0000
+++ b/sql/sql_lex.cc 2009-07-08 09:53:41 +0000
@@ -1929,13 +1929,7 @@
}
Item_subselect *subquery_predicate= s->master_unit()->item;
if (subquery_predicate)
- {
- subquery_predicate->is_correlated= TRUE;
- subquery_predicate->furthest_correlated_ancestor=
- max(subquery_predicate->furthest_correlated_ancestor, n_levels);
- if (n_levels > 1)
- subquery_predicate->ancestor_used_tables[n_levels - 2]= dep_map;
- }
+ subquery_predicate->mark_as_dependent(n_levels, dep_map);
n_levels--;
}
}