diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item.cc | 71 | ||||
-rw-r--r-- | sql/item.h | 41 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 33 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 1 | ||||
-rw-r--r-- | sql/item_subselect.cc | 17 | ||||
-rw-r--r-- | sql/item_subselect.h | 10 | ||||
-rw-r--r-- | sql/item_sum.cc | 11 | ||||
-rw-r--r-- | sql/item_sum.h | 1 | ||||
-rw-r--r-- | sql/opt_range.cc | 10 | ||||
-rw-r--r-- | sql/sql_base.cc | 5 | ||||
-rw-r--r-- | sql/sql_class.h | 16 | ||||
-rw-r--r-- | sql/sql_expression_cache.cc | 61 | ||||
-rw-r--r-- | sql/sql_expression_cache.h | 20 | ||||
-rw-r--r-- | sql/sql_lex.cc | 53 | ||||
-rw-r--r-- | sql/sql_lex.h | 1 | ||||
-rw-r--r-- | sql/sql_list.h | 13 | ||||
-rw-r--r-- | sql/sql_select.cc | 8 | ||||
-rw-r--r-- | sql/sql_select.h | 2 |
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> ¶meters) { }; }; +/** + 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> ¶meters) +{ /* 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> ¶meters); }; 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> ¶meters) +{ + Collect_deps_prm prm= { unit->first_select()->nest_level, ¶meters }; + 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> ¶meters); 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; |