From 367ded9f71c7209c851e212ecedc538ca810d8da Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 30 Dec 2003 14:08:19 +0400 Subject: [PATCH 01/11] Fix for prepared statements Here i added Item_*::cleanup() functions, removed a lot of ~Item_*'s, added code to restore order_list and group_list sql/item.cc: cleanups methods implemented Item_ref constructors changed sql/item.h: cleanups declared Item_ref constructors changed some ~Item_* deleted sql/item_cmpfunc.cc: new Item_ref format sql/item_cmpfunc.h: saving/restoring of the original arguments added to eq and equal functions sql/item_func.cc: New Item_ref format sql/item_func.h: destructors removed/changed to 'cleanup()' sql/item_row.cc: New Item_ref format sql/item_row.h: ~Item_row -> cleanup() sql/item_strfunc.cc: new Item_ref format sql/item_strfunc.h: destructors removed sql/item_subselect.cc: Item_subselect implementation, new Item_ref() format sql/item_subselect.h: cleanups for subselects declared sql/item_sum.cc: cleanups implementations sql/item_sum.h: cleanups declarations destructors removed sql/mysql_priv.h: free_items, cleanup_items exported sql/sql_prepare.cc: cleanup_items, free_items calls added stmt->query_id= thd->query_id restored cleanup procedures for group_list and order_list added sql/sql_yacc.yy: New Item_ref() format --- sql/item.cc | 18 +++++++++++++++++- sql/item.h | 35 ++++++++++++++++++++++------------- sql/item_cmpfunc.cc | 3 +-- sql/item_cmpfunc.h | 15 +++++++++------ sql/item_func.cc | 2 +- sql/item_func.h | 10 +--------- sql/item_row.cc | 2 +- sql/item_row.h | 6 +++++- sql/item_strfunc.cc | 5 +++-- sql/item_strfunc.h | 2 -- sql/item_subselect.cc | 17 +++++++++++++++-- sql/item_subselect.h | 10 ++++++++++ sql/item_sum.cc | 26 ++++++++++++++++++++------ sql/item_sum.h | 17 ++++++++--------- sql/mysql_priv.h | 5 +++++ sql/sql_prepare.cc | 20 +++++++++++++------- sql/sql_yacc.yy | 10 +++++----- 17 files changed, 136 insertions(+), 67 deletions(-) diff --git a/sql/item.cc b/sql/item.cc index 417f05680cf..e364f095a70 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -920,6 +920,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) Item_ref *rf; *ref= rf= new Item_ref(last->ref_pointer_array + counter, + ref, (char *)table_name, (char *)field_name); if (!rf) @@ -936,7 +937,8 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) if (last->having_fix_field) { Item_ref *rf; - *ref= rf= new Item_ref((where->db[0]?where->db:0), + *ref= rf= new Item_ref(ref, this, + (where->db[0]?where->db:0), (char *)where->alias, (char *)field_name); if (!rf) @@ -962,6 +964,12 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) return 0; } +void Item_field::cleanup() +{ + Item_ident::cleanup(); + field= 0; + result_field= 0; +} void Item::init_make_field(Send_field *tmp_field, enum enum_field_types field_type) @@ -1601,6 +1609,14 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) } +void Item_ref::cleanup() +{ + Item_ident::cleanup(); + if (hook_ptr) + *hook_ptr= orig_item; +} + + void Item_ref::print(String *str) { if (ref && *ref) diff --git a/sql/item.h b/sql/item.h index 5def1e2b710..e1318224498 100644 --- a/sql/item.h +++ b/sql/item.h @@ -290,6 +290,7 @@ public: bool get_time(TIME *ltime); bool is_null() { return field->is_null(); } Item *get_tmp_table_item(THD *thd); + void cleanup(); friend class Item_default_value; friend class Item_insert_value; }; @@ -498,7 +499,6 @@ public: set_name(name_par,0,cs); decimals=NOT_FIXED_DEC; } - ~Item_string() {} enum Type type() const { return STRING_ITEM; } double val() { @@ -565,7 +565,6 @@ class Item_varbinary :public Item { public: Item_varbinary(const char *str,uint str_length); - ~Item_varbinary() {} enum Type type() const { return VARBIN_ITEM; } double val() { return (double) Item_varbinary::val_int(); } longlong val_int(); @@ -602,20 +601,25 @@ public: class Item_ref :public Item_ident { public: - Field *result_field; /* Save result here */ + Field *result_field; /* Save result here */ Item **ref; - Item_ref(const char *db_par, const char *table_name_par, - const char *field_name_par) - :Item_ident(db_par,table_name_par,field_name_par),ref(0) {} - Item_ref(Item **item, const char *table_name_par, const char *field_name_par) - :Item_ident(NullS,table_name_par,field_name_par),ref(item) {} + Item **hook_ptr; /* These two to restore */ + Item *orig_item; /* things in 'cleanup()' */ + Item_ref(Item **hook, Item *original,const char *db_par, + const char *table_name_par, const char *field_name_par) + :Item_ident(db_par,table_name_par,field_name_par),ref(0), hook_ptr(hook), + orig_item(original) {} + Item_ref(Item **item, Item **hook, + const char *table_name_par, const char *field_name_par) + :Item_ident(NullS,table_name_par,field_name_par), + ref(item), hook_ptr(hook), orig_item(hook ? *hook:0) {} // Constructor need to process subselect with temporary tables (see Item) - Item_ref(THD *thd, Item_ref &item) - :Item_ident(thd, item), ref(item.ref) {} + Item_ref(THD *thd, Item_ref &item, Item **hook) + :Item_ident(thd, item), ref(item.ref), + hook_ptr(hook), orig_item(hook ? *hook : 0) {} enum Type type() const { return REF_ITEM; } bool eq(const Item *item, bool binary_cmp) const { return ref && (*ref)->eq(item, binary_cmp); } - ~Item_ref() { if (ref && (*ref) && (*ref) != this) delete *ref; } double val() { double tmp=(*ref)->val_result(); @@ -660,6 +664,7 @@ public: } Item *real_item() { return *ref; } void print(String *str); + void cleanup(); }; class Item_in_subselect; @@ -670,7 +675,7 @@ protected: public: Item_ref_null_helper(Item_in_subselect* master, Item **item, const char *table_name_par, const char *field_name_par): - Item_ref(item, table_name_par, field_name_par), owner(master) {} + Item_ref(item, NULL, table_name_par, field_name_par), owner(master) {} double val(); longlong val_int(); String* val_str(String* s); @@ -734,7 +739,6 @@ public: name=item->name; cached_field_type= item->field_type(); } - ~Item_copy_string() { delete item; } enum Type type() const { return COPY_STR_ITEM; } enum Item_result result_type () const { return STRING_RESULT; } enum_field_types field_type() const { return cached_field_type; } @@ -982,6 +986,11 @@ public: bool check_cols(uint c); bool null_inside(); void bring_value(); + void cleanup() + { + Item_cache::cleanup(); + values= 0; + } }; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index a79ef21e97a..4b270c6aad0 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -496,7 +496,6 @@ longlong Item_func_eq::val_int() return value == 0 ? 1 : 0; } - /* Same as Item_func_eq, but NULL = NULL */ void Item_func_equal::fix_length_and_dec() @@ -1754,7 +1753,7 @@ void Item_cond::split_sum_func(Item **ref_pointer_array, List &fields) uint el= fields.elements; fields.push_front(item); ref_pointer_array[el]= item; - li.replace(new Item_ref(ref_pointer_array + el, 0, item->name)); + li.replace(new Item_ref(ref_pointer_array + el, li.ref(), 0, item->name)); } item->update_used_tables(); used_tables_cache|=item->used_tables(); diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 541bc47557d..50c5449c1ec 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -197,11 +197,19 @@ public: class Item_bool_rowready_func2 :public Item_bool_func2 { + Item *orig_a, *orig_b; /* propagate_const can change parameters */ public: - Item_bool_rowready_func2(Item *a,Item *b) :Item_bool_func2(a,b) + Item_bool_rowready_func2(Item *a,Item *b) :Item_bool_func2(a,b), + orig_a(a), orig_b(b) { allowed_arg_cols= a->cols(); } + void cleanup() + { + Item_bool_func2::cleanup(); + tmp_arg[0]= orig_a; + tmp_arg[1]= orig_b; + } }; class Item_func_not :public Item_bool_func @@ -705,10 +713,6 @@ class Item_func_in :public Item_int_func } longlong val_int(); void fix_length_and_dec(); - ~Item_func_in() - { - cleanup(); /* This is not called by Item::~Item() */ - } void cleanup() { delete array; @@ -888,7 +892,6 @@ public: Item_cond(THD *thd, Item_cond &item); Item_cond(List &nlist) :Item_bool_func(), list(nlist), abort_on_null(0) {} - ~Item_cond() { list.delete_elements(); } bool add(Item *item) { return list.push_back(item); } bool fix_fields(THD *, struct st_table_list *, Item **ref); diff --git a/sql/item_func.cc b/sql/item_func.cc index a251be402ce..33c443ac1c5 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -252,7 +252,7 @@ void Item_func::split_sum_func(Item **ref_pointer_array, List &fields) uint el= fields.elements; fields.push_front(item); ref_pointer_array[el]= item; - *arg= new Item_ref(ref_pointer_array + el, 0, item->name); + *arg= new Item_ref(ref_pointer_array + el, arg, 0, item->name); } } } diff --git a/sql/item_func.h b/sql/item_func.h index ac67b5a4065..634880db7ad 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -107,7 +107,6 @@ public: Item_func(List &list); // Constructor used for Item_cond_and/or (see Item comment) Item_func(THD *thd, Item_func &item); - ~Item_func() {} /* Nothing to do; Items are freed automaticly */ bool fix_fields(THD *,struct st_table_list *, Item **ref); table_map used_tables() const; table_map not_null_tables() const; @@ -755,7 +754,6 @@ public: Item_udf_func(udf_func *udf_arg) :Item_func(), udf(udf_arg) {} Item_udf_func(udf_func *udf_arg, List &list) :Item_func(list), udf(udf_arg) {} - ~Item_udf_func() {} const char *func_name() const { return udf.name(); } bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref) { @@ -776,7 +774,6 @@ class Item_func_udf_float :public Item_udf_func Item_func_udf_float(udf_func *udf_arg) :Item_udf_func(udf_arg) {} Item_func_udf_float(udf_func *udf_arg, List &list) :Item_udf_func(udf_arg,list) {} - ~Item_func_udf_float() {} longlong val_int() { return (longlong) Item_func_udf_float::val(); } double val(); String *val_str(String *str); @@ -790,7 +787,6 @@ public: Item_func_udf_int(udf_func *udf_arg) :Item_udf_func(udf_arg) {} Item_func_udf_int(udf_func *udf_arg, List &list) :Item_udf_func(udf_arg,list) {} - ~Item_func_udf_int() {} longlong val_int(); double val() { return (double) Item_func_udf_int::val_int(); } String *val_str(String *str); @@ -805,7 +801,6 @@ public: Item_func_udf_str(udf_func *udf_arg) :Item_udf_func(udf_arg) {} Item_func_udf_str(udf_func *udf_arg, List &list) :Item_udf_func(udf_arg,list) {} - ~Item_func_udf_str() {} String *val_str(String *); double val() { @@ -830,7 +825,6 @@ class Item_func_udf_float :public Item_real_func public: Item_func_udf_float(udf_func *udf_arg) :Item_real_func() {} Item_func_udf_float(udf_func *udf_arg, List &list) :Item_real_func(list) {} - ~Item_func_udf_float() {} double val() { return 0.0; } }; @@ -840,7 +834,6 @@ class Item_func_udf_int :public Item_int_func public: Item_func_udf_int(udf_func *udf_arg) :Item_int_func() {} Item_func_udf_int(udf_func *udf_arg, List &list) :Item_int_func(list) {} - ~Item_func_udf_int() {} longlong val_int() { return 0; } }; @@ -850,7 +843,6 @@ class Item_func_udf_str :public Item_func public: Item_func_udf_str(udf_func *udf_arg) :Item_func() {} Item_func_udf_str(udf_func *udf_arg, List &list) :Item_func(list) {} - ~Item_func_udf_str() {} String *val_str(String *) { null_value=1; return 0; } double val() { null_value=1; return 0.0; } longlong val_int() { null_value=1; return 0; } @@ -997,7 +989,7 @@ public: Item_func_match(List &a, uint b): Item_real_func(a), key(0), flags(b), join_key(0), ft_handler(0), table(0), master(0), concat(0) { } - ~Item_func_match() + void cleanup() { if (!master && ft_handler) { diff --git a/sql/item_row.cc b/sql/item_row.cc index 89b38c8a753..7f847bd1d4e 100644 --- a/sql/item_row.cc +++ b/sql/item_row.cc @@ -91,7 +91,7 @@ void Item_row::split_sum_func(Item **ref_pointer_array, List &fields) uint el= fields.elements; fields.push_front(*arg); ref_pointer_array[el]= *arg; - *arg= new Item_ref(ref_pointer_array + el, 0, (*arg)->name); + *arg= new Item_ref(ref_pointer_array + el, arg, 0, (*arg)->name); } } } diff --git a/sql/item_row.h b/sql/item_row.h index a09bd1a2c31..1b792f981fd 100644 --- a/sql/item_row.h +++ b/sql/item_row.h @@ -34,10 +34,14 @@ public: with_null(0) {} - ~Item_row() + void cleanup() { if (array_holder && items) + { sql_element_free(items); + items= 0; + array_holder= 0; + } } enum Type type() const { return ROW_ITEM; }; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 3cb03d7ea49..b4580c79f9c 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -616,7 +616,8 @@ void Item_func_concat_ws::split_sum_func(Item **ref_pointer_array, uint el= fields.elements; fields.push_front(separator); ref_pointer_array[el]= separator; - separator= new Item_ref(ref_pointer_array + el, 0, separator->name); + separator= new Item_ref(ref_pointer_array + el, + &separator, 0, separator->name); } Item_str_func::split_sum_func(ref_pointer_array, fields); } @@ -1709,7 +1710,7 @@ void Item_func_make_set::split_sum_func(Item **ref_pointer_array, uint el= fields.elements; fields.push_front(item); ref_pointer_array[el]= item; - item= new Item_ref(ref_pointer_array + el, 0, item->name); + item= new Item_ref(ref_pointer_array + el, &item, 0, item->name); } Item_str_func::split_sum_func(ref_pointer_array, fields); } diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 40b00cdd488..fd0afb19726 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -95,7 +95,6 @@ class Item_func_concat_ws :public Item_str_func public: Item_func_concat_ws(Item *a,List &list) :Item_str_func(list),separator(a) {} - ~Item_func_concat_ws() { delete separator; } String *val_str(String *); void fix_length_and_dec(); void update_used_tables(); @@ -409,7 +408,6 @@ class Item_func_make_set :public Item_str_func public: Item_func_make_set(Item *a,List &list) :Item_str_func(list),item(a) {} - ~Item_func_make_set() { delete item; } String *val_str(String *str); bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) { diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 43775e1c96c..e0d9bcf3bd6 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -63,6 +63,11 @@ void Item_subselect::init(st_select_lex *select_lex, DBUG_VOID_RETURN; } +void Item_subselect::cleanup() +{ + Item_result_field::cleanup(); + engine->cleanup(); +} Item_subselect::~Item_subselect() { @@ -641,7 +646,8 @@ Item_in_subselect::single_value_transformer(JOIN *join, As far as Item_ref_in_optimizer do not substitude itself on fix_fields we can use same item for all selects. */ - expr= new Item_ref((Item**)optimizer->get_cache(), + expr= new Item_ref((Item**)optimizer->get_cache(), + NULL, (char *)"", (char *)in_left_expr_name); @@ -791,7 +797,8 @@ Item_in_subselect::row_value_transformer(JOIN *join) (char *) ""); func= eq_creator.create(new Item_ref((*optimizer->get_cache())-> - addr(i), + addr(i), + NULL, (char *)"", (char *)in_left_expr_name), func); @@ -889,6 +896,12 @@ subselect_single_select_engine(st_select_lex *select, this->select_lex= select_lex; } +void subselect_single_select_engine::cleanup() +{ + prepared= 0; + optimized= 0; + executed= 0; +} subselect_union_engine::subselect_union_engine(st_select_lex_unit *u, select_subselect *result_arg, diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 8444dc7bf66..dc3d07540da 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -69,6 +69,7 @@ public: select_subselect *result); ~Item_subselect(); + void cleanup(); virtual void reset() { null_value= 1; @@ -199,6 +200,13 @@ public: {} + void cleanup() + { + Item_exists_subselect::cleanup(); + abort_on_null= 0; + transformed= 0; + upper_not= 0; + } subs_type substype() { return IN_SUBS; } void reset() { @@ -261,6 +269,7 @@ public: maybe_null= 0; } virtual ~subselect_engine() {}; // to satisfy compiler + virtual void cleanup() {} // set_thd should be called before prepare() void set_thd(THD *thd_arg) { thd= thd_arg; } @@ -290,6 +299,7 @@ public: subselect_single_select_engine(st_select_lex *select, select_subselect *result, Item_subselect *item); + void cleanup(); int prepare(); void fix_length_and_dec(Item_cache** row); int exec(); diff --git a/sql/item_sum.cc b/sql/item_sum.cc index f187650515a..84d00ce8732 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1082,8 +1082,9 @@ int dump_leaf(byte* key, uint32 count __attribute__((unused)), } -Item_sum_count_distinct::~Item_sum_count_distinct() +void Item_sum_count_distinct::cleanup() { + Item_sum_int::cleanup(); /* Free table and tree if they belong to this item (if item have not pointer to original item from which was made copy => it own its objects ) @@ -1095,6 +1096,7 @@ Item_sum_count_distinct::~Item_sum_count_distinct() delete tmp_table_param; if (use_tree) delete_tree(tree); + table= 0; } } @@ -1661,6 +1663,23 @@ Item_func_group_concat::Item_func_group_concat(bool is_distinct, } +void Item_func_group_concat::cleanup() +{ + /* + Free table and tree if they belong to this item (if item have not pointer + to original item from which was made copy => it own its objects ) + */ + if (!original) + { + THD *thd= current_thd; + if (table) + free_tmp_table(thd, table); + delete tmp_table_param; + if (tree_mode) + delete_tree(tree); + } +} + Item_func_group_concat::~Item_func_group_concat() { /* @@ -1676,11 +1695,6 @@ Item_func_group_concat::~Item_func_group_concat() sprintf(warn_buff, ER(ER_CUT_VALUE_GROUP_CONCAT), count_cut_values); warning->set_msg(thd, warn_buff); } - if (table) - free_tmp_table(thd, table); - delete tmp_table_param; - if (tree_mode) - delete_tree(tree); } } diff --git a/sql/item_sum.h b/sql/item_sum.h index 8065218df97..dd180d42011 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -58,7 +58,11 @@ public: Item_sum(List &list); //Copy constructor, need to perform subselects with temporary tables Item_sum(THD *thd, Item_sum &item); - ~Item_sum() { result_field=0; } + void cleanup() + { + Item_result_field::cleanup(); + result_field=0; + } enum Type type() const { return SUM_FUNC_ITEM; } virtual enum Sumfunctype sum_func () const=0; @@ -235,7 +239,7 @@ class Item_sum_count_distinct :public Item_sum_int rec_offset(item.rec_offset), use_tree(item.use_tree), always_null(item.always_null) {} - ~Item_sum_count_distinct(); + void cleanup(); table_map used_tables() const { return used_table_cache; } enum Sumfunctype sum_func () const { return COUNT_DISTINCT_FUNC; } @@ -523,7 +527,6 @@ public: { quick_group=0;} Item_udf_sum(THD *thd, Item_udf_sum &item) :Item_sum(thd, item), udf(item.udf) {} - ~Item_udf_sum() {} const char *func_name() const { return udf.name(); } bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { @@ -548,7 +551,6 @@ class Item_sum_udf_float :public Item_udf_sum :Item_udf_sum(udf_arg,list) {} Item_sum_udf_float(THD *thd, Item_sum_udf_float &item) :Item_udf_sum(thd, item) {} - ~Item_sum_udf_float() {} longlong val_int() { return (longlong) Item_sum_udf_float::val(); } double val(); String *val_str(String*str); @@ -565,7 +567,6 @@ public: :Item_udf_sum(udf_arg,list) {} Item_sum_udf_int(THD *thd, Item_sum_udf_int &item) :Item_udf_sum(thd, item) {} - ~Item_sum_udf_int() {} longlong val_int(); double val() { return (double) Item_sum_udf_int::val_int(); } String *val_str(String*str); @@ -583,7 +584,6 @@ public: :Item_udf_sum(udf_arg,list) {} Item_sum_udf_str(THD *thd, Item_sum_udf_str &item) :Item_udf_sum(thd, item) {} - ~Item_sum_udf_str() {} String *val_str(String *); double val() { @@ -612,7 +612,6 @@ class Item_sum_udf_float :public Item_sum_num Item_sum_udf_float(udf_func *udf_arg, List &list) :Item_sum_num() {} Item_sum_udf_float(THD *thd, Item_sum_udf_float &item) :Item_sum_num(thd, item) {} - ~Item_sum_udf_float() {} enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } double val() { return 0.0; } void clear() {} @@ -628,7 +627,6 @@ public: Item_sum_udf_int(udf_func *udf_arg, List &list) :Item_sum_num() {} Item_sum_udf_int(THD *thd, Item_sum_udf_int &item) :Item_sum_num(thd, item) {} - ~Item_sum_udf_int() {} enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } longlong val_int() { return 0; } double val() { return 0; } @@ -645,7 +643,6 @@ public: Item_sum_udf_str(udf_func *udf_arg, List &list) :Item_sum_num() {} Item_sum_udf_str(THD *thd, Item_sum_udf_str &item) :Item_sum_num(thd, item) {} - ~Item_sum_udf_str() {} String *val_str(String *) { null_value=1; return 0; } double val() { null_value=1; return 0.0; } longlong val_int() { null_value=1; return 0; } @@ -734,6 +731,8 @@ class Item_func_group_concat : public Item_sum quick_group= item.quick_group; }; ~Item_func_group_concat(); + void cleanup(); + enum Sumfunctype sum_func () const {return GROUP_CONCAT_FUNC;} const char *func_name() const { return "group_concat"; } enum Type type() const { return SUM_FUNC_ITEM; } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 15a99385285..d5a521dffe7 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -759,6 +759,11 @@ uint find_type(TYPELIB *lib, const char *find, uint length, bool part_match); uint check_word(TYPELIB *lib, const char *val, const char *end, const char **end_of_word); +/* sql_parse.cc */ +void free_items(Item *item); +void cleanup_items(Item *item); + + /* External variables */ diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 5d6ab165641..dd5825f27ac 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -756,7 +756,9 @@ static bool mysql_test_select_fields(Prepared_statement *stmt, JOIN *join= new JOIN(thd, fields, select_options, result); thd->used_tables= 0; // Updated by setup_fields - if (join->prepare(&select_lex->ref_pointer_array, tables, +// if (join->prepare(&select_lex->ref_pointer_array, tables, + if (join->prepare(&select_lex->ref_pointer_array, + (TABLE_LIST*)select_lex->table_list.first, wild_num, conds, og_num, order, group, having, proc, select_lex, unit)) DBUG_RETURN(1); @@ -925,6 +927,7 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length) sl->prep_where= sl->where; } + cleanup_items(thd->free_list); stmt->set_statement(thd); thd->set_statement(&thd->stmt_backup); @@ -975,14 +978,10 @@ void mysql_stmt_execute(THD *thd, char *packet) DBUG_VOID_RETURN; } - /* - XXX: while thd->query_id is incremented for each command, stmt->query_id - holds query_id of prepare stage. Keeping old query_id seems to be more - natural, but differs from the way prepared statements work in 4.1: - */ - /* stmt->query_id= thd->query_id; */ + stmt->query_id= thd->query_id; thd->stmt_backup.set_statement(thd); thd->set_statement(stmt); + thd->free_list= 0; /* To make sure that all runtime data is stored in its own memory root and @@ -1006,6 +1005,11 @@ void mysql_stmt_execute(THD *thd, char *packet) if (sl->prep_where) sl->where= sl->prep_where->copy_andor_structure(thd); DBUG_ASSERT(sl->join == 0); + ORDER *order; + for (order=(ORDER *)sl->group_list.first ; order ; order=order->next) + order->item= (Item **)(order+1); + for (order=(ORDER *)sl->order_list.first ; order ; order=order->next) + order->item= (Item **)(order+1); } /* @@ -1042,6 +1046,8 @@ void mysql_stmt_execute(THD *thd, char *packet) if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(), WAIT_PRIOR); + free_items(thd->free_list); + cleanup_items(stmt->free_list); free_root(&thd->mem_root, MYF(0)); thd->set_statement(&thd->stmt_backup); DBUG_VOID_RETURN; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 310d8a41be2..5fee5ab13a7 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4486,7 +4486,7 @@ simple_ident: $$= (sel->parsing_place != SELECT_LEX_NODE::IN_HAVING || sel->get_in_sum_expr() > 0) ? (Item*) new Item_field(NullS,NullS,$1.str) : - (Item*) new Item_ref(NullS,NullS,$1.str); + (Item*) new Item_ref(0,0, NullS,NullS,$1.str); } | ident '.' ident { @@ -4502,7 +4502,7 @@ simple_ident: $$= (sel->parsing_place != SELECT_LEX_NODE::IN_HAVING || sel->get_in_sum_expr() > 0) ? (Item*) new Item_field(NullS,$1.str,$3.str) : - (Item*) new Item_ref(NullS,$1.str,$3.str); + (Item*) new Item_ref(0,0,NullS,$1.str,$3.str); } | '.' ident '.' ident { @@ -4518,7 +4518,7 @@ simple_ident: $$= (sel->parsing_place != SELECT_LEX_NODE::IN_HAVING || sel->get_in_sum_expr() > 0) ? (Item*) new Item_field(NullS,$2.str,$4.str) : - (Item*) new Item_ref(NullS,$2.str,$4.str); + (Item*) new Item_ref(0,0,NullS,$2.str,$4.str); } | ident '.' ident '.' ident { @@ -4536,8 +4536,8 @@ simple_ident: (Item*) new Item_field((YYTHD->client_capabilities & CLIENT_NO_SCHEMA ? NullS : $1.str), $3.str, $5.str) : - (Item*) new Item_ref((YYTHD->client_capabilities & - CLIENT_NO_SCHEMA ? NullS : $1.str), + (Item*) new Item_ref(0,0,(YYTHD->client_capabilities & + CLIENT_NO_SCHEMA ? NullS : $1.str), $3.str, $5.str); }; From fbf563e86a219d02fa9bae0c8fb52c34c60bacbe Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 4 Jan 2004 23:44:33 +0200 Subject: [PATCH 02/11] allow UPDATE and DELETE stetements with tables derived from subquery if they are not updated (BUG#2117) allow delete table by alias in multi-delete statement include/mysqld_error.h: new error message about non-updateable table mysql-test/r/derived.result: test of multi-update and multi-delete mysql-test/t/derived.test: test of multi-update and multi-delete sql/share/czech/errmsg.txt: new error message about non-updateable table sql/share/danish/errmsg.txt: new error message about non-updateable table sql/share/dutch/errmsg.txt: new error message about non-updateable table sql/share/english/errmsg.txt: new error message about non-updateable table sql/share/estonian/errmsg.txt: new error message about non-updateable table sql/share/french/errmsg.txt: new error message about non-updateable table sql/share/german/errmsg.txt: new error message about non-updateable table sql/share/greek/errmsg.txt: new error message about non-updateable table sql/share/hungarian/errmsg.txt: new error message about non-updateable table sql/share/italian/errmsg.txt: new error message about non-updateable table sql/share/japanese/errmsg.txt: new error message about non-updateable table sql/share/korean/errmsg.txt: new error message about non-updateable table sql/share/norwegian-ny/errmsg.txt: new error message about non-updateable table sql/share/norwegian/errmsg.txt: new error message about non-updateable table sql/share/polish/errmsg.txt: new error message about non-updateable table sql/share/portuguese/errmsg.txt: new error message about non-updateable table sql/share/romanian/errmsg.txt: new error message about non-updateable table sql/share/russian/errmsg.txt: new error message about non-updateable table sql/share/serbian/errmsg.txt: new error message about non-updateable table sql/share/slovak/errmsg.txt: new error message about non-updateable table sql/share/spanish/errmsg.txt: new error message about non-updateable table sql/share/swedish/errmsg.txt: new error message about non-updateable table sql/share/ukrainian/errmsg.txt: new error message about non-updateable table sql/sql_parse.cc: allow delete table by alias separate error message for try to delete derived table sql/sql_update.cc: test "is updated table derived?" sql/sql_yacc.yy: error message in case of try to update derived table --- include/mysqld_error.h | 3 ++- mysql-test/r/derived.result | 27 +++++++++++++++++++++- mysql-test/t/derived.test | 21 +++++++++++++++++- sql/share/czech/errmsg.txt | 1 + sql/share/danish/errmsg.txt | 1 + sql/share/dutch/errmsg.txt | 1 + sql/share/english/errmsg.txt | 1 + sql/share/estonian/errmsg.txt | 1 + sql/share/french/errmsg.txt | 1 + sql/share/german/errmsg.txt | 1 + sql/share/greek/errmsg.txt | 1 + sql/share/hungarian/errmsg.txt | 1 + sql/share/italian/errmsg.txt | 1 + sql/share/japanese/errmsg.txt | 1 + sql/share/korean/errmsg.txt | 1 + sql/share/norwegian-ny/errmsg.txt | 1 + sql/share/norwegian/errmsg.txt | 1 + sql/share/polish/errmsg.txt | 1 + sql/share/portuguese/errmsg.txt | 1 + sql/share/romanian/errmsg.txt | 1 + sql/share/russian/errmsg.txt | 1 + sql/share/serbian/errmsg.txt | 1 + sql/share/slovak/errmsg.txt | 1 + sql/share/spanish/errmsg.txt | 1 + sql/share/swedish/errmsg.txt | 1 + sql/share/ukrainian/errmsg.txt | 1 + sql/sql_parse.cc | 21 +++++++++++++++--- sql/sql_update.cc | 37 ++++++++++++++++++++++++++++++- sql/sql_yacc.yy | 14 ++++++------ 29 files changed, 132 insertions(+), 14 deletions(-) diff --git a/include/mysqld_error.h b/include/mysqld_error.h index 6a484d0419c..179a2f823d7 100644 --- a/include/mysqld_error.h +++ b/include/mysqld_error.h @@ -303,4 +303,5 @@ #define ER_WARN_HOSTNAME_WONT_WORK 1284 #define ER_UNKNOWN_STORAGE_ENGINE 1285 #define ER_WARN_DEPRECATED_SYNTAX 1286 -#define ER_ERROR_MESSAGES 287 +#define ER_NON_UPDATABLE_TABLE 1287 +#define ER_ERROR_MESSAGES 288 diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result index bb268cd1094..f311b56f519 100644 --- a/mysql-test/r/derived.result +++ b/mysql-test/r/derived.result @@ -209,7 +209,7 @@ ERROR 42000: You have an error in your SQL syntax. Check the manual that corres create table t1 (a int); insert into t1 values (1),(2),(3); update (select * from t1) as t1 set a = 5; -ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use +ERROR HY000: The target table t1 of the UPDATE is not updatable. delete from (select * from t1); ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '(select * from t1)' at line 1 insert into (select * from t1) values (5); @@ -245,3 +245,28 @@ id select_type table type possible_keys key key_len ref rows Extra 2 DERIVED t1 ALL NULL NULL NULL NULL 2 3 UNION t1 ALL NULL NULL NULL NULL 2 drop table t1; +CREATE TABLE `t1` ( +`N` int(11) unsigned NOT NULL default '0', +`M` tinyint(1) default '0', +) TYPE=MyISAM DEFAULT CHARSET=latin1; +Warnings: +Warning 1286 'TYPE=database_engine' is deprecated. Use 'ENGINE=database_engine' instead. +INSERT INTO `t1` (N, M) VALUES (1, 0),(1, 0),(1, 0),(2, 0),(2, 0),(3, 0); +UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2; +select * from t1; +N M +1 2 +1 2 +1 2 +2 2 +2 2 +3 0 +UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2, P2.N = 2; +ERROR HY000: The target table P2 of the UPDATE is not updatable. +delete P1.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N; +select * from t1; +N M +3 0 +delete P1.*,P2.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N; +ERROR HY000: The target table P2 of the DELETE is not updatable. +drop table t1; diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test index caf673d95c1..77e76d16772 100644 --- a/mysql-test/t/derived.test +++ b/mysql-test/t/derived.test @@ -115,7 +115,7 @@ select mail_id, if(folder.f_description!='', folder.f_description, folder.f_nam # create table t1 (a int); insert into t1 values (1),(2),(3); --- error 1149 +-- error 1287 update (select * from t1) as t1 set a = 5; -- error 1064 delete from (select * from t1); @@ -138,3 +138,22 @@ insert into t1 values (1),(2); select * from ( select * from t1 union select * from t1) a,(select * from t1 union select * from t1) b; explain select * from ( select * from t1 union select * from t1) a,(select * from t1 union select * from t1) b; drop table t1; + + +# +# multi-update & multi-delete with derived tables +# +CREATE TABLE `t1` ( + `N` int(11) unsigned NOT NULL default '0', + `M` tinyint(1) default '0', +) TYPE=MyISAM DEFAULT CHARSET=latin1; +INSERT INTO `t1` (N, M) VALUES (1, 0),(1, 0),(1, 0),(2, 0),(2, 0),(3, 0); +UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2; +select * from t1; +-- error 1287 +UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2, P2.N = 2; +delete P1.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N; +select * from t1; +-- error 1287 +delete P1.*,P2.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N; +drop table t1; diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index 85606a060e7..cf5f573774b 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -299,3 +299,4 @@ character-set=latin2 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index d005150cb89..2a42570ded3 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -293,3 +293,4 @@ character-set=latin1 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 3fd44f9ec69..53463c31d02 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -301,3 +301,4 @@ character-set=latin1 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index afce57a9a74..71c8c8f1559 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -290,3 +290,4 @@ character-set=latin1 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index dcdc74f5ab8..fecf0cde7be 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -295,3 +295,4 @@ character-set=latin7 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 94922ca40f4..afc1879a526 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -290,3 +290,4 @@ character-set=latin1 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index 74f50289d86..56e263bc64e 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -302,3 +302,4 @@ character-set=latin1 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index 5813717f57a..1596b1adbab 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -290,3 +290,4 @@ character-set=greek "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index 77ce0b8d4d2..bcd17fca7cc 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -292,3 +292,4 @@ character-set=latin2 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index 204e1f980cc..22a09ac1a1b 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -290,3 +290,4 @@ character-set=latin1 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index af22a2eb49a..b76fa5d8f6d 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -292,3 +292,4 @@ character-set=ujis "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index 6e348736698..482bc91852c 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -290,3 +290,4 @@ character-set=euckr "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index 248d88bd1c9..a442a5879b8 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -292,3 +292,4 @@ character-set=latin1 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index 9055b84f5e9..47660e29676 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -292,3 +292,4 @@ character-set=latin1 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index ec9f3782b08..7f81facf6f5 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -294,3 +294,4 @@ character-set=latin2 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index ffb70632bd4..8ddd281b346 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -291,3 +291,4 @@ character-set=latin1 "MySQL foi inicializado em modo --skip-name-resolve. Você necesita reincializá-lo sem esta opção para este grant funcionar", "Motor de tabela desconhecido '%s'", "'%s' é desatualizado. Use '%s' em seu lugar.", +"The target table %-.100s of the %s is not updatable.", diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index e3640fb7a7a..2235871738c 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -294,3 +294,4 @@ character-set=latin2 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index 5224f19b001..76fc04f42e4 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -292,3 +292,4 @@ character-set=koi8r "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"ôÁÂÌÉÃÁ %-.100s × %s ÎÅ ÍÏÖÅÔ ÉÚÍÅÎÑÔÓÑ.", diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt index 904c8f0c8b9..a61c6a25ccc 100644 --- a/sql/share/serbian/errmsg.txt +++ b/sql/share/serbian/errmsg.txt @@ -285,3 +285,4 @@ character-set=cp1250 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index c7e543a5497..36437930095 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -298,3 +298,4 @@ character-set=latin2 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 845a7da36eb..8e61ce6a62f 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -292,3 +292,4 @@ character-set=latin1 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index 9da0a511ddb..9c13347cc3c 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -290,3 +290,4 @@ character-set=latin1 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"The target table %-.100s of the %s is not updatable.", diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index 7186e0550b2..b5d5f74ef77 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -295,3 +295,4 @@ character-set=koi8u "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work", "Unknown table engine '%s'", "'%s' is deprecated. Use '%s' instead.", +"ôÁÂÌÉÃÑ %-.100s Õ %s ÎÅ ÍÏÖÅ ÏÎÏ×ÌÀ×ÁÔÉÓØ.", diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 465d840e2b8..4310f69d2a7 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2663,15 +2663,30 @@ mysql_execute_command(THD *thd) table_count++; /* All tables in aux_tables must be found in FROM PART */ TABLE_LIST *walk; - for (walk=(TABLE_LIST*) tables ; walk ; walk=walk->next) + for (walk= (TABLE_LIST*) tables; walk; walk= walk->next) { - if (!strcmp(auxi->real_name,walk->real_name) && + if ((!strcmp(auxi->real_name,walk->real_name) || + !strcmp(auxi->real_name,walk->alias)) && !strcmp(walk->db,auxi->db)) break; } if (!walk) { - net_printf(thd,ER_NONUNIQ_TABLE,auxi->real_name); + if (lex->derived_tables) + { + // are we trying to delete derived table? + for (walk= (TABLE_LIST*) tables; walk; walk= walk->next) + { + if (!strcmp(auxi->real_name,walk->alias) && + walk->derived) + { + net_printf(thd, ER_NON_UPDATABLE_TABLE, + auxi->real_name, "DELETE"); + goto error; + } + } + } + net_printf(thd, ER_NONUNIQ_TABLE, auxi->real_name); goto error; } walk->lock_type= auxi->lock_type; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index cdea32ad3f6..87421c482d5 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -434,13 +434,36 @@ int mysql_multi_update(THD *thd, fix_tables_pointers(thd->lex->all_selects_list); select_lex->select_limit= HA_POS_ERROR; + + table_map item_tables= 0, derived_tables= 0; + if (thd->lex->derived_tables) + { + // Assign table map values to check updatability of derived tables + uint tablenr=0; + for (TABLE_LIST *table_list= (TABLE_LIST*) select_lex->table_list.first; + table_list; + table_list= table_list->next, tablenr++) + { + table_list->table->map= (table_map) 1 << tablenr; + } + } if (setup_fields(thd, 0, table_list, *fields, 1, 0, 0)) DBUG_RETURN(-1); + if (thd->lex->derived_tables) + { + // Find tables used in items + List_iterator_fast it(*fields); + Item *item; + while ((item= it++)) + { + item_tables|= item->used_tables(); + } + } /* Count tables and setup timestamp handling */ - for (tl= select_lex->get_table_list() ; tl ; tl=tl->next) + for (tl= select_lex->get_table_list() ; tl ; tl= tl->next) { TABLE *table= tl->table; if (table->timestamp_field) @@ -450,6 +473,18 @@ int mysql_multi_update(THD *thd, if (table->timestamp_field->query_id != thd->query_id) table->time_stamp= table->timestamp_field->offset() +1; } + if (tl->derived) + derived_tables|= table->map; + } + if (thd->lex->derived_tables && (item_tables & derived_tables)) + { + // find derived table which cause error + for (tl= select_lex->get_table_list() ; tl ; tl= tl->next) + { + if (tl->derived && (item_tables & tl->table->map)) + my_printf_error(ER_NON_UPDATABLE_TABLE, ER(ER_NON_UPDATABLE_TABLE), + MYF(0), tl->alias, "UPDATE"); + } } if (!(result=new multi_update(thd, table_list, fields, values, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 310d8a41be2..41fb93891fb 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3155,13 +3155,6 @@ join_table: | '(' SELECT_SYM select_derived ')' opt_table_alias { LEX *lex=Lex; - if (lex->sql_command == SQLCOM_UPDATE && - &lex->select_lex == lex->current_select->outer_select()) - { - send_error(lex->thd, ER_SYNTAX_ERROR); - YYABORT; - } - SELECT_LEX_UNIT *unit= lex->current_select->master_unit(); lex->current_select= unit->outer_select(); if (!($$= lex->current_select-> @@ -3838,6 +3831,13 @@ update: Select->set_lock_for_tables($3); if (lex->select_lex.table_list.elements > 1) lex->sql_command= SQLCOM_UPDATE_MULTI; + else if (lex->select_lex.get_table_list()->derived) + { + /* it is single table update and it is update of derived table */ + net_printf(lex->thd, ER_NON_UPDATABLE_TABLE, + lex->select_lex.get_table_list()->alias, "UPDATE"); + YYABORT; + } } ; From c8eff1773e1a0896ccba36da559bb5db3b8197c8 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 19 Jan 2004 19:53:25 +0400 Subject: [PATCH 03/11] Code cleanup (working on PS & cleanup() code) Item & changed with Item* in Item_xxx constructors tables_list.first -> get_table_list() sql/item.cc: Item& -> Item* sql/item.h: Item& -> Item* sql/item_cmpfunc.cc: Item& -> Item* sql/item_cmpfunc.h: Item& -> Item* sql/item_func.cc: Item& -> Item* sql/item_func.h: Item& -> Item* sql/item_sum.cc: Item& -> Item* sql/item_sum.h: Item& -> Item* sql/item_uniq.h: Item& -> Item* sql/sql_prepare.cc: Code cleanup sql/sql_select.cc: Item& -> Item* --- sql/item.cc | 49 +++++++++-------- sql/item.h | 14 ++--- sql/item_cmpfunc.cc | 6 +-- sql/item_cmpfunc.h | 12 ++--- sql/item_func.cc | 14 ++--- sql/item_func.h | 4 +- sql/item_sum.cc | 38 +++++++------- sql/item_sum.h | 124 ++++++++++++++++++++++---------------------- sql/item_uniq.h | 4 +- sql/sql_prepare.cc | 4 +- sql/sql_select.cc | 2 +- 11 files changed, 135 insertions(+), 136 deletions(-) diff --git a/sql/item.cc b/sql/item.cc index e364f095a70..cbac16cba8d 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -71,18 +71,18 @@ Item::Item(): Used for duplicating lists in processing queries with temporary tables */ -Item::Item(THD *thd, Item &item): - str_value(item.str_value), - name(item.name), - max_length(item.max_length), - marker(item.marker), - decimals(item.decimals), - maybe_null(item.maybe_null), - null_value(item.null_value), - unsigned_flag(item.unsigned_flag), - with_sum_func(item.with_sum_func), - fixed(item.fixed), - collation(item.collation) +Item::Item(THD *thd, Item *item): + str_value(item->str_value), + name(item->name), + max_length(item->max_length), + marker(item->marker), + decimals(item->decimals), + maybe_null(item->maybe_null), + null_value(item->null_value), + unsigned_flag(item->unsigned_flag), + with_sum_func(item->with_sum_func), + fixed(item->fixed), + collation(item->collation) { next= thd->free_list; // Put in free list thd->free_list= this; @@ -110,12 +110,12 @@ Item_ident::Item_ident(const char *db_name_par,const char *table_name_par, } // Constructor used by Item_field & Item_ref (see Item comment) -Item_ident::Item_ident(THD *thd, Item_ident &item): +Item_ident::Item_ident(THD *thd, Item_ident *item): Item(thd, item), - db_name(item.db_name), - table_name(item.table_name), - field_name(item.field_name), - depended_from(item.depended_from) + db_name(item->db_name), + table_name(item->table_name), + field_name(item->field_name), + depended_from(item->depended_from) {} bool Item_ident::remove_dependence_processor(byte * arg) @@ -296,10 +296,10 @@ Item_field::Item_field(Field *f) :Item_ident(NullS,f->table_name,f->field_name) } // Constructor need to process subselect with temporary tables (see Item) -Item_field::Item_field(THD *thd, Item_field &item) +Item_field::Item_field(THD *thd, Item_field *item) :Item_ident(thd, item), - field(item.field), - result_field(item.result_field) + field(item->field), + result_field(item->result_field) { collation.set(DERIVATION_IMPLICIT); } @@ -455,7 +455,7 @@ table_map Item_field::used_tables() const Item *Item_field::get_tmp_table_item(THD *thd) { - Item_field *new_item= new Item_field(thd, *this); + Item_field *new_item= new Item_field(thd, this); if (new_item) new_item->field= new_item->result_field; return new_item; @@ -937,7 +937,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) if (last->having_fix_field) { Item_ref *rf; - *ref= rf= new Item_ref(ref, this, + *ref= rf= new Item_ref(ref, *ref, (where->db[0]?where->db:0), (char *)where->alias, (char *)field_name); @@ -967,8 +967,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) void Item_field::cleanup() { Item_ident::cleanup(); - field= 0; - result_field= 0; + field= result_field= 0; } void Item::init_make_field(Send_field *tmp_field, @@ -2028,7 +2027,7 @@ void Item_cache_row::bring_value() Item_type_holder::Item_type_holder(THD *thd, Item *item) - :Item(thd, *item), item_type(item->result_type()) + :Item(thd, item), item_type(item->result_type()) { DBUG_ASSERT(item->fixed); diff --git a/sql/item.h b/sql/item.h index e1318224498..dc3a9114601 100644 --- a/sql/item.h +++ b/sql/item.h @@ -124,7 +124,7 @@ public: top AND/OR ctructure of WHERE clause to protect it of optimisation changes in prepared statements */ - Item(THD *thd, Item &item); + Item(THD *thd, Item *item); virtual ~Item() { name=0; cleanup(); } /*lint -e1509 */ void set_name(const char *str,uint length, CHARSET_INFO *cs); void init_make_field(Send_field *tmp_field,enum enum_field_types type); @@ -240,7 +240,7 @@ public: st_select_lex *depended_from; Item_ident(const char *db_name_par,const char *table_name_par, const char *field_name_par); - Item_ident::Item_ident(THD *thd, Item_ident &item); + Item_ident::Item_ident(THD *thd, Item_ident *item); const char *full_name() const; bool remove_dependence_processor(byte * arg); @@ -259,7 +259,7 @@ public: :Item_ident(db_par,table_name_par,field_name_par),field(0),result_field(0) { collation.set(DERIVATION_IMPLICIT); } // Constructor need to process subselect with temporary tables (see Item) - Item_field(THD *thd, Item_field &item); + Item_field(THD *thd, Item_field *item); Item_field(Field *field); enum Type type() const { return FIELD_ITEM; } bool eq(const Item *item, bool binary_cmp) const; @@ -581,8 +581,8 @@ public: Field *result_field; /* Save result here */ Item_result_field() :result_field(0) {} // Constructor used for Item_sum/Item_cond_and/or (see Item comment) - Item_result_field(THD *thd, Item_result_field &item): - Item(thd, item), result_field(item.result_field) + Item_result_field(THD *thd, Item_result_field *item): + Item(thd, item), result_field(item->result_field) {} ~Item_result_field() {} /* Required with gcc 2.95 */ Field *get_tmp_table_field() { return result_field; } @@ -614,8 +614,8 @@ public: :Item_ident(NullS,table_name_par,field_name_par), ref(item), hook_ptr(hook), orig_item(hook ? *hook:0) {} // Constructor need to process subselect with temporary tables (see Item) - Item_ref(THD *thd, Item_ref &item, Item **hook) - :Item_ident(thd, item), ref(item.ref), + Item_ref(THD *thd, Item_ref *item, Item **hook) + :Item_ident(thd, item), ref(item->ref), hook_ptr(hook), orig_item(hook ? *hook : 0) {} enum Type type() const { return REF_ITEM; } bool eq(const Item *item, bool binary_cmp) const diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 4b270c6aad0..0b9c7f8d92a 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1651,10 +1651,10 @@ longlong Item_func_bit_and::val_int() return (longlong) (arg1 & arg2); } -Item_cond::Item_cond(THD *thd, Item_cond &item) +Item_cond::Item_cond(THD *thd, Item_cond *item) :Item_bool_func(thd, item), - abort_on_null(item.abort_on_null), - and_tables_cache(item.and_tables_cache) + abort_on_null(item->abort_on_null), + and_tables_cache(item->and_tables_cache) { /* here should be following text: diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 50c5449c1ec..3ad3b928c01 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -82,7 +82,7 @@ public: Item_bool_func() :Item_int_func() {} Item_bool_func(Item *a) :Item_int_func(a) {} Item_bool_func(Item *a,Item *b) :Item_int_func(a,b) {} - Item_bool_func(THD *thd, Item_bool_func &item) :Item_int_func(thd, item) {} + Item_bool_func(THD *thd, Item_bool_func *item) :Item_int_func(thd, item) {} void fix_length_and_dec() { decimals=0; max_length=1; } }; @@ -889,7 +889,7 @@ public: list.push_back(i1); list.push_back(i2); } - Item_cond(THD *thd, Item_cond &item); + Item_cond(THD *thd, Item_cond *item); Item_cond(List &nlist) :Item_bool_func(), list(nlist), abort_on_null(0) {} bool add(Item *item) { return list.push_back(item); } @@ -914,7 +914,7 @@ class Item_cond_and :public Item_cond public: Item_cond_and() :Item_cond() {} Item_cond_and(Item *i1,Item *i2) :Item_cond(i1,i2) {} - Item_cond_and(THD *thd, Item_cond_and &item) :Item_cond(thd, item) {} + Item_cond_and(THD *thd, Item_cond_and *item) :Item_cond(thd, item) {} Item_cond_and(List &list): Item_cond(list) {} enum Functype functype() const { return COND_AND_FUNC; } longlong val_int(); @@ -922,7 +922,7 @@ public: Item* copy_andor_structure(THD *thd) { Item_cond_and *item; - if((item= new Item_cond_and(thd, *this))) + if((item= new Item_cond_and(thd, this))) item->copy_andor_arguments(thd, this); return item; } @@ -934,7 +934,7 @@ class Item_cond_or :public Item_cond public: Item_cond_or() :Item_cond() {} Item_cond_or(Item *i1,Item *i2) :Item_cond(i1,i2) {} - Item_cond_or(THD *thd, Item_cond_or &item) :Item_cond(thd, item) {} + Item_cond_or(THD *thd, Item_cond_or *item) :Item_cond(thd, item) {} Item_cond_or(List &list): Item_cond(list) {} enum Functype functype() const { return COND_OR_FUNC; } longlong val_int(); @@ -943,7 +943,7 @@ public: Item* copy_andor_structure(THD *thd) { Item_cond_or *item; - if((item= new Item_cond_or(thd, *this))) + if((item= new Item_cond_or(thd, this))) item->copy_andor_arguments(thd, this); return item; } diff --git a/sql/item_func.cc b/sql/item_func.cc index 6dbfcc3ef8c..592195dd4b8 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -130,13 +130,13 @@ Item_func::Item_func(List &list) set_arguments(list); } -Item_func::Item_func(THD *thd, Item_func &item) +Item_func::Item_func(THD *thd, Item_func *item) :Item_result_field(thd, item), - allowed_arg_cols(item.allowed_arg_cols), - arg_count(item.arg_count), - used_tables_cache(item.used_tables_cache), - not_null_tables_cache(item.not_null_tables_cache), - const_item_cache(item.const_item_cache) + allowed_arg_cols(item->allowed_arg_cols), + arg_count(item->arg_count), + used_tables_cache(item->used_tables_cache), + not_null_tables_cache(item->not_null_tables_cache), + const_item_cache(item->const_item_cache) { if (arg_count) { @@ -147,7 +147,7 @@ Item_func::Item_func(THD *thd, Item_func &item) if (!(args=(Item**) thd->alloc(sizeof(Item*)*arg_count))) return; } - memcpy((char*) args, (char*) item.args, sizeof(Item*)*arg_count); + memcpy((char*) args, (char*) item->args, sizeof(Item*)*arg_count); } } diff --git a/sql/item_func.h b/sql/item_func.h index 634880db7ad..75839bb80c3 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -106,7 +106,7 @@ public: } Item_func(List &list); // Constructor used for Item_cond_and/or (see Item comment) - Item_func(THD *thd, Item_func &item); + Item_func(THD *thd, Item_func *item); bool fix_fields(THD *,struct st_table_list *, Item **ref); table_map used_tables() const; table_map not_null_tables() const; @@ -199,7 +199,7 @@ public: Item_int_func(Item *a,Item *b) :Item_func(a,b) { max_length=21; } Item_int_func(Item *a,Item *b,Item *c) :Item_func(a,b,c) { max_length=21; } Item_int_func(List &list) :Item_func(list) { max_length=21; } - Item_int_func(THD *thd, Item_int_func &item) :Item_func(thd, item) {} + Item_int_func(THD *thd, Item_int_func *item) :Item_func(thd, item) {} double val() { return (double) val_int(); } String *val_str(String*str); enum Item_result result_type () const { return INT_RESULT; } diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 84d00ce8732..7c2d5501c06 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -42,17 +42,17 @@ Item_sum::Item_sum(List &list) } // Constructor used in processing select with temporary tebles -Item_sum::Item_sum(THD *thd, Item_sum &item): - Item_result_field(thd, item), quick_group(item.quick_group) +Item_sum::Item_sum(THD *thd, Item_sum *item): + Item_result_field(thd, item), quick_group(item->quick_group) { - arg_count= item.arg_count; + arg_count= item->arg_count; if (arg_count <= 2) args=tmp_args; else if (!(args=(Item**) sql_alloc(sizeof(Item*)*arg_count))) return; for (uint i= 0; i < arg_count; i++) - args[i]= item.args[i]; + args[i]= item->args[i]; } void Item_sum::mark_as_sum_func() @@ -240,7 +240,7 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) Item *Item_sum_sum::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_sum_sum(thd, *this); + return new (&thd->mem_root) Item_sum_sum(thd, this); } @@ -267,7 +267,7 @@ double Item_sum_sum::val() Item *Item_sum_count::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_sum_count(thd, *this); + return new (&thd->mem_root) Item_sum_count(thd, this); } @@ -301,7 +301,7 @@ longlong Item_sum_count::val_int() Item *Item_sum_avg::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_sum_avg(thd, *this); + return new (&thd->mem_root) Item_sum_avg(thd, this); } @@ -346,7 +346,7 @@ double Item_sum_std::val() Item *Item_sum_std::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_sum_std(thd, *this); + return new (&thd->mem_root) Item_sum_std(thd, this); } @@ -356,7 +356,7 @@ Item *Item_sum_std::copy_or_same(THD* thd) Item *Item_sum_variance::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_sum_variance(thd, *this); + return new (&thd->mem_root) Item_sum_variance(thd, this); } @@ -497,7 +497,7 @@ Item_sum_hybrid::val_str(String *str) Item *Item_sum_min::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_sum_min(thd, *this); + return new (&thd->mem_root) Item_sum_min(thd, this); } @@ -550,7 +550,7 @@ bool Item_sum_min::add() Item *Item_sum_max::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_sum_max(thd, *this); + return new (&thd->mem_root) Item_sum_max(thd, this); } @@ -616,7 +616,7 @@ void Item_sum_bit::clear() Item *Item_sum_or::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_sum_or(thd, *this); + return new (&thd->mem_root) Item_sum_or(thd, this); } @@ -630,7 +630,7 @@ bool Item_sum_or::add() Item *Item_sum_xor::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_sum_xor(thd, *this); + return new (&thd->mem_root) Item_sum_xor(thd, this); } @@ -644,7 +644,7 @@ bool Item_sum_xor::add() Item *Item_sum_and::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_sum_and(thd, *this); + return new (&thd->mem_root) Item_sum_and(thd, this); } @@ -1281,7 +1281,7 @@ int Item_sum_count_distinct::tree_to_myisam() Item *Item_sum_count_distinct::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_sum_count_distinct(thd, *this); + return new (&thd->mem_root) Item_sum_count_distinct(thd, this); } @@ -1381,7 +1381,7 @@ bool Item_udf_sum::add() Item *Item_sum_udf_float::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_sum_udf_float(thd, *this); + return new (&thd->mem_root) Item_sum_udf_float(thd, this); } double Item_sum_udf_float::val() @@ -1404,7 +1404,7 @@ String *Item_sum_udf_float::val_str(String *str) Item *Item_sum_udf_int::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_sum_udf_int(thd, *this); + return new (&thd->mem_root) Item_sum_udf_int(thd, this); } @@ -1440,7 +1440,7 @@ void Item_sum_udf_str::fix_length_and_dec() Item *Item_sum_udf_str::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_sum_udf_str(thd, *this); + return new (&thd->mem_root) Item_sum_udf_str(thd, this); } @@ -1701,7 +1701,7 @@ Item_func_group_concat::~Item_func_group_concat() Item *Item_func_group_concat::copy_or_same(THD* thd) { - return new (&thd->mem_root) Item_func_group_concat(thd, *this); + return new (&thd->mem_root) Item_func_group_concat(thd, this); } diff --git a/sql/item_sum.h b/sql/item_sum.h index dd180d42011..9f1c8a09a4e 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -57,7 +57,7 @@ public: } Item_sum(List &list); //Copy constructor, need to perform subselects with temporary tables - Item_sum(THD *thd, Item_sum &item); + Item_sum(THD *thd, Item_sum *item); void cleanup() { Item_result_field::cleanup(); @@ -110,7 +110,7 @@ public: Item_sum_num(Item *item_par) :Item_sum(item_par) {} Item_sum_num(Item *a, Item* b) :Item_sum(a,b) {} Item_sum_num(List &list) :Item_sum(list) {} - Item_sum_num(THD *thd, Item_sum_num &item) :Item_sum(thd, item) {} + Item_sum_num(THD *thd, Item_sum_num *item) :Item_sum(thd, item) {} bool fix_fields(THD *, TABLE_LIST *, Item **); longlong val_int() { return (longlong) val(); } /* Real as default */ String *val_str(String*str); @@ -123,7 +123,7 @@ class Item_sum_int :public Item_sum_num public: Item_sum_int(Item *item_par) :Item_sum_num(item_par) {} Item_sum_int(List &list) :Item_sum_num(list) {} - Item_sum_int(THD *thd, Item_sum_int &item) :Item_sum_num(thd, item) {} + Item_sum_int(THD *thd, Item_sum_int *item) :Item_sum_num(thd, item) {} double val() { return (double) val_int(); } String *val_str(String*str); enum Item_result result_type () const { return INT_RESULT; } @@ -139,8 +139,8 @@ class Item_sum_sum :public Item_sum_num public: Item_sum_sum(Item *item_par) :Item_sum_num(item_par),sum(0.0) {} - Item_sum_sum(THD *thd, Item_sum_sum &item) - :Item_sum_num(thd, item), sum(item.sum) {} + Item_sum_sum(THD *thd, Item_sum_sum *item) + :Item_sum_num(thd, item), sum(item->sum) {} enum Sumfunctype sum_func () const {return SUM_FUNC;} void clear(); bool add(); @@ -162,9 +162,9 @@ class Item_sum_count :public Item_sum_int Item_sum_count(Item *item_par) :Item_sum_int(item_par),count(0),used_table_cache(~(table_map) 0) {} - Item_sum_count(THD *thd, Item_sum_count &item) - :Item_sum_int(thd, item), count(item.count), - used_table_cache(item.used_table_cache) + Item_sum_count(THD *thd, Item_sum_count *item) + :Item_sum_int(thd, item), count(item->count), + used_table_cache(item->used_table_cache) {} table_map used_tables() const { return used_table_cache; } bool const_item() const { return !used_table_cache; } @@ -230,14 +230,14 @@ class Item_sum_count_distinct :public Item_sum_int tmp_table_param(0), tree(&tree_base), original(0), use_tree(0), always_null(0) { quick_group= 0; } - Item_sum_count_distinct(THD *thd, Item_sum_count_distinct &item) - :Item_sum_int(thd, item), table(item.table), - used_table_cache(item.used_table_cache), - field_lengths(item.field_lengths), tmp_table_param(item.tmp_table_param), - tree(item.tree), original(&item), key_length(item.key_length), - max_elements_in_tree(item.max_elements_in_tree), - rec_offset(item.rec_offset), use_tree(item.use_tree), - always_null(item.always_null) + Item_sum_count_distinct(THD *thd, Item_sum_count_distinct *item) + :Item_sum_int(thd, item), table(item->table), + used_table_cache(item->used_table_cache), + field_lengths(item->field_lengths), tmp_table_param(item->tmp_table_param), + tree(item->tree), original(item), key_length(item->key_length), + max_elements_in_tree(item->max_elements_in_tree), + rec_offset(item->rec_offset), use_tree(item->use_tree), + always_null(item->always_null) {} void cleanup(); @@ -285,8 +285,8 @@ class Item_sum_avg :public Item_sum_num public: Item_sum_avg(Item *item_par) :Item_sum_num(item_par),count(0) {} - Item_sum_avg(THD *thd, Item_sum_avg &item) - :Item_sum_num(thd, item), sum(item.sum), count(item.count) {} + Item_sum_avg(THD *thd, Item_sum_avg *item) + :Item_sum_num(thd, item), sum(item->sum), count(item->count) {} enum Sumfunctype sum_func () const {return AVG_FUNC;} void clear(); bool add(); @@ -337,9 +337,9 @@ class Item_sum_variance : public Item_sum_num public: Item_sum_variance(Item *item_par) :Item_sum_num(item_par),count(0) {} - Item_sum_variance(THD *thd, Item_sum_variance &item): - Item_sum_num(thd, item), sum(item.sum), sum_sqr(item.sum_sqr), - count(item.count) {} + Item_sum_variance(THD *thd, Item_sum_variance *item): + Item_sum_num(thd, item), sum(item->sum), sum_sqr(item->sum_sqr), + count(item->count) {} enum Sumfunctype sum_func () const { return VARIANCE_FUNC; } void clear(); bool add(); @@ -370,7 +370,7 @@ class Item_sum_std :public Item_sum_variance { public: Item_sum_std(Item *item_par) :Item_sum_variance(item_par) {} - Item_sum_std(THD *thd, Item_sum_std &item) + Item_sum_std(THD *thd, Item_sum_std *item) :Item_sum_variance(thd, item) {} enum Sumfunctype sum_func () const { return STD_FUNC; } @@ -401,11 +401,11 @@ class Item_sum_hybrid :public Item_sum used_table_cache(~(table_map) 0), cmp_charset(&my_charset_bin) {} - Item_sum_hybrid(THD *thd, Item_sum_hybrid &item): - Item_sum(thd, item), value(item.value), tmp_value(item.tmp_value), - sum(item.sum), sum_int(item.sum_int), hybrid_type(item.hybrid_type), - hybrid_field_type(item.hybrid_field_type),cmp_sign(item.cmp_sign), - used_table_cache(item.used_table_cache), cmp_charset(item.cmp_charset) {} + Item_sum_hybrid(THD *thd, Item_sum_hybrid *item): + Item_sum(thd, item), value(item->value), tmp_value(item->tmp_value), + sum(item->sum), sum_int(item->sum_int), hybrid_type(item->hybrid_type), + hybrid_field_type(item->hybrid_field_type),cmp_sign(item->cmp_sign), + used_table_cache(item->used_table_cache), cmp_charset(item->cmp_charset) {} bool fix_fields(THD *, TABLE_LIST *, Item **); table_map used_tables() const { return used_table_cache; } bool const_item() const { return !used_table_cache; } @@ -436,7 +436,7 @@ class Item_sum_min :public Item_sum_hybrid { public: Item_sum_min(Item *item_par) :Item_sum_hybrid(item_par,1) {} - Item_sum_min(THD *thd, Item_sum_min &item) :Item_sum_hybrid(thd, item) {} + Item_sum_min(THD *thd, Item_sum_min *item) :Item_sum_hybrid(thd, item) {} enum Sumfunctype sum_func () const {return MIN_FUNC;} bool add(); @@ -449,7 +449,7 @@ class Item_sum_max :public Item_sum_hybrid { public: Item_sum_max(Item *item_par) :Item_sum_hybrid(item_par,-1) {} - Item_sum_max(THD *thd, Item_sum_max &item) :Item_sum_hybrid(thd, item) {} + Item_sum_max(THD *thd, Item_sum_max *item) :Item_sum_hybrid(thd, item) {} enum Sumfunctype sum_func () const {return MAX_FUNC;} bool add(); @@ -466,8 +466,8 @@ protected: public: Item_sum_bit(Item *item_par,ulonglong reset_arg) :Item_sum_int(item_par),reset_bits(reset_arg),bits(reset_arg) {} - Item_sum_bit(THD *thd, Item_sum_bit &item): - Item_sum_int(thd, item), reset_bits(item.reset_bits), bits(item.bits) {} + Item_sum_bit(THD *thd, Item_sum_bit *item): + Item_sum_int(thd, item), reset_bits(item->reset_bits), bits(item->bits) {} enum Sumfunctype sum_func () const {return SUM_BIT_FUNC;} void clear(); longlong val_int(); @@ -482,7 +482,7 @@ class Item_sum_or :public Item_sum_bit { public: Item_sum_or(Item *item_par) :Item_sum_bit(item_par,LL(0)) {} - Item_sum_or(THD *thd, Item_sum_or &item) :Item_sum_bit(thd, item) {} + Item_sum_or(THD *thd, Item_sum_or *item) :Item_sum_bit(thd, item) {} bool add(); const char *func_name() const { return "bit_or"; } Item *copy_or_same(THD* thd); @@ -493,7 +493,7 @@ class Item_sum_and :public Item_sum_bit { public: Item_sum_and(Item *item_par) :Item_sum_bit(item_par, ULONGLONG_MAX) {} - Item_sum_and(THD *thd, Item_sum_and &item) :Item_sum_bit(thd, item) {} + Item_sum_and(THD *thd, Item_sum_and *item) :Item_sum_bit(thd, item) {} bool add(); const char *func_name() const { return "bit_and"; } Item *copy_or_same(THD* thd); @@ -503,7 +503,7 @@ class Item_sum_xor :public Item_sum_bit { public: Item_sum_xor(Item *item_par) :Item_sum_bit(item_par,LL(0)) {} - Item_sum_xor(THD *thd, Item_sum_xor &item) :Item_sum_bit(thd, item) {} + Item_sum_xor(THD *thd, Item_sum_xor *item) :Item_sum_bit(thd, item) {} bool add(); const char *func_name() const { return "bit_xor"; } Item *copy_or_same(THD* thd); @@ -525,8 +525,8 @@ public: Item_udf_sum( udf_func *udf_arg, List &list ) :Item_sum( list ), udf(udf_arg) { quick_group=0;} - Item_udf_sum(THD *thd, Item_udf_sum &item) - :Item_sum(thd, item), udf(item.udf) {} + Item_udf_sum(THD *thd, Item_udf_sum *item) + :Item_sum(thd, item), udf(item->udf) {} const char *func_name() const { return udf.name(); } bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { @@ -549,7 +549,7 @@ class Item_sum_udf_float :public Item_udf_sum Item_sum_udf_float(udf_func *udf_arg) :Item_udf_sum(udf_arg) {} Item_sum_udf_float(udf_func *udf_arg, List &list) :Item_udf_sum(udf_arg,list) {} - Item_sum_udf_float(THD *thd, Item_sum_udf_float &item) + Item_sum_udf_float(THD *thd, Item_sum_udf_float *item) :Item_udf_sum(thd, item) {} longlong val_int() { return (longlong) Item_sum_udf_float::val(); } double val(); @@ -565,7 +565,7 @@ public: Item_sum_udf_int(udf_func *udf_arg) :Item_udf_sum(udf_arg) {} Item_sum_udf_int(udf_func *udf_arg, List &list) :Item_udf_sum(udf_arg,list) {} - Item_sum_udf_int(THD *thd, Item_sum_udf_int &item) + Item_sum_udf_int(THD *thd, Item_sum_udf_int *item) :Item_udf_sum(thd, item) {} longlong val_int(); double val() { return (double) Item_sum_udf_int::val_int(); } @@ -582,7 +582,7 @@ public: Item_sum_udf_str(udf_func *udf_arg) :Item_udf_sum(udf_arg) {} Item_sum_udf_str(udf_func *udf_arg, List &list) :Item_udf_sum(udf_arg,list) {} - Item_sum_udf_str(THD *thd, Item_sum_udf_str &item) + Item_sum_udf_str(THD *thd, Item_sum_udf_str *item) :Item_udf_sum(thd, item) {} String *val_str(String *); double val() @@ -704,31 +704,31 @@ class Item_func_group_concat : public Item_sum Item_func_group_concat(bool is_distinct,List *is_select, SQL_LIST *is_order,String *is_separator); - Item_func_group_concat(THD *thd, Item_func_group_concat &item) + Item_func_group_concat(THD *thd, Item_func_group_concat *item) :Item_sum(thd, item),item_thd(thd), - tmp_table_param(item.tmp_table_param), - max_elements_in_tree(item.max_elements_in_tree), - warning(item.warning), - warning_available(item.warning_available), - key_length(item.key_length), - rec_offset(item.rec_offset), - tree_mode(item.tree_mode), - distinct(item.distinct), - warning_for_row(item.warning_for_row), - separator(item.separator), - tree(item.tree), - table(item.table), - order(item.order), - tables_list(item.tables_list), - group_concat_max_len(item.group_concat_max_len), - show_elements(item.show_elements), - arg_count_order(item.arg_count_order), - arg_count_field(item.arg_count_field), - arg_show_fields(item.arg_show_fields), - count_cut_values(item.count_cut_values), - original(&item) + tmp_table_param(item->tmp_table_param), + max_elements_in_tree(item->max_elements_in_tree), + warning(item->warning), + warning_available(item->warning_available), + key_length(item->key_length), + rec_offset(item->rec_offset), + tree_mode(item->tree_mode), + distinct(item->distinct), + warning_for_row(item->warning_for_row), + separator(item->separator), + tree(item->tree), + table(item->table), + order(item->order), + tables_list(item->tables_list), + group_concat_max_len(item->group_concat_max_len), + show_elements(item->show_elements), + arg_count_order(item->arg_count_order), + arg_count_field(item->arg_count_field), + arg_show_fields(item->arg_show_fields), + count_cut_values(item->count_cut_values), + original(item) { - quick_group= item.quick_group; + quick_group= item->quick_group; }; ~Item_func_group_concat(); void cleanup(); diff --git a/sql/item_uniq.h b/sql/item_uniq.h index 5c6f6eefb6b..47f967b52c6 100644 --- a/sql/item_uniq.h +++ b/sql/item_uniq.h @@ -38,7 +38,7 @@ class Item_sum_unique_users :public Item_sum_num public: Item_sum_unique_users(Item *name_arg,int start,int end,Item *item_arg) :Item_sum_num(item_arg) {} - Item_sum_unique_users(THD *thd, Item_sum_unique_users &item) + Item_sum_unique_users(THD *thd, Item_sum_unique_users *item) :Item_sum_num(thd, item) {} double val() { return 0.0; } enum Sumfunctype sum_func () const {return UNIQUE_USERS_FUNC;} @@ -53,7 +53,7 @@ public: } Item *copy_or_same(THD* thd) { - return new Item_sum_unique_users(thd, *this); + return new Item_sum_unique_users(thd, this); } void print(String *str) { str->append("0.0", 3); } }; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index dd5825f27ac..52ad9b5e5fc 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -756,9 +756,8 @@ static bool mysql_test_select_fields(Prepared_statement *stmt, JOIN *join= new JOIN(thd, fields, select_options, result); thd->used_tables= 0; // Updated by setup_fields -// if (join->prepare(&select_lex->ref_pointer_array, tables, if (join->prepare(&select_lex->ref_pointer_array, - (TABLE_LIST*)select_lex->table_list.first, + (TABLE_LIST*)select_lex->get_table_list(), wild_num, conds, og_num, order, group, having, proc, select_lex, unit)) DBUG_RETURN(1); @@ -1106,6 +1105,7 @@ void mysql_stmt_free(THD *thd, char *packet) if (!(stmt= find_prepared_statement(thd, stmt_id, "close"))) DBUG_VOID_RETURN; + free_items(stmt->free_list); /* Statement map deletes statement on erase */ thd->stmt_map.erase(stmt); DBUG_VOID_RETURN; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index a1f6abfd53a..58b876704b0 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8282,7 +8282,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, if (pos->type() == Item::FIELD_ITEM) { Item_field *item; - if (!(item= new Item_field(thd, *((Item_field*) pos)))) + if (!(item= new Item_field(thd, ((Item_field*) pos)))) goto err; pos= item; if (item->field->flags & BLOB_FLAG) From 584e137887326584e1f24d2061e75486d745584e Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 19 Jan 2004 21:05:26 +0400 Subject: [PATCH 04/11] Code cleanup Superfluous line removed sql/sql_prepare.cc: Line is not needed --- sql/sql_prepare.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 52ad9b5e5fc..b5dd4083dcf 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1105,7 +1105,6 @@ void mysql_stmt_free(THD *thd, char *packet) if (!(stmt= find_prepared_statement(thd, stmt_id, "close"))) DBUG_VOID_RETURN; - free_items(stmt->free_list); /* Statement map deletes statement on erase */ thd->stmt_map.erase(stmt); DBUG_VOID_RETURN; From 4e6744a45fd95a5ca86b183277fe0684b0c9d795 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 20 Jan 2004 17:35:51 +0200 Subject: [PATCH 05/11] row0sel.c: Remove extra mtr_start() innobase/row/row0sel.c: Remove extra mtr_start() --- innobase/row/row0sel.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c index 5a5da3ba59a..57de309c090 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -2903,8 +2903,6 @@ row_search_for_mysql( mtr_start(&mtr); - mtr_start(&mtr); - /*-------------------------------------------------------------*/ /* PHASE 2: Try fast adaptive hash index search if possible */ From 9768dc84c83eee93954a57f310ef3896861432b2 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 20 Jan 2004 20:55:47 +0400 Subject: [PATCH 06/11] Pack of changes about 'cleanup()'-s Some errorneous code trimmed sql/item.cc: initialization of the Item_type_holder::orig_item added sql/item.h: No use to call cleanup() in ~Item this only calls Item::cleanup() We should use item->delete_self() instead of 'delete item' now Code added to restore Item_type_holder::item_type value sql/item_row.h: this cleanup is wrong sql/item_sum.cc: initialization added sql/item_sum.h: Item_xxx& -> Item_xxx* sql/sql_parse.cc: delete item -> item->delete_self() --- sql/item.cc | 3 ++- sql/item.h | 13 ++++++++++++- sql/item_row.h | 10 ---------- sql/item_sum.cc | 1 + sql/item_sum.h | 6 +++--- sql/sql_parse.cc | 2 +- 6 files changed, 19 insertions(+), 16 deletions(-) diff --git a/sql/item.cc b/sql/item.cc index 72c5ac3fd55..09328dfbf07 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2024,7 +2024,8 @@ void Item_cache_row::bring_value() Item_type_holder::Item_type_holder(THD *thd, Item *item) - :Item(thd, item), item_type(item->result_type()) + :Item(thd, item), item_type(item->result_type()), + orig_type(item_type) { DBUG_ASSERT(item->fixed); diff --git a/sql/item.h b/sql/item.h index e9d34568350..d06977f555e 100644 --- a/sql/item.h +++ b/sql/item.h @@ -125,7 +125,7 @@ public: optimisation changes in prepared statements */ Item(THD *thd, Item *item); - virtual ~Item() { name=0; cleanup(); } /*lint -e1509 */ + virtual ~Item() { name=0; } /*lint -e1509 */ void set_name(const char *str,uint length, CHARSET_INFO *cs); void init_make_field(Send_field *tmp_field,enum enum_field_types type); virtual void cleanup() { fixed=0; } @@ -227,6 +227,11 @@ public: /* Used in sql_select.cc:eliminate_not_funcs() */ virtual Item *neg_transformer() { return NULL; } + void delete_self() + { + cleanup(); + delete this; + } }; @@ -1003,6 +1008,7 @@ class Item_type_holder: public Item { protected: Item_result item_type; + Item_result orig_type; Field *field_example; public: Item_type_holder(THD*, Item*); @@ -1014,6 +1020,11 @@ public: String *val_str(String*); bool join_types(THD *thd, Item *); Field *example() { return field_example; } + void cleanup() + { + Item::cleanup(); + item_type= orig_type; + } }; diff --git a/sql/item_row.h b/sql/item_row.h index 1b792f981fd..f87b4f66e80 100644 --- a/sql/item_row.h +++ b/sql/item_row.h @@ -34,16 +34,6 @@ public: with_null(0) {} - void cleanup() - { - if (array_holder && items) - { - sql_element_free(items); - items= 0; - array_holder= 0; - } - } - enum Type type() const { return ROW_ITEM; }; void illegal_method_call(const char *); bool is_null() { return null_value; } diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 7c2d5501c06..e01f9db3463 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1097,6 +1097,7 @@ void Item_sum_count_distinct::cleanup() if (use_tree) delete_tree(tree); table= 0; + use_tree= 0; } } diff --git a/sql/item_sum.h b/sql/item_sum.h index 9f1c8a09a4e..dc84e4d4ab7 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -610,7 +610,7 @@ class Item_sum_udf_float :public Item_sum_num public: Item_sum_udf_float(udf_func *udf_arg) :Item_sum_num() {} Item_sum_udf_float(udf_func *udf_arg, List &list) :Item_sum_num() {} - Item_sum_udf_float(THD *thd, Item_sum_udf_float &item) + Item_sum_udf_float(THD *thd, Item_sum_udf_float *item) :Item_sum_num(thd, item) {} enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } double val() { return 0.0; } @@ -625,7 +625,7 @@ class Item_sum_udf_int :public Item_sum_num public: Item_sum_udf_int(udf_func *udf_arg) :Item_sum_num() {} Item_sum_udf_int(udf_func *udf_arg, List &list) :Item_sum_num() {} - Item_sum_udf_int(THD *thd, Item_sum_udf_int &item) + Item_sum_udf_int(THD *thd, Item_sum_udf_int *item) :Item_sum_num(thd, item) {} enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } longlong val_int() { return 0; } @@ -641,7 +641,7 @@ class Item_sum_udf_str :public Item_sum_num public: Item_sum_udf_str(udf_func *udf_arg) :Item_sum_num() {} Item_sum_udf_str(udf_func *udf_arg, List &list) :Item_sum_num() {} - Item_sum_udf_str(THD *thd, Item_sum_udf_str &item) + Item_sum_udf_str(THD *thd, Item_sum_udf_str *item) :Item_sum_num(thd, item) {} String *val_str(String *) { null_value=1; return 0; } double val() { null_value=1; return 0.0; } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index de75ed301e5..7929247676f 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1109,7 +1109,7 @@ end: void free_items(Item *item) { for (; item ; item=item->next) - delete item; + item->delete_self(); } /* This works because items are allocated with sql_alloc() */ From 7a1a5cd2d828d67120d10eb623c6c5bd83733260 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 20 Jan 2004 19:16:18 +0200 Subject: [PATCH 07/11] for multy-delete command used same algorithm of table reference (alias) mysql-test/t/multi_update.test: new results of changed multi-delete mysql-test/t/update.test: new results of changed multi-delete mysql-test/r/multi_update.result: new results of changed multi-delete mysql-test/r/update.result: new results of changed multi-delete --- mysql-test/r/multi_update.result | 2 +- mysql-test/r/update.result | 2 +- mysql-test/t/multi_update.test | 2 +- mysql-test/t/update.test | 2 +- sql/sql_parse.cc | 5 ++--- 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result index d335c9c1d10..a61ce31b8ae 100644 --- a/mysql-test/r/multi_update.result +++ b/mysql-test/r/multi_update.result @@ -244,7 +244,7 @@ select * from t2; n d 1 30 1 30 -DELETE t1, t2 FROM t1 a,t2 b where a.n=b.n; +DELETE a, b FROM t1 a,t2 b where a.n=b.n; select * from t1; n d 3 2 diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result index 6a5546200ce..0037fb9ea95 100644 --- a/mysql-test/r/update.result +++ b/mysql-test/r/update.result @@ -158,7 +158,7 @@ insert into t1 (F1,F2,F3,cnt,groupid) values ('0','0','0',1,6), ('0','1','2',1,5), ('0','2','0',1,3), ('1','0','1',1,2), ('1','2','1',1,1), ('1','2','2',1,1), ('2','0','1',2,4), ('2','2','0',1,7); -delete from t1 using t1 m1,t1 m2 where m1.groupid=m2.groupid and (m1.cnt < m2.cnt or m1.cnt=m2.cnt and m1.F3>m2.F3); +delete from m1 using t1 m1,t1 m2 where m1.groupid=m2.groupid and (m1.cnt < m2.cnt or m1.cnt=m2.cnt and m1.F3>m2.F3); select * from t1; F1 F2 F3 cnt groupid 0 0 0 1 6 diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test index 6f012801972..e52b373a4a6 100644 --- a/mysql-test/t/multi_update.test +++ b/mysql-test/t/multi_update.test @@ -218,7 +218,7 @@ select * from t2; UPDATE t1 a ,t2 b SET a.d=b.d,b.d=30 WHERE a.n=b.n; select * from t1; select * from t2; -DELETE t1, t2 FROM t1 a,t2 b where a.n=b.n; +DELETE a, b FROM t1 a,t2 b where a.n=b.n; select * from t1; select * from t2; drop table t1,t2; diff --git a/mysql-test/t/update.test b/mysql-test/t/update.test index 8e50fee56fd..3406dfd6158 100644 --- a/mysql-test/t/update.test +++ b/mysql-test/t/update.test @@ -126,6 +126,6 @@ insert into t1 (F1,F2,F3,cnt,groupid) values ('0','0','0',1,6), ('1','2','1',1,1), ('1','2','2',1,1), ('2','0','1',2,4), ('2','2','0',1,7); -delete from t1 using t1 m1,t1 m2 where m1.groupid=m2.groupid and (m1.cnt < m2.cnt or m1.cnt=m2.cnt and m1.F3>m2.F3); +delete from m1 using t1 m1,t1 m2 where m1.groupid=m2.groupid and (m1.cnt < m2.cnt or m1.cnt=m2.cnt and m1.F3>m2.F3); select * from t1; drop table t1; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 4310f69d2a7..64af7d21927 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2665,9 +2665,8 @@ mysql_execute_command(THD *thd) TABLE_LIST *walk; for (walk= (TABLE_LIST*) tables; walk; walk= walk->next) { - if ((!strcmp(auxi->real_name,walk->real_name) || - !strcmp(auxi->real_name,walk->alias)) && - !strcmp(walk->db,auxi->db)) + if (!strcmp(auxi->real_name, walk->alias) && + !strcmp(walk->db, auxi->db)) break; } if (!walk) From 53d6a088bcbab1777e32777e80a548b46f1140af Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Jan 2004 00:08:18 +0400 Subject: [PATCH 08/11] Fix for #2278 (mysql_prepare and mysql_execute not exported in libmysqld.dll) Actually no PS-related methods were exported. Now they're in the libmysqld.def VC++Files/libmysqld/libmysqld.def: PS related methods added --- VC++Files/libmysqld/libmysqld.def | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/VC++Files/libmysqld/libmysqld.def b/VC++Files/libmysqld/libmysqld.def index c3f757b5f1a..37a6114a6d0 100644 --- a/VC++Files/libmysqld/libmysqld.def +++ b/VC++Files/libmysqld/libmysqld.def @@ -92,6 +92,28 @@ EXPORTS mysql_thread_safe mysql_use_result mysql_warning_count + mysql_prepare + mysql_execute + mysql_param_count + mysql_bind_param + mysql_bind_result + mysql_fetch + mysql_fetch_column + mysql_send_long_data + mysql_get_metadata + mysql_param_result + mysql_stmt_close + mysql_stmt_reset + mysql_stmt_free_result + mysql_stmt_errno + mysql_stmt_error + mysql_stmt_sqlstate + mysql_stmt_affected_rows + mysql_stmt_store_result + mysql_stmt_row_seek + mysql_stmt_row_tell + mysql_stmt_data_seek + mysql_stmt_num_rows net_buffer_length set_dynamic strcend From cf240e4ee83b39fbbccf92a35f394cb2793437a5 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Jan 2004 14:15:19 +0400 Subject: [PATCH 09/11] Further fixes for 2390: ucs2 alignment --- mysql-test/r/ctype_ucs.result | 56 +++++++++++++++++++++++++++++++++++ mysql-test/t/ctype_ucs.test | 38 +++++++++++++++++++++++- sql/field.cc | 16 ++++------ sql/sql_string.cc | 54 ++++++++++++++++++++++++++++++--- sql/sql_string.h | 3 ++ 5 files changed, 152 insertions(+), 15 deletions(-) diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index d6e9cc690a2..8d9c7579771 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -324,3 +324,59 @@ HEX(_ucs2 0x0123456789ABCDE) SELECT HEX(_ucs2 0x0123456789ABCDEF); HEX(_ucs2 0x0123456789ABCDEF) 0123456789ABCDEF +SELECT hex(cast(0xAA as char character set ucs2)); +hex(cast(0xAA as char character set ucs2)) +00AA +SELECT hex(convert(0xAA using ucs2)); +hex(convert(0xAA using ucs2)) +00AA +CREATE TABLE t1 (a char(10) character set ucs2); +INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA); +SELECT HEX(a) FROM t1; +HEX(a) +000A +00AA +0AAA +AAAA +000AAAAA +DROP TABLE t1; +CREATE TABLE t1 (a varchar(10) character set ucs2); +INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA); +SELECT HEX(a) FROM t1; +HEX(a) +000A +00AA +0AAA +AAAA +000AAAAA +DROP TABLE t1; +CREATE TABLE t1 (a text character set ucs2); +INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA); +SELECT HEX(a) FROM t1; +HEX(a) +000A +00AA +0AAA +AAAA +000AAAAA +DROP TABLE t1; +CREATE TABLE t1 (a mediumtext character set ucs2); +INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA); +SELECT HEX(a) FROM t1; +HEX(a) +000A +00AA +0AAA +AAAA +000AAAAA +DROP TABLE t1; +CREATE TABLE t1 (a longtext character set ucs2); +INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA); +SELECT HEX(a) FROM t1; +HEX(a) +000A +00AA +0AAA +AAAA +000AAAAA +DROP TABLE t1; diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index fd2a1b1cd7d..021147e258a 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -200,7 +200,7 @@ DROP TABLE t1; # Bug #2390 -# Check alignment +# Check alignment for constants # SELECT HEX(_ucs2 0x0); SELECT HEX(_ucs2 0x01); @@ -218,3 +218,39 @@ SELECT HEX(_ucs2 0x0123456789ABC); SELECT HEX(_ucs2 0x0123456789ABCD); SELECT HEX(_ucs2 0x0123456789ABCDE); SELECT HEX(_ucs2 0x0123456789ABCDEF); + +# +# Check alignment for from-binary-conversion with CAST and CONVERT +# +SELECT hex(cast(0xAA as char character set ucs2)); +SELECT hex(convert(0xAA using ucs2)); + +# +# Check alignment for string types +# +CREATE TABLE t1 (a char(10) character set ucs2); +INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA); +SELECT HEX(a) FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a varchar(10) character set ucs2); +INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA); +SELECT HEX(a) FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a text character set ucs2); +INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA); +SELECT HEX(a) FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a mediumtext character set ucs2); +INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA); +SELECT HEX(a) FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a longtext character set ucs2); +INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA); +SELECT HEX(a) FROM t1; +DROP TABLE t1; + +-- the same should be also done with enum and set diff --git a/sql/field.cc b/sql/field.cc index 1a0716326fe..8dc133adae8 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4055,18 +4055,13 @@ void Field_datetime::sql_type(String &res) const /* Copy a string and fill with space */ -static bool use_conversion(CHARSET_INFO *cs1, CHARSET_INFO *cs2) -{ - return (cs1 != &my_charset_bin) && (cs2 != &my_charset_bin) && (cs1!=cs2); -} - int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) { int error= 0; char buff[80]; String tmpstr(buff,sizeof(buff), &my_charset_bin); /* Convert character set if nesessary */ - if (use_conversion(cs, field_charset)) + if (String::needs_conversion(from, length, cs, field_charset)) { tmpstr.copy(from, length, cs, field_charset); from= tmpstr.ptr(); @@ -4254,7 +4249,7 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs) char buff[80]; String tmpstr(buff,sizeof(buff), &my_charset_bin); /* Convert character set if nesessary */ - if (use_conversion(cs, field_charset)) + if (String::needs_conversion(from, length, cs, field_charset)) { tmpstr.copy(from, length, cs, field_charset); from= tmpstr.ptr(); @@ -4572,7 +4567,8 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) String tmpstr(buff,sizeof(buff), &my_charset_bin); /* Convert character set if nesessary */ - if ((was_conversion= use_conversion(cs, field_charset))) + if ((was_conversion= String::needs_conversion(from, length, + cs, field_charset))) { tmpstr.copy(from, length, cs, field_charset); from= tmpstr.ptr(); @@ -5082,7 +5078,7 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs) char buff[80]; String tmpstr(buff,sizeof(buff), &my_charset_bin); /* Convert character set if nesessary */ - if (use_conversion(cs, field_charset)) + if (String::needs_conversion(from, length, cs, field_charset)) { tmpstr.copy(from, length, cs, field_charset); from= tmpstr.ptr(); @@ -5263,7 +5259,7 @@ int Field_set::store(const char *from,uint length,CHARSET_INFO *cs) String tmpstr(buff,sizeof(buff), &my_charset_bin); /* Convert character set if nesessary */ - if (use_conversion(cs, field_charset)) + if (String::needs_conversion(from, length, cs, field_charset)) { tmpstr.copy(from, length, cs, field_charset); from= tmpstr.ptr(); diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 9534c5605fe..225076bc555 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -228,6 +228,32 @@ bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *cs) return FALSE; } + +/* + Checks that the source string can be just copied + to the destination string without conversion. + If either character set conversion or adding leading + zeros (e.g. for UCS-2) must be done then return + value is TRUE else FALSE. +*/ +bool String::needs_conversion(const char *str, uint32 arg_length, + CHARSET_INFO *from_cs, + CHARSET_INFO *to_cs) +{ + if (to_cs == &my_charset_bin) + return FALSE; + if (to_cs == from_cs) + return FALSE; + if (my_charset_same(from_cs, to_cs)) + return FALSE; + if ((from_cs == &my_charset_bin)) + { + if (!(arg_length % to_cs->mbminlen)) + return FALSE; + } + return TRUE; +} + /* ** For real multi-byte, ascii incompatible charactser sets, ** like UCS-2, add leading zeros if we have an incomplete character. @@ -237,15 +263,15 @@ bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *cs) ** SELECT _ucs2 0x00AA */ -bool String::set_or_copy_aligned(const char *str,uint32 arg_length, - CHARSET_INFO *cs) +bool String::copy_aligned(const char *str,uint32 arg_length, + CHARSET_INFO *cs) { /* How many bytes are in incomplete character */ uint32 offs= (arg_length % cs->mbminlen); if (!offs) /* All characters are complete, just copy */ { - set(str, arg_length, cs); + copy(str, arg_length, cs); return FALSE; } @@ -274,15 +300,35 @@ bool String::set_or_copy_aligned(const char *str,uint32 arg_length, return FALSE; } + +bool String::set_or_copy_aligned(const char *str,uint32 arg_length, + CHARSET_INFO *cs) +{ + /* How many bytes are in incomplete character */ + uint32 offs= (arg_length % cs->mbminlen); + + if (!offs) /* All characters are complete, just copy */ + { + set(str, arg_length, cs); + return FALSE; + } + return copy_aligned(str, arg_length, cs); +} + /* Copy with charset convertion */ bool String::copy(const char *str, uint32 arg_length, CHARSET_INFO *from_cs, CHARSET_INFO *to_cs) { - if ((from_cs == &my_charset_bin) || (to_cs == &my_charset_bin)) + if (!needs_conversion(str, arg_length, from_cs, to_cs)) { return copy(str, arg_length, to_cs); } + if ((from_cs == &my_charset_bin) && (arg_length % to_cs->mbminlen)) + { + return copy_aligned(str, arg_length, to_cs); + } + uint32 new_length= to_cs->mbmaxlen*arg_length; if (alloc(new_length)) return TRUE; diff --git a/sql/sql_string.h b/sql/sql_string.h index 8817aa8eab8..9c0900137e3 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -183,6 +183,9 @@ public: bool copy(); // Alloc string if not alloced bool copy(const String &s); // Allocate new string bool copy(const char *s,uint32 arg_length, CHARSET_INFO *cs); // Allocate new string + static bool needs_conversion(const char *s, uint32 arg_length, + CHARSET_INFO *cs_from, CHARSET_INFO *cs_to); + bool copy_aligned(const char *s, uint32 arg_length, CHARSET_INFO *cs); bool set_or_copy_aligned(const char *s, uint32 arg_length, CHARSET_INFO *cs); bool copy(const char*s,uint32 arg_length, CHARSET_INFO *csfrom, CHARSET_INFO *csto); From 335ad8f25514a3c78887a7c8a34f47efc2cf71de Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Jan 2004 14:32:02 +0400 Subject: [PATCH 10/11] sql_string.cc: Rewrote to comply the coding style sql/sql_string.cc: Rewrote to comply the coding style --- sql/sql_string.cc | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 225076bc555..42e700b27aa 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -240,17 +240,12 @@ bool String::needs_conversion(const char *str, uint32 arg_length, CHARSET_INFO *from_cs, CHARSET_INFO *to_cs) { - if (to_cs == &my_charset_bin) + if ((to_cs == &my_charset_bin) || + (to_cs == from_cs) || + my_charset_same(from_cs, to_cs) || + ((from_cs == &my_charset_bin) && (!(arg_length % to_cs->mbminlen)))) return FALSE; - if (to_cs == from_cs) - return FALSE; - if (my_charset_same(from_cs, to_cs)) - return FALSE; - if ((from_cs == &my_charset_bin)) - { - if (!(arg_length % to_cs->mbminlen)) - return FALSE; - } + return TRUE; } From b5567d15031a8a84d184038f73fedc5f24fc1a08 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Jan 2004 15:47:47 +0400 Subject: [PATCH 11/11] yet another cleanup()-related fix sql/sql_lex.cc: We need these to be clean. Otherwise restoring of the order_list and group_list could fail in mysql_stmt_execute() --- sql/sql_lex.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index efb0ce92ad0..fea16dccd4a 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -127,6 +127,8 @@ LEX *lex_start(THD *thd, uchar *buf,uint length) lex->select_lex.expr_list.empty(); lex->select_lex.ftfunc_list_alloc.empty(); lex->select_lex.ftfunc_list= &lex->select_lex.ftfunc_list_alloc; + lex->select_lex.group_list.empty(); + lex->select_lex.order_list.empty(); lex->current_select= &lex->select_lex; lex->yacc_yyss=lex->yacc_yyvs=0; lex->ignore_space=test(thd->variables.sql_mode & MODE_IGNORE_SPACE);