diff options
author | unknown <serg@serg.mylan> | 2004-05-15 11:26:58 +0200 |
---|---|---|
committer | unknown <serg@serg.mylan> | 2004-05-15 11:26:58 +0200 |
commit | 36bce251128b8fd300c4a6329d0c2d8f601a14bc (patch) | |
tree | 7511a87efd9dc5060078495d60fc5092288b31ec /sql | |
parent | b40430e08cf40d931c511d4d31ea517b7294417b (diff) | |
parent | fdd4717730796ba178cc59c3609e8693ed967105 (diff) | |
download | mariadb-git-36bce251128b8fd300c4a6329d0c2d8f601a14bc.tar.gz |
merged
mysql-test/r/innodb.result:
Auto merged
mysql-test/t/innodb.test:
Auto merged
sql/sql_select.cc:
Auto merged
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item_subselect.cc | 107 | ||||
-rw-r--r-- | sql/item_subselect.h | 4 | ||||
-rw-r--r-- | sql/item_sum.cc | 8 | ||||
-rw-r--r-- | sql/item_sum.h | 8 | ||||
-rw-r--r-- | sql/sql_base.cc | 9 | ||||
-rw-r--r-- | sql/sql_class.cc | 2 | ||||
-rw-r--r-- | sql/sql_lex.cc | 3 | ||||
-rw-r--r-- | sql/sql_lex.h | 1 | ||||
-rw-r--r-- | sql/sql_select.cc | 29 | ||||
-rw-r--r-- | sql/sql_select.h | 1 | ||||
-rw-r--r-- | sql/sql_table.cc | 11 | ||||
-rw-r--r-- | sql/sql_union.cc | 29 |
12 files changed, 185 insertions, 27 deletions
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 2d10be62d53..4503c1b63a9 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -56,10 +56,24 @@ void Item_subselect::init(st_select_lex *select_lex, DBUG_PRINT("subs", ("select_lex 0x%xl", (ulong) select_lex)); unit= select_lex->master_unit(); - if (select_lex->next_select()) - engine= new subselect_union_engine(unit, result, this); + if (unit->item) + { + /* + Item can be changed in JOIN::prepare while engine in JOIN::optimize + => we do not copy old_engine here + */ + engine= unit->item->engine; + unit->item->engine= 0; + unit->item= this; + engine->change_item(this, result); + } else - engine= new subselect_single_select_engine(select_lex, result, this); + { + if (select_lex->next_select()) + engine= new subselect_union_engine(unit, result, this); + else + engine= new subselect_single_select_engine(select_lex, result, this); + } DBUG_VOID_RETURN; } @@ -69,11 +83,13 @@ void Item_subselect::cleanup() Item_result_field::cleanup(); if (old_engine) { - engine->cleanup(); + if (engine) + engine->cleanup(); engine= old_engine; old_engine= 0; } - engine->cleanup(); + if (engine) + engine->cleanup(); reset(); value_assigned= 0; DBUG_VOID_RETURN; @@ -127,7 +143,6 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref) if (have_to_be_excluded) engine->exclude(); substitution= 0; - fixed= 1; thd->where= "checking transformed subquery"; if (!(*ref)->fixed) ret= (*ref)->fix_fields(thd, tables, ref); @@ -660,10 +675,20 @@ Item_in_subselect::single_value_transformer(JOIN *join, item= new Item_sum_min(*select_lex->ref_pointer_array); } *select_lex->ref_pointer_array= item; - select_lex->item_list.empty(); - select_lex->item_list.push_back(item); + { + List_iterator<Item> it(select_lex->item_list); + it++; + it.replace(item); + } - // fix_fields call for 'item' will be made during new subquery fix_fields + /* + Item_sum_(max|min) can't substitute other item => we can use 0 as + reference + */ + if (item->fix_fields(thd, join->tables_list, 0)) + goto err; + /* we added aggregate function => we have to change statistic */ + count_field_types(&join->tmp_table_param, join->all_fields, 0); subs= new Item_singlerow_subselect(select_lex); } @@ -1428,3 +1453,67 @@ void subselect_indexsubquery_engine::print(String *str) } str->append(')'); } + +/* + change select_result object of engine + + SINOPSYS + subselect_single_select_engine::change_result() + si new subselect Item + res new select_result object + + RETURN + 0 OK + -1 error +*/ + +int subselect_single_select_engine::change_item(Item_subselect *si, + select_subselect *res) +{ + item= si; + result= res; + return select_lex->join->change_result(result); +} + + +/* + change select_result object of engine + + SINOPSYS + subselect_single_select_engine::change_result() + si new subselect Item + res new select_result object + + RETURN + 0 OK + -1 error +*/ + +int subselect_union_engine::change_item(Item_subselect *si, + select_subselect *res) +{ + item= si; + int rc= unit->change_result(res, result); + result= res; + return rc; +} + + +/* + change select_result emulation, never should be called + + SINOPSYS + subselect_single_select_engine::change_result() + si new subselect Item + res new select_result object + + RETURN + -1 error +*/ + +int subselect_uniquesubquery_engine::change_item(Item_subselect *si, + select_subselect *res) +{ + DBUG_ASSERT(0); + return -1; +} diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 6d8f5353695..364781de362 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -290,6 +290,7 @@ public: virtual table_map upper_select_const_tables()= 0; static table_map calc_const_tables(TABLE_LIST *); virtual void print(String *str)= 0; + virtual int change_item(Item_subselect *si, select_subselect *result)= 0; }; @@ -313,6 +314,7 @@ public: void exclude(); table_map upper_select_const_tables(); void print (String *str); + int change_item(Item_subselect *si, select_subselect *result); }; @@ -332,6 +334,7 @@ public: void exclude(); table_map upper_select_const_tables(); void print (String *str); + int change_item(Item_subselect *si, select_subselect *result); }; @@ -360,6 +363,7 @@ public: void exclude(); table_map upper_select_const_tables() { return 0; } void print (String *str); + int change_item(Item_subselect *si, select_subselect *result); }; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index eac8d31b256..0c5b29fc069 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -502,6 +502,14 @@ void Item_sum_variance::update_field() /* min & max */ +void Item_sum_hybrid::clear() +{ + sum= 0.0; + sum_int= 0; + value.length(0); + null_value= 1; +} + double Item_sum_hybrid::val() { DBUG_ASSERT(fixed == 1); diff --git a/sql/item_sum.h b/sql/item_sum.h index 4cded41a9f6..ef947900fd2 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -415,13 +415,7 @@ class Item_sum_hybrid :public Item_sum table_map used_tables() const { return used_table_cache; } bool const_item() const { return !used_table_cache; } - void clear() - { - sum=0.0; - sum_int=0; - value.length(0); - null_value=1; - } + void clear(); double val(); longlong val_int(); void reset_field(); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 3a18b7eaabc..14a54a410a2 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2096,7 +2096,14 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter, if (field_name && item->type() == Item::FIELD_ITEM) { Item_field *item_field= (Item_field*) item; - if (!my_strcasecmp(system_charset_info, item_field->name, field_name)) + /* + In case of group_concat() with ORDER BY condition in the QUERY + item_field can be field of temporary table without item name + (if this field created from expression argument of group_concat()), + => we have to check presence of name before compare + */ + if (item_field->name && + !my_strcasecmp(system_charset_info, item_field->name, field_name)) { if (!table_name) { diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 03d67c4f300..f7992c3db9e 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -86,7 +86,7 @@ bool key_part_spec::operator==(const key_part_spec& other) const /* - Test if a foreign key is a prefix of the given key + Test if a foreign key (= generated key) is a prefix of the given key (ignoring key name, key type and order of columns) NOTES: diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 5fa8b37285e..1038066f6ef 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1710,6 +1710,7 @@ TABLE_LIST *st_lex::link_first_table_back(TABLE_LIST *tables, st_select_lex::print is in sql_select.h st_select_lex_unit::prepare, st_select_lex_unit::exec, - st_select_lex_unit::cleanup, st_select_lex_unit::reinit_exec_mechanism + st_select_lex_unit::cleanup, st_select_lex_unit::reinit_exec_mechanism, + st_select_lex_unit::change_result are in sql_union.cc */ diff --git a/sql/sql_lex.h b/sql/sql_lex.h index aa3e81fd9c9..557c037c799 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -371,6 +371,7 @@ public: void print(String *str); ulong init_prepare_fake_select_lex(THD *thd); + int change_result(select_subselect *result, select_subselect *old_result); friend void mysql_init_query(THD *thd); friend int subselect_union_engine::exec(); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 92bc13cb01e..a89ef6b05ea 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1584,8 +1584,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array, if (select_lex->linkage != GLOBAL_OPTIONS_TYPE) { //here is EXPLAIN of subselect or derived table - join->result= result; - if (!join->procedure && result->prepare(join->fields_list, unit)) + if (join->change_result(result)) { DBUG_RETURN(-1); } @@ -9385,7 +9384,7 @@ void st_select_lex::print(THD *thd, String *str) if (!thd->lex->safe_to_cache_query) str->append("sql_no_cache ", 13); if (options & OPTION_TO_QUERY_CACHE) - str->append("cache ", 6); + str->append("sql_cache ", 10); //Item List bool first= 1; @@ -9513,3 +9512,27 @@ void st_select_lex::print(THD *thd, String *str) // PROCEDURE unsupported here } + + +/* + change select_result object of JOIN + + SYNOPSIS + JOIN::change_result() + res new select_result object + + RETURN + 0 - OK + -1 - error +*/ + +int JOIN::change_result(select_result *res) +{ + DBUG_ENTER("JOIN::change_result"); + result= res; + if (!procedure && result->prepare(fields_list, select_lex->master_unit())) + { + DBUG_RETURN(-1); + } + DBUG_RETURN(0); +} diff --git a/sql/sql_select.h b/sql/sql_select.h index 5a246a477cf..8aca43484d2 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -304,6 +304,7 @@ class JOIN :public Sql_alloc return (do_send_rows && tmp_table_param.sum_func_count != 0 && !group_list); } + int change_result(select_result *result); }; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 8d5ec56add9..e017bc7e6b5 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -684,12 +684,13 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, while ((key2 = key_iterator2++) != key) { /* - foreign_key_prefix(key, key2) returns 0 if key or key2, or both, is - 'generated', and a generated key is a prefix of the other key. Then we - do not need the generated shorter key. + foreign_key_prefix(key, key2) returns 0 if key or key2, or both, is + 'generated', and a generated key is a prefix of the other key. + Then we do not need the generated shorter key. */ - if (key2->name != ignore_key && key2->type != Key::FOREIGN_KEY && - !foreign_key_prefix(key, key2)) + if ((key2->type != Key::FOREIGN_KEY && + key2->name != ignore_key && + !foreign_key_prefix(key, key2))) { /* TODO: issue warning message */ /* mark that the generated key should be ignored */ diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 63638b618d9..de3eeec0db0 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -555,3 +555,32 @@ void st_select_lex_unit::reinit_exec_mechanism() } #endif } + + +/* + change select_result object of unit + + SYNOPSIS + st_select_lex_unit::change_result() + result new select_result object + old_result old select_result object + + RETURN + 0 - OK + -1 - error +*/ + +int st_select_lex_unit::change_result(select_subselect *result, + select_subselect *old_result) +{ + int res= 0; + for (SELECT_LEX *sl= first_select_in_union(); sl; sl= sl->next_select()) + { + if (sl->join && sl->join->result == old_result) + if ((res= sl->join->change_result(result))) + return (res); + } + if (fake_select_lex && fake_select_lex->join) + res= fake_select_lex->join->change_result(result); + return (res); +} |