diff options
author | unknown <bell@sanja.is.com.ua> | 2003-11-23 17:59:28 +0200 |
---|---|---|
committer | unknown <bell@sanja.is.com.ua> | 2003-11-23 17:59:28 +0200 |
commit | 105087127ed6f05c03b34f79402341cebfb8b71a (patch) | |
tree | e1e76ccec7e31e26c1b2989bbb32189db8f475f9 /sql | |
parent | c1dd9540a4e397668040ab4027500138c238081b (diff) | |
parent | 3e21b667bcf164779674e0c08d8c1b9044acc2b5 (diff) | |
download | mariadb-git-105087127ed6f05c03b34f79402341cebfb8b71a.tar.gz |
Merge sanja.is.com.ua:/home/bell/mysql/bk/mysql-4.1
into sanja.is.com.ua:/home/bell/mysql/bk/work-union-4.1
sql/item.cc:
Auto merged
sql/item.h:
Auto merged
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.h | 48 | ||||
-rw-r--r-- | sql/item.cc | 121 | ||||
-rw-r--r-- | sql/item.h | 32 | ||||
-rw-r--r-- | sql/item_subselect.cc | 49 | ||||
-rw-r--r-- | sql/mysql_priv.h | 5 | ||||
-rw-r--r-- | sql/sql_base.cc | 14 | ||||
-rw-r--r-- | sql/sql_class.h | 1 | ||||
-rw-r--r-- | sql/sql_derived.cc | 152 | ||||
-rw-r--r-- | sql/sql_lex.h | 11 | ||||
-rw-r--r-- | sql/sql_parse.cc | 2 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 2 | ||||
-rw-r--r-- | sql/sql_select.cc | 222 | ||||
-rw-r--r-- | sql/sql_select.h | 2 | ||||
-rw-r--r-- | sql/sql_union.cc | 154 | ||||
-rw-r--r-- | sql/sql_update.cc | 2 |
15 files changed, 508 insertions, 309 deletions
diff --git a/sql/field.h b/sql/field.h index 692e64d1146..ef6920f4d89 100644 --- a/sql/field.h +++ b/sql/field.h @@ -230,6 +230,24 @@ public: virtual bool has_charset(void) const { return FALSE; } virtual void set_charset(CHARSET_INFO *charset) { } void set_warning(const unsigned int level, const unsigned int code); + /* + number which describe preferences of field type converion, + for example, if we have int and float, float is prefered as more general + + ennumiration begins from: + 100 for int types + 300 for float point + 500 time/date + 700 string + */ + virtual uint convert_order()= 0; + /* + Is this type is compatible with given + (given can be stored in it) + Should take care only of types 'less' then current + */ + virtual bool convert_order_compatible(uint order) { return 0; } + friend bool reopen_table(THD *,struct st_table *,bool); friend int cre_myisam(my_string name, register TABLE *form, uint options, ulonglong auto_increment_value); @@ -334,6 +352,7 @@ public: void overflow(bool negative); bool zero_pack() const { return 0; } void sql_type(String &str) const; + uint convert_order() { return 130; } }; @@ -369,6 +388,7 @@ public: void sort_string(char *buff,uint length); uint32 pack_length() const { return 1; } void sql_type(String &str) const; + uint convert_order() { return 100; } }; @@ -404,6 +424,7 @@ public: void sort_string(char *buff,uint length); uint32 pack_length() const { return 2; } void sql_type(String &str) const; + uint convert_order() { return 101; } }; @@ -434,6 +455,7 @@ public: void sort_string(char *buff,uint length); uint32 pack_length() const { return 3; } void sql_type(String &str) const; + uint convert_order() { return 102; } }; @@ -469,6 +491,7 @@ public: void sort_string(char *buff,uint length); uint32 pack_length() const { return 4; } void sql_type(String &str) const; + uint convert_order() { return 103; } }; @@ -507,6 +530,7 @@ public: uint32 pack_length() const { return 8; } void sql_type(String &str) const; bool store_for_compare() { return 1; } + uint convert_order() { return 104; } }; #endif @@ -540,6 +564,7 @@ public: void sort_string(char *buff,uint length); uint32 pack_length() const { return sizeof(float); } void sql_type(String &str) const; + uint convert_order() { return 300; } }; @@ -573,6 +598,7 @@ public: void sort_string(char *buff,uint length); uint32 pack_length() const { return sizeof(double); } void sql_type(String &str) const; + uint convert_order() { return 301; } }; @@ -606,6 +632,7 @@ public: uint32 pack_length() const { return 0; } void sql_type(String &str) const; uint size_of() const { return sizeof(*this); } + uint convert_order() { return 0; } }; @@ -649,6 +676,8 @@ public: } bool get_date(TIME *ltime,uint fuzzydate); bool get_time(TIME *ltime); + uint convert_order() { return 520; } + bool convert_order_compatible(uint ord) { return ord<520; } }; @@ -674,6 +703,8 @@ public: String *val_str(String*,String *); bool send_binary(Protocol *protocol); void sql_type(String &str) const; + uint convert_order() { return 501; } + bool convert_order_compatible(uint ord) { return ord<520; } }; @@ -706,6 +737,8 @@ public: void sql_type(String &str) const; bool store_for_compare() { return 1; } bool zero_pack() const { return 1; } + uint convert_order() { return 502; } + bool convert_order_compatible(uint ord) { return ord<520; } }; class Field_newdate :public Field_str { @@ -737,6 +770,8 @@ public: bool zero_pack() const { return 1; } bool get_date(TIME *ltime,uint fuzzydate); bool get_time(TIME *ltime); + uint convert_order() { return 503; } + bool convert_order_compatible(uint ord) { return ord<520; } }; @@ -770,6 +805,8 @@ public: void sql_type(String &str) const; bool store_for_compare() { return 1; } bool zero_pack() const { return 1; } + uint convert_order() { return 504; } + bool convert_order_compatible(uint ord) { return ord<520; } }; @@ -807,6 +844,8 @@ public: bool zero_pack() const { return 1; } bool get_date(TIME *ltime,uint fuzzydate); bool get_time(TIME *ltime); + uint convert_order() { return 530; } + bool convert_order_compatible(uint ord) { return ord<=501; } }; @@ -851,6 +890,7 @@ public: uint size_of() const { return sizeof(*this); } enum_field_types real_type() const { return FIELD_TYPE_STRING; } bool has_charset(void) const { return TRUE; } + uint convert_order() { return 700; } }; @@ -894,6 +934,7 @@ public: uint size_of() const { return sizeof(*this); } enum_field_types real_type() const { return FIELD_TYPE_VAR_STRING; } bool has_charset(void) const { return TRUE; } + uint convert_order() { return 701; } }; @@ -983,6 +1024,7 @@ public: uint size_of() const { return sizeof(*this); } bool has_charset(void) const { return charset() == &my_charset_bin ? FALSE : TRUE; } + uint convert_order() { return 701; } }; @@ -1011,6 +1053,8 @@ public: void get_key_image(char *buff,uint length, CHARSET_INFO *cs,imagetype type); void set_key_image(char *buff,uint length, CHARSET_INFO *cs); + uint convert_order() { return 750; } + bool convert_order_compatible(uint ord) { return ord < 750; }; }; @@ -1052,6 +1096,8 @@ public: bool optimize_range(uint idx) { return 0; } bool eq_def(Field *field); bool has_charset(void) const { return TRUE; } + uint convert_order() { return 30; } + bool convert_order_compatible(uint ord) { return ord < 30; }; }; @@ -1077,6 +1123,8 @@ public: void sql_type(String &str) const; enum_field_types real_type() const { return FIELD_TYPE_SET; } bool has_charset(void) const { return TRUE; } + uint convert_order() { return 40; } + bool convert_order_compatible(uint ord) { return ord < 40; }; }; diff --git a/sql/item.cc b/sql/item.cc index 1d43351688b..e5a9f9db740 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -312,7 +312,7 @@ void Item_field::set_field(Field *field_par) const char *Item_ident::full_name() const { char *tmp; - if (!table_name) + if (!table_name || !field_name) return field_name ? field_name : name ? name : "tmp_field"; if (db_name && db_name[0]) { @@ -1881,6 +1881,8 @@ void Item_cache_str::store(Item *item) } collation.set(item->collation); } + + double Item_cache_str::val() { int err; @@ -1890,6 +1892,8 @@ double Item_cache_str::val() else return (double)0; } + + longlong Item_cache_str::val_int() { int err; @@ -1900,6 +1904,7 @@ longlong Item_cache_str::val_int() return (longlong)0; } + bool Item_cache_row::allocate(uint num) { item_count= num; @@ -1908,6 +1913,7 @@ bool Item_cache_row::allocate(uint num) (Item_cache **) thd->calloc(sizeof(Item_cache *)*item_count))); } + bool Item_cache_row::setup(Item * item) { example= item; @@ -1924,6 +1930,7 @@ bool Item_cache_row::setup(Item * item) return 0; } + void Item_cache_row::store(Item * item) { null_value= 0; @@ -1935,6 +1942,7 @@ void Item_cache_row::store(Item * item) } } + void Item_cache_row::illegal_method_call(const char *method) { DBUG_ENTER("Item_cache_row::illegal_method_call"); @@ -1944,6 +1952,7 @@ void Item_cache_row::illegal_method_call(const char *method) DBUG_VOID_RETURN; } + bool Item_cache_row::check_cols(uint c) { if (c != item_count) @@ -1954,6 +1963,7 @@ bool Item_cache_row::check_cols(uint c) return 0; } + bool Item_cache_row::null_inside() { for (uint i= 0; i < item_count; i++) @@ -1973,6 +1983,7 @@ bool Item_cache_row::null_inside() return 0; } + void Item_cache_row::bring_value() { for (uint i= 0; i < item_count; i++) @@ -1980,6 +1991,114 @@ void Item_cache_row::bring_value() return; } + +Item_type_holder::Item_type_holder(THD *thd, Item *item) + :Item(thd, *item), item_type(item->result_type()) +{ + DBUG_ASSERT(item->fixed); + if (item->type() == Item::FIELD_ITEM) + { + Item_field *fitem= (Item_field*) item; + field_example= (Field*) thd->memdup((const char*)fitem->field, + fitem->field->size_of()); + } + else + field_example= 0; +} + + +// STRING_RESULT, REAL_RESULT, INT_RESULT, ROW_RESULT +static Item_result type_convertor[4][4]= +{{STRING_RESULT, STRING_RESULT, STRING_RESULT, ROW_RESULT}, + {STRING_RESULT, REAL_RESULT, REAL_RESULT, ROW_RESULT}, + {STRING_RESULT, REAL_RESULT, INT_RESULT, ROW_RESULT}, + {ROW_RESULT, ROW_RESULT, ROW_RESULT, ROW_RESULT}}; + +void Item_type_holder::join_types(THD *thd, Item *item) +{ + bool change_field= 0, skip_store_field= 0; + Item_result new_type= type_convertor[item_type][item->result_type()]; + + // we have both fields + if (field_example && item->type() == Item::FIELD_ITEM) + { + Field *field= ((Item_field *)item)->field; + + // is new field better + if ((change_field= + field_example->convert_order() < field->convert_order())) + { + // is it compatible? + if (field->convert_order_compatible(field_example->convert_order())) + skip_store_field= 1; + } + else + { + /* + if old field can't store value of 'worse' new field we will make + decision about result field tipe based only on Item result type + */ + if (field_example->convert_order_compatible(field->convert_order())) + skip_store_field= 1; + } + } + + // size/type should be changed + if (change_field || + (new_type != item_type) || + (max_length < item->max_length) || + ((new_type == INT_RESULT) && + (decimals < item->decimals)) || + (!maybe_null && item->maybe_null)) + { + // new field has some parameters worse then current + skip_store_field|= (change_field && + (max_length > item->max_length) || + ((new_type == INT_RESULT) && + (decimals > item->decimals)) || + (maybe_null && !item->maybe_null)); + if (skip_store_field || item->type() != Item::FIELD_ITEM) + field_example= 0; + else + { + /* + we do not need following, because we use mem_root + if (field_example) + thd->free(field_example) + */ + Item_field *fitem= (Item_field*) item; + field_example= (Field*) thd->memdup((const char*)fitem->field, + fitem->field->size_of()); + } + max_length= max(max_length, item->max_length); + decimals= max(decimals, item->decimals); + maybe_null|= item->maybe_null; + item_type= new_type; + } + DBUG_ASSERT(item_type != ROW_RESULT); +} + + +double Item_type_holder::val() +{ + DBUG_ASSERT(0); // should never be called + return 0.0; +} + + +longlong Item_type_holder::val_int() +{ + DBUG_ASSERT(0); // should never be called + return 0; +} + + +String *Item_type_holder::val_str(String*) +{ + DBUG_ASSERT(0); // should never be called + return 0; +} + /***************************************************************************** ** Instantiate templates *****************************************************************************/ diff --git a/sql/item.h b/sql/item.h index 53db177b360..c79964f5811 100644 --- a/sql/item.h +++ b/sql/item.h @@ -98,7 +98,7 @@ public: COPY_STR_ITEM, FIELD_AVG_ITEM, DEFAULT_VALUE_ITEM, PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_ITEM, FIELD_VARIANCE_ITEM, INSERT_VALUE_ITEM, - SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM}; + SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM, TYPE_HOLDER}; enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE }; @@ -390,17 +390,17 @@ class Item_int :public Item public: const longlong value; Item_int(int32 i,uint length=11) :value((longlong) i) - { max_length=length;} + { max_length=length; fixed= 1; } #ifdef HAVE_LONG_LONG Item_int(longlong i,uint length=21) :value(i) - { max_length=length;} + { max_length=length; fixed= 1;} #endif Item_int(const char *str_arg,longlong i,uint length) :value(i) - { max_length=length; name=(char*) str_arg;} + { max_length=length; name=(char*) str_arg; fixed= 1; } Item_int(const char *str_arg) : value(str_arg[0] == '-' ? strtoll(str_arg,(char**) 0,10) : (longlong) strtoull(str_arg,(char**) 0,10)) - { max_length= (uint) strlen(str_arg); name=(char*) str_arg;} + { max_length= (uint) strlen(str_arg); name=(char*) str_arg; fixed= 1; } enum Type type() const { return INT_ITEM; } enum Item_result result_type () const { return INT_RESULT; } enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; } @@ -988,6 +988,28 @@ public: void bring_value(); }; + +/* + Used to store type. name, length of Item for UNIONS & derived table +*/ +class Item_type_holder: public Item +{ +protected: + Item_result item_type; + Field *field_example; +public: + Item_type_holder(THD*, Item*); + + Item_result result_type () const { return item_type; } + enum Type type() const { return TYPE_HOLDER; } + double val(); + longlong val_int(); + String *val_str(String*); + void join_types(THD *thd, Item *); + Field *example() { return field_example; } +}; + + extern Item_buff *new_Item_buff(Item *item); extern Item_result item_cmp_type(Item_result a,Item_result b); extern Item *resolve_const_item(Item *item,Item *cmp_item); diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index a60a35aac6b..367400d6b0b 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -924,7 +924,7 @@ int subselect_single_select_engine::prepare() (ORDER*) select_lex->group_list.first, select_lex->having, (ORDER*) 0, select_lex, - select_lex->master_unit(), 0)) + select_lex->master_unit())) return 1; thd->lex.current_select= save_select; return 0; @@ -932,7 +932,7 @@ int subselect_single_select_engine::prepare() int subselect_union_engine::prepare() { - return unit->prepare(thd, result, 0); + return unit->prepare(thd, result); } int subselect_uniquesubquery_engine::prepare() @@ -942,12 +942,12 @@ int subselect_uniquesubquery_engine::prepare() return 1; } -static Item_result set_row(SELECT_LEX *select_lex, Item * item, +static Item_result set_row(List<Item> &item_list, Item *item, Item_cache **row, bool *maybe_null) { Item_result res_type= STRING_RESULT; Item *sel_item; - List_iterator_fast<Item> li(select_lex->item_list); + List_iterator_fast<Item> li(item_list); for (uint i= 0; (sel_item= li++); i++) { item->max_length= sel_item->max_length; @@ -962,7 +962,7 @@ static Item_result set_row(SELECT_LEX *select_lex, Item * item, row[i]->collation.set(sel_item->collation); } } - if (select_lex->item_list.elements > 1) + if (item_list.elements > 1) res_type= ROW_RESULT; return res_type; } @@ -970,7 +970,7 @@ static Item_result set_row(SELECT_LEX *select_lex, Item * item, void subselect_single_select_engine::fix_length_and_dec(Item_cache **row) { DBUG_ASSERT(row || select_lex->item_list.elements==1); - res_type= set_row(select_lex, item, row, &maybe_null); + res_type= set_row(select_lex->item_list, item, row, &maybe_null); item->collation.set(row[0]->collation); if (cols() != 1) maybe_null= 0; @@ -981,44 +981,11 @@ void subselect_union_engine::fix_length_and_dec(Item_cache **row) DBUG_ASSERT(row || unit->first_select()->item_list.elements==1); if (unit->first_select()->item_list.elements == 1) - { - uint32 mlen= 0, len; - Item *sel_item= 0; - for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select()) - { - List_iterator_fast<Item> li(sl->item_list); - Item *s_item= li++; - if ((len= s_item->max_length) > mlen) - mlen= len; - if (!sel_item) - sel_item= s_item; - maybe_null= s_item->maybe_null; - } - item->max_length= mlen; - res_type= sel_item->result_type(); - item->decimals= sel_item->decimals; - if (row) - { - if (!(row[0]= Item_cache::get_cache(res_type))) - return; - row[0]->set_len_n_dec(mlen, sel_item->decimals); - } - } + res_type= set_row(unit->types, item, row, &maybe_null); else { - SELECT_LEX *sl= unit->first_select(); bool fake= 0; - res_type= set_row(sl, item, row, &fake); - for (sl= sl->next_select(); sl; sl= sl->next_select()) - { - List_iterator_fast<Item> li(sl->item_list); - Item *sel_item; - for (uint i= 0; (sel_item= li++); i++) - { - if (sel_item->max_length > row[i]->max_length) - row[i]->max_length= sel_item->max_length; - } - } + res_type= set_row(unit->types, item, row, &fake); } } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index b9032381c45..5cf352aff99 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -482,7 +482,7 @@ int mysql_select(THD *thd, Item ***rref_pointer_array, COND *conds, uint og_num, ORDER *order, ORDER *group, Item *having, ORDER *proc_param, ulong select_type, select_result *result, SELECT_LEX_UNIT *unit, - SELECT_LEX *select_lex, bool tables_and_fields_initied); + SELECT_LEX *select_lex); void free_underlaid_joins(THD *thd, SELECT_LEX *select); void fix_tables_pointers(SELECT_LEX *select_lex); void fix_tables_pointers(SELECT_LEX_UNIT *select_lex); @@ -491,7 +491,7 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type, select_result *result); int mysql_union(THD *thd, LEX *lex, select_result *result, - SELECT_LEX_UNIT *unit, bool tables_and_fields_initied); + SELECT_LEX_UNIT *unit); int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t); Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, Item ***copy_func, Field **from_field, @@ -675,7 +675,6 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields, int setup_fields(THD *thd, Item** ref_pointer_array, TABLE_LIST *tables, List<Item> &item, bool set_query_id, List<Item> *sum_func_list, bool allow_sum_func); -void unfix_item_list(List<Item> item_list); int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds); int setup_ftfuncs(SELECT_LEX* select); int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 7a657841845..775aa1cd43f 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2023,20 +2023,6 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, DBUG_RETURN(test(thd->net.report_error)); } -/* - Mark all items in list as not fixed (0 assigned to 'fixed' field) - - SYNOPSYS - unfix_item_list() - item_list - list of items -*/ -void unfix_item_list(List<Item> item_list) -{ - Item *item; - List_iterator_fast<Item> it(item_list); - while ((item= it++)) - item->walk(&Item::remove_fixed, 0); -} /* Remap table numbers if INSERT ... SELECT diff --git a/sql/sql_class.h b/sql/sql_class.h index b19caf057e6..36faeae8f57 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -946,6 +946,7 @@ class select_union :public select_result { bool send_data(List<Item> &items); bool send_eof(); bool flush(); + void set_table(TABLE *tbl) { table= tbl; } }; /* Base subselect interface class */ diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 719686a56c3..591c6579a46 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -62,16 +62,15 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *org_table_list) { - SELECT_LEX *select_cursor= unit->first_select(); - List<Item> item_list; + SELECT_LEX *first_select= unit->first_select(); TABLE *table; int res; select_union *derived_result; - TABLE_LIST *tables= (TABLE_LIST *)select_cursor->table_list.first; + TABLE_LIST *tables= (TABLE_LIST *)first_select->table_list.first; TMP_TABLE_PARAM tmp_table_param; - bool is_union= select_cursor->next_select() && - select_cursor->next_select()->linkage == UNION_TYPE; - bool is_subsel= select_cursor->first_inner_unit() ? 1: 0; + bool is_union= first_select->next_select() && + first_select->next_select()->linkage == UNION_TYPE; + bool is_subsel= first_select->first_inner_unit() ? 1: 0; SELECT_LEX *save_current_select= lex->current_select; DBUG_ENTER("mysql_derived"); @@ -112,16 +111,12 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, fix_tables_pointers(unit); } - lex->current_select= select_cursor; - TABLE_LIST *first_table= (TABLE_LIST*) select_cursor->table_list.first; - /* Setting up. A must if a join or IGNORE, USE or similar are utilised */ - if (setup_tables(first_table) || - setup_wild(thd, first_table, select_cursor->item_list, 0, - select_cursor->with_wild)) - { - res= -1; + if(!(derived_result= new select_union(0))) + DBUG_RETURN(1); // out of memory + + // st_select_lex_unit::prepare coppectly work for single select + if ((res= unit->prepare(thd, derived_result))) goto exit; - } /* This is done in order to redo all field optimisations when any of the @@ -133,30 +128,16 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, cursor->table->clear_query_id= 1; } - item_list= select_cursor->item_list; - select_cursor->with_wild= 0; - if (select_cursor->setup_ref_array(thd, - select_cursor->order_list.elements + - select_cursor->group_list.elements) || - setup_fields(thd, select_cursor->ref_pointer_array, first_table, - item_list, 0, 0, 1)) - { - res= -1; - goto exit; - } - // Item list should be fix_fielded yet another time in JOIN::prepare - unfix_item_list(item_list); - bzero((char*) &tmp_table_param,sizeof(tmp_table_param)); - tmp_table_param.field_count= item_list.elements; + tmp_table_param.field_count= unit->types.elements; /* Temp table is created so that it hounours if UNION without ALL is to be processed */ - if (!(table= create_tmp_table(thd, &tmp_table_param, item_list, + if (!(table= create_tmp_table(thd, &tmp_table_param, unit->types, (ORDER*) 0, is_union && !unit->union_option, 1, - (select_cursor->options | thd->options | + (first_select->options | thd->options | TMP_TABLE_ALL_COLUMNS), HA_POS_ERROR, org_table_list->alias))) @@ -164,70 +145,69 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, res= -1; goto exit; } - - if ((derived_result=new select_union(table))) + derived_result->set_table(table); + derived_result->tmp_table_param=tmp_table_param; + + unit->offset_limit_cnt= first_select->offset_limit; + unit->select_limit_cnt= first_select->select_limit+ + first_select->offset_limit; + if (unit->select_limit_cnt < first_select->select_limit) + unit->select_limit_cnt= HA_POS_ERROR; + if (unit->select_limit_cnt == HA_POS_ERROR) + first_select->options&= ~OPTION_FOUND_ROWS; + + if (is_union) + res= mysql_union(thd, lex, derived_result, unit); + else + res= mysql_select(thd, &first_select->ref_pointer_array, + (TABLE_LIST*) first_select->table_list.first, + first_select->with_wild, + first_select->item_list, first_select->where, + (first_select->order_list.elements+ + first_select->group_list.elements), + (ORDER *) first_select->order_list.first, + (ORDER *) first_select->group_list.first, + first_select->having, (ORDER*) NULL, + (first_select->options | thd->options | + SELECT_NO_UNLOCK), + derived_result, unit, first_select); + + if (!res) { - derived_result->tmp_table_param=tmp_table_param; - unit->offset_limit_cnt= select_cursor->offset_limit; - unit->select_limit_cnt= select_cursor->select_limit+ - select_cursor->offset_limit; - if (unit->select_limit_cnt < select_cursor->select_limit) - unit->select_limit_cnt= HA_POS_ERROR; - if (unit->select_limit_cnt == HA_POS_ERROR) - select_cursor->options&= ~OPTION_FOUND_ROWS; - - if (is_union) - res= mysql_union(thd, lex, derived_result, unit, 1); + /* + Here we entirely fix both TABLE_LIST and list of SELECT's as + there were no derived tables + */ + if (derived_result->flush()) + res= 1; else - res= mysql_select(thd, &select_cursor->ref_pointer_array, - (TABLE_LIST*) select_cursor->table_list.first, - select_cursor->with_wild, - select_cursor->item_list, select_cursor->where, - (select_cursor->order_list.elements+ - select_cursor->group_list.elements), - (ORDER *) select_cursor->order_list.first, - (ORDER *) select_cursor->group_list.first, - select_cursor->having, (ORDER*) NULL, - (select_cursor->options | thd->options | - SELECT_NO_UNLOCK), - derived_result, unit, select_cursor, 1); - - if (!res) { - /* - Here we entirely fix both TABLE_LIST and list of SELECT's as - there were no derived tables - */ - if (derived_result->flush()) - res= 1; - else - { - org_table_list->real_name=table->real_name; - org_table_list->table=table; - table->derived_select_number= select_cursor->select_number; - table->tmp_table= TMP_TABLE; + org_table_list->real_name=table->real_name; + org_table_list->table=table; + table->derived_select_number= first_select->select_number; + table->tmp_table= TMP_TABLE; #ifndef NO_EMBEDDED_ACCESS_CHECKS - org_table_list->grant.privilege= SELECT_ACL; + org_table_list->grant.privilege= SELECT_ACL; #endif - if (lex->describe) + if (lex->describe) + { + // to fix a problem in EXPLAIN + if (tables) { - // to fix a problem in EXPLAIN - if (tables) - { - for (TABLE_LIST *cursor= tables; cursor; cursor= cursor->next) - if (cursor->table_list) - cursor->table_list->table=cursor->table; - } + for (TABLE_LIST *cursor= tables; cursor; cursor= cursor->next) + if (cursor->table_list) + cursor->table_list->table=cursor->table; } - else - unit->exclude_tree(); - org_table_list->db= (char *)""; - // Force read of table stats in the optimizer - table->file->info(HA_STATUS_VARIABLE); } + else + unit->exclude_tree(); + org_table_list->db= (char *)""; + // Force read of table stats in the optimizer + table->file->info(HA_STATUS_VARIABLE); } - delete derived_result; } + delete derived_result; + if (res) free_tmp_table(thd, table); else diff --git a/sql/sql_lex.h b/sql/sql_lex.h index d2345165eb9..29301053c59 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -295,7 +295,6 @@ class JOIN; class select_union; class st_select_lex_unit: public st_select_lex_node { protected: - List<Item> item_list; TABLE_LIST result_table_list; select_union *union_result; TABLE *table; /* temporary table using for appending UNION results */ @@ -305,9 +304,13 @@ protected: ulong found_rows_for_union; bool prepared, // prepare phase already performed for UNION (unit) optimized, // optimize phase already performed for UNION (unit) - executed, // already executed - t_and_f; // used for transferring tables_and_fields_initied UNIT:: methods + executed; // already executed + public: + // list of fields which points to temporary table for union + List<Item> item_list; + // list of types of items inside union (used for union & derived tables) + List<Item> types; /* Pointer to 'last' select or pointer to unit where stored global parameters for union @@ -342,7 +345,7 @@ public: void exclude_tree(); /* UNION methods */ - int prepare(THD *thd, select_result *result, bool tables_and_fields_initied); + int prepare(THD *thd, select_result *result); int exec(); int cleanup(); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 9f4b10682ba..d5a15de422d 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2716,7 +2716,7 @@ mysql_execute_command(THD *thd) (ORDER *)NULL, select_lex->options | thd->options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK, - result, unit, select_lex, 0); + result, unit, select_lex); if (thd->net.report_error) res= -1; delete result; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 354214a4da5..69517b171cb 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -682,7 +682,7 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables, if (join->prepare(&select_lex->ref_pointer_array, tables, wild_num, conds, og_num, order, group, having, proc, - select_lex, unit, 0)) + select_lex, unit)) DBUG_RETURN(1); if (send_prep_stmt(stmt, fields.elements) || thd->protocol_simple.send_fields(&fields, 0) || diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 44b403c0bb1..ba4dd9f856e 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -177,7 +177,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result) fix_tables_pointers(lex->all_selects_list); if (select_lex->next_select()) - res=mysql_union(thd, lex, result, &lex->unit, 0); + res=mysql_union(thd, lex, result, &lex->unit); else res= mysql_select(thd, &select_lex->ref_pointer_array, (TABLE_LIST*) select_lex->table_list.first, @@ -190,7 +190,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result) select_lex->having, (ORDER*) lex->proc_list.first, select_lex->options | thd->options, - result, &(lex->unit), &(lex->select_lex), 0); + result, &(lex->unit), &(lex->select_lex)); /* Don't set res if it's -1 as we may want this later */ DBUG_PRINT("info",("res: %d report_error: %d", res, @@ -285,8 +285,7 @@ JOIN::prepare(Item ***rref_pointer_array, ORDER *order_init, ORDER *group_init, Item *having_init, ORDER *proc_param_init, SELECT_LEX *select, - SELECT_LEX_UNIT *unit, - bool tables_and_fields_initied) + SELECT_LEX_UNIT *unit) { DBUG_ENTER("JOIN::prepare"); @@ -302,10 +301,8 @@ JOIN::prepare(Item ***rref_pointer_array, /* Check that all tables, fields, conds and order are ok */ - if ((tables_and_fields_initied ? 0 : (setup_tables(tables_list) || - setup_wild(thd, tables_list, - fields_list, - &all_fields, wild_num))) || + if (setup_tables(tables_list) || + setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) || select_lex->setup_ref_array(thd, og_num) || setup_fields(thd, (*rref_pointer_array), tables_list, fields_list, 1, &all_fields, 1) || @@ -1536,7 +1533,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array, COND *conds, uint og_num, ORDER *order, ORDER *group, Item *having, ORDER *proc_param, ulong select_options, select_result *result, SELECT_LEX_UNIT *unit, - SELECT_LEX *select_lex, bool tables_and_fields_initied) + SELECT_LEX *select_lex) { int err; bool free_join= 1; @@ -1546,26 +1543,31 @@ mysql_select(THD *thd, Item ***rref_pointer_array, if (select_lex->join != 0) { join= select_lex->join; - if (select_lex->linkage != GLOBAL_OPTIONS_TYPE) + // is it single SELECT in derived table, called in derived table creation + if (select_lex->linkage != DERIVED_TABLE_TYPE || + (select_options & SELECT_DESCRIBE)) { - //here is EXPLAIN of subselect or derived table - join->result= result; - if (!join->procedure && result->prepare(join->fields_list, unit)) + if (select_lex->linkage != GLOBAL_OPTIONS_TYPE) { - DBUG_RETURN(-1); + //here is EXPLAIN of subselect or derived table + join->result= result; + if (!join->procedure && result->prepare(join->fields_list, unit)) + { + DBUG_RETURN(-1); + } } - } - else - { - if (join->prepare(rref_pointer_array, tables, wild_num, - conds, og_num, order, group, having, proc_param, - select_lex, unit, tables_and_fields_initied)) + else { - goto err; + if (join->prepare(rref_pointer_array, tables, wild_num, + conds, og_num, order, group, having, proc_param, + select_lex, unit)) + { + goto err; + } } + free_join= 0; } join->select_options= select_options; - free_join= 0; } else { @@ -1574,7 +1576,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array, thd->used_tables=0; // Updated by setup_fields if (join->prepare(rref_pointer_array, tables, wild_num, conds, og_num, order, group, having, proc_param, - select_lex, unit, tables_and_fields_initied)) + select_lex, unit)) { goto err; } @@ -4546,6 +4548,115 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item) ****************************************************************************/ /* + Create field for temporary table from given field + + SYNOPSIS + create_tmp_field_from_field() + thd Thread handler + org_field field from which new field will be created + item Item to create a field for + table Temporary table + modify_item 1 if item->result_field should point to new item. + This is relevent for how fill_record() is going to + work: + If modify_item is 1 then fill_record() will update + the record in the original table. + If modify_item is 0 then fill_record() will update + the temporary table + + RETURN + 0 on error + new_created field +*/ +static Field* create_tmp_field_from_field(THD *thd, + Field* org_field, + Item *item, + TABLE *table, + bool modify_item) +{ + Field *new_field; + + // The following should always be true + if ((new_field= org_field->new_field(&thd->mem_root,table))) + { + if (modify_item) + ((Item_field *)item)->result_field= new_field; + else + new_field->field_name= item->name; + if (org_field->maybe_null()) + new_field->flags&= ~NOT_NULL_FLAG; // Because of outer join + if (org_field->type() == FIELD_TYPE_VAR_STRING) + table->db_create_options|= HA_OPTION_PACK_RECORD; + } + return new_field; +} + +/* + Create field for temporary table using type of given item + + SYNOPSIS + create_tmp_field_from_item() + thd Thread handler + item Item to create a field for + table Temporary table + copy_func If set and item is a function, store copy of item + in this array + modify_item 1 if item->result_field should point to new item. + This is relevent for how fill_record() is going to + work: + If modify_item is 1 then fill_record() will update + the record in the original table. + If modify_item is 0 then fill_record() will update + the temporary table + + RETURN + 0 on error + new_created field +*/ +static Field* create_tmp_field_from_item(THD *thd, + Item *item, + TABLE *table, + Item ***copy_func, + bool modify_item) +{ + bool maybe_null=item->maybe_null; + Field *new_field; + LINT_INIT(new_field); + + switch (item->result_type()) { + case REAL_RESULT: + new_field=new Field_double(item->max_length, maybe_null, + item->name, table, item->decimals); + break; + case INT_RESULT: + new_field=new Field_longlong(item->max_length, maybe_null, + item->name, table, item->unsigned_flag); + break; + case STRING_RESULT: + if (item->max_length > 255) + new_field= new Field_blob(item->max_length, maybe_null, + item->name, table, + item->collation.collation); + else + new_field= new Field_string(item->max_length, maybe_null, + item->name, table, + item->collation.collation); + break; + case ROW_RESULT: + default: + // This case should never be choosen + DBUG_ASSERT(0); + new_field= 0; // to satisfy compiler (uninitialized variable) + break; + } + if (copy_func && item->is_result_field()) + *((*copy_func)++) = item; // Save for copy_funcs + if (modify_item) + item->set_result_field(new_field); + return new_field; +} + +/* Create field for temporary table SYNOPSIS @@ -4556,6 +4667,8 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item) type Type of item (normally item->type) copy_func If set and item is a function, store copy of item in this array + from_field if field will be created using other field as example, + pointer example field will be written here group 1 if we are going to do a relative group by on result modify_item 1 if item->result_field should point to new item. This is relevent for how fill_record() is going to @@ -4622,24 +4735,9 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, return 0; // Error } case Item::FIELD_ITEM: - { - Field *org_field=((Item_field*) item)->field,*new_field; - - *from_field=org_field; - // The following should always be true - if ((new_field= org_field->new_field(&thd->mem_root,table))) - { - if (modify_item) - ((Item_field*) item)->result_field= new_field; - else - new_field->field_name=item->name; - if (org_field->maybe_null()) - new_field->flags&= ~NOT_NULL_FLAG; // Because of outer join - if (org_field->type()==FIELD_TYPE_VAR_STRING) - table->db_create_options|= HA_OPTION_PACK_RECORD; - } - return new_field; - } + return create_tmp_field_from_field(thd, (*from_field= + ((Item_field*) item)->field), + item, table, modify_item); case Item::FUNC_ITEM: case Item::COND_ITEM: case Item::FIELD_AVG_ITEM: @@ -4653,40 +4751,14 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, case Item::REF_ITEM: case Item::NULL_ITEM: case Item::VARBIN_ITEM: + return create_tmp_field_from_item(thd, item, table, + copy_func, modify_item); + case Item::TYPE_HOLDER: { - bool maybe_null=item->maybe_null; - Field *new_field; - LINT_INIT(new_field); - - switch (item->result_type()) { - case REAL_RESULT: - new_field=new Field_double(item->max_length,maybe_null, - item->name,table,item->decimals); - break; - case INT_RESULT: - new_field=new Field_longlong(item->max_length,maybe_null, - item->name,table, item->unsigned_flag); - break; - case STRING_RESULT: - if (item->max_length > 255) - new_field= new Field_blob(item->max_length,maybe_null, - item->name,table,item->collation.collation); - else - new_field= new Field_string(item->max_length,maybe_null, - item->name,table,item->collation.collation); - break; - case ROW_RESULT: - default: - // This case should never be choosen - DBUG_ASSERT(0); - new_field= 0; // to satisfy compiler (uninitialized variable) - break; - } - if (copy_func && item->is_result_field()) - *((*copy_func)++) = item; // Save for copy_funcs - if (modify_item) - item->set_result_field(new_field); - return new_field; + Field *example= ((Item_type_holder *)item)->example(); + if (example) + return create_tmp_field_from_field(thd, example, item, table, 0); + return create_tmp_field_from_item(thd, item, table, copy_func, 0); } default: // Dosen't have to be stored return 0; @@ -9077,7 +9149,7 @@ int mysql_explain_select(THD *thd, SELECT_LEX *select_lex, char const *type, select_lex->having, (ORDER*) thd->lex.proc_list.first, select_lex->options | thd->options | SELECT_DESCRIBE, - result, unit, select_lex, 0); + result, unit, select_lex); DBUG_RETURN(res); } diff --git a/sql/sql_select.h b/sql/sql_select.h index 5f0370a5a32..2e101c78613 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -266,7 +266,7 @@ class JOIN :public Sql_alloc int prepare(Item ***rref_pointer_array, TABLE_LIST *tables, uint wind_num, COND *conds, uint og_num, ORDER *order, ORDER *group, Item *having, ORDER *proc_param, SELECT_LEX *select, - SELECT_LEX_UNIT *unit, bool tables_and_fields_initied); + SELECT_LEX_UNIT *unit); int optimize(); int reinit(); void exec(); diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 5292299f928..e2c90e4ff4c 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -25,11 +25,11 @@ #include "sql_select.h" int mysql_union(THD *thd, LEX *lex, select_result *result, - SELECT_LEX_UNIT *unit, bool tables_and_fields_initied) + SELECT_LEX_UNIT *unit) { DBUG_ENTER("mysql_union"); int res= 0; - if (!(res= unit->prepare(thd, result, tables_and_fields_initied))) + if (!(res= unit->prepare(thd, result))) res= unit->exec(); res|= unit->cleanup(); DBUG_RETURN(res); @@ -59,12 +59,6 @@ select_union::~select_union() int select_union::prepare(List<Item> &list, SELECT_LEX_UNIT *u) { unit= u; - if (not_describe && list.elements != table->fields) - { - my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT, - ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),MYF(0)); - return -1; - } return 0; } @@ -112,11 +106,11 @@ bool select_union::flush() } -int st_select_lex_unit::prepare(THD *thd, select_result *sel_result, - bool tables_and_fields_initied) +int st_select_lex_unit::prepare(THD *thd, select_result *sel_result) { SELECT_LEX *lex_select_save= thd->lex.current_select; - SELECT_LEX *select_cursor,*sl; + SELECT_LEX *sl, *first_select; + select_result *tmp_result; DBUG_ENTER("st_select_lex_unit::prepare"); /* @@ -129,74 +123,33 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result, DBUG_RETURN(0); prepared= 1; res= 0; - found_rows_for_union= first_select_in_union()->options & OPTION_FOUND_ROWS; TMP_TABLE_PARAM tmp_table_param; - t_and_f= tables_and_fields_initied; bzero((char *)&tmp_table_param,sizeof(TMP_TABLE_PARAM)); - thd->lex.current_select= sl= select_cursor= first_select_in_union(); + thd->lex.current_select= sl= first_select= first_select_in_union(); + found_rows_for_union= first_select->options & OPTION_FOUND_ROWS; + /* Global option */ - if (t_and_f) + + if (first_select->next_select()) { - // Item list and tables will be initialized by mysql_derived - item_list= select_cursor->item_list; + if (!(tmp_result= union_result= new select_union(0))) + goto err; + union_result->not_describe= 1; + union_result->tmp_table_param= tmp_table_param; } else { - item_list.empty(); - TABLE_LIST *first_table= (TABLE_LIST*) select_cursor->table_list.first; - - if (setup_tables(first_table) || - setup_wild(thd, first_table, select_cursor->item_list, 0, - select_cursor->with_wild)) - goto err; - List_iterator<Item> it(select_cursor->item_list); - Item *item; - item_list= select_cursor->item_list; - select_cursor->with_wild= 0; - if (select_cursor->setup_ref_array(thd, - select_cursor->order_list.elements + - select_cursor->group_list.elements) || - setup_fields(thd, select_cursor->ref_pointer_array, first_table, - item_list, 0, 0, 1)) - goto err; - // Item list should be fix_fielded yet another time in JOIN::prepare - unfix_item_list(item_list); - - t_and_f= 1; - while((item=it++)) - { - item->maybe_null=1; - if (item->type() == Item::FIELD_ITEM) - ((class Item_field *)item)->field->table->maybe_null=1; - } + tmp_result= sel_result; + // single select should be processed like select in p[arantses + first_select->braces= 1; } - tmp_table_param.field_count=item_list.elements; - if (!(table= create_tmp_table(thd, &tmp_table_param, item_list, - (ORDER*) 0, !union_option, - 1, (select_cursor->options | thd->options | - TMP_TABLE_ALL_COLUMNS), - HA_POS_ERROR, (char*) ""))) - goto err; - table->file->extra(HA_EXTRA_WRITE_CACHE); - table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); - bzero((char*) &result_table_list,sizeof(result_table_list)); - result_table_list.db= (char*) ""; - result_table_list.real_name=result_table_list.alias= (char*) "union"; - result_table_list.table=table; - - if (!(union_result=new select_union(table))) - goto err; - - union_result->not_describe=1; - union_result->tmp_table_param=tmp_table_param; - for (;sl; sl= sl->next_select()) { JOIN *join= new JOIN(thd, sl->item_list, sl->options | thd->options | SELECT_NO_UNLOCK, - union_result); + tmp_result); thd->lex.current_select= sl; offset_limit_cnt= sl->offset_limit; select_limit_cnt= sl->select_limit+sl->offset_limit; @@ -215,27 +168,76 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result, (ORDER*) sl->group_list.first, sl->having, (ORDER*) NULL, - sl, this, t_and_f); - t_and_f= 0; + sl, this); if (res || thd->is_fatal_error) goto err; + if (sl == first_select) + { + types.empty(); + List_iterator_fast<Item> it(sl->item_list); + Item *item; + while((item= it++)) + { + types.push_back(new Item_type_holder(thd, item)); + } + + if (thd->is_fatal_error) + goto err; // out of memory + } + else + { + if (types.elements != sl->item_list.elements) + { + my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT, + ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),MYF(0)); + goto err; + } + List_iterator_fast<Item> it(sl->item_list); + List_iterator_fast<Item> tp(types); + Item *type, *item; + while((type= tp++, item= it++)) + { + ((Item_type_holder*)type)->join_types(thd, item); + } + } } - item_list.empty(); - thd->lex.current_select= lex_select_save; + if (first_select->next_select()) { - List_iterator<Item> it(select_cursor->item_list); - Field **field; + tmp_table_param.field_count= types.elements; + if (!(table= create_tmp_table(thd, &tmp_table_param, types, + (ORDER*) 0, !union_option, 1, + (first_select_in_union()->options | + thd->options | + TMP_TABLE_ALL_COLUMNS), + HA_POS_ERROR, (char*) ""))) + goto err; + table->file->extra(HA_EXTRA_WRITE_CACHE); + table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); + bzero((char*) &result_table_list, sizeof(result_table_list)); + result_table_list.db= (char*) ""; + result_table_list.real_name= result_table_list.alias= (char*) "union"; + result_table_list.table= table; + union_result->set_table(table); - for (field= table->field; *field; field++) + item_list.empty(); + thd->lex.current_select= lex_select_save; { - (void) it++; - if (item_list.push_back(new Item_field(*field))) - DBUG_RETURN(-1); + Field **field; + for (field= table->field; *field; field++) + { + if (item_list.push_back(new Item_field(*field))) + DBUG_RETURN(-1); + } } } + else + first_select->braces= 0; // remove our changes + + thd->lex.current_select= lex_select_save; DBUG_RETURN(res || thd->is_fatal_error ? 1 : 0); + err: thd->lex.current_select= lex_select_save; DBUG_RETURN(-1); @@ -419,7 +421,7 @@ int st_select_lex_unit::exec() (ORDER*)global_parameters->order_list.first, (ORDER*) NULL, NULL, (ORDER*) NULL, options | SELECT_NO_UNLOCK, - result, this, fake_select_lex, 0); + result, this, fake_select_lex); if (!res) thd->limit_found_rows = (ulonglong)table->file->records + add_rows; /* diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 9214894e214..8b77f6958d0 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -461,7 +461,7 @@ int mysql_multi_update(THD *thd, conds, 0, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL, (ORDER *)NULL, options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK, - result, unit, select_lex, 0); + result, unit, select_lex); delete result; DBUG_RETURN(res); } |