summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/item.cc71
-rw-r--r--sql/item.h41
-rw-r--r--sql/item_cmpfunc.cc33
-rw-r--r--sql/item_cmpfunc.h1
-rw-r--r--sql/item_subselect.cc17
-rw-r--r--sql/item_subselect.h10
-rw-r--r--sql/item_sum.cc11
-rw-r--r--sql/item_sum.h1
-rw-r--r--sql/opt_range.cc10
-rw-r--r--sql/sql_base.cc5
-rw-r--r--sql/sql_class.h16
-rw-r--r--sql/sql_expression_cache.cc61
-rw-r--r--sql/sql_expression_cache.h20
-rw-r--r--sql/sql_lex.cc53
-rw-r--r--sql/sql_lex.h1
-rw-r--r--sql/sql_list.h13
-rw-r--r--sql/sql_select.cc8
-rw-r--r--sql/sql_select.h2
18 files changed, 200 insertions, 174 deletions
diff --git a/sql/item.cc b/sql/item.cc
index ca49cf20cd9..ca4d41fcbdb 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -31,6 +31,16 @@ const String my_null_string("NULL", 4, default_charset_info);
static int save_field_in_field(Field *from, bool *null_value,
Field *to, bool no_conversions);
+
+/**
+ Compare two Items for List<Item>::add_unique()
+*/
+
+bool cmp_items(Item *a, Item *b)
+{
+ return a->eq(b, FALSE);
+}
+
/****************************************************************************/
/* Hybrid_type_traits {_real} */
@@ -651,14 +661,14 @@ Item* Item::transform(Item_transformer transformer, uchar *arg)
A pointer to created wrapper item if successful, NULL - otherwise
*/
-Item* Item::set_expr_cache(THD *thd, List<Item *> &depends_on)
+Item* Item::set_expr_cache(THD *thd)
{
DBUG_ENTER("Item::set_expr_cache");
Item_cache_wrapper *wrapper;
if ((wrapper= new Item_cache_wrapper(this)) &&
!wrapper->fix_fields(thd, (Item**)&wrapper))
{
- if (wrapper->set_cache(thd, depends_on))
+ if (wrapper->set_cache(thd))
DBUG_RETURN(NULL);
DBUG_RETURN(wrapper);
}
@@ -742,6 +752,15 @@ bool Item_ident::remove_dependence_processor(uchar * arg)
}
+bool Item_ident::collect_outer_ref_processor(uchar *param)
+{
+ Collect_deps_prm *prm= (Collect_deps_prm *)param;
+ if (depended_from && depended_from->nest_level < prm->nest_level)
+ prm->parameters->add_unique(this, &cmp_items);
+ return FALSE;
+}
+
+
/**
Store the pointer to this item field into a list if not already there.
@@ -4357,9 +4376,6 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
((ref_type == REF_ITEM || ref_type == FIELD_ITEM) ?
(Item_ident*) (*reference) :
0));
- context->select_lex->
- register_dependency_item(last_checked_context->select_lex,
- reference);
/*
A reference to a view field had been found and we
substituted it instead of this Item (find_field_in_tables
@@ -4460,9 +4476,6 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
mark_as_dependent(thd, last_checked_context->select_lex,
context->select_lex, rf,
rf);
- context->select_lex->
- register_dependency_item(last_checked_context->select_lex,
- reference);
return 0;
}
@@ -4471,9 +4484,6 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
mark_as_dependent(thd, last_checked_context->select_lex,
context->select_lex,
this, (Item_ident*)*reference);
- context->select_lex->
- register_dependency_item(last_checked_context->select_lex,
- reference);
if (last_checked_context->select_lex->having_fix_field)
{
Item_ref *rf;
@@ -6304,9 +6314,6 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
refer_type == FIELD_ITEM) ?
(Item_ident*) (*reference) :
0));
- context->select_lex->
- register_dependency_item(last_checked_context->select_lex,
- reference);
/*
view reference found, we substituted it instead of this
Item, so can quit
@@ -6357,9 +6364,6 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
thd->change_item_tree(reference, fld);
mark_as_dependent(thd, last_checked_context->select_lex,
thd->lex->current_select, fld, fld);
- context->select_lex->
- register_dependency_item(last_checked_context->select_lex,
- reference);
/*
A reference is resolved to a nest level that's outer or the same as
the nest level of the enclosing set function : adjust the value of
@@ -6383,9 +6387,6 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
DBUG_ASSERT(*ref && (*ref)->fixed);
mark_as_dependent(thd, last_checked_context->select_lex,
context->select_lex, this, this);
- context->select_lex->
- register_dependency_item(last_checked_context->select_lex,
- reference);
/*
A reference is resolved to a nest level that's outer or the same as
the nest level of the enclosing set function : adjust the value of
@@ -6400,12 +6401,6 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
}
else if (ref_type() != VIEW_REF)
{
- if (depended_from && reference)
- {
- DBUG_ASSERT(context->select_lex != get_depended_from());
- context->select_lex->register_dependency_item(get_depended_from(),
- reference);
- }
/*
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
@@ -6914,6 +6909,7 @@ Item_cache_wrapper::Item_cache_wrapper(Item *item_arg)
unsigned_flag= orig_item->unsigned_flag;
name= item_arg->name;
name_length= item_arg->name_length;
+ with_subselect= orig_item->with_subselect;
if ((expr_value= Item_cache::get_cache(orig_item)))
expr_value->setup(orig_item);
@@ -6922,11 +6918,28 @@ Item_cache_wrapper::Item_cache_wrapper(Item *item_arg)
}
+/**
+ Initialize the cache if it is needed
+*/
+
+void Item_cache_wrapper::init_on_demand()
+{
+ if (!expr_cache->is_inited())
+ {
+ orig_item->get_cache_parameters(parameters);
+ expr_cache->init();
+ }
+}
+
+
void Item_cache_wrapper::print(String *str, enum_query_type query_type)
{
str->append(func_name());
if (expr_cache)
+ {
+ init_on_demand();
expr_cache->print(str, query_type);
+ }
else
str->append(STRING_WITH_LEN("<<DISABLED>>"));
str->append('(');
@@ -6962,6 +6975,7 @@ void Item_cache_wrapper::cleanup()
expr_cache= 0;
/* expr_value is Item so it will be destroyed from list of Items */
expr_value= 0;
+ parameters.empty();
DBUG_VOID_RETURN;
}
@@ -6982,11 +6996,11 @@ void Item_cache_wrapper::cleanup()
@retval TRUE Error
*/
-bool Item_cache_wrapper::set_cache(THD *thd, List<Item*> &depends_on)
+bool Item_cache_wrapper::set_cache(THD *thd)
{
DBUG_ENTER("Item_cache_wrapper::set_cache");
DBUG_ASSERT(expr_cache == 0);
- expr_cache= new Expression_cache_tmptable(thd, depends_on, expr_value);
+ expr_cache= new Expression_cache_tmptable(thd, parameters, expr_value);
DBUG_RETURN(expr_cache == NULL);
}
@@ -7011,6 +7025,7 @@ Item *Item_cache_wrapper::check_cache()
{
Expression_cache_tmptable::result res;
Item *cached_value;
+ init_on_demand();
res= expr_cache->check_value(&cached_value);
if (res == Expression_cache_tmptable::HIT)
DBUG_RETURN(cached_value);
diff --git a/sql/item.h b/sql/item.h
index de819dae8ee..f2e7a2587da 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1155,6 +1155,15 @@ public:
{
return FALSE;
}
+ struct Collect_deps_prm
+ {
+ int nest_level;
+ List<Item> *parameters;
+ };
+ /**
+ Collect outer references
+ */
+ virtual bool collect_outer_ref_processor(uchar *arg) {return FALSE; }
/**
Find a function of a given type
@@ -1249,7 +1258,7 @@ public:
{ return Field::GEOM_GEOMETRY; };
String *check_well_formed_result(String *str, bool send_error= 0);
bool eq_by_collation(Item *item, bool binary_cmp, CHARSET_INFO *cs);
- Item* set_expr_cache(THD *thd, List<Item*> &depends_on);
+ Item* set_expr_cache(THD *thd);
virtual Item *get_cached_item() { return NULL; }
virtual Item_equal *get_item_equal() { return NULL; }
@@ -1273,9 +1282,25 @@ public:
walk(&Item::view_used_tables_processor, 0, (uchar *) view);
return view->view_used_tables;
}
+
+ /**
+ Collect and add to the list cache parameters for this Item.
+
+ @note Now implemented only for subqueries and in_optimizer,
+ if we need it for general function then this method should
+ be defined for Item_func.
+ */
+ virtual void get_cache_parameters(List<Item> &parameters) { };
};
+/**
+ Compare two Items for List<Item>::add_unique()
+*/
+
+bool cmp_items(Item *a, Item *b);
+
+
/*
Class to be used to enumerate all field references in an item tree. This
includes references to outside but not fields of the tables within a
@@ -1677,6 +1702,10 @@ public:
virtual void print(String *str, enum_query_type query_type);
virtual bool change_context_processor(uchar *cntx)
{ context= (Name_resolution_context *)cntx; return FALSE; }
+ /**
+ Collect outer references
+ */
+ virtual bool collect_outer_ref_processor(uchar *arg);
friend bool insert_fields(THD *thd, Name_resolution_context *context,
const char *db_name,
const char *table_name, List_iterator<Item> *it,
@@ -2739,8 +2768,11 @@ private:
*/
Item_cache *expr_value;
+ List<Item> parameters;
+
Item *check_cache();
- inline void cache();
+ void cache();
+ void init_on_demand();
public:
Item_cache_wrapper(Item *item_arg);
@@ -2750,7 +2782,7 @@ public:
enum Type type() const { return EXPR_CACHE_ITEM; }
enum Type real_type() const { return orig_item->type(); }
- bool set_cache(THD *thd, List<Item*> &depends_on);
+ bool set_cache(THD *thd);
bool fix_fields(THD *thd, Item **it);
void fix_length_and_dec() {}
@@ -2832,6 +2864,9 @@ public:
if (result_type() == ROW_RESULT)
orig_item->bring_value();
}
+ virtual bool is_expensive() { return orig_item->is_expensive(); }
+ bool is_expensive_processor(uchar *arg)
+ { return orig_item->is_expensive_processor(arg); }
bool check_vcol_func_processor(uchar *arg)
{
return trace_unsupported_by_check_vcol_func_processor("cache");
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 74a63337e49..aff2b3d8825 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1464,32 +1464,41 @@ Item *Item_in_optimizer::expr_cache_insert_transformer(uchar *thd_arg)
DBUG_ENTER("Item_in_optimizer::expr_cache_insert_transformer");
if (args[1]->type() != Item::SUBSELECT_ITEM)
DBUG_RETURN(this); // MAX/MIN transformed => do nothing
- List<Item*> &depends_on= ((Item_subselect *)args[1])->depends_on;
if (expr_cache)
DBUG_RETURN(expr_cache);
+ if (args[1]->expr_cache_is_needed(thd) &&
+ (expr_cache= set_expr_cache(thd)))
+ DBUG_RETURN(expr_cache);
+
+ DBUG_RETURN(this);
+}
+
+
+
+/**
+ Collect and add to the list cache parameters for this Item.
+
+ @param parameters The list where to add parameters
+*/
+
+void Item_in_optimizer::get_cache_parameters(List<Item> &parameters)
+{
/* Add left expression to the list of the parameters of the subquery */
if (args[0]->cols() == 1)
- depends_on.push_front((Item**)args);
+ parameters.add_unique(args[0], &cmp_items);
else
{
for (uint i= 0; i < args[0]->cols(); i++)
{
- depends_on.push_front(args[0]->addr(i));
+ parameters.add_unique(args[0]->element_index(i), &cmp_items);
}
}
-
- if (args[1]->expr_cache_is_needed(thd) &&
- (expr_cache= set_expr_cache(thd, depends_on)))
- DBUG_RETURN(expr_cache);
-
- /* no cache => return list in original state just to be safe */
- for (uint i= 0; i < args[0]->cols(); i++)
- depends_on.pop();
- DBUG_RETURN(this);
+ args[1]->get_cache_parameters(parameters);
}
+
/*
The implementation of optimized \<outer expression\> [NOT] IN \<subquery\>
predicates. The implementation works as follows.
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 4a0cf62dfa3..63d38c8e53e 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -259,6 +259,7 @@ public:
bool is_expensive();
void set_join_tab_idx(uint join_tab_idx_arg)
{ args[1]->set_join_tab_idx(join_tab_idx_arg); }
+ virtual void get_cache_parameters(List<Item> &parameters);
};
class Comp_creator
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 94172678974..6f05285fa4b 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -128,7 +128,6 @@ void Item_subselect::cleanup()
}
if (engine)
engine->cleanup();
- depends_on.empty();
reset();
value_assigned= 0;
expr_cache= 0;
@@ -583,6 +582,12 @@ bool Item_subselect::exec()
}
+void Item_subselect::get_cache_parameters(List<Item> &parameters)
+{
+ Collect_deps_prm prm= { unit->first_select()->nest_level, &parameters };
+ walk(&Item::collect_outer_ref_processor, TRUE, (uchar*)&prm);
+}
+
int Item_in_subselect::optimize(double *out_rows, double *cost)
{
int res;
@@ -647,7 +652,7 @@ int Item_in_subselect::optimize(double *out_rows, double *cost)
bool Item_subselect::expr_cache_is_needed(THD *thd)
{
- return (depends_on.elements &&
+ return ((engine->uncacheable() & UNCACHEABLE_DEPENDENT) &&
engine->cols() == 1 &&
optimizer_flag(thd, OPTIMIZER_SWITCH_SUBQUERY_CACHE) &&
!(engine->uncacheable() & (UNCACHEABLE_RAND |
@@ -675,8 +680,7 @@ bool Item_subselect::expr_cache_is_needed(THD *thd)
bool Item_in_subselect::expr_cache_is_needed(THD *thd)
{
- return (depends_on.elements &&
- optimizer_flag(thd, OPTIMIZER_SWITCH_SUBQUERY_CACHE) &&
+ return (optimizer_flag(thd, OPTIMIZER_SWITCH_SUBQUERY_CACHE) &&
!(engine->uncacheable() & (UNCACHEABLE_RAND |
UNCACHEABLE_SIDEEFFECT)));
}
@@ -1009,7 +1013,7 @@ Item* Item_singlerow_subselect::expr_cache_insert_transformer(uchar *thd_arg)
DBUG_RETURN(expr_cache);
if (expr_cache_is_needed(thd) &&
- (expr_cache= set_expr_cache(thd, depends_on)))
+ (expr_cache= set_expr_cache(thd)))
DBUG_RETURN(expr_cache);
DBUG_RETURN(this);
}
@@ -1270,7 +1274,7 @@ Item* Item_exists_subselect::expr_cache_insert_transformer(uchar *thd_arg)
DBUG_RETURN(expr_cache);
if (substype() == EXISTS_SUBS && expr_cache_is_needed(thd) &&
- (expr_cache= set_expr_cache(thd, depends_on)))
+ (expr_cache= set_expr_cache(thd)))
DBUG_RETURN(expr_cache);
DBUG_RETURN(this);
}
@@ -5725,3 +5729,4 @@ end:
void subselect_table_scan_engine::cleanup()
{
}
+
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index 5eb24bd311e..2c1e3bddb2d 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -102,14 +102,6 @@ public:
List<Ref_to_outside> upper_refs;
st_select_lex *parent_select;
- /**
- List of references on items subquery depends on (externally resolved);
-
- @note We can't store direct links on Items because it could be
- substituted with other item (for example for grouping).
- */
- List<Item*> depends_on;
-
/*
TRUE<=>Table Elimination has made it redundant to evaluate this select
(and so it is not part of QEP, etc)
@@ -225,6 +217,7 @@ public:
@retval FALSE otherwise
*/
bool is_expensive_processor(uchar *arg) { return TRUE; }
+
/**
Get the SELECT_LEX structure associated with this Item.
@return the SELECT_LEX structure associated with this Item
@@ -232,6 +225,7 @@ public:
st_select_lex* get_select_lex();
const char *func_name() const { DBUG_ASSERT(0); return "subselect"; }
virtual bool expr_cache_is_needed(THD *);
+ virtual void get_cache_parameters(List<Item> &parameters);
friend class select_result_interceptor;
friend class Item_in_optimizer;
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index bc4ab876b55..65314a0ff91 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -319,7 +319,6 @@ bool Item_sum::register_sum_func(THD *thd, Item **ref)
if (aggr_level >= 0)
{
ref_by= ref;
- thd->lex->current_select->register_dependency_item(aggr_sel, ref);
/* Add the object to the list of registered objects assigned to aggr_sel */
if (!aggr_sel->inner_sum_func_list)
next= this;
@@ -356,6 +355,16 @@ bool Item_sum::register_sum_func(THD *thd, Item **ref)
}
+bool Item_sum::collect_outer_ref_processor(uchar *param)
+{
+ Collect_deps_prm *prm= (Collect_deps_prm *)param;
+ SELECT_LEX *ds;
+ if ((ds= depended_from()) && ds->nest_level < prm->nest_level)
+ prm->parameters->add_unique(this, &cmp_items);
+ return FALSE;
+}
+
+
Item_sum::Item_sum(List<Item> &list) :arg_count(list.elements),
forced_const(FALSE)
{
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 851b77ddeae..7b6bdbabf7f 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -374,6 +374,7 @@ public:
virtual Field *create_tmp_field(bool group, TABLE *table,
uint convert_blob_length);
bool walk(Item_processor processor, bool walk_subquery, uchar *argument);
+ virtual bool collect_outer_ref_processor(uchar *param);
bool init_sum_func_check(THD *thd);
bool check_sum_func(THD *thd, Item **ref);
bool register_sum_func(THD *thd, Item **ref);
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 88cd2a5e4cd..99c7430198f 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -11731,17 +11731,19 @@ check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item,
Disallow loose index scan if the MIN/MAX argument field is referenced by
a subquery in the WHERE clause.
*/
+
if (cond_type == Item::SUBSELECT_ITEM)
{
Item_subselect *subs_cond= (Item_subselect*) cond;
if (subs_cond->is_correlated)
{
- DBUG_ASSERT(subs_cond->depends_on.elements > 0);
- List_iterator_fast<Item*> li(subs_cond->depends_on);
- Item **dep;
+ DBUG_ASSERT(subs_cond->upper_refs.elements > 0);
+ List_iterator_fast<Item_subselect::Ref_to_outside>
+ li(subs_cond->upper_refs);
+ Item_subselect::Ref_to_outside *dep;
while ((dep= li++))
{
- if ((*dep)->eq(min_max_arg_item, FALSE))
+ if (dep->item->eq(min_max_arg_item, FALSE))
DBUG_RETURN(FALSE);
}
}
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 7cf607b28d9..5f5f8125c79 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -6454,11 +6454,6 @@ find_field_in_tables(THD *thd, Item_ident *item,
{
mark_select_range_as_dependent(thd, last_select, current_sel,
found, *ref, item);
- if (item->can_be_depended)
- {
- DBUG_ASSERT((*ref) == (Item*)item);
- current_sel->register_dependency_item(last_select, ref);
- }
}
}
return found;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index d5a6f25b3cd..c97cc34e166 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -74,6 +74,22 @@ public:
/**
+ Item iterator over List_iterator_fast for Items
+*/
+
+class Item_iterator_list: public Item_iterator
+{
+ List_iterator<Item> list;
+public:
+ Item_iterator_list(List_iterator<Item> &arg_list):
+ list(arg_list) {}
+ void open() { list.rewind(); }
+ Item *next() { return (list++); }
+ void close() {}
+};
+
+
+/**
Item iterator over Item interface for rows
*/
diff --git a/sql/sql_expression_cache.cc b/sql/sql_expression_cache.cc
index d79dca03e42..6b7a51bfa1c 100644
--- a/sql/sql_expression_cache.cc
+++ b/sql/sql_expression_cache.cc
@@ -23,9 +23,9 @@
ulong subquery_cache_miss, subquery_cache_hit;
Expression_cache_tmptable::Expression_cache_tmptable(THD *thd,
- List<Item*> &dependants,
- Item *value)
- :cache_table(NULL), table_thd(thd), list(&dependants), val(value),
+ List<Item> &dependants,
+ Item *value)
+ :cache_table(NULL), table_thd(thd), items(dependants), val(value),
inited (0)
{
DBUG_ENTER("Expression_cache_tmptable::Expression_cache_tmptable");
@@ -60,50 +60,32 @@ static uint field_enumerator(uchar *arg)
void Expression_cache_tmptable::init()
{
- List_iterator<Item*> li(*list);
- Item_iterator_ref_list it(li);
- Item **item;
+ List_iterator<Item> li(items);
+ Item_iterator_list it(li);
uint field_counter;
DBUG_ENTER("Expression_cache_tmptable::init");
DBUG_ASSERT(!inited);
inited= TRUE;
cache_table= NULL;
- while ((item= li++))
- {
- DBUG_ASSERT(item);
- if (*item)
- {
- DBUG_ASSERT((*item)->fixed);
- items.push_back((*item));
- }
- else
- {
- /*
- This is possible when optimizer already executed this subquery and
- optimized out the condition predicate.
- */
- li.remove();
- }
- }
-
- if (list->elements == 0)
+ if (items.elements == 0)
{
DBUG_PRINT("info", ("All parameters were removed by optimizer."));
DBUG_VOID_RETURN;
}
+ /* add result field */
+ items.push_front(val);
+
cache_table_param.init();
/* dependent items and result */
- cache_table_param.field_count= list->elements + 1;
+ cache_table_param.field_count= items.elements;
/* postpone table creation to index description */
cache_table_param.skip_create_table= 1;
- items.push_front(val);
-
if (!(cache_table= create_tmp_table(table_thd, &cache_table_param,
items, (ORDER*) NULL,
- FALSE, FALSE,
+ FALSE, TRUE,
((table_thd->options |
TMP_TABLE_ALL_COLUMNS) &
~(OPTION_BIG_TABLES |
@@ -122,16 +104,13 @@ void Expression_cache_tmptable::init()
goto error;
}
- /* This list do not contain result field */
- it.open();
-
- field_counter=1;
+ field_counter= 1;
if (cache_table->alloc_keys(1) ||
cache_table->add_tmp_key(0, items.elements - 1, &field_enumerator,
(uchar*)&field_counter, TRUE) ||
ref.tmp_table_index_lookup_init(table_thd, cache_table->key_info, it,
- TRUE))
+ TRUE, 1 /* skip result field*/))
{
DBUG_PRINT("error", ("creating index failed"));
goto error;
@@ -192,13 +171,6 @@ Expression_cache::result Expression_cache_tmptable::check_value(Item **value)
int res;
DBUG_ENTER("Expression_cache_tmptable::check_value");
- /*
- We defer cache initialization to get item references that are
- used at the execution phase.
- */
- if (!inited)
- init();
-
if (cache_table)
{
DBUG_PRINT("info", ("status: %u has_record %u",
@@ -274,16 +246,17 @@ err:
void Expression_cache_tmptable::print(String *str, enum_query_type query_type)
{
- List_iterator<Item*> li(*list);
- Item **item;
+ List_iterator<Item> li(items);
+ Item *item;
bool is_first= TRUE;
str->append('<');
+ li++; // skip result field
while ((item= li++))
{
if (!is_first)
str->append(',');
- (*item)->print(str, query_type);
+ item->print(str, query_type);
is_first= FALSE;
}
str->append('>');
diff --git a/sql/sql_expression_cache.h b/sql/sql_expression_cache.h
index 88f71e0cf32..f1d141abbd1 100644
--- a/sql/sql_expression_cache.h
+++ b/sql/sql_expression_cache.h
@@ -37,6 +37,15 @@ public:
Print cache parameters
*/
virtual void print(String *str, enum_query_type query_type)= 0;
+
+ /**
+ Is this cache initialized
+ */
+ virtual bool is_inited()= 0;
+ /**
+ Initialize this cache
+ */
+ virtual void init()= 0;
};
struct st_table_ref;
@@ -51,15 +60,16 @@ class Item_field;
class Expression_cache_tmptable :public Expression_cache
{
public:
- Expression_cache_tmptable(THD *thd, List<Item*> &dependants, Item *value);
+ Expression_cache_tmptable(THD *thd, List<Item> &dependants, Item *value);
virtual ~Expression_cache_tmptable();
virtual result check_value(Item **value);
virtual my_bool put_value(Item *value);
void print(String *str, enum_query_type query_type);
+ bool is_inited() { return inited; };
+ void init();
private:
- void init();
/* tmp table parameters */
TMP_TABLE_PARAM cache_table_param;
@@ -71,10 +81,8 @@ private:
struct st_table_ref ref;
/* Cached result */
Item_field *cached_result;
- /* List of references to the parameters of the expression */
- List<Item*> *list;
- /* List of items */
- List<Item> items;
+ /* List of parameter items */
+ List<Item> &items;
/* Value Item example */
Item *val;
/* Set on if the object has been succesfully initialized with init() */
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index f540c39ef91..021e7a3b5e8 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1879,59 +1879,6 @@ void st_select_lex_unit::exclude_tree()
}
-/**
- Register reference to an item which the subqueries depends on
-
- @param def_sel select against which the item is resolved
- @param dependency reference to the item
-
- @details
- This function puts the reference dependency to an item that is either an
- outer field or an aggregate function resolved against an outer select into
- the list 'depends_on'. It adds it to the 'depends_on' lists for each
- subquery between this one and 'def_sel' - the subquery against which the
- item is resolved.
-*/
-
-void st_select_lex::register_dependency_item(st_select_lex *def_sel,
- Item **dependency)
-{
- SELECT_LEX *s= this;
- DBUG_ENTER("st_select_lex::register_dependency_item");
- DBUG_ASSERT(this != def_sel);
- DBUG_ASSERT(*dependency);
- //psergey-add-stupid:
- while (def_sel->merged_into)
- def_sel= def_sel->merged_into;
- //:eof
- do
- {
- /* check duplicates */
- List_iterator_fast<Item*> li(s->master_unit()->item->depends_on);
- Item **dep;
- while ((dep= li++))
- {
- if ((*dep)->eq(*dependency, FALSE))
- {
- DBUG_PRINT("info", ("dependency %s already present",
- ((*dependency)->name ?
- (*dependency)->name :
- "<no name>")));
- DBUG_VOID_RETURN;
- }
- }
-
- s->master_unit()->item->depends_on.push_back(dependency);
- DBUG_PRINT("info", ("depends_on: Select: %d added: %s",
- s->select_number,
- ((*dependency)->name ?
- (*dependency)->name :
- "<no name>")));
- } while ((s= s->outer_select()) != def_sel);
- DBUG_VOID_RETURN;
-}
-
-
/*
st_select_lex_node::mark_as_dependent mark all st_select_lex struct from
this to 'last' as dependent
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 14ab445a366..fe79e6e2908 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -793,7 +793,6 @@ public:
inline bool is_subquery_function() { return master_unit()->item != 0; }
bool mark_as_dependent(THD *thd, st_select_lex *last, Item *dependency);
- void register_dependency_item(st_select_lex *last, Item **dependency);
bool set_braces(bool value);
bool inc_in_sum_expr();
diff --git a/sql/sql_list.h b/sql/sql_list.h
index 38235a10c18..50673921aeb 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -152,6 +152,7 @@ struct list_node :public Sql_alloc
}
};
+typedef bool List_eq(void *a, void *b);
extern MYSQL_PLUGIN_IMPORT list_node end_of_list;
@@ -295,6 +296,16 @@ public:
inline void **head_ref() { return first != &end_of_list ? &first->info : 0; }
inline bool is_empty() { return first == &end_of_list ; }
inline list_node *last_ref() { return &end_of_list; }
+ inline bool add_unique(void *info, List_eq *eq)
+ {
+ list_node *node= first;
+ for (;
+ node != &end_of_list && (!(*eq)(node->info, info));
+ node= node->next) ;
+ if (node == &end_of_list)
+ return push_back(info);
+ return 1;
+ }
friend class base_list_iterator;
friend class error_list;
friend class error_list_iterator;
@@ -465,6 +476,8 @@ public:
inline void concat(List<T> *list) { base_list::concat(list); }
inline void disjoin(List<T> *list) { base_list::disjoin(list); }
inline void prepand(List<T> *list) { base_list::prepand(list); }
+ inline bool add_unique(T *a, bool (*eq)(T *a, T *b))
+ { return base_list::add_unique(a, (List_eq *)eq); }
void delete_elements(void)
{
list_node *element,*next;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index a3b18f28522..d4727c04324 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -9613,6 +9613,7 @@ bool JOIN_TAB::preread_init()
@param thd Thread handle
@param tmp_key The temporary table key
@param it The iterator of items for lookup in the key
+ @param skip Number of fields from the beginning to skip
@details
Build TABLE_REF object for lookup in the key 'tmp_key' using items
@@ -9625,9 +9626,11 @@ bool JOIN_TAB::preread_init()
bool TABLE_REF::tmp_table_index_lookup_init(THD *thd,
KEY *tmp_key,
Item_iterator &it,
- bool value)
+ bool value,
+ uint skip)
{
uint tmp_key_parts= tmp_key->key_parts;
+ uint i;
DBUG_ENTER("TABLE_REF::tmp_table_index_lookup_init");
key= 0; /* The only temp table index. */
@@ -9648,7 +9651,8 @@ bool TABLE_REF::tmp_table_index_lookup_init(THD *thd,
uchar *cur_ref_buff= key_buff;
it.open();
- for (uint i= 0; i < tmp_key_parts; i++, cur_key_part++, ref_key++)
+ for (i= 0; i < skip; i++) it.next();
+ for (i= 0; i < tmp_key_parts; i++, cur_key_part++, ref_key++)
{
Item *item= it.next();
DBUG_ASSERT(item);
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 54b83a3c379..bbf390aaf7e 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -135,7 +135,7 @@ typedef struct st_table_ref
bool disable_cache;
bool tmp_table_index_lookup_init(THD *thd, KEY *tmp_key, Item_iterator &it,
- bool value);
+ bool value, uint skip= 0);
} TABLE_REF;