Commit 71a2047d authored by Sergey Petrunya's avatar Sergey Petrunya

Change Field_enumerator to enumerate Item_field-s not Field-s.

In Item_ref::fix_fields() do invoke mark_as_dependent() for outside 
references in all cases (see email for more details)

sql/item.cc:
  In Item_ref::fix_fields() do invoke mark_as_dependent() for outside references in all cases.
sql/item.h:
  Change Field_enumerator to enumerate Item_field-s not Field-s.
sql/item_subselect.cc:
  Change Field_enumerator to enumerate Item_field-s not Field-s.
sql/opt_table_elimination.cc:
  Change Field_enumerator to enumerate Item_field-s not Field-s.
parent 2419ef96
...@@ -1959,7 +1959,7 @@ void Item_field::reset_field(Field *f) ...@@ -1959,7 +1959,7 @@ void Item_field::reset_field(Field *f)
bool Item_field::enumerate_field_refs_processor(uchar *arg) bool Item_field::enumerate_field_refs_processor(uchar *arg)
{ {
Field_enumerator *fe= (Field_enumerator*)arg; Field_enumerator *fe= (Field_enumerator*)arg;
fe->visit_field(field); fe->visit_field(this);
return FALSE; return FALSE;
} }
...@@ -5779,6 +5779,35 @@ Item_ref::Item_ref(Name_resolution_context *context_arg, ...@@ -5779,6 +5779,35 @@ Item_ref::Item_ref(Name_resolution_context *context_arg,
set_properties(); set_properties();
} }
/*
A Field_enumerator-compatible class that invokes mark_as_dependent() for
each field that is a reference to some ancestor of current_select.
*/
class Dependency_marker: public Field_enumerator
{
public:
THD *thd;
st_select_lex *current_select;
virtual void visit_field(Item_field *item)
{
// Find which select the field is in. This is achieved by walking up
// the select tree and looking for the table of interest.
st_select_lex *sel;
for (sel= current_select; sel; sel= sel->outer_select())
{
TABLE_LIST *tbl;
for (tbl= sel->leaf_tables; tbl; tbl= tbl->next_leaf)
{
if (tbl->table == item->field->table)
{
if (sel != current_select)
mark_as_dependent(thd, sel, current_select, item, item);
return;
}
}
}
}
};
/** /**
Resolve the name of a reference to a column reference. Resolve the name of a reference to a column reference.
...@@ -6038,6 +6067,20 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) ...@@ -6038,6 +6067,20 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
last_checked_context->select_lex->nest_level); last_checked_context->select_lex->nest_level);
} }
} }
else
{
;
/*
It could be that we're referring to something that's in ancestor selects.
We must make an appropriate mark_as_dependent() call for each such
outside reference.
*/
Dependency_marker dep_marker;
dep_marker.current_select= current_sel;
dep_marker.thd= thd;
(*ref)->walk(&Item::enumerate_field_refs_processor, FALSE,
(uchar*)&dep_marker);
}
DBUG_ASSERT(*ref); DBUG_ASSERT(*ref);
/* /*
......
...@@ -1134,7 +1134,7 @@ public: ...@@ -1134,7 +1134,7 @@ public:
class Field_enumerator class Field_enumerator
{ {
public: public:
virtual void visit_field(Field *field)= 0; virtual void visit_field(Item_field *field)= 0;
virtual ~Field_enumerator() {}; /* purecov: inspected */ virtual ~Field_enumerator() {}; /* purecov: inspected */
}; };
......
...@@ -319,13 +319,13 @@ class Field_fixer: public Field_enumerator ...@@ -319,13 +319,13 @@ class Field_fixer: public Field_enumerator
public: public:
table_map used_tables; /* Collect used_tables here */ table_map used_tables; /* Collect used_tables here */
st_select_lex *new_parent; /* Select we're in */ st_select_lex *new_parent; /* Select we're in */
virtual void visit_field(Field *field) virtual void visit_field(Item_field *item)
{ {
//for (TABLE_LIST *tbl= new_parent->leaf_tables; tbl; tbl= tbl->next_local) //for (TABLE_LIST *tbl= new_parent->leaf_tables; tbl; tbl= tbl->next_local)
//{ //{
// if (tbl->table == field->table) // if (tbl->table == field->table)
// { // {
used_tables|= field->table->map; used_tables|= item->field->table->map;
// return; // return;
// } // }
//} //}
......
...@@ -922,8 +922,9 @@ public: ...@@ -922,8 +922,9 @@ public:
Field_dependency_recorder(Dep_analysis_context *ctx_arg): ctx(ctx_arg) Field_dependency_recorder(Dep_analysis_context *ctx_arg): ctx(ctx_arg)
{} {}
void visit_field(Field *field) void visit_field(Item_field *item)
{ {
Field *field= item->field;
Dep_value_table *tbl_dep; Dep_value_table *tbl_dep;
if ((tbl_dep= ctx->table_deps[field->table->tablenr])) if ((tbl_dep= ctx->table_deps[field->table->tablenr]))
{ {
......
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