From d868d032aa5f12ad95c1b9f9ffa54cbdda61cafc Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 5 Apr 2006 12:39:06 +0200 Subject: [PATCH 01/32] BUG#18198: Too much expressiveness in partition functions allowed First step sql/item.h: Add function to check for partition function whether allowed or not. In this first step allow only a field on its own. Further steps will add a lot more possibilities. sql/partition_info.cc: Add a check whether the partition function is allowed by walking the partition function expression. sql/share/errmsg.txt: Add a new error code for partition function not allowed --- sql/item.h | 6 ++++++ sql/partition_info.cc | 7 +++++++ sql/share/errmsg.txt | 3 +++ 3 files changed, 16 insertions(+) diff --git a/sql/item.h b/sql/item.h index 6c7a0976df1..9c979eb4acd 100644 --- a/sql/item.h +++ b/sql/item.h @@ -744,6 +744,11 @@ public: virtual bool find_item_in_field_list_processor(byte *arg) { return 0; } virtual bool change_context_processor(byte *context) { return 0; } virtual bool reset_query_id_processor(byte *query_id) { return 0; } + virtual bool check_partition_func_processor(byte *bool_arg) + { + *(bool *)bool_arg= FALSE; + return 0; + } virtual Item *equal_fields_propagator(byte * arg) { return this; } virtual Item *set_no_const_sub(byte *arg) { return this; } @@ -1202,6 +1207,7 @@ public: result_field->query_id= field->query_id; return 0; } + bool check_partition_func_processor(byte *bool_arg) { return 0; } void cleanup(); Item_equal *find_item_equal(COND_EQUAL *cond_equal); Item *equal_fields_propagator(byte *arg); diff --git a/sql/partition_info.cc b/sql/partition_info.cc index ad0aa053ae2..9c7999b136b 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -655,8 +655,15 @@ bool partition_info::check_partition_info(handlerton **eng_type, uint i, tot_partitions; bool result= TRUE; char *same_name; + bool part_expression_ok= TRUE; DBUG_ENTER("partition_info::check_partition_info"); + if (part_expr->walk(Item::check_partition_func_processor, + (byte*)&part_expression_ok)) + { + my_error(ER_PARTITION_FUNC_NOT_ALLOWED, MYF(0)); + goto end; + } if (unlikely(!is_sub_partitioned() && !(use_default_subpartitions && use_default_no_subpartitions))) { diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index e8766b3d882..01202bb5b71 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5826,3 +5826,6 @@ ER_NDB_CANT_SWITCH_BINLOG_FORMAT eng "The NDB cluster engine does not support changing the binlog format on the fly yet" ER_PARTITION_NO_TEMPORARY eng "Cannot create temporary table with partitions" +ER_PARTITION_FUNCTION_NOT_ALLOWED + eng "This partition function is not allowed" + swe "Denna partitioneringsfunktion är inte tillåten" From 32591e6959f5176ed64b7ace6e857fb20ee9151a Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 5 Apr 2006 12:49:38 +0200 Subject: [PATCH 02/32] BUG#18198: Too much expressiveness in partition function allowed Fixed the error check sql/partition_info.cc: Fixed the error check --- sql/partition_info.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sql/partition_info.cc b/sql/partition_info.cc index 9c7999b136b..c671164578a 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -658,8 +658,13 @@ bool partition_info::check_partition_info(handlerton **eng_type, bool part_expression_ok= TRUE; DBUG_ENTER("partition_info::check_partition_info"); - if (part_expr->walk(Item::check_partition_func_processor, - (byte*)&part_expression_ok)) + if (part_type != HASH_PARTITION || !list_of_part_fields) + part_expr->walk(Item::check_partition_func_processor, + (byte*)&part_expression_ok); + if (is_sub_partitioned() && !list_of_subpart_fields) + subpart_expr->walk(Item::check_partition_func_processor, + (byte*)&part_expression_ok); + if (!part_expression_ok) { my_error(ER_PARTITION_FUNC_NOT_ALLOWED, MYF(0)); goto end; From 09250cc6b74b6de006ec86606e4a345d0451fa92 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 8 Apr 2006 18:10:20 -0400 Subject: [PATCH 03/32] BUG#18198: Errors due to too much allowed in partition functions Added functions to enable/disable allowed/disallowed partition functions sql/item.h: Added functions to enable/disable allowed/disallowed partition functions sql/item_cmpfunc.h: Added functions to enable/disable allowed/disallowed partition functions sql/item_func.h: Added functions to enable/disable allowed/disallowed partition functions sql/item_strfunc.h: Added functions to enable/disable allowed/disallowed partition functions sql/item_timefunc.h: Added functions to enable/disable allowed/disallowed partition functions sql/item_xmlfunc.h: Added functions to enable/disable allowed/disallowed partition functions sql/partition_info.cc: Added functions to enable/disable allowed/disallowed partition functions sql/share/errmsg.txt: Added new error message --- sql/item.h | 38 ++++++++++++++++++++++++++++++++++---- sql/item_cmpfunc.h | 15 +++++++++++++++ sql/item_func.h | 32 +++++++++++++++++++++++++++++++- sql/item_strfunc.h | 24 ++++++++++++++++++++++++ sql/item_timefunc.h | 30 ++++++++++++++++++++++++++++++ sql/item_xmlfunc.h | 1 + sql/partition_info.cc | 10 +++++----- sql/share/errmsg.txt | 2 +- 8 files changed, 141 insertions(+), 11 deletions(-) diff --git a/sql/item.h b/sql/item.h index 9c979eb4acd..d5cddaa7177 100644 --- a/sql/item.h +++ b/sql/item.h @@ -744,11 +744,22 @@ public: virtual bool find_item_in_field_list_processor(byte *arg) { return 0; } virtual bool change_context_processor(byte *context) { return 0; } virtual bool reset_query_id_processor(byte *query_id) { return 0; } + /* + check_partition_func_processor is used to check if a partition function + uses an allowed function. The default is that an item is not allowed + in a partition function. However all mathematical functions, string + manipulation functions, date functions are allowed. Allowed functions + can never depend on server version, they cannot depend on anything + related to the environment. They can also only depend on a set of + fields in the table itself. They cannot depend on other tables and + cannot contain any queries and cannot contain udf's or similar. + If a new Item class is defined and it inherits from a class that is + allowed in a partition function then it is very important to consider + whether this should be inherited to the new class. If not the function + below should be defined in the new Item class. + */ virtual bool check_partition_func_processor(byte *bool_arg) - { - *(bool *)bool_arg= FALSE; - return 0; - } + { *(bool *)bool_arg= FALSE; return 0; } virtual Item *equal_fields_propagator(byte * arg) { return this; } virtual Item *set_no_const_sub(byte *arg) { return this; } @@ -1020,6 +1031,7 @@ public: Item::maybe_null= TRUE; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0; } bool fix_fields(THD *, Item **); enum Type type() const; @@ -1066,6 +1078,7 @@ public: Item_num() {} /* Remove gcc warning */ virtual Item_num *neg()= 0; Item *safe_charset_converter(CHARSET_INFO *tocs); + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; #define NO_CACHED_FIELD_INDEX ((uint)(-1)) @@ -1251,6 +1264,7 @@ public: bool is_null() { return 1; } void print(String *str) { str->append(STRING_WITH_LEN("NULL")); } Item *safe_charset_converter(CHARSET_INFO *tocs); + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_null_result :public Item_null @@ -1263,6 +1277,8 @@ public: { save_in_field(result_field, no_conversions); } + virtual bool check_partition_func_processor(byte *bool_arg) + { *(bool *)bool_arg= FALSE; return 0; } }; /* Item represents one placeholder ('?') of prepared statement */ @@ -1446,6 +1462,8 @@ public: {} Item *safe_charset_converter(CHARSET_INFO *tocs); void print(String *str) { str->append(func_name); } + virtual bool check_partition_func_processor(byte *bool_arg) + { *(bool *)bool_arg= FALSE; return 0; } }; @@ -1564,6 +1582,8 @@ public: {} void print(String *str) { str->append(func_name); } Item *safe_charset_converter(CHARSET_INFO *tocs); + virtual bool check_partition_func_processor(byte *bool_arg) + { *(bool *)bool_arg= FALSE; return 0; } }; @@ -1641,6 +1661,7 @@ public: void print(String *str); // to prevent drop fixed flag (no need parent cleanup call) void cleanup() {} + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -1655,6 +1676,8 @@ public: {} Item *safe_charset_converter(CHARSET_INFO *tocs); void print(String *str) { str->append(func_name); } + virtual bool check_partition_func_processor(byte *bool_arg) + { *(bool *)bool_arg= FALSE; return 0; } }; @@ -1667,6 +1690,8 @@ public: &my_charset_bin) { max_length=19;} enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; } + virtual bool check_partition_func_processor(byte *bool_arg) + { *(bool *)bool_arg= FALSE; return 0; } }; class Item_empty_string :public Item_string @@ -1689,6 +1714,8 @@ public: unsigned_flag=1; } enum_field_types field_type() const { return int_field_type; } + virtual bool check_partition_func_processor(byte *bool_arg) + { *(bool *)bool_arg= FALSE; return 0; } }; @@ -1712,6 +1739,7 @@ public: void cleanup() {} bool eq(const Item *item, bool binary_cmp) const; virtual Item *safe_charset_converter(CHARSET_INFO *tocs); + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -1949,6 +1977,8 @@ public: } Item *new_item(); virtual Item *real_item() { return ref; } + virtual bool check_partition_func_processor(byte *bool_arg) + { *(bool *)bool_arg= FALSE; return 0; } }; #ifdef MYSQL_SERVER diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 67f0a5f5e2e..0472fe17975 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -239,6 +239,7 @@ public: } Item *neg_transformer(THD *thd); virtual Item *negated_item(); + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_not :public Item_bool_func @@ -249,6 +250,7 @@ public: enum Functype functype() const { return NOT_FUNC; } const char *func_name() const { return "not"; } Item *neg_transformer(THD *thd); + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_maxmin_subselect; @@ -463,6 +465,7 @@ public: bool is_bool_func() { return 1; } CHARSET_INFO *compare_collation() { return cmp_collation.collation; } uint decimal_precision() const { return 1; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -474,6 +477,7 @@ public: optimize_type select_optimize() const { return OPTIMIZE_NONE; } const char *func_name() const { return "strcmp"; } void print(String *str) { Item_func::print(str); } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -536,6 +540,7 @@ public: const char *func_name() const { return "ifnull"; } Field *tmp_table_field(TABLE *table); uint decimal_precision() const; + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -576,6 +581,7 @@ public: void print(String *str) { Item_func::print(str); } table_map not_null_tables() const { return 0; } bool is_null(); + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -618,6 +624,7 @@ public: void print(String *str); Item *find_item(String *str); CHARSET_INFO *compare_collation() { return cmp_collation.collation; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -897,6 +904,7 @@ class Item_func_in :public Item_func_opt_neg bool nulls_in_row(); bool is_bool_func() { return 1; } CHARSET_INFO *compare_collation() { return cmp_collation.collation; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; /* Functions used by where clause */ @@ -938,6 +946,7 @@ public: optimize_type select_optimize() const { return OPTIMIZE_NULL; } Item *neg_transformer(THD *thd); CHARSET_INFO *compare_collation() { return args[0]->collation.collation; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; /* Functions used by HAVING for rewriting IN subquery */ @@ -959,6 +968,8 @@ public: */ table_map used_tables() const { return used_tables_cache | RAND_TABLE_BIT; } + virtual bool check_partition_func_processor(byte *bool_arg) + { *(bool *)bool_arg= FALSE; return 0; } }; @@ -981,6 +992,7 @@ public: void print(String *str); CHARSET_INFO *compare_collation() { return args[0]->collation.collation; } void top_level_item() { abort_on_null=1; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -1019,6 +1031,7 @@ public: const char *func_name() const { return "like"; } bool fix_fields(THD *thd, Item **ref); void cleanup(); + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; #ifdef USE_REGEX @@ -1041,6 +1054,7 @@ public: const char *func_name() const { return "regexp"; } void print(String *str) { print_op(str); } CHARSET_INFO *compare_collation() { return cmp_collation.collation; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; #else @@ -1097,6 +1111,7 @@ public: Item *transform(Item_transformer transformer, byte *arg); void traverse_cond(Cond_traverser, void *arg, traverse_order order); void neg_arguments(THD *thd); + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; diff --git a/sql/item_func.h b/sql/item_func.h index ccbbbab1df4..58ac28aeb9d 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -247,6 +247,7 @@ public: void fix_num_length_and_dec(); void find_num_type(); String *str_op(String *str) { DBUG_ASSERT(0); return 0; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -259,6 +260,7 @@ class Item_num_op :public Item_func_numhybrid void print(String *str) { print_op(str); } void find_num_type(); String *str_op(String *str) { DBUG_ASSERT(0); return 0; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -296,7 +298,7 @@ public: { max_length=args[0]->max_length; unsigned_flag=0; } void print(String *str); uint decimal_precision() const { return args[0]->decimal_precision(); } - + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -330,6 +332,7 @@ public: void fix_length_and_dec() {}; const char *func_name() const { return "decimal_typecast"; } void print(String *); + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -398,6 +401,7 @@ public: const char *func_name() const { return "DIV"; } void fix_length_and_dec(); void print(String *str) { print_op(str); } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -470,6 +474,7 @@ public: Item_func_exp(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "exp"; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -479,6 +484,7 @@ public: Item_func_ln(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "ln"; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -489,6 +495,7 @@ public: Item_func_log(Item *a,Item *b) :Item_dec_func(a,b) {} double val_real(); const char *func_name() const { return "log"; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -498,6 +505,7 @@ public: Item_func_log2(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "log2"; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -507,6 +515,7 @@ public: Item_func_log10(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "log10"; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -516,6 +525,7 @@ public: Item_func_sqrt(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "sqrt"; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -525,6 +535,7 @@ public: Item_func_pow(Item *a,Item *b) :Item_dec_func(a,b) {} double val_real(); const char *func_name() const { return "pow"; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -534,6 +545,7 @@ public: Item_func_acos(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "acos"; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_asin :public Item_dec_func @@ -542,6 +554,7 @@ public: Item_func_asin(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "asin"; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_atan :public Item_dec_func @@ -551,6 +564,7 @@ public: Item_func_atan(Item *a,Item *b) :Item_dec_func(a,b) {} double val_real(); const char *func_name() const { return "atan"; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_cos :public Item_dec_func @@ -559,6 +573,7 @@ public: Item_func_cos(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "cos"; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_sin :public Item_dec_func @@ -567,6 +582,7 @@ public: Item_func_sin(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "sin"; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_tan :public Item_dec_func @@ -575,6 +591,7 @@ public: Item_func_tan(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "tan"; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_integer :public Item_int_func @@ -651,6 +668,7 @@ public: Item_func_sign(Item *a) :Item_int_func(a) {} const char *func_name() const { return "sign"; } longlong val_int(); + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -665,6 +683,7 @@ public: const char *func_name() const { return name; } void fix_length_and_dec() { decimals= NOT_FIXED_DEC; max_length= float_length(decimals); } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -682,6 +701,7 @@ public: my_decimal *val_decimal(my_decimal *); void fix_length_and_dec(); enum Item_result result_type () const { return cmp_type; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_min :public Item_func_min_max @@ -707,6 +727,7 @@ public: longlong val_int(); const char *func_name() const { return "length"; } void fix_length_and_dec() { max_length=10; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_bit_length :public Item_func_length @@ -726,6 +747,7 @@ public: longlong val_int(); const char *func_name() const { return "char_length"; } void fix_length_and_dec() { max_length=10; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_coercibility :public Item_int_func @@ -736,6 +758,7 @@ public: const char *func_name() const { return "coercibility"; } void fix_length_and_dec() { max_length=10; maybe_null= 0; } table_map not_null_tables() const { return 0; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_locate :public Item_int_func @@ -749,6 +772,7 @@ public: longlong val_int(); void fix_length_and_dec(); void print(String *str); + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -773,6 +797,7 @@ public: longlong val_int(); const char *func_name() const { return "ascii"; } void fix_length_and_dec() { max_length=3; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_ord :public Item_int_func @@ -782,6 +807,7 @@ public: Item_func_ord(Item *a) :Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "ord"; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_find_in_set :public Item_int_func @@ -795,6 +821,7 @@ public: longlong val_int(); const char *func_name() const { return "find_in_set"; } void fix_length_and_dec(); + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; /* Base class for all bit functions: '~', '|', '^', '&', '>>', '<<' */ @@ -806,6 +833,7 @@ public: Item_func_bit(Item *a) :Item_int_func(a) {} void fix_length_and_dec() { unsigned_flag= 1; } void print(String *str) { print_op(str); } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_bit_or :public Item_func_bit @@ -831,6 +859,7 @@ public: longlong val_int(); const char *func_name() const { return "bit_count"; } void fix_length_and_dec() { max_length=2; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_shift_left :public Item_func_bit @@ -1257,6 +1286,7 @@ public: longlong val_int(); const char *func_name() const { return "inet_aton"; } void fix_length_and_dec() { decimals = 0; max_length = 21; maybe_null=1;} + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 6a95a9e5d1f..5e4fe49e281 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -46,6 +46,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "md5"; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -56,6 +57,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "sha"; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_aes_encrypt :public Item_str_func @@ -86,6 +88,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "concat"; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_concat_ws :public Item_str_func @@ -106,6 +109,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "reverse"; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -143,6 +147,7 @@ protected: public: Item_str_conv(Item *item) :Item_str_func(item) {} String *val_str(String *); + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -206,6 +211,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "substr"; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -217,6 +223,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "substring_index"; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -231,6 +238,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "trim"; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -410,6 +418,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "soundex"; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -517,6 +526,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "rpad"; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -529,6 +539,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "lpad"; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -543,6 +554,7 @@ public: collation.set(default_charset()); decimals=0; max_length=64; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -559,6 +571,7 @@ public: decimals=0; max_length=args[0]->max_length*2*collation.collation->mbmaxlen; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_unhex :public Item_str_func @@ -574,6 +587,7 @@ public: decimals=0; max_length=(1+args[0]->max_length)/2; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -597,6 +611,7 @@ public: } void print(String *str); const char *func_name() const { return "cast_as_binary"; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -636,6 +651,7 @@ public: String* val_str(String* str); const char *func_name() const { return "inet_ntoa"; } void fix_length_and_dec() { decimals = 0; max_length=3*8+7; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_quote :public Item_str_func @@ -650,6 +666,7 @@ public: collation.set(args[0]->collation); max_length= args[0]->max_length * 2 + 2; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_conv_charset :public Item_str_func @@ -692,6 +709,7 @@ public: void fix_length_and_dec(); const char *func_name() const { return "convert"; } void print(String *str); + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_set_collation :public Item_str_func @@ -724,6 +742,7 @@ public: maybe_null= 0; }; table_map not_null_tables() const { return 0; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_collation :public Item_str_func @@ -739,6 +758,7 @@ public: maybe_null= 0; }; table_map not_null_tables() const { return 0; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_crc32 :public Item_int_func @@ -749,6 +769,7 @@ public: const char *func_name() const { return "crc32"; } void fix_length_and_dec() { max_length=10; } longlong val_int(); + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_uncompressed_length : public Item_int_func @@ -759,6 +780,7 @@ public: const char *func_name() const{return "uncompressed_length";} void fix_length_and_dec() { max_length=10; } longlong val_int(); + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; #ifdef HAVE_COMPRESS @@ -775,6 +797,7 @@ public: void fix_length_and_dec(){max_length= (args[0]->max_length*120)/100+12;} const char *func_name() const{return "compress";} String *val_str(String *) ZLIB_DEPENDED_FUNCTION + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_uncompress: public Item_str_func @@ -785,6 +808,7 @@ public: void fix_length_and_dec(){max_length= MAX_BLOB_WIDTH;} const char *func_name() const{return "uncompress";} String *val_str(String *) ZLIB_DEPENDED_FUNCTION + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; #define UUID_LENGTH (8+1+4+1+4+1+4+1+12) diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index fd2f3945fca..ffe049873fc 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -39,6 +39,7 @@ public: { max_length=6*MY_CHARSET_BIN_MB_MAXLEN; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -53,6 +54,7 @@ public: decimals=0; max_length=6*MY_CHARSET_BIN_MB_MAXLEN; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -69,6 +71,7 @@ public: maybe_null=1; } enum_monotonicity_info get_monotonicity_info() const; + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -84,6 +87,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -108,6 +112,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -140,6 +145,7 @@ public: max_length=3*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -155,6 +161,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -170,6 +177,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -185,6 +193,7 @@ public: max_length=1*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -200,6 +209,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -215,6 +225,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_yearweek :public Item_int_func @@ -229,6 +240,7 @@ public: max_length=6*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -245,6 +257,7 @@ public: max_length=4*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -274,6 +287,7 @@ public: max_length=1*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_dayname :public Item_func_weekday @@ -306,6 +320,7 @@ public: decimals=0; max_length=10*MY_CHARSET_BIN_MB_MAXLEN; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -320,6 +335,7 @@ public: decimals=0; max_length=10*MY_CHARSET_BIN_MB_MAXLEN; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -526,6 +542,7 @@ public: Item_func_from_days(Item *a) :Item_date(a) {} const char *func_name() const { return "from_days"; } bool get_date(TIME *res, uint fuzzy_date); + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -543,6 +560,7 @@ public: void fix_length_and_dec(); uint format_length(const String *format); bool eq(const Item *item, bool binary_cmp) const; + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -561,6 +579,7 @@ class Item_func_from_unixtime :public Item_date_func const char *func_name() const { return "from_unixtime"; } void fix_length_and_dec(); bool get_date(TIME *res, uint fuzzy_date); + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -627,6 +646,7 @@ public: { return tmp_table_field_from_field_type(table, 0); } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -648,6 +668,7 @@ public: longlong val_int(); bool get_date(TIME *res, uint fuzzy_date); void print(String *str); + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -665,6 +686,7 @@ class Item_extract :public Item_int_func void fix_length_and_dec(); bool eq(const Item *item, bool binary_cmp) const; void print(String *str); + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -701,6 +723,7 @@ public: max_length=args[0]->max_length; maybe_null= 1; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -720,6 +743,7 @@ public: String *val_str(String *a); void fix_length_and_dec(); void print(String *str); + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -791,6 +815,7 @@ public: { return tmp_table_field_from_field_type(table, 0); } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -813,6 +838,7 @@ public: } void print(String *str); const char *func_name() const { return "add_time"; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_timediff :public Item_str_func @@ -852,6 +878,7 @@ public: { return tmp_table_field_from_field_type(table, 0); } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_microsecond :public Item_int_func @@ -865,6 +892,7 @@ public: decimals=0; maybe_null=1; } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -882,6 +910,7 @@ public: maybe_null=1; } void print(String *str); + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -928,6 +957,7 @@ public: { return tmp_table_field_from_field_type(table, 1); } + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; diff --git a/sql/item_xmlfunc.h b/sql/item_xmlfunc.h index bc47e9c5bb1..53302283296 100644 --- a/sql/item_xmlfunc.h +++ b/sql/item_xmlfunc.h @@ -42,6 +42,7 @@ public: Item_func_xml_extractvalue(Item *a,Item *b) :Item_xml_str_func(a,b) {} const char *func_name() const { return "extractvalue"; } String *val_str(String *); + virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} }; diff --git a/sql/partition_info.cc b/sql/partition_info.cc index c671164578a..c957efa71fb 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -659,14 +659,14 @@ bool partition_info::check_partition_info(handlerton **eng_type, DBUG_ENTER("partition_info::check_partition_info"); if (part_type != HASH_PARTITION || !list_of_part_fields) - part_expr->walk(Item::check_partition_func_processor, - (byte*)&part_expression_ok); + part_expr->walk(&Item::check_partition_func_processor, + (byte*)(&part_expression_ok)); if (is_sub_partitioned() && !list_of_subpart_fields) - subpart_expr->walk(Item::check_partition_func_processor, - (byte*)&part_expression_ok); + subpart_expr->walk(&Item::check_partition_func_processor, + (byte*)(&part_expression_ok)); if (!part_expression_ok) { - my_error(ER_PARTITION_FUNC_NOT_ALLOWED, MYF(0)); + my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0)); goto end; } if (unlikely(!is_sub_partitioned() && diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 01202bb5b71..da2e0f4e275 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5826,6 +5826,6 @@ ER_NDB_CANT_SWITCH_BINLOG_FORMAT eng "The NDB cluster engine does not support changing the binlog format on the fly yet" ER_PARTITION_NO_TEMPORARY eng "Cannot create temporary table with partitions" -ER_PARTITION_FUNCTION_NOT_ALLOWED +ER_PARTITION_FUNCTION_IS_NOT_ALLOWED eng "This partition function is not allowed" swe "Denna partitioneringsfunktion är inte tillåten" From b1e20006b686180f8b6cbe2234dd6ab2a7c4f9ef Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 5 May 2006 17:18:47 +0200 Subject: [PATCH 04/32] Bug#16997 Table rename that changes database does not rename indexes, recreate indexes in new database --- mysql-test/r/ndb_rename.result | 14 ++++++++++ mysql-test/t/ndb_rename.test | 32 ++++++++++++++++++++++ ndb/include/ndbapi/NdbDictionary.hpp | 23 ++++++++++++++-- ndb/src/ndbapi/NdbDictionary.cpp | 16 +++++++++++ ndb/src/ndbapi/NdbDictionaryImpl.cpp | 27 ++++-------------- ndb/src/ndbapi/NdbDictionaryImpl.hpp | 22 +++++++++++---- sql/ha_ndbcluster.cc | 41 +++++++++++++++++++++++++++- 7 files changed, 143 insertions(+), 32 deletions(-) create mode 100644 mysql-test/r/ndb_rename.result create mode 100644 mysql-test/t/ndb_rename.test diff --git a/mysql-test/r/ndb_rename.result b/mysql-test/r/ndb_rename.result new file mode 100644 index 00000000000..cacef136311 --- /dev/null +++ b/mysql-test/r/ndb_rename.result @@ -0,0 +1,14 @@ +DROP TABLE IF EXISTS t1,t2; +drop database if exists mysqltest; +CREATE TABLE t1 ( +pk1 INT NOT NULL PRIMARY KEY, +attr1 INT NOT NULL, +attr2 INT, +attr3 VARCHAR(10), +INDEX i1(attr1) +) ENGINE=ndbcluster; +alter table t1 rename t2; +create database ndbtest; +alter table t2 rename ndbtest.t2; +drop table ndbtest.t2; +drop database ndbtest; diff --git a/mysql-test/t/ndb_rename.test b/mysql-test/t/ndb_rename.test new file mode 100644 index 00000000000..99c344bc29e --- /dev/null +++ b/mysql-test/t/ndb_rename.test @@ -0,0 +1,32 @@ +-- source include/have_ndb.inc +-- source include/not_embedded.inc + +--disable_warnings +DROP TABLE IF EXISTS t1,t2; +drop database if exists mysqltest; +--enable_warnings + +# +# Table rename tests +# + +# +# Create a normal table with primary key +# +CREATE TABLE t1 ( + pk1 INT NOT NULL PRIMARY KEY, + attr1 INT NOT NULL, + attr2 INT, + attr3 VARCHAR(10), + INDEX i1(attr1) +) ENGINE=ndbcluster; + +alter table t1 rename t2; + +create database ndbtest; +alter table t2 rename ndbtest.t2; + +drop table ndbtest.t2; +drop database ndbtest; + +# End of 4.1 tests diff --git a/ndb/include/ndbapi/NdbDictionary.hpp b/ndb/include/ndbapi/NdbDictionary.hpp index a541cd5190e..196fd99d09d 100644 --- a/ndb/include/ndbapi/NdbDictionary.hpp +++ b/ndb/include/ndbapi/NdbDictionary.hpp @@ -956,14 +956,14 @@ public: /** * Create defined table given defined Table instance - * @param Table Table to create + * @param Table instance to create * @return 0 if successful otherwise -1. */ int createTable(const Table &); /** * Drop table given retrieved Table instance - * @param Table Table to drop + * @param Table instance to drop * @return 0 if successful otherwise -1. */ int dropTable(Table &); @@ -1027,7 +1027,15 @@ public: */ int dropIndex(const char * indexName, const char * tableName); - + + + /** + * Drop index the defined Index instance + * @param Index to drop + * @return 0 if successful otherwise -1. + */ + int dropIndex(const Index &); + /** * Get index with given name, NULL if undefined * @param indexName Name of index to get. @@ -1037,6 +1045,15 @@ public: const Index * getIndex(const char * indexName, const char * tableName); + /** + * Get index with given name, NULL if undefined + * @param indexName Name of index to get. + * @param Table instance table that index belongs to. + * @return index if successful, otherwise 0. + */ + const Index * getIndex(const char * indexName, + const Table & table); + #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL /** * Invalidate cached index object diff --git a/ndb/src/ndbapi/NdbDictionary.cpp b/ndb/src/ndbapi/NdbDictionary.cpp index 00db5704949..8ed85995d69 100644 --- a/ndb/src/ndbapi/NdbDictionary.cpp +++ b/ndb/src/ndbapi/NdbDictionary.cpp @@ -786,6 +786,12 @@ NdbDictionary::Dictionary::dropIndex(const char * indexName, return m_impl.dropIndex(indexName, tableName); } +int +NdbDictionary::Dictionary::dropIndex(const Index & ind) +{ + return m_impl.dropIndex(NdbIndexImpl::getImpl(ind)); +} + const NdbDictionary::Index * NdbDictionary::Dictionary::getIndex(const char * indexName, const char * tableName) @@ -796,6 +802,16 @@ NdbDictionary::Dictionary::getIndex(const char * indexName, return 0; } +const NdbDictionary::Index * +NdbDictionary::Dictionary::getIndex(const char * indexName, + const Table & t) +{ + NdbIndexImpl * i = m_impl.getIndex(indexName, & NdbTableImpl::getImpl(t)); + if(i) + return i->m_facade; + return 0; +} + void NdbDictionary::Dictionary::invalidateIndex(const char * indexName, const char * tableName){ diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/ndb/src/ndbapi/NdbDictionaryImpl.cpp index 8b1847502d9..80a584651d1 100644 --- a/ndb/src/ndbapi/NdbDictionaryImpl.cpp +++ b/ndb/src/ndbapi/NdbDictionaryImpl.cpp @@ -2147,7 +2147,7 @@ NdbDictionaryImpl::dropIndex(const char * indexName, m_error.code = 4243; return -1; } - int ret = dropIndex(*idx, tableName); + int ret = dropIndex(*idx); //, tableName); // If index stored in cache is incompatible with the one in the kernel // we must clear the cache and try again if (ret == INCOMPATIBLE_VERSION) { @@ -2169,40 +2169,23 @@ NdbDictionaryImpl::dropIndex(const char * indexName, } int -NdbDictionaryImpl::dropIndex(NdbIndexImpl & impl, const char * tableName) +NdbDictionaryImpl::dropIndex(NdbIndexImpl & impl) { - const char * indexName = impl.getName(); - if (tableName || m_ndb.usingFullyQualifiedNames()) { NdbTableImpl * timpl = impl.m_table; if (timpl == 0) { m_error.code = 709; return -1; } - - const char * internalIndexName = (tableName) - ? - m_ndb.internalizeIndexName(getTable(tableName), indexName) - : - m_ndb.internalizeTableName(indexName); // Index is also a table - - if(impl.m_status == NdbDictionary::Object::New){ - return dropIndex(indexName, tableName); - } - int ret = m_receiver.dropIndex(impl, *timpl); if(ret == 0){ - m_localHash.drop(internalIndexName); + m_localHash.drop(timpl->m_internalName.c_str()); m_globalHash->lock(); - impl.m_table->m_status = NdbDictionary::Object::Invalid; - m_globalHash->drop(impl.m_table); + timpl->m_status = NdbDictionary::Object::Invalid; + m_globalHash->drop(timpl); m_globalHash->unlock(); } return ret; - } - - m_error.code = 4243; - return -1; } int diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.hpp b/ndb/src/ndbapi/NdbDictionaryImpl.hpp index 602a2d6b6ca..8763a444503 100644 --- a/ndb/src/ndbapi/NdbDictionaryImpl.hpp +++ b/ndb/src/ndbapi/NdbDictionaryImpl.hpp @@ -379,7 +379,8 @@ public: int createIndex(NdbIndexImpl &ix); int dropIndex(const char * indexName, const char * tableName); - int dropIndex(NdbIndexImpl &, const char * tableName); + // int dropIndex(NdbIndexImpl &, const char * tableName); + int dropIndex(NdbIndexImpl &); NdbTableImpl * getIndexTable(NdbIndexImpl * index, NdbTableImpl * table); @@ -397,6 +398,8 @@ public: bool do_add_blob_tables); NdbIndexImpl * getIndex(const char * indexName, const char * tableName); + NdbIndexImpl * getIndex(const char * indexName, + NdbTableImpl * table); NdbIndexImpl * getIndexImpl(const char * name, const char * internalName); NdbEventImpl * getEvent(const char * eventName); NdbEventImpl * getEventImpl(const char * internalName); @@ -643,17 +646,24 @@ NdbDictionaryImpl::get_local_table_info(const char * internalTableName, return info; // autoincrement already initialized } + inline NdbIndexImpl * NdbDictionaryImpl::getIndex(const char * indexName, const char * tableName) { - if (tableName || m_ndb.usingFullyQualifiedNames()) { + return getIndex(indexName, (tableName) ? getTable(tableName) : NULL); +} + +inline +NdbIndexImpl * +NdbDictionaryImpl::getIndex(const char * indexName, + NdbTableImpl * table) +{ + if (table || m_ndb.usingFullyQualifiedNames()) { const char * internalIndexName = 0; - if (tableName) { - NdbTableImpl * t = getTable(tableName); - if (t != 0) - internalIndexName = m_ndb.internalizeIndexName(t, indexName); + if (table) { + internalIndexName = m_ndb.internalizeIndexName(table, indexName); } else { internalIndexName = m_ndb.internalizeTableName(indexName); // Index is also a table diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 876d5d2f8fd..8fe75f433b3 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -898,6 +898,8 @@ static int fix_unique_index_attr_order(NDB_INDEX_DATA &data, DBUG_RETURN(0); } + + int ha_ndbcluster::build_index_list(Ndb *ndb, TABLE *tab, enum ILBP phase) { uint i; @@ -3926,7 +3928,6 @@ int ha_ndbcluster::create_index(const char *name, DBUG_RETURN(0); } - /* Rename a table in NDB Cluster */ @@ -3935,12 +3936,16 @@ int ha_ndbcluster::rename_table(const char *from, const char *to) { NDBDICT *dict; char new_tabname[FN_HEADLEN]; + char new_dbname[FN_HEADLEN]; const NDBTAB *orig_tab; int result; + bool recreate_indexes= FALSE; + NDBDICT::List index_list; DBUG_ENTER("ha_ndbcluster::rename_table"); DBUG_PRINT("info", ("Renaming %s to %s", from, to)); set_dbname(from); + set_dbname(to, new_dbname); set_tabname(from); set_tabname(to, new_tabname); @@ -3958,6 +3963,12 @@ int ha_ndbcluster::rename_table(const char *from, const char *to) if (!(orig_tab= dict->getTable(m_tabname))) ERR_RETURN(dict->getNdbError()); } + if (my_strcasecmp(system_charset_info, new_dbname, m_dbname)) + { + dict->listIndexes(index_list, m_tabname); + recreate_indexes= TRUE; + } + m_table= (void *)orig_tab; // Change current database to that of target table set_dbname(to); @@ -3968,6 +3979,34 @@ int ha_ndbcluster::rename_table(const char *from, const char *to) result= handler::rename_table(from, to); } + // If we are moving tables between databases, we need to recreate + // indexes + if (recreate_indexes) + { + const NDBTAB *new_tab; + set_tabname(to); + if (!(new_tab= dict->getTable(m_tabname))) + ERR_RETURN(dict->getNdbError()); + + for (unsigned i = 0; i < index_list.count; i++) { + NDBDICT::List::Element& index_el = index_list.elements[i]; + set_dbname(from); + ndb->setDatabaseName(m_dbname); + const NDBINDEX * index= dict->getIndex(index_el.name, *new_tab); + set_dbname(to); + ndb->setDatabaseName(m_dbname); + DBUG_PRINT("info", ("Creating index %s/%s", + m_dbname, index->getName())); + dict->createIndex(*index); + DBUG_PRINT("info", ("Dropping index %s/%s", + m_dbname, index->getName())); + + set_dbname(from); + ndb->setDatabaseName(m_dbname); + dict->dropIndex(*index); + } + } + DBUG_RETURN(result); } From fb1ed3900b2036c3ad82e1f94d4a94f1a0b7c6e3 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 17 May 2006 22:16:51 +0200 Subject: [PATCH 05/32] Removing the binlog-show-xid option as it was only a temporary solution until we have replace-regex which we have now. That option was used to suppress the XID from the output of SHOW BINLOG EVENTS (to create a repeatable testsuite), was available only in debug builds, and was explicitely marked as "may be removed in future versions" in mysqld --help. Idea of the removal approved by the replication team. mysql-test/extra/binlog_tests/binlog.test: use replace-regex to remove xid mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test: use replace-regex to remove xid mysql-test/mysql-test-run.pl: option removed mysql-test/mysql-test-run.sh: option removed sql/log_event.cc: no more need to hide XID in tests output as we have replace-regex sql/log_event.h: no more need to hide XID in tests output as we have replace-regex sql/mysqld.cc: no more need to hide XID in tests output as we have replace-regex --- mysql-test/extra/binlog_tests/binlog.test | 6 ++--- .../mix_innodb_myisam_binlog.test | 26 +++++++++---------- mysql-test/mysql-test-run.pl | 2 -- mysql-test/mysql-test-run.sh | 3 --- sql/log_event.cc | 14 +--------- sql/log_event.h | 3 --- sql/mysqld.cc | 8 ------ 7 files changed, 17 insertions(+), 45 deletions(-) diff --git a/mysql-test/extra/binlog_tests/binlog.test b/mysql-test/extra/binlog_tests/binlog.test index ff43debf967..6f7990893f0 100644 --- a/mysql-test/extra/binlog_tests/binlog.test +++ b/mysql-test/extra/binlog_tests/binlog.test @@ -22,7 +22,7 @@ insert t2 values (5); commit; # first COMMIT must be Query_log_event, second - Xid_log_event --replace_column 2 # 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events from 102; drop table t1,t2; @@ -44,8 +44,8 @@ while ($1) commit; drop table t1; --replace_column 2 # 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events in 'master-bin.000001' from 102; --replace_column 2 # 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events in 'master-bin.000002' from 102; diff --git a/mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test b/mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test index b75a326d5a8..241c96d078b 100644 --- a/mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test +++ b/mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test @@ -30,7 +30,7 @@ insert into t2 select * from t1; commit; --replace_column 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events from 102; delete from t1; @@ -44,7 +44,7 @@ insert into t2 select * from t1; rollback; --replace_column 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events from 102; delete from t1; @@ -60,7 +60,7 @@ rollback to savepoint my_savepoint; commit; --replace_column 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events from 102; delete from t1; @@ -78,7 +78,7 @@ commit; select a from t1 order by a; # check that savepoints work :) --replace_column 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events from 102; # and when ROLLBACK is not explicit? @@ -100,7 +100,7 @@ connection con2; # logging has been done, we use a user lock. select get_lock("a",10); --replace_column 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events from 102; # and when not in a transact1on? @@ -112,7 +112,7 @@ insert into t1 values(9); insert into t2 select * from t1; --replace_column 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events from 102; # Check that when the query updat1ng the MyISAM table is the first in the @@ -125,13 +125,13 @@ insert into t1 values(10); # first make t1 non-empty begin; insert into t2 select * from t1; --replace_column 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events from 102; insert into t1 values(11); commit; --replace_column 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events from 102; @@ -150,7 +150,7 @@ insert into t2 select * from t1; commit; --replace_column 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events from 102; delete from t1; @@ -163,7 +163,7 @@ insert into t2 select * from t1; rollback; --replace_column 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events from 102; delete from t1; @@ -179,7 +179,7 @@ rollback to savepoint my_savepoint; commit; --replace_column 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events from 102; delete from t1; @@ -197,7 +197,7 @@ commit; select a from t1 order by a; # check that savepoints work :) --replace_column 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events from 102; # Test for BUG#5714, where a MyISAM update in the transaction used to @@ -258,7 +258,7 @@ disconnect con2; connection con3; select get_lock("lock1",60); --replace_column 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events from 102; do release_lock("lock1"); drop table t0,t2; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index c14e6d4d534..c95e3a77ac6 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -2597,7 +2597,6 @@ sub mysqld_arguments ($$$$$$) { mtr_add_arg($args, "%s--character-sets-dir=%s", $prefix, $path_charsetsdir); mtr_add_arg($args, "%s--core", $prefix); mtr_add_arg($args, "%s--log-bin-trust-function-creators", $prefix); - mtr_add_arg($args, "%s--loose-binlog-show-xid=0", $prefix); mtr_add_arg($args, "%s--default-character-set=latin1", $prefix); mtr_add_arg($args, "%s--language=%s", $prefix, $path_language); mtr_add_arg($args, "%s--tmpdir=$opt_tmpdir", $prefix); @@ -2743,7 +2742,6 @@ sub mysqld_arguments ($$$$$$) { mtr_add_arg($args, "%s--sort_buffer=256K", $prefix); mtr_add_arg($args, "%s--max_heap_table_size=1M", $prefix); mtr_add_arg($args, "%s--log-bin-trust-function-creators", $prefix); - mtr_add_arg($args, "%s--loose-binlog-show-xid=0", $prefix); if ( $opt_ssl_supported ) { diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index f56099f3a49..d4e70054d82 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -1345,7 +1345,6 @@ start_master() --innodb_data_file_path=ibdata1:128M:autoextend \ --open-files-limit=1024 \ --log-bin-trust-function-creators \ - --loose-binlog-show-xid=0 \ $MASTER_40_ARGS \ $SMALL_SERVER \ $MASTER_MYSQLD_BINLOG_OPT \ @@ -1369,7 +1368,6 @@ start_master() --language=$LANGUAGE \ --innodb_data_file_path=ibdata1:128M:autoextend \ --log-bin-trust-function-creators \ - --loose-binlog-show-xid=0 \ $MASTER_40_ARGS \ $SMALL_SERVER \ $MASTER_MYSQLD_BINLOG_OPT \ @@ -1542,7 +1540,6 @@ start_slave() --master-retry-count=10 \ -O slave_net_timeout=10 \ --log-bin-trust-function-creators \ - --loose-binlog-show-xid=0 \ $SMALL_SERVER \ $SLAVE_MYSQLD_BINLOG_OPT \ $EXTRA_SLAVE_MYSQLD_OPT $EXTRA_SLAVE_OPT \ diff --git a/sql/log_event.cc b/sql/log_event.cc index d51a0ef4c9f..31cbf0fffd6 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -3481,24 +3481,12 @@ int Rand_log_event::exec_event(struct st_relay_log_info* rli) Xid_log_event methods **************************************************************************/ -#if !defined(DBUG_OFF) && !defined(MYSQL_CLIENT) -/* - This static class member could be removed when mysqltest is made to support - a --replace-regex command: then tests which have XIDs in their output can - use this command to suppress non-deterministic XID values. -*/ -my_bool Xid_log_event::show_xid; -#endif - #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) void Xid_log_event::pack_info(Protocol *protocol) { char buf[128], *pos; pos= strmov(buf, "COMMIT /* xid="); -#if !defined(DBUG_OFF) && !defined(MYSQL_CLIENT) - if (show_xid) -#endif - pos= longlong10_to_str(xid, pos, 10); + pos= longlong10_to_str(xid, pos, 10); pos= strmov(pos, " */"); protocol->store(buf, (uint) (pos-buf), &my_charset_bin); } diff --git a/sql/log_event.h b/sql/log_event.h index b24686514e3..cd58dacf147 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -1221,9 +1221,6 @@ class Xid_log_event: public Log_event bool write(IO_CACHE* file); #endif bool is_valid() const { return 1; } -#if !defined(DBUG_OFF) && !defined(MYSQL_CLIENT) - static my_bool show_xid; -#endif }; /***************************************************************************** diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 0c02971a2bc..0bf430da0e6 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4877,14 +4877,6 @@ Disable with --skip-bdb (will save memory).", {"binlog-ignore-db", OPT_BINLOG_IGNORE_DB, "Tells the master that updates to the given database should not be logged tothe binary log.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#if !defined(DBUG_OFF) && !defined(MYSQL_CLIENT) - {"binlog-show-xid", OPT_BINLOG_SHOW_XID, - "Option used by mysql-test for debugging and testing: " - "do not display the XID in SHOW BINLOG EVENTS; " - "may be removed in future versions", - (gptr*) &Xid_log_event::show_xid, (gptr*) &Xid_log_event::show_xid, - 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, -#endif #ifdef HAVE_ROW_BASED_REPLICATION {"binlog-row-event-max-size", OPT_BINLOG_ROWS_EVENT_MAX_SIZE, "The maximum size of a row-based binary log event in bytes. Rows will be " From 83cd9eca3044a0fe0bbae59d5e55d014488d741b Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 24 May 2006 10:58:12 +0200 Subject: [PATCH 06/32] Bug #16997 Table rename that changes database does not rename indexes: merge --- ndb/include/ndbapi/NdbDictionary.hpp | 29 ++++++++++++++-------------- ndb/src/ndbapi/NdbDictionary.cpp | 2 +- ndb/src/ndbapi/NdbDictionaryImpl.hpp | 3 ++- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/ndb/include/ndbapi/NdbDictionary.hpp b/ndb/include/ndbapi/NdbDictionary.hpp index b1dd212ebca..1413931035d 100644 --- a/ndb/include/ndbapi/NdbDictionary.hpp +++ b/ndb/include/ndbapi/NdbDictionary.hpp @@ -1182,6 +1182,15 @@ public: const Index * getIndex(const char * indexName, const char * tableName) const; + /** + * Get index with given name, NULL if undefined + * @param indexName Name of index to get. + * @param Table instance table that index belongs to. + * @return index if successful, otherwise 0. + */ + const Index * getIndex(const char * indexName, + const Table & table) const; + /** * Fetch list of indexes of given table. * @param list Reference to list where to store the listed indexes @@ -1301,23 +1310,15 @@ public: */ int dropIndex(const char * indexName, const char * tableName); - /** - * Get index with given name, NULL if undefined - * @param indexName Name of index to get. - * @param tableName Name of table that index belongs to. - * @return index if successful, otherwise 0. - */ - const Index * getIndex(const char * indexName, - const char * tableName); /** - * Get index with given name, NULL if undefined - * @param indexName Name of index to get. - * @param Table instance table that index belongs to. - * @return index if successful, otherwise 0. + * Drop index the defined Index instance + * @param Index to drop + * @return 0 if successful otherwise -1. */ - const Index * getIndex(const char * indexName, - const Table & table); + int dropIndex(const Index &); + + #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL /** * Invalidate cached index object diff --git a/ndb/src/ndbapi/NdbDictionary.cpp b/ndb/src/ndbapi/NdbDictionary.cpp index 2f5c1756000..a342a5d5926 100644 --- a/ndb/src/ndbapi/NdbDictionary.cpp +++ b/ndb/src/ndbapi/NdbDictionary.cpp @@ -818,7 +818,7 @@ NdbDictionary::Dictionary::getIndex(const char * indexName, const NdbDictionary::Index * NdbDictionary::Dictionary::getIndex(const char * indexName, - const Table & t) + const Table & t) const { NdbIndexImpl * i = m_impl.getIndex(indexName, & NdbTableImpl::getImpl(t)); if(i) diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.hpp b/ndb/src/ndbapi/NdbDictionaryImpl.hpp index d464c9a7a9c..b0b7adf25f3 100644 --- a/ndb/src/ndbapi/NdbDictionaryImpl.hpp +++ b/ndb/src/ndbapi/NdbDictionaryImpl.hpp @@ -702,6 +702,7 @@ inline NdbIndexImpl * NdbDictionaryImpl::getIndex(const char * index_name, const char * table_name) +{ return getIndex(index_name, (table_name) ? getTable(table_name) : NULL); } @@ -710,7 +711,7 @@ NdbIndexImpl * NdbDictionaryImpl::getIndex(const char * index_name, NdbTableImpl * table) { - if (table || m_ndb.usingFullyQualifiedNames()) { + if (table || m_ndb.usingFullyQualifiedNames()) { const BaseString internal_indexname( (table) From f04b7da96fba46b73466efdc4f1d6aa3f3426988 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 25 May 2006 12:48:31 +0200 Subject: [PATCH 07/32] fix for BSD make --- unittest/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittest/Makefile.am b/unittest/Makefile.am index fd7530ee262..bfa9f40f8ce 100644 --- a/unittest/Makefile.am +++ b/unittest/Makefile.am @@ -23,5 +23,5 @@ examples: cd examples && $(MAKE) unit: $(srcdir)/unit.pl - cp $< $@ + cp $(srcdir)/unit.pl $@ chmod +x $@ From e2e582d1fba236d40e7233dcdb47d46618529390 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 28 May 2006 14:51:01 +0200 Subject: [PATCH 08/32] handlerton cleanup: duplicate fields removed, st_mysql_storage_engine added to support run-time handlerton initialization (no compiler warnings), handler API is now tied to MySQL version, handlerton->plugin mapping added (slot-based), dummy default_hton removed, plugin-type-specific initialization generalized, built-in plugins are now initialized too, --default-storage-engine no longer needs a list of storage engines in handle_options(). mysql-test-run.pl bugfixes include/mysql/plugin.h: added st_mysql_storage_engine made handlerton tied to MySQL version mysql-test/mysql-test-run.pl: bugfixes (umask, --no-defaults) mysql-test/r/ndb_dd_basic.result: update error message mysql-test/t/partition_mgm_err2.test: fix typo sql/ha_berkeley.cc: handlerton cleanup: remove duplicate fields, add st_mysql_storage_engine, initialize handlerton run-time to avoid compiler warnings sql/ha_berkeley.h: handlerton cleanup: remove duplicate fields, add st_mysql_storage_engine, initialize handlerton run-time to avoid compiler warnings sql/ha_federated.cc: handlerton cleanup: remove duplicate fields, add st_mysql_storage_engine, initialize handlerton run-time to avoid compiler warnings sql/ha_heap.cc: handlerton cleanup: remove duplicate fields, add st_mysql_storage_engine, initialize handlerton run-time to avoid compiler warnings sql/ha_innodb.cc: handlerton cleanup: remove duplicate fields, add st_mysql_storage_engine, initialize handlerton run-time to avoid compiler warnings sql/ha_innodb.h: handlerton cleanup: remove duplicate fields, add st_mysql_storage_engine, initialize handlerton run-time to avoid compiler warnings sql/ha_myisam.cc: handlerton cleanup: remove duplicate fields, add st_mysql_storage_engine, initialize handlerton run-time to avoid compiler warnings sql/ha_myisammrg.cc: handlerton cleanup: remove duplicate fields, add st_mysql_storage_engine, initialize handlerton run-time to avoid compiler warnings sql/ha_ndbcluster.cc: handlerton cleanup: remove duplicate fields, add st_mysql_storage_engine, initialize handlerton run-time to avoid compiler warnings sql/ha_ndbcluster.h: handlerton cleanup: remove duplicate fields, add st_mysql_storage_engine, initialize handlerton run-time to avoid compiler warnings sql/ha_ndbcluster_binlog.cc: no 'name' in the handlerton anymore sql/ha_partition.cc: handlerton cleanup: remove duplicate fields, add st_mysql_storage_engine, initialize handlerton run-time to avoid compiler warnings sql/handler.cc: handlerton cleanup: remove duplicate fields, add st_mysql_storage_engine, handlerton->plugin mapping sql/handler.h: handlerton cleanup: remove duplicate fields sql/log.cc: handlerton cleanup: remove duplicate fields, add st_mysql_storage_engine, initialize handlerton run-time to avoid compiler warnings sql/mysql_priv.h: handler.h needs plugin.h sql/mysqld.cc: Convert --default-storage-engine to a handlerton* when all storage engines are initialized and not in getopt sql/set_var.cc: no name in the handlerton anymore sql/sql_parse.cc: no default_hton anymore sql/sql_partition.cc: no name in the handlerton anymore sql/sql_plugin.cc: generalize plugin type-specific initialization. initialize built-in plugins too sql/sql_plugin.h: generalize plugin type-specific initialization. sql/sql_show.cc: st_mysql_storage_engine structure no name in the handlerton anymore sql/sql_table.cc: no name in the handlerton anymore no default_hton anymore sql/sql_tablespace.cc: no name in the handlerton anymore no default_hton anymore sql/sql_yacc.yy: no default_hton anymore issue "unknown storage engine" warning where it is discovered storage/archive/ha_archive.cc: handlerton cleanup: remove duplicate fields, add st_mysql_storage_engine, initialize handlerton run-time to avoid compiler warnings storage/archive/ha_archive.h: handlerton cleanup: remove duplicate fields, add st_mysql_storage_engine, initialize handlerton run-time to avoid compiler warnings storage/blackhole/ha_blackhole.cc: handlerton cleanup: remove duplicate fields, add st_mysql_storage_engine, initialize handlerton run-time to avoid compiler warnings storage/csv/ha_tina.cc: handlerton cleanup: remove duplicate fields, add st_mysql_storage_engine, initialize handlerton run-time to avoid compiler warnings storage/example/ha_example.cc: handlerton cleanup: remove duplicate fields, add st_mysql_storage_engine, initialize handlerton run-time to avoid compiler warnings --- include/mysql/plugin.h | 24 ++++- mysql-test/mysql-test-run.pl | 4 +- mysql-test/r/ndb_dd_basic.result | 2 +- mysql-test/t/partition_mgm_err2.test | 2 +- sql/ha_berkeley.cc | 81 ++++++--------- sql/ha_berkeley.h | 2 +- sql/ha_federated.cc | 63 +++-------- sql/ha_heap.cc | 61 +++-------- sql/ha_innodb.cc | 89 +++++++--------- sql/ha_innodb.h | 2 +- sql/ha_myisam.cc | 75 ++++---------- sql/ha_myisammrg.cc | 63 ++++------- sql/ha_ndbcluster.cc | 54 ++++------ sql/ha_ndbcluster.h | 4 + sql/ha_ndbcluster_binlog.cc | 6 +- sql/ha_partition.cc | 60 +++-------- sql/handler.cc | 150 ++++++++++----------------- sql/handler.h | 31 +----- sql/log.cc | 71 ++++--------- sql/mysql_priv.h | 2 +- sql/mysqld.cc | 52 +++++----- sql/set_var.cc | 2 +- sql/sql_parse.cc | 4 +- sql/sql_partition.cc | 16 +-- sql/sql_plugin.cc | 44 ++++---- sql/sql_plugin.h | 2 + sql/sql_show.cc | 51 +++++---- sql/sql_table.cc | 9 +- sql/sql_tablespace.cc | 10 +- sql/sql_yacc.yy | 16 ++- storage/archive/ha_archive.cc | 64 +++--------- storage/archive/ha_archive.h | 2 +- storage/blackhole/ha_blackhole.cc | 70 +++---------- storage/csv/ha_tina.cc | 53 ++-------- storage/example/ha_example.cc | 68 +++--------- 35 files changed, 459 insertions(+), 850 deletions(-) diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h index ab5ca6e7be4..926b7e34c5b 100644 --- a/include/mysql/plugin.h +++ b/include/mysql/plugin.h @@ -28,7 +28,7 @@ */ #define MYSQL_UDF_PLUGIN 0 /* User-defined function */ #define MYSQL_STORAGE_ENGINE_PLUGIN 1 /* Storage Engine */ -#define MYSQL_FTPARSER_PLUGIN 2 /* Full-text [pre]parser */ +#define MYSQL_FTPARSER_PLUGIN 2 /* Full-text parser plugin */ #define MYSQL_MAX_PLUGIN_TYPE_NUM 3 /* The number of plugin types */ /* @@ -95,7 +95,7 @@ struct st_mysql_plugin }; /************************************************************************* - API for Full-text [pre]parser plugin. (MYSQL_FTPARSER_PLUGIN) + API for Full-text parser plugin. (MYSQL_FTPARSER_PLUGIN) */ #define MYSQL_FTPARSER_INTERFACE_VERSION 0x0000 @@ -265,5 +265,25 @@ struct st_mysql_ftparser int (*init)(MYSQL_FTPARSER_PARAM *param); int (*deinit)(MYSQL_FTPARSER_PARAM *param); }; + +/************************************************************************* + API for Storage Engine plugin. (MYSQL_STORAGE_ENGINE_PLUGIN) +*/ + +/* handlertons of different MySQL releases are incompatible */ +#define MYSQL_HANDLERTON_INTERFACE_VERSION (MYSQL_VERSION_ID << 8) + +/* + The real API is in the sql/handler.h + Here we define only the descriptor structure, that is referred from + st_mysql_plugin. +*/ + +struct st_mysql_storage_engine +{ + int interface_version; + struct handlerton *handlerton; +}; + #endif diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index c14e6d4d534..926b85dc183 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1171,6 +1171,8 @@ sub executable_setup () { sub environment_setup () { + umask(022); + # -------------------------------------------------------------------------- # We might not use a standard installation directory, like /usr/lib. # Set LD_LIBRARY_PATH to make sure we find our installed libraries. @@ -3218,7 +3220,7 @@ sub run_mysqltest ($) { } my $cmdline_mysql= - "$exe_mysql --host=localhost --user=root --password= " . + "$exe_mysql --no-defaults --host=localhost --user=root --password= " . "--port=$master->[0]->{'path_myport'} " . "--socket=$master->[0]->{'path_mysock'}"; diff --git a/mysql-test/r/ndb_dd_basic.result b/mysql-test/r/ndb_dd_basic.result index 008be3aa79f..6c10fbe63b3 100644 --- a/mysql-test/r/ndb_dd_basic.result +++ b/mysql-test/r/ndb_dd_basic.result @@ -11,7 +11,7 @@ ADD UNDOFILE 'undofile02.dat' INITIAL_SIZE = 4M ENGINE=XYZ; Warnings: -Error 1266 Using storage engine MyISAM for table 'lg1' +Error 1286 Unknown table engine 'XYZ' Error 1465 Table storage engine 'MyISAM' does not support the create option 'TABLESPACE or LOGFILE GROUP' CREATE TABLESPACE ts1 ADD DATAFILE 'datafile.dat' diff --git a/mysql-test/t/partition_mgm_err2.test b/mysql-test/t/partition_mgm_err2.test index dd96731ccdd..7d15bd7b19f 100644 --- a/mysql-test/t/partition_mgm_err2.test +++ b/mysql-test/t/partition_mgm_err2.test @@ -15,7 +15,7 @@ enable_query_log; --system mkdir $MYSQLTEST_VARDIR/tmp/bug14354 disable_query_log; eval CREATE TABLE t1 (id int) PARTITION BY RANGE(id) ( -PARTITION p1 VALUES LESS THAN (20) ENGINE=myiasm +PARTITION p1 VALUES LESS THAN (20) ENGINE=myisam DATA DIRECTORY="$MYSQLTEST_VARDIR/tmp/bug14354" INDEX DIRECTORY="$MYSQLTEST_VARDIR/tmp/bug14354"); enable_query_log; diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc index 473fb149871..9a144066057 100644 --- a/sql/ha_berkeley.cc +++ b/sql/ha_berkeley.cc @@ -97,6 +97,9 @@ pthread_mutex_t bdb_mutex; static DB_ENV *db_env; static HASH bdb_open_tables; +static const char berkeley_hton_name[]= "BerkeleyDB"; +static const int berkeley_hton_name_length=sizeof(berkeley_hton_name)-1; + const char *berkeley_lock_names[] = { "DEFAULT", "OLDEST", "RANDOM", "YOUNGEST", "EXPIRE", "MAXLOCKS", "MAXWRITE", "MINLOCKS", "MINWRITE", 0 }; @@ -125,47 +128,7 @@ static int berkeley_savepoint(THD* thd, void *savepoint); static int berkeley_release_savepoint(THD* thd, void *savepoint); static handler *berkeley_create_handler(TABLE_SHARE *table); -static const char berkeley_hton_name[]= "BerkeleyDB"; -static const char berkeley_hton_comment[]= - "Supports transactions and page-level locking"; - -handlerton berkeley_hton = { - MYSQL_HANDLERTON_INTERFACE_VERSION, - berkeley_hton_name, - SHOW_OPTION_YES, - berkeley_hton_comment, - DB_TYPE_BERKELEY_DB, - berkeley_init, - 0, /* slot */ - sizeof(DB_TXN *), /* savepoint size */ - berkeley_close_connection, - berkeley_savepoint, /* savepoint_set */ - berkeley_rollback_to_savepoint, /* savepoint_rollback */ - berkeley_release_savepoint, /* savepoint_release */ - berkeley_commit, - berkeley_rollback, - NULL, /* prepare */ - NULL, /* recover */ - NULL, /* commit_by_xid */ - NULL, /* rollback_by_xid */ - NULL, /* create_cursor_read_view */ - NULL, /* set_cursor_read_view */ - NULL, /* close_cursor_read_view */ - berkeley_create_handler, /* Create a new handler */ - NULL, /* Drop a database */ - berkeley_end, /* Panic call */ - NULL, /* Start Consistent Snapshot */ - berkeley_flush_logs, /* Flush logs */ - berkeley_show_status, /* Show status */ - NULL, /* Partition flags */ - NULL, /* Alter table flags */ - NULL, /* Alter Tablespace */ - NULL, /* Fill Files Table */ - HTON_CLOSE_CURSORS_AT_COMMIT | HTON_FLUSH_AFTER_RENAME, - NULL, /* binlog_func */ - NULL, /* binlog_log_query */ - NULL /* release_temporary_latches */ -}; +handlerton berkeley_hton; handler *berkeley_create_handler(TABLE_SHARE *table) { @@ -181,12 +144,27 @@ typedef struct st_berkeley_trx_data { /* General functions */ -bool berkeley_init(void) +int berkeley_init(void) { DBUG_ENTER("berkeley_init"); + berkeley_hton.state=SHOW_OPTION_YES; + berkeley_hton.db_type=DB_TYPE_BERKELEY_DB; + berkeley_hton.savepoint_offset=sizeof(DB_TXN *); + berkeley_hton.close_connection=berkeley_close_connection; + berkeley_hton.savepoint_set=berkeley_savepoint; + berkeley_hton.savepoint_rollback=berkeley_rollback_to_savepoint; + berkeley_hton.savepoint_release=berkeley_release_savepoint; + berkeley_hton.commit=berkeley_commit; + berkeley_hton.rollback=berkeley_rollback; + berkeley_hton.create=berkeley_create_handler; + berkeley_hton.panic=berkeley_end; + berkeley_hton.flush_logs=berkeley_flush_logs; + berkeley_hton.show_status=berkeley_show_status; + berkeley_hton.flags=HTON_CLOSE_CURSORS_AT_COMMIT | HTON_FLUSH_AFTER_RENAME; + if (have_berkeley_db != SHOW_OPTION_YES) - goto error; + return 0; // nothing else to do if (!berkeley_tmpdir) berkeley_tmpdir=mysql_tmpdir; @@ -373,7 +351,6 @@ static int berkeley_release_savepoint(THD* thd, void *savepoint) static bool berkeley_show_logs(THD *thd, stat_print_fn *stat_print) { char **all_logs, **free_logs, **a, **f; - uint hton_name_len= strlen(berkeley_hton.name); int error=1; MEM_ROOT **root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**,THR_MALLOC); MEM_ROOT show_logs_root, *old_mem_root= *root_ptr; @@ -401,15 +378,15 @@ static bool berkeley_show_logs(THD *thd, stat_print_fn *stat_print) if (f && *f && strcmp(*a, *f) == 0) { f++; - if ((error= stat_print(thd, berkeley_hton.name, hton_name_len, - *a, strlen(*a), + if ((error= stat_print(thd, berkeley_hton_name, + berkeley_hton_name_length, *a, strlen(*a), STRING_WITH_LEN(SHOW_LOG_STATUS_FREE)))) break; } else { - if ((error= stat_print(thd, berkeley_hton.name, hton_name_len, - *a, strlen(*a), + if ((error= stat_print(thd, berkeley_hton_name, + berkeley_hton_name_length, *a, strlen(*a), STRING_WITH_LEN(SHOW_LOG_STATUS_INUSE)))) break; } @@ -2732,15 +2709,17 @@ bool ha_berkeley::check_if_incompatible_data(HA_CREATE_INFO *info, return COMPATIBLE_DATA_YES; } +struct st_mysql_storage_engine berkeley_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION, &berkeley_hton }; mysql_declare_plugin(berkeley) { MYSQL_STORAGE_ENGINE_PLUGIN, - &berkeley_hton, + &berkeley_storage_engine, berkeley_hton_name, "Sleepycat Software", - berkeley_hton_comment, - NULL, /* Plugin Init */ + "Supports transactions and page-level locking", + berkeley_init, /* Plugin Init */ NULL, /* Plugin Deinit */ 0x0100, /* 1.0 */ 0 diff --git a/sql/ha_berkeley.h b/sql/ha_berkeley.h index 21b618b8d6d..50a2aec3963 100644 --- a/sql/ha_berkeley.h +++ b/sql/ha_berkeley.h @@ -172,7 +172,7 @@ extern char *berkeley_home, *berkeley_tmpdir, *berkeley_logdir; extern long berkeley_lock_scan_time; extern TYPELIB berkeley_lock_typelib; -bool berkeley_init(void); +int berkeley_init(void); int berkeley_end(ha_panic_function type); bool berkeley_flush_logs(void); bool berkeley_show_status(THD *thd, stat_print_fn *print, enum ha_stat_type); diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index f4fc5f47193..30988c6c8d0 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -370,47 +370,7 @@ static int federated_rollback(THD *thd, bool all); /* Federated storage engine handlerton */ -static const char federated_hton_name[]= "FEDERATED"; -static const char federated_hton_comment[]= "Federated MySQL storage engine"; - -handlerton federated_hton= { - MYSQL_HANDLERTON_INTERFACE_VERSION, - federated_hton_name, - SHOW_OPTION_YES, - federated_hton_comment, - DB_TYPE_FEDERATED_DB, - federated_db_init, - 0, /* slot */ - 0, /* savepoint size. */ - NULL, /* close_connection */ - NULL, /* savepoint */ - NULL, /* rollback to savepoint */ - NULL, /* release savepoint */ - federated_commit, /* commit */ - federated_rollback, /* rollback */ - NULL, /* prepare */ - NULL, /* recover */ - NULL, /* commit_by_xid */ - NULL, /* rollback_by_xid */ - NULL, /* create_cursor_read_view */ - NULL, /* set_cursor_read_view */ - NULL, /* close_cursor_read_view */ - federated_create_handler, /* Create a new handler */ - NULL, /* Drop a database */ - federated_db_end, /* Panic call */ - NULL, /* Start Consistent Snapshot */ - NULL, /* Flush logs */ - NULL, /* Show status */ - NULL, /* Partition flags */ - NULL, /* Alter table flags */ - NULL, /* Alter Tablespace */ - NULL, /* Fill FILES table */ - HTON_ALTER_NOT_SUPPORTED, - NULL, /* binlog_func */ - NULL, /* binlog_log_query */ - NULL /* release_temporary_latches */ -}; - +handlerton federated_hton; static handler *federated_create_handler(TABLE_SHARE *table) { @@ -442,6 +402,15 @@ static byte *federated_get_key(FEDERATED_SHARE *share, uint *length, bool federated_db_init() { DBUG_ENTER("federated_db_init"); + + federated_hton.state= SHOW_OPTION_YES; + federated_hton.db_type= DB_TYPE_FEDERATED_DB; + federated_hton.commit= federated_commit; + federated_hton.rollback= federated_rollback; + federated_hton.create= federated_create_handler; + federated_hton.panic= federated_db_end; + federated_hton.flags= HTON_ALTER_NOT_SUPPORTED; + if (pthread_mutex_init(&federated_mutex, MY_MUTEX_INIT_FAST)) goto error; if (!hash_init(&federated_open_tables, system_charset_info, 32, 0, 0, @@ -2797,7 +2766,7 @@ int ha_federated::connection_autocommit(bool state) DBUG_ENTER("ha_federated::connection_autocommit"); text= (state == true) ? "SET AUTOCOMMIT=1" : "SET AUTOCOMMIT=0"; DBUG_RETURN(execute_simple_query(text, 16)); -} +} int ha_federated::execute_simple_query(const char *query, int len) @@ -2811,15 +2780,17 @@ int ha_federated::execute_simple_query(const char *query, int len) DBUG_RETURN(0); } +struct st_mysql_storage_engine federated_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION, &federated_hton }; mysql_declare_plugin(federated) { MYSQL_STORAGE_ENGINE_PLUGIN, - &federated_hton, - federated_hton_name, + &federated_storage_engine, + "FEDERATED", "Patrick Galbraith and Brian Aker, MySQL AB", - federated_hton_comment, - NULL, /* Plugin Init */ + "Federated MySQL storage engine", + federated_db_init, /* Plugin Init */ NULL, /* Plugin Deinit */ 0x0100 /* 1.0 */, } diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index 1a7efb42748..15cec9ec4a6 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -26,47 +26,17 @@ static handler *heap_create_handler(TABLE_SHARE *table); -static const char heap_hton_name[]= "MEMORY"; -static const char heap_hton_comment[]= - "Hash based, stored in memory, useful for temporary tables"; +handlerton heap_hton; -handlerton heap_hton= { - MYSQL_HANDLERTON_INTERFACE_VERSION, - heap_hton_name, - SHOW_OPTION_YES, - heap_hton_comment, - DB_TYPE_HEAP, - NULL, - 0, /* slot */ - 0, /* savepoint size. */ - NULL, /* close_connection */ - NULL, /* savepoint */ - NULL, /* rollback to savepoint */ - NULL, /* release savepoint */ - NULL, /* commit */ - NULL, /* rollback */ - NULL, /* prepare */ - NULL, /* recover */ - NULL, /* commit_by_xid */ - NULL, /* rollback_by_xid */ - NULL, /* create_cursor_read_view */ - NULL, /* set_cursor_read_view */ - NULL, /* close_cursor_read_view */ - heap_create_handler, /* Create a new handler */ - NULL, /* Drop a database */ - heap_panic, /* Panic call */ - NULL, /* Start Consistent Snapshot */ - NULL, /* Flush logs */ - NULL, /* Show status */ - NULL, /* Partition flags */ - NULL, /* Alter table flags */ - NULL, /* Alter Tablespace */ - NULL, /* Fill Files Table */ - HTON_CAN_RECREATE, - NULL, /* binlog_func */ - NULL, /* binlog_log_query */ - NULL /* release_temporary_latches */ -}; +int heap_init() +{ + heap_hton.state= SHOW_OPTION_YES; + heap_hton.db_type= DB_TYPE_HEAP; + heap_hton.create= heap_create_handler; + heap_hton.panic= heap_panic; + heap_hton.flags= HTON_CAN_RECREATE; + return 0; +} static handler *heap_create_handler(TABLE_SHARE *table) { @@ -711,14 +681,17 @@ bool ha_heap::check_if_incompatible_data(HA_CREATE_INFO *info, return COMPATIBLE_DATA_YES; } +struct st_mysql_storage_engine heap_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION, &heap_hton}; + mysql_declare_plugin(heap) { MYSQL_STORAGE_ENGINE_PLUGIN, - &heap_hton, - heap_hton_name, + &heap_storage_engine, + "MEMORY", "MySQL AB", - heap_hton_comment, - NULL, + "Hash based, stored in memory, useful for temporary tables", + heap_init, NULL, 0x0100, /* 1.0 */ 0 diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 0b2f561e8c9..4be8a81b845 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -42,7 +42,6 @@ have disables the InnoDB inlining in this file. */ #define MAX_ULONG_BIT ((ulong) 1 << (sizeof(ulong)*8-1)) -#ifdef WITH_INNOBASE_STORAGE_ENGINE #include "ha_innodb.h" pthread_mutex_t innobase_share_mutex, /* to protect innobase_open_files */ @@ -206,47 +205,8 @@ static int innobase_release_savepoint(THD* thd, void *savepoint); static handler *innobase_create_handler(TABLE_SHARE *table); static const char innobase_hton_name[]= "InnoDB"; -static const char innobase_hton_comment[]= - "Supports transactions, row-level locking, and foreign keys"; - -handlerton innobase_hton = { - MYSQL_HANDLERTON_INTERFACE_VERSION, - innobase_hton_name, - SHOW_OPTION_YES, - innobase_hton_comment, - DB_TYPE_INNODB, - innobase_init, - 0, /* slot */ - sizeof(trx_named_savept_t), /* savepoint size. TODO: use it */ - innobase_close_connection, - innobase_savepoint, - innobase_rollback_to_savepoint, - innobase_release_savepoint, - innobase_commit, /* commit */ - innobase_rollback, /* rollback */ - innobase_xa_prepare, /* prepare */ - innobase_xa_recover, /* recover */ - innobase_commit_by_xid, /* commit_by_xid */ - innobase_rollback_by_xid, /* rollback_by_xid */ - innobase_create_cursor_view, - innobase_set_cursor_view, - innobase_close_cursor_view, - innobase_create_handler, /* Create a new handler */ - innobase_drop_database, /* Drop a database */ - innobase_end, /* Panic call */ - innobase_start_trx_and_assign_read_view, /* Start Consistent Snapshot */ - innobase_flush_logs, /* Flush logs */ - innobase_show_status, /* Show status */ - NULL, /* Partition flags */ - NULL, /* Alter table flags */ - NULL, /* alter_tablespace */ - NULL, /* Fill FILES table */ - HTON_NO_FLAGS, - NULL, /* binlog_func */ - NULL, /* binlog_log_query */ - innobase_release_temporary_latches -}; +handlerton innobase_hton; static handler *innobase_create_handler(TABLE_SHARE *table) { @@ -1230,10 +1190,9 @@ ha_innobase::init_table_handle_for_HANDLER(void) /************************************************************************* Opens an InnoDB database. */ -bool +int innobase_init(void) /*===============*/ - /* out: &innobase_hton, or NULL on error */ { static char current_dir[3]; /* Set if using current lib */ int err; @@ -1242,8 +1201,33 @@ innobase_init(void) DBUG_ENTER("innobase_init"); + innobase_hton.state=have_innodb; + innobase_hton.db_type= DB_TYPE_INNODB; + innobase_hton.savepoint_offset=sizeof(trx_named_savept_t); + innobase_hton.close_connection=innobase_close_connection; + innobase_hton.savepoint_set=innobase_savepoint; + innobase_hton.savepoint_rollback=innobase_rollback_to_savepoint; + innobase_hton.savepoint_release=innobase_release_savepoint; + innobase_hton.commit=innobase_commit; + innobase_hton.rollback=innobase_rollback; + innobase_hton.prepare=innobase_xa_prepare; + innobase_hton.recover=innobase_xa_recover; + innobase_hton.commit_by_xid=innobase_commit_by_xid; + innobase_hton.rollback_by_xid=innobase_rollback_by_xid; + innobase_hton.create_cursor_read_view=innobase_create_cursor_view; + innobase_hton.set_cursor_read_view=innobase_set_cursor_view; + innobase_hton.close_cursor_read_view=innobase_close_cursor_view; + innobase_hton.create=innobase_create_handler; + innobase_hton.drop_database=innobase_drop_database; + innobase_hton.panic=innobase_end; + innobase_hton.start_consistent_snapshot=innobase_start_trx_and_assign_read_view; + innobase_hton.flush_logs=innobase_flush_logs; + innobase_hton.show_status=innobase_show_status; + innobase_hton.flags=HTON_NO_FLAGS; + innobase_hton.release_temporary_latches=innobase_release_temporary_latches; + if (have_innodb != SHOW_OPTION_YES) - goto error; + DBUG_RETURN(0); // nothing else to do ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR); @@ -6473,7 +6457,7 @@ innodb_show_status( bool result = FALSE; - if (stat_print(thd, innobase_hton.name, strlen(innobase_hton.name), + if (stat_print(thd, innobase_hton_name, strlen(innobase_hton_name), STRING_WITH_LEN(""), str, flen)) { result= TRUE; } @@ -6500,7 +6484,7 @@ innodb_mutex_show_status( ulint rw_lock_count_os_wait= 0; ulint rw_lock_count_os_yield= 0; ulonglong rw_lock_wait_time= 0; - uint hton_name_len= strlen(innobase_hton.name), buf1len, buf2len; + uint hton_name_len= strlen(innobase_hton_name), buf1len, buf2len; DBUG_ENTER("innodb_mutex_show_status"); #ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER @@ -6527,7 +6511,7 @@ innodb_mutex_show_status( mutex->count_os_yield, mutex->lspent_time/1000); - if (stat_print(thd, innobase_hton.name, + if (stat_print(thd, innobase_hton_name, hton_name_len, buf1, buf1len, buf2, buf2len)) { #ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER @@ -6557,7 +6541,7 @@ innodb_mutex_show_status( rw_lock_count_os_wait, rw_lock_count_os_yield, rw_lock_wait_time/1000); - if (stat_print(thd, innobase_hton.name, hton_name_len, + if (stat_print(thd, innobase_hton_name, hton_name_len, STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) { DBUG_RETURN(1); } @@ -7459,19 +7443,20 @@ bool ha_innobase::check_if_incompatible_data( return COMPATIBLE_DATA_YES; } +struct st_mysql_storage_engine innobase_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION, &innobase_hton}; mysql_declare_plugin(innobase) { MYSQL_STORAGE_ENGINE_PLUGIN, - &innobase_hton, + &innobase_storage_engine, innobase_hton_name, "Innobase OY", - innobase_hton_comment, - NULL, /* Plugin Init */ + "Supports transactions, row-level locking, and foreign keys", + innobase_init, /* Plugin Init */ NULL, /* Plugin Deinit */ 0x0100 /* 1.0 */, 0 } mysql_declare_plugin_end; -#endif diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index 4f0c9eb151b..638ecc432b9 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -249,7 +249,7 @@ extern ulong srv_thread_concurrency; extern ulong srv_commit_concurrency; } -bool innobase_init(void); +int innobase_init(void); int innobase_end(ha_panic_function type); bool innobase_flush_logs(void); uint innobase_get_free_space(void); diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 786d45a4966..645998602bb 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -52,63 +52,11 @@ TYPELIB myisam_stats_method_typelib= { ** MyISAM tables *****************************************************************************/ -static handler *myisam_create_handler(TABLE_SHARE *table); - -/* MyISAM handlerton */ - -static const char myisam_hton_name[]= "MyISAM"; -static const char myisam_hton_comment[]= - "Default engine as of MySQL 3.23 with great performance"; - -handlerton myisam_hton= { - MYSQL_HANDLERTON_INTERFACE_VERSION, - myisam_hton_name, - SHOW_OPTION_YES, - myisam_hton_comment, - DB_TYPE_MYISAM, - NULL, - 0, /* slot */ - 0, /* savepoint size. */ - NULL, /* close_connection */ - NULL, /* savepoint */ - NULL, /* rollback to savepoint */ - NULL, /* release savepoint */ - NULL, /* commit */ - NULL, /* rollback */ - NULL, /* prepare */ - NULL, /* recover */ - NULL, /* commit_by_xid */ - NULL, /* rollback_by_xid */ - NULL, /* create_cursor_read_view */ - NULL, /* set_cursor_read_view */ - NULL, /* close_cursor_read_view */ - /* - MyISAM doesn't support transactions and doesn't have - transaction-dependent context: cursors can survive a commit. - */ - myisam_create_handler, /* Create a new handler */ - NULL, /* Drop a database */ - mi_panic,/* Panic call */ - NULL, /* Start Consistent Snapshot */ - NULL, /* Flush logs */ - NULL, /* Show status */ - NULL, /* Partition flags */ - NULL, /* Alter table flags */ - NULL, /* Alter Tablespace */ - NULL, /* Fill Files Table */ - HTON_CAN_RECREATE, - NULL, /* binlog_func */ - NULL, /* binlog_log_query */ - NULL /* release_temporary_latches */ -}; - - static handler *myisam_create_handler(TABLE_SHARE *table) { return new ha_myisam(table); } - // collect errors printed by mi_check routines static void mi_check_print_msg(MI_CHECK *param, const char* msg_type, @@ -1797,17 +1745,32 @@ bool ha_myisam::check_if_incompatible_data(HA_CREATE_INFO *info, return COMPATIBLE_DATA_YES; } +handlerton myisam_hton; + +static int myisam_init() +{ + myisam_hton.state=SHOW_OPTION_YES; + myisam_hton.db_type=DB_TYPE_MYISAM; + myisam_hton.create=myisam_create_handler; + myisam_hton.panic=mi_panic; + myisam_hton.flags=HTON_CAN_RECREATE; + return 0; +} + +struct st_mysql_storage_engine myisam_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION, &myisam_hton }; mysql_declare_plugin(myisam) { MYSQL_STORAGE_ENGINE_PLUGIN, - &myisam_hton, - myisam_hton_name, + &myisam_storage_engine, + "MyISAM", "MySQL AB", - myisam_hton_comment, - NULL, /* Plugin Init */ + "Default engine as of MySQL 3.23 with great performance", + myisam_init, /* Plugin Init */ NULL, /* Plugin Deinit */ 0x0100, /* 1.0 */ 0 } mysql_declare_plugin_end; + diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc index f4a052cea8a..b874923a077 100644 --- a/sql/ha_myisammrg.cc +++ b/sql/ha_myisammrg.cc @@ -38,47 +38,7 @@ static handler *myisammrg_create_handler(TABLE_SHARE *table); /* MyISAM MERGE handlerton */ -static const char myisammrg_hton_name[]= "MRG_MYISAM"; -static const char myisammrg_hton_comment[]= - "Collection of identical MyISAM tables"; - -handlerton myisammrg_hton= { - MYSQL_HANDLERTON_INTERFACE_VERSION, - myisammrg_hton_name, - SHOW_OPTION_YES, - myisammrg_hton_comment, - DB_TYPE_MRG_MYISAM, - NULL, - 0, /* slot */ - 0, /* savepoint size. */ - NULL, /* close_connection */ - NULL, /* savepoint */ - NULL, /* rollback to savepoint */ - NULL, /* release savepoint */ - NULL, /* commit */ - NULL, /* rollback */ - NULL, /* prepare */ - NULL, /* recover */ - NULL, /* commit_by_xid */ - NULL, /* rollback_by_xid */ - NULL, /* create_cursor_read_view */ - NULL, /* set_cursor_read_view */ - NULL, /* close_cursor_read_view */ - myisammrg_create_handler, /* Create a new handler */ - NULL, /* Drop a database */ - myrg_panic, /* Panic call */ - NULL, /* Start Consistent Snapshot */ - NULL, /* Flush logs */ - NULL, /* Show status */ - NULL, /* Partition flags */ - NULL, /* Alter table flags */ - NULL, /* Alter Tablespace */ - NULL, /* Fill Files Table */ - HTON_CAN_RECREATE | HTON_ALTER_CANNOT_CREATE, - NULL, /* binlog_func */ - NULL, /* binlog_log_query */ - NULL /* release_temporary_latches */ -}; +handlerton myisammrg_hton; static handler *myisammrg_create_handler(TABLE_SHARE *table) { @@ -580,14 +540,27 @@ bool ha_myisammrg::check_if_incompatible_data(HA_CREATE_INFO *info, return COMPATIBLE_DATA_NO; } +static int myisammrg_init() +{ + myisammrg_hton.state=SHOW_OPTION_YES; + myisammrg_hton.db_type=DB_TYPE_MRG_MYISAM; + myisammrg_hton.create=myisammrg_create_handler; + myisammrg_hton.panic=myrg_panic; + myisammrg_hton.flags= HTON_CAN_RECREATE | HTON_ALTER_CANNOT_CREATE; + return 0; +} + +struct st_mysql_storage_engine myisammrg_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION, &myisammrg_hton }; + mysql_declare_plugin(myisammrg) { MYSQL_STORAGE_ENGINE_PLUGIN, - &myisammrg_hton, - myisammrg_hton_name, + &myisammrg_storage_engine, + "MRG_MYISAM", "MySQL AB", - myisammrg_hton_comment, - NULL, /* Plugin Init */ + "Collection of identical MyISAM tables", + myisammrg_init, /* Plugin Init */ NULL, /* Plugin Deinit */ 0x0100, /* 1.0 */ 0 diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 89b9ed93d69..d62660343dc 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -63,26 +63,13 @@ static const int max_transactions= 3; // should really be 2 but there is a trans static uint ndbcluster_partition_flags(); static uint ndbcluster_alter_table_flags(uint flags); -static bool ndbcluster_init(void); +static int ndbcluster_init(void); static int ndbcluster_end(ha_panic_function flag); static bool ndbcluster_show_status(THD*,stat_print_fn *,enum ha_stat_type); static int ndbcluster_alter_tablespace(THD* thd, st_alter_tablespace *info); static int ndbcluster_fill_files_table(THD *thd, TABLE_LIST *tables, COND *cond); -static const char ndbcluster_hton_name[]= "ndbcluster"; -static const char ndbcluster_hton_comment[]= "Clustered, fault-tolerant tables"; - -handlerton ndbcluster_hton = { - MYSQL_HANDLERTON_INTERFACE_VERSION, - "ndbcluster", - SHOW_OPTION_YES, - "Clustered, fault-tolerant tables", - DB_TYPE_NDBCLUSTER, - ndbcluster_init, - ~(uint)0, /* slot */ - /* below are initialized by name in ndbcluster_init() */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -}; +handlerton ndbcluster_hton; static handler *ndbcluster_create_handler(TABLE_SHARE *table) { @@ -6080,17 +6067,18 @@ static int connect_callback() } extern int ndb_dictionary_is_mysqld; -static bool ndbcluster_init() + +static int ndbcluster_init() { int res; DBUG_ENTER("ndbcluster_init"); ndb_dictionary_is_mysqld= 1; - if (have_ndbcluster != SHOW_OPTION_YES) - goto ndbcluster_init_error; { handlerton &h= ndbcluster_hton; + h.state= have_ndbcluster; + h.db_type= DB_TYPE_NDBCLUSTER; h.close_connection= ndbcluster_close_connection; h.commit= ndbcluster_commit; h.rollback= ndbcluster_rollback; @@ -6108,6 +6096,9 @@ static bool ndbcluster_init() h.flags= HTON_TEMPORARY_NOT_SUPPORTED; } + if (have_ndbcluster != SHOW_OPTION_YES) + DBUG_RETURN(0); // nothing else to do + // Set connectstring if specified if (opt_ndbcluster_connectstring != 0) DBUG_PRINT("connectstring", ("%s", opt_ndbcluster_connectstring)); @@ -6179,7 +6170,7 @@ static bool ndbcluster_init() if (ndbcluster_binlog_start()) goto ndbcluster_init_error; #endif /* HAVE_NDB_BINLOG */ - + pthread_mutex_init(&LOCK_ndb_util_thread, MY_MUTEX_INIT_FAST); pthread_cond_init(&COND_ndb_util_thread, NULL); @@ -6195,7 +6186,7 @@ static bool ndbcluster_init() pthread_cond_destroy(&COND_ndb_util_thread); goto ndbcluster_init_error; } - + ndbcluster_inited= 1; DBUG_RETURN(FALSE); @@ -9356,9 +9347,8 @@ ndbcluster_show_status(THD* thd, stat_print_fn *stat_print, ndb_connected_host, ndb_connected_port, ndb_number_of_storage_nodes); - if (stat_print(thd, ndbcluster_hton.name, strlen(ndbcluster_hton.name), - "connection", strlen("connection"), - buf, buflen)) + if (stat_print(thd, ndbcluster_hton_name, ndbcluster_hton_name_length, + STRING_WITH_LEN("connection"), buf, buflen)) DBUG_RETURN(TRUE); if (get_thd_ndb(thd) && get_thd_ndb(thd)->ndb) @@ -9372,7 +9362,7 @@ ndbcluster_show_status(THD* thd, stat_print_fn *stat_print, my_snprintf(buf, sizeof(buf), "created=%u, free=%u, sizeof=%u", tmp.m_created, tmp.m_free, tmp.m_sizeof); - if (stat_print(thd, ndbcluster_hton.name, strlen(ndbcluster_hton.name), + if (stat_print(thd, ndbcluster_hton_name, ndbcluster_hton_name_length, tmp.m_name, strlen(tmp.m_name), buf, buflen)) DBUG_RETURN(TRUE); } @@ -10037,8 +10027,8 @@ static int ndbcluster_fill_files_table(THD *thd, TABLE_LIST *tables, COND *cond) strlen(ts.getDefaultLogfileGroup()), system_charset_info); table->field[c++]->set_null(); // LOGFILE_GROUP_NUMBER - table->field[c++]->store(ndbcluster_hton.name, - strlen(ndbcluster_hton.name), + table->field[c++]->store(ndbcluster_hton_name, + ndbcluster_hton_name_length, system_charset_info); // ENGINE table->field[c++]->set_null(); // FULLTEXT_KEYS @@ -10131,8 +10121,8 @@ static int ndbcluster_fill_files_table(THD *thd, TABLE_LIST *tables, COND *cond) strlen(uf.getLogfileGroup()), system_charset_info); table->field[c++]->store(uf.getLogfileGroupId()); // LOGFILE_GROUP_NUMBER - table->field[c++]->store(ndbcluster_hton.name, - strlen(ndbcluster_hton.name), + table->field[c++]->store(ndbcluster_hton_name, + ndbcluster_hton_name_length, system_charset_info); // ENGINE table->field[c++]->set_null(); // FULLTEXT_KEYS @@ -10178,15 +10168,17 @@ static int ndbcluster_fill_files_table(THD *thd, TABLE_LIST *tables, COND *cond) DBUG_RETURN(0); } +struct st_mysql_storage_engine ndbcluster_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION, &ndbcluster_hton }; mysql_declare_plugin(ndbcluster) { MYSQL_STORAGE_ENGINE_PLUGIN, - &ndbcluster_hton, + &ndbcluster_storage_engine, ndbcluster_hton_name, "MySQL AB", - ndbcluster_hton_comment, - NULL, /* Plugin Init */ + "Clustered, fault-tolerant tables", + ndbcluster_init, /* Plugin Init */ NULL, /* Plugin Deinit */ 0x0100 /* 1.0 */, 0 diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h index f407cb0090f..e2e8f04bf00 100644 --- a/sql/ha_ndbcluster.h +++ b/sql/ha_ndbcluster.h @@ -889,3 +889,7 @@ int ndbcluster_find_files(THD *thd,const char *db,const char *path, int ndbcluster_table_exists_in_engine(THD* thd, const char *db, const char *name); void ndbcluster_print_error(int error, const NdbOperation *error_op); + +static const char ndbcluster_hton_name[]= "ndbcluster"; +static const int ndbcluster_hton_name_length=sizeof(ndbcluster_hton_name)-1; + diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index a125fd5e722..c2190e79bfc 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -2323,9 +2323,9 @@ ndbcluster_create_event(Ndb *ndb, const NDBTAB *ndbtab, push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_ILLEGAL_HA_CREATE_OPTION, ER(ER_ILLEGAL_HA_CREATE_OPTION), - ndbcluster_hton.name, + ndbcluster_hton_name, "Binlog of table with BLOB attribute and no PK"); - + share->flags|= NSF_NO_BINLOG; DBUG_RETURN(-1); } @@ -3688,7 +3688,7 @@ ndbcluster_show_status_binlog(THD* thd, stat_print_fn *stat_print, ndb_latest_received_binlog_epoch, ndb_latest_handled_binlog_epoch, ndb_latest_applied_binlog_epoch); - if (stat_print(thd, ndbcluster_hton.name, strlen(ndbcluster_hton.name), + if (stat_print(thd, ndbcluster_hton_name, ndbcluster_hton_name_length, "binlog", strlen("binlog"), buf, buflen)) DBUG_RETURN(TRUE); diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 7b9dd00ed56..2f69fb50a92 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -73,46 +73,18 @@ static handler *partition_create_handler(TABLE_SHARE *share); static uint partition_flags(); static uint alter_table_flags(uint flags); -static const char partition_hton_name[]= "partition"; -static const char partition_hton_comment[]= "Partition Storage Engine Helper"; +handlerton partition_hton; -handlerton partition_hton = { - MYSQL_HANDLERTON_INTERFACE_VERSION, - partition_hton_name, - SHOW_OPTION_YES, - partition_hton_comment, /* A comment used by SHOW to describe an engine */ - DB_TYPE_PARTITION_DB, - 0, /* Method that initializes a storage engine */ - 0, /* slot */ - 0, /* savepoint size */ - NULL /*ndbcluster_close_connection*/, - NULL, /* savepoint_set */ - NULL, /* savepoint_rollback */ - NULL, /* savepoint_release */ - NULL /*ndbcluster_commit*/, - NULL /*ndbcluster_rollback*/, - NULL, /* prepare */ - NULL, /* recover */ - NULL, /* commit_by_xid */ - NULL, /* rollback_by_xid */ - NULL, - NULL, - NULL, - partition_create_handler, /* Create a new handler */ - NULL, /* Drop a database */ - NULL, /* Panic call */ - NULL, /* Start Consistent Snapshot */ - NULL, /* Flush logs */ - NULL, /* Show status */ - partition_flags, /* Partition flags */ - alter_table_flags, /* Partition flags */ - NULL, /* Alter Tablespace */ - NULL, /* Fill FILES table */ - HTON_NOT_USER_SELECTABLE | HTON_HIDDEN, - NULL, /* binlog_func */ - NULL, /* binlog_log_query */ - NULL /* release_temporary_latches */ -}; +static int partition_initialize() +{ + partition_hton.state= SHOW_OPTION_YES; + partition_hton.db_type= DB_TYPE_PARTITION_DB; + partition_hton.create= partition_create_handler; + partition_hton.partition_flags= partition_flags; + partition_hton.alter_table_flags= alter_table_flags; + partition_hton.flags= HTON_NOT_USER_SELECTABLE | HTON_HIDDEN; + return 0; +} /* Create new partition handler @@ -5525,15 +5497,17 @@ static int free_share(PARTITION_SHARE *share) } #endif /* NOT_USED */ +struct st_mysql_storage_engine partition_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION, &partition_hton }; mysql_declare_plugin(partition) { MYSQL_STORAGE_ENGINE_PLUGIN, - &partition_hton, - partition_hton_name, + &partition_storage_engine, + "partition", "Mikael Ronstrom, MySQL AB", - partition_hton_comment, - NULL, /* Plugin Init */ + "Partition Storage Engine Helper", + partition_initialize, /* Plugin Init */ NULL, /* Plugin Deinit */ 0x0100, /* 1.0 */ 0 diff --git a/sql/handler.cc b/sql/handler.cc index b9ef05a33c2..22ce41decef 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -48,6 +48,7 @@ check for dups and to find handlerton from legacy_db_type. Remove when legacy_db_type is finally gone */ static handlerton *installed_htons[128]; +st_mysql_plugin *hton2plugin[MAX_HA]; #define BITMAP_STACKBUF_SIZE (128/8) @@ -57,35 +58,14 @@ KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NullS,0} }; static handler *create_default(TABLE_SHARE *table); -const handlerton default_hton = -{ - MYSQL_HANDLERTON_INTERFACE_VERSION, - "DEFAULT", - SHOW_OPTION_YES, - NULL, - DB_TYPE_DEFAULT, - NULL, - 0, 0, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, - create_default, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, /* alter_tablespace */ - NULL, /* fill_files_table */ - HTON_NO_FLAGS, /* flags */ - NULL, /* binlog_func */ - NULL, /* binlog_log_query */ - NULL /* release_temporary_latches */ -}; - static SHOW_COMP_OPTION have_yes= SHOW_OPTION_YES; /* number of entries in handlertons[] */ -ulong total_ha; +ulong total_ha= 0; /* number of storage engines (from handlertons[]) that support 2pc */ -ulong total_ha_2pc; +ulong total_ha_2pc= 0; /* size of savepoint storage area (see ha_init) */ -ulong savepoint_alloc_size; +ulong savepoint_alloc_size= 0; struct show_table_alias_st sys_table_aliases[]= { @@ -122,7 +102,7 @@ handlerton *ha_resolve_by_name(THD *thd, LEX_STRING *name) if ((plugin= plugin_lock(name, MYSQL_STORAGE_ENGINE_PLUGIN))) { - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; if (!(hton->flags & HTON_NOT_USER_SELECTABLE)) return hton; plugin_unlock(plugin); @@ -155,7 +135,7 @@ const char *ha_get_storage_engine(enum legacy_db_type db_type) default: if (db_type > DB_TYPE_UNKNOWN && db_type < DB_TYPE_DEFAULT && installed_htons[db_type]) - return installed_htons[db_type]->name; + return hton2plugin[installed_htons[db_type]->slot]->name; return "*NONE*"; } } @@ -164,8 +144,7 @@ const char *ha_get_storage_engine(enum legacy_db_type db_type) static handler *create_default(TABLE_SHARE *table) { handlerton *hton=ha_resolve_by_legacy_type(current_thd, DB_TYPE_DEFAULT); - return (hton && hton != &default_hton && hton->create) ? - hton->create(table) : NULL; + return (hton && hton->create) ? hton->create(table) : NULL; } @@ -183,7 +162,7 @@ handlerton *ha_resolve_by_legacy_type(THD *thd, enum legacy_db_type db_type) default: if (db_type > DB_TYPE_UNKNOWN && db_type < DB_TYPE_DEFAULT) return installed_htons[db_type]; - return NULL; + return NULL; } } @@ -375,7 +354,7 @@ int ha_finalize_handlerton(st_plugin_int *plugin) handlerton *hton; DBUG_ENTER("ha_finalize_handlerton"); - if (!(hton= (handlerton *) plugin->plugin->info)) + if (!(hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton)) DBUG_RETURN(1); switch (hton->state) @@ -396,37 +375,26 @@ int ha_finalize_handlerton(st_plugin_int *plugin) int ha_initialize_handlerton(st_plugin_int *plugin) { - handlerton *hton; + handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; + DBUG_ENTER("ha_initialize_handlerton"); - if (!(hton= (handlerton *) plugin->plugin->info)) - DBUG_RETURN(1); - - /* for the sake of sanity, we set the handlerton name to be the - same as the plugin name */ - hton->name= plugin->name.str; - - + /* + the switch below and hton->state should be removed when + command-line options for plugins will be implemented + */ switch (hton->state) { case SHOW_OPTION_NO: break; case SHOW_OPTION_YES: - if (!hton->init || !hton->init()) { - uint tmp= hton->savepoint_offset; - hton->savepoint_offset= savepoint_alloc_size; - savepoint_alloc_size+= tmp; - hton->slot= total_ha++; - if (hton->prepare) - total_ha_2pc++; - /* now check the db_type for conflict */ - if (hton->db_type <= DB_TYPE_UNKNOWN || + if (hton->db_type <= DB_TYPE_UNKNOWN || hton->db_type >= DB_TYPE_DEFAULT || installed_htons[hton->db_type]) { int idx= (int) DB_TYPE_FIRST_DYNAMIC; - + while (idx < (int) DB_TYPE_DEFAULT && installed_htons[idx]) idx++; @@ -437,10 +405,17 @@ int ha_initialize_handlerton(st_plugin_int *plugin) } if (hton->db_type != DB_TYPE_UNKNOWN) sql_print_warning("Storage engine '%s' has conflicting typecode. " - "Assigning value %d.", hton->name, idx); + "Assigning value %d.", plugin->plugin->name, idx); hton->db_type= (enum legacy_db_type) idx; } installed_htons[hton->db_type]= hton; + uint tmp= hton->savepoint_offset; + hton->savepoint_offset= savepoint_alloc_size; + savepoint_alloc_size+= tmp; + hton->slot= total_ha++; + hton2plugin[hton->slot]=plugin->plugin; + if (hton->prepare) + total_ha_2pc++; break; } /* fall through */ @@ -451,33 +426,14 @@ int ha_initialize_handlerton(st_plugin_int *plugin) DBUG_RETURN(0); } - -static my_bool init_handlerton(THD *unused1, st_plugin_int *plugin, - void *unused2) -{ - if (plugin->state == PLUGIN_IS_UNINITIALIZED) - { - ha_initialize_handlerton(plugin); - plugin->state= PLUGIN_IS_READY; - } - return FALSE; -} - - int ha_init() { int error= 0; - total_ha= savepoint_alloc_size= 0; DBUG_ENTER("ha_init"); - bzero(installed_htons, sizeof(installed_htons)); - if (ha_init_errors()) DBUG_RETURN(1); - if (plugin_foreach(NULL, init_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, 0)) - DBUG_RETURN(1); - DBUG_ASSERT(total_ha < MAX_HA); /* Check if there is a transaction-capable storage engine besides the @@ -498,7 +454,7 @@ int ha_init() static my_bool panic_handlerton(THD *unused1, st_plugin_int *plugin, void *arg) { - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; if (hton->state == SHOW_OPTION_YES && hton->panic) ((int*)arg)[0]|= hton->panic((enum ha_panic_function)((int*)arg)[1]); return FALSE; @@ -508,10 +464,10 @@ static my_bool panic_handlerton(THD *unused1, st_plugin_int *plugin, int ha_panic(enum ha_panic_function flag) { int error[2]; - + error[0]= 0; error[1]= (int)flag; plugin_foreach(NULL, panic_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, error); - + if (flag == HA_PANIC_CLOSE && ha_finish_errors()) error[0]= 1; return error[0]; @@ -520,7 +476,7 @@ int ha_panic(enum ha_panic_function flag) static my_bool dropdb_handlerton(THD *unused1, st_plugin_int *plugin, void *path) { - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; if (hton->state == SHOW_OPTION_YES && hton->drop_database) hton->drop_database((char *)path); return FALSE; @@ -536,8 +492,8 @@ void ha_drop_database(char* path) static my_bool closecon_handlerton(THD *thd, st_plugin_int *plugin, void *unused) { - handlerton *hton= (handlerton *) plugin->plugin->info; - /* there's no need to rollback here as all transactions must + handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; + /* there's no need to rollback here as all transactions must be rolled back already */ if (hton->state == SHOW_OPTION_YES && hton->close_connection && thd->ha_data[hton->slot]) @@ -628,7 +584,8 @@ int ha_prepare(THD *thd) else { push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA), (*ht)->name); + ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA), + hton2plugin[(*ht)->slot]->name); } } } @@ -867,7 +824,7 @@ struct xahton_st { static my_bool xacommit_handlerton(THD *unused1, st_plugin_int *plugin, void *arg) { - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; if (hton->state == SHOW_OPTION_YES && hton->recover) { hton->commit_by_xid(((struct xahton_st *)arg)->xid); @@ -879,7 +836,7 @@ static my_bool xacommit_handlerton(THD *unused1, st_plugin_int *plugin, static my_bool xarollback_handlerton(THD *unused1, st_plugin_int *plugin, void *arg) { - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; if (hton->state == SHOW_OPTION_YES && hton->recover) { hton->rollback_by_xid(((struct xahton_st *)arg)->xid); @@ -986,16 +943,16 @@ struct xarecover_st static my_bool xarecover_handlerton(THD *unused, st_plugin_int *plugin, void *arg) { - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; struct xarecover_st *info= (struct xarecover_st *) arg; int got; - + if (hton->state == SHOW_OPTION_YES && hton->recover) { while ((got= hton->recover(info->list, info->len)) > 0 ) { sql_print_information("Found %d prepared transaction(s) in %s", - got, hton->name); + got, hton2plugin[hton->slot]->name); for (int i=0; i < got; i ++) { my_xid x=info->list[i].get_my_xid(); @@ -1175,7 +1132,7 @@ bool mysql_xa_recover(THD *thd) static my_bool release_temporary_latches(THD *thd, st_plugin_int *plugin, void *unused) { - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; if (hton->state == SHOW_OPTION_YES && hton->release_temporary_latches) hton->release_temporary_latches(thd); @@ -1300,7 +1257,7 @@ int ha_release_savepoint(THD *thd, SAVEPOINT *sv) static my_bool snapshot_handlerton(THD *thd, st_plugin_int *plugin, void *arg) { - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; if (hton->state == SHOW_OPTION_YES && hton->start_consistent_snapshot) { @@ -1331,7 +1288,7 @@ int ha_start_consistent_snapshot(THD *thd) static my_bool flush_handlerton(THD *thd, st_plugin_int *plugin, void *arg) { - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; if (hton->state == SHOW_OPTION_YES && hton->flush_logs && hton->flush_logs()) return TRUE; return FALSE; @@ -2635,7 +2592,7 @@ struct binlog_func_st static my_bool binlog_func_list(THD *thd, st_plugin_int *plugin, void *arg) { hton_list_st *hton_list= (hton_list_st *)arg; - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; if (hton->state == SHOW_OPTION_YES && hton->binlog_func) { uint sz= hton_list->sz; @@ -3006,7 +2963,7 @@ int handler::index_read_idx(byte * buf, uint index, const byte * key, SYNOPSIS ha_known_exts() - + NOTES No mutexes, worst case race is a minor surplus memory allocation We have to recreate the extension map if mysqld is restarted (for example @@ -3020,14 +2977,14 @@ static my_bool exts_handlerton(THD *unused, st_plugin_int *plugin, void *arg) { List *found_exts= (List *) arg; - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; handler *file; if (hton->state == SHOW_OPTION_YES && hton->create && (file= hton->create((TABLE_SHARE*) 0))) { List_iterator_fast it(*found_exts); const char **ext, *old_ext; - + for (ext= file->bas_ext(); *ext; ext++) { while ((old_ext= it++)) @@ -3056,14 +3013,14 @@ TYPELIB *ha_known_exts(void) known_extensions_id= mysys_usage_id; found_exts.push_back((char*) triggers_file_ext); found_exts.push_back((char*) trigname_file_ext); - - plugin_foreach(NULL, exts_handlerton, + + plugin_foreach(NULL, exts_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, &found_exts); ext= (const char **) my_once_alloc(sizeof(char *)* (found_exts.elements+1), MYF(MY_WME | MY_FAE)); - + DBUG_ASSERT(ext != 0); known_extensions.count= found_exts.elements; known_extensions.type_names= ext; @@ -3096,7 +3053,7 @@ static my_bool showstat_handlerton(THD *thd, st_plugin_int *plugin, void *arg) { enum ha_stat_type stat= *(enum ha_stat_type *) arg; - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; if (hton->state == SHOW_OPTION_YES && hton->show_status && hton->show_status(thd, stat_print, stat)) return TRUE; @@ -3119,16 +3076,19 @@ bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat) if (db_type == NULL) { - result= plugin_foreach(thd, showstat_handlerton, + result= plugin_foreach(thd, showstat_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, &stat); } else { if (db_type->state != SHOW_OPTION_YES) - result= stat_print(thd, db_type->name, strlen(db_type->name), + { + const char *name=hton2plugin[db_type->slot]->name; + result= stat_print(thd, name, strlen(name), "", 0, "DISABLED", 8) ? 1 : 0; + } else - result= db_type->show_status && + result= db_type->show_status && db_type->show_status(thd, stat_print, stat) ? 1 : 0; } diff --git a/sql/handler.h b/sql/handler.h index afee6bb9f8d..83143d9729d 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -177,6 +177,7 @@ so: innodb + bdb + ndb + binlog + myisam + myisammrg + archive + example + csv + heap + blackhole + federated + 0 (yes, the sum is deliberately inaccurate) + TODO remove the limit, use dynarrays */ #define MAX_HA 15 @@ -460,6 +461,7 @@ typedef bool (stat_print_fn)(THD *thd, const char *type, uint type_len, const char *file, uint file_len, const char *status, uint status_len); enum ha_stat_type { HA_ENGINE_STATUS, HA_ENGINE_LOGS, HA_ENGINE_MUTEX }; +extern st_mysql_plugin *hton2plugin[MAX_HA]; /* handlerton is a singleton structure - one instance per storage engine - @@ -475,38 +477,15 @@ enum ha_stat_type { HA_ENGINE_STATUS, HA_ENGINE_LOGS, HA_ENGINE_MUTEX }; struct handlerton { /* - handlerton structure version - */ - const int interface_version; -/* last version change: 0x0001 in 5.1.6 */ -#define MYSQL_HANDLERTON_INTERFACE_VERSION 0x0001 - - - /* - storage engine name as it should be printed to a user - */ - const char *name; - - /* - Historical marker for if the engine is available of not + Historical marker for if the engine is available of not */ SHOW_COMP_OPTION state; - /* - A comment used by SHOW to describe an engine. - */ - const char *comment; - /* Historical number used for frm file to determine the correct storage engine. This is going away and new engines will just use "name" for this. */ enum legacy_db_type db_type; - /* - Method that initizlizes a storage engine - */ - bool (*init)(); - /* each storage engine has it's own memory area (actually a pointer) in the thd, for storing per-connection information. @@ -587,8 +566,6 @@ struct handlerton int (*release_temporary_latches)(THD *thd); }; -extern const handlerton default_hton; - struct show_table_alias_st { const char *alias; enum legacy_db_type type; @@ -1552,7 +1529,7 @@ static inline enum legacy_db_type ha_legacy_type(const handlerton *db_type) static inline const char *ha_resolve_storage_engine_name(const handlerton *db_type) { - return db_type == NULL ? "UNKNOWN" : db_type->name; + return db_type == NULL ? "UNKNOWN" : hton2plugin[db_type->slot]->name; } static inline bool ha_check_storage_engine_flag(const handlerton *db_type, uint32 flag) diff --git a/sql/log.cc b/sql/log.cc index 7c8f314bc08..1f8bb5f0b69 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -47,7 +47,7 @@ ulong sync_binlog_counter= 0; static bool test_if_number(const char *str, long *res, bool allow_wildcards); -static bool binlog_init(); +static int binlog_init(); static int binlog_close_connection(THD *thd); static int binlog_savepoint_set(THD *thd, void *sv); static int binlog_savepoint_rollback(THD *thd, void *sv); @@ -70,49 +70,7 @@ struct binlog_trx_data { Rows_log_event *pending; // The pending binrows event }; -static const char binlog_hton_name[]= "binlog"; -static const char binlog_hton_comment[]= - "This is a meta storage engine to represent the binlog in a transaction"; - -handlerton binlog_hton = { - MYSQL_HANDLERTON_INTERFACE_VERSION, - binlog_hton_name, - SHOW_OPTION_YES, - binlog_hton_comment, - DB_TYPE_BINLOG, /* IGNORE for now */ - binlog_init, - 0, - sizeof(my_off_t), /* savepoint size = binlog offset */ - binlog_close_connection, - binlog_savepoint_set, - binlog_savepoint_rollback, - NULL, /* savepoint_release */ - binlog_commit, - binlog_rollback, - binlog_prepare, - NULL, /* recover */ - NULL, /* commit_by_xid */ - NULL, /* rollback_by_xid */ - NULL, /* create_cursor_read_view */ - NULL, /* set_cursor_read_view */ - NULL, /* close_cursor_read_view */ - NULL, /* Create a new handler */ - NULL, /* Drop a database */ - NULL, /* Panic call */ - NULL, /* Start Consistent Snapshot */ - NULL, /* Flush logs */ - NULL, /* Show status */ - NULL, /* Partition flags */ - NULL, /* Alter table flags */ - NULL, /* Alter Tablespace */ - NULL, /* Fill FILES table */ - HTON_NOT_USER_SELECTABLE | HTON_HIDDEN, - NULL, /* binlog_func */ - NULL, /* binlog_log_query */ - NULL /* release_temporary_latches */ -}; - - +handlerton binlog_hton; /* Open log table of a given type (general or slow log) @@ -1058,9 +1016,20 @@ void Log_to_csv_event_handler:: should be moved here. */ -bool binlog_init() +int binlog_init() { - return !opt_bin_log; + + binlog_hton.state=opt_bin_log ? SHOW_OPTION_YES : SHOW_OPTION_NO; + binlog_hton.db_type=DB_TYPE_BINLOG; + binlog_hton.savepoint_offset= sizeof(my_off_t); + binlog_hton.close_connection= binlog_close_connection; + binlog_hton.savepoint_set= binlog_savepoint_set; + binlog_hton.savepoint_rollback= binlog_savepoint_rollback; + binlog_hton.commit= binlog_commit; + binlog_hton.rollback= binlog_rollback; + binlog_hton.prepare= binlog_prepare; + binlog_hton.flags= HTON_NOT_USER_SELECTABLE | HTON_HIDDEN; + return 0; } static int binlog_close_connection(THD *thd) @@ -4354,15 +4323,17 @@ err1: return 1; } +struct st_mysql_storage_engine binlog_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION, &binlog_hton }; mysql_declare_plugin(binlog) { MYSQL_STORAGE_ENGINE_PLUGIN, - &binlog_hton, - binlog_hton_name, + &binlog_storage_engine, + "binlog", "MySQL AB", - binlog_hton_comment, - NULL, /* Plugin Init */ + "This is a pseudo storage engine to represent the binlog in a transaction", + binlog_init, /* Plugin Init */ NULL, /* Plugin Deinit */ 0x0100 /* 1.0 */, } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 127aa6c5acd..5dea2473fa0 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -502,13 +502,13 @@ typedef my_bool (*qc_engine_callback)(THD *thd, char *table_key, #include "sql_list.h" #include "sql_map.h" #include "my_decimal.h" +#include "sql_plugin.h" #include "handler.h" #include "parse_file.h" #include "table.h" #include "sql_error.h" #include "field.h" /* Field definitions */ #include "protocol.h" -#include "sql_plugin.h" #include "sql_udf.h" #include "sql_partition.h" diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 0c02971a2bc..fa8b80bf9b6 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -330,7 +330,7 @@ static char *opt_init_slave, *language_ptr, *opt_init_connect; static char *default_character_set_name; static char *character_set_filesystem_name; static char *my_bind_addr_str; -static char *default_collation_name; +static char *default_collation_name, *default_storage_engine_str; static char mysql_data_home_buff[2]; static struct passwd *user_info; static I_List thread_cache; @@ -2630,12 +2630,6 @@ static int init_common_variables(const char *conf_file_name, int argc, if (add_status_vars(status_vars)) return 1; // an error was already reported - if (plugin_init()) - { - sql_print_error("Failed to init plugins."); - return 1; - } - load_defaults(conf_file_name, groups, &argc, &argv); defaults_argv=argv; get_options(argc,argv); @@ -3151,6 +3145,12 @@ server."); using_update_log=1; } + if (plugin_init()) + { + sql_print_error("Failed to init plugins."); + return 1; + } + /* We have to initialize the storage engines before CSV logging */ if (ha_init()) { @@ -3197,15 +3197,27 @@ server."); /* Check that the default storage engine is actually available. */ - if (!ha_storage_engine_is_enabled(global_system_variables.table_type)) { - if (!opt_bootstrap) + LEX_STRING name= { default_storage_engine_str, + strlen(default_storage_engine_str) }; + handlerton *hton= ha_resolve_by_name(0, &name); + if (hton == NULL) { - sql_print_error("Default storage engine (%s) is not available", - global_system_variables.table_type->name); + sql_print_error("Unknown/unsupported table type: %s", + default_storage_engine_str); unireg_abort(1); } - global_system_variables.table_type= &myisam_hton; + if (!ha_storage_engine_is_enabled(hton)) + { + if (!opt_bootstrap) + { + sql_print_error("Default storage engine (%s) is not available", + default_storage_engine_str); + unireg_abort(1); + } + hton= &myisam_hton; + } + global_system_variables.table_type= hton; } tc_log= (total_ha_2pc > 1 ? (opt_bin_log ? @@ -4951,7 +4963,8 @@ Disable with --skip-bdb (will save memory).", "Set the default storage engine (table type) for tables.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"default-table-type", OPT_STORAGE_ENGINE, - "(deprecated) Use --default-storage-engine.", 0, 0, + "(deprecated) Use --default-storage-engine.", + (gptr*)default_storage_engine_str, (gptr*)default_storage_engine_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"default-time-zone", OPT_DEFAULT_TIME_ZONE, "Set the default time zone.", (gptr*) &default_tz_name, (gptr*) &default_tz_name, @@ -6980,8 +6993,8 @@ static void mysql_init_variables(void) sys_charset_system.value= (char*) system_charset_info->csname; character_set_filesystem_name= (char*) "binary"; - /* Set default values for some option variables */ + default_storage_engine_str="MyISAM"; global_system_variables.table_type= &myisam_hton; global_system_variables.tx_isolation= ISO_REPEATABLE_READ; global_system_variables.select_limit= (ulonglong) HA_POS_ERROR; @@ -7423,17 +7436,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), case OPT_BOOTSTRAP: opt_noacl=opt_bootstrap=1; break; - case OPT_STORAGE_ENGINE: - { - LEX_STRING name= { argument, strlen(argument) }; - if ((global_system_variables.table_type= - ha_resolve_by_name(current_thd, &name)) == NULL) - { - fprintf(stderr,"Unknown/unsupported table type: %s\n",argument); - exit(1); - } - break; - } case OPT_SERVER_ID: server_id_supplied = 1; break; diff --git a/sql/set_var.cc b/sql/set_var.cc index 57eeeed46e1..c69d5505a8f 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -3250,7 +3250,7 @@ byte *sys_var_thd_storage_engine::value_ptr(THD *thd, enum_var_type type, handlerton *val; val= (type == OPT_GLOBAL) ? global_system_variables.*offset : thd->variables.*offset; - return (byte *) val->name; + return (byte *) hton2plugin[val->slot]->name; } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 6bba78a836e..8d45cbcad2c 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -7104,7 +7104,7 @@ bool mysql_create_index(THD *thd, TABLE_LIST *table_list, List &keys) HA_CREATE_INFO create_info; DBUG_ENTER("mysql_create_index"); bzero((char*) &create_info,sizeof(create_info)); - create_info.db_type= (handlerton*) &default_hton; + create_info.db_type= 0; create_info.default_table_charset= thd->variables.collation_database; DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->table_name, &create_info, table_list, @@ -7120,7 +7120,7 @@ bool mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info) HA_CREATE_INFO create_info; DBUG_ENTER("mysql_drop_index"); bzero((char*) &create_info,sizeof(create_info)); - create_info.db_type= (handlerton*) &default_hton; + create_info.db_type= 0; create_info.default_table_charset= thd->variables.collation_database; alter_info->clear(); alter_info->flags= ALTER_DROP_INDEX; diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index e946e972968..03dfe378ec2 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1665,7 +1665,7 @@ static int add_keyword_int(File fptr, const char *keyword, longlong num) static int add_engine(File fptr, handlerton *engine_type) { - const char *engine_str= engine_type->name; + const char *engine_str= hton2plugin[engine_type->slot]->name; DBUG_PRINT("info", ("ENGINE = %s", engine_str)); int err= add_string(fptr, "ENGINE = "); return err + add_string(fptr, engine_str); @@ -3559,17 +3559,9 @@ static bool check_engine_condition(partition_element *p_elem, DBUG_ENTER("check_engine_condition"); DBUG_PRINT("enter", ("def_eng = %u, first = %u", default_engine, *first)); - if (*engine_type) - DBUG_PRINT("info", ("engine_type = %s", (*engine_type)->name)); - else - DBUG_PRINT("info", ("engine_type = NULL")); if (*first && default_engine) { *engine_type= p_elem->engine_type; - if (*engine_type) - DBUG_PRINT("info", ("engine_type changed to = %s", (*engine_type)->name)); - else - DBUG_PRINT("info", ("engine_type changed to = NULL")); } *first= FALSE; if ((!default_engine && @@ -4524,7 +4516,7 @@ the generated partition syntax in a correct manner. create_info->db_type= table->part_info->default_engine_type; } DBUG_PRINT("info", ("New engine type = %s", - create_info->db_type->name)); + hton2plugin[create_info->db_type->slot]->name)); thd->work_part_info= NULL; *partition_changed= TRUE; } @@ -4586,11 +4578,9 @@ the generated partition syntax in a correct manner. } if (!is_native_partitioned) { - DBUG_ASSERT(create_info->db_type != &default_hton); + DBUG_ASSERT(create_info->db_type); create_info->db_type= &partition_hton; } - DBUG_PRINT("info", ("default_engine_type = %s", - thd->work_part_info->default_engine_type->name)); } } DBUG_RETURN(FALSE); diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 01faae22c57..d06a682bdce 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -23,12 +23,18 @@ extern struct st_mysql_plugin *mysqld_builtins[]; char *opt_plugin_dir_ptr; char opt_plugin_dir[FN_REFLEN]; -LEX_STRING plugin_type_names[]= +LEX_STRING plugin_type_names[MYSQL_MAX_PLUGIN_TYPE_NUM]= { { (char *)STRING_WITH_LEN("UDF") }, { (char *)STRING_WITH_LEN("STORAGE ENGINE") }, { (char *)STRING_WITH_LEN("FTPARSER") } }; + +plugin_type_init plugin_type_initialize[MYSQL_MAX_PLUGIN_TYPE_NUM]= +{ + 0,ha_initialize_handlerton,0 +}; + static const char *plugin_interface_version_sym= "_mysql_plugin_interface_version_"; static const char *sizeof_st_plugin_sym= @@ -522,27 +528,15 @@ static int plugin_initialize(struct st_plugin_int *plugin) { sql_print_error("Plugin '%s' init function returned error.", plugin->name.str); - DBUG_PRINT("warning", ("Plugin '%s' init function returned error.", - plugin->name.str)); goto err; } } - - switch (plugin->plugin->type) + if (plugin_type_initialize[plugin->plugin->type] && + (*plugin_type_initialize[plugin->plugin->type])(plugin)) { - case MYSQL_STORAGE_ENGINE_PLUGIN: - if (ha_initialize_handlerton(plugin)) - { - sql_print_error("Plugin '%s' handlerton init returned error.", - plugin->name.str); - DBUG_PRINT("warning", ("Plugin '%s' handlerton init returned error.", - plugin->name.str)); - goto err; - } - break; - - default: - break; + sql_print_error("Plugin '%s' registration as a %s failed.", + plugin->name.str, plugin_type_names[plugin->plugin->type]); + goto err; } DBUG_RETURN(0); @@ -554,14 +548,14 @@ static int plugin_finalize(THD *thd, struct st_plugin_int *plugin) { int rc; DBUG_ENTER("plugin_finalize"); - + if (plugin->ref_count) { push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, "Plugin is busy and will be uninstalled on shutdown"); goto err; } - + switch (plugin->plugin->type) { case MYSQL_STORAGE_ENGINE_PLUGIN: @@ -591,7 +585,7 @@ static int plugin_finalize(THD *thd, struct st_plugin_int *plugin) goto err; } } - + DBUG_RETURN(0); err: DBUG_RETURN(1); @@ -676,7 +670,7 @@ int plugin_init(void) get_hash_key, NULL, 0)) goto err; } - + /* Register all the built-in plugins */ for (builtins= mysqld_builtins; *builtins; builtins++) { @@ -684,6 +678,12 @@ int plugin_init(void) { if (plugin_register_builtin(plugin)) goto err; + struct st_plugin_int *tmp=dynamic_element(&plugin_array, + plugin_array.elements-1, + struct st_plugin_int *); + if (plugin_initialize(tmp)) + goto err; + tmp->state= PLUGIN_IS_READY; } } diff --git a/sql/sql_plugin.h b/sql/sql_plugin.h index 672db105cd1..8459346fb53 100644 --- a/sql/sql_plugin.h +++ b/sql/sql_plugin.h @@ -61,6 +61,8 @@ struct st_plugin_int uint ref_count; /* number of threads using the plugin */ }; +typedef int (*plugin_type_init)(struct st_plugin_int *); + extern char *opt_plugin_dir_ptr; extern char opt_plugin_dir[FN_REFLEN]; extern LEX_STRING plugin_type_names[]; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 5fad0c7e09b..d8ae1bc1abb 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -46,7 +46,7 @@ static void store_key_options(THD *thd, String *packet, TABLE *table, KEY *key_info); /*************************************************************************** -** List all table types supported +** List all table types supported ***************************************************************************/ static my_bool show_handlerton(THD *thd, st_plugin_int *plugin, @@ -54,25 +54,25 @@ static my_bool show_handlerton(THD *thd, st_plugin_int *plugin, { handlerton *default_type= (handlerton *) arg; Protocol *protocol= thd->protocol; - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; if (!(hton->flags & HTON_HIDDEN)) { protocol->prepare_for_resend(); - protocol->store(hton->name, system_charset_info); + protocol->store(plugin->plugin->name, system_charset_info); const char *option_name= show_comp_option_name[(int) hton->state]; if (hton->state == SHOW_OPTION_YES && default_type == hton) option_name= "DEFAULT"; protocol->store(option_name, system_charset_info); - protocol->store(hton->comment, system_charset_info); + protocol->store(plugin->plugin->descr, system_charset_info); protocol->store(hton->commit ? "YES" : "NO", system_charset_info); protocol->store(hton->prepare ? "YES" : "NO", system_charset_info); protocol->store(hton->savepoint_set ? "YES" : "NO", system_charset_info); - + return protocol->write() ? 1 : 0; } - return 0; + return 0; } bool mysqld_show_storage_engines(THD *thd) @@ -92,7 +92,7 @@ bool mysqld_show_storage_engines(THD *thd) Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(TRUE); - if (plugin_foreach(thd, show_handlerton, + if (plugin_foreach(thd, show_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, thd->variables.table_type)) DBUG_RETURN(TRUE); @@ -3055,7 +3055,7 @@ static my_bool iter_schema_engines(THD *thd, st_plugin_int *plugin, void *ptable) { TABLE *table= (TABLE *) ptable; - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS; CHARSET_INFO *scs= system_charset_info; DBUG_ENTER("iter_schema_engines"); @@ -3063,21 +3063,26 @@ static my_bool iter_schema_engines(THD *thd, st_plugin_int *plugin, if (!(hton->flags & HTON_HIDDEN)) { if (!(wild && wild[0] && - wild_case_compare(scs, hton->name,wild))) + wild_case_compare(scs, plugin->plugin->name,wild))) { - const char *tmp; + LEX_STRING state[2]={{STRING_WITH_LEN("ENABLED")}, + {STRING_WITH_LEN("DISABLED")}}; + LEX_STRING yesno[2]={{STRING_WITH_LEN("NO")}, {STRING_WITH_LEN("YES")}}; + LEX_STRING *tmp; restore_record(table, s->default_values); - table->field[0]->store(hton->name, strlen(hton->name), scs); - tmp= hton->state ? "DISABLED" : "ENABLED"; - table->field[1]->store( tmp, strlen(tmp), scs); - table->field[2]->store(hton->comment, strlen(hton->comment), scs); - tmp= hton->commit ? "YES" : "NO"; - table->field[3]->store( tmp, strlen(tmp), scs); - tmp= hton->prepare ? "YES" : "NO"; - table->field[4]->store( tmp, strlen(tmp), scs); - tmp= hton->savepoint_set ? "YES" : "NO"; - table->field[5]->store( tmp, strlen(tmp), scs); + table->field[0]->store(plugin->plugin->name, + strlen(plugin->plugin->name), scs); + tmp= &state[test(hton->state)]; + table->field[1]->store(tmp->str, tmp->length, scs); + table->field[2]->store(plugin->plugin->descr, + strlen(plugin->plugin->descr), scs); + tmp= &yesno[test(hton->commit)]; + table->field[3]->store(tmp->str, tmp->length, scs); + tmp= &yesno[test(hton->prepare)]; + table->field[4]->store(tmp->str, tmp->length, scs); + tmp= &yesno[test(hton->savepoint_set)]; + table->field[5]->store(tmp->str, tmp->length, scs); if (schema_table_store_record(thd, table)) DBUG_RETURN(1); @@ -3089,7 +3094,7 @@ static my_bool iter_schema_engines(THD *thd, st_plugin_int *plugin, int fill_schema_engines(THD *thd, TABLE_LIST *tables, COND *cond) { - return plugin_foreach(thd, iter_schema_engines, + return plugin_foreach(thd, iter_schema_engines, MYSQL_STORAGE_ENGINE_PLUGIN, tables->table); } @@ -3104,7 +3109,7 @@ int fill_schema_collation(THD *thd, TABLE_LIST *tables, COND *cond) { CHARSET_INFO **cl; CHARSET_INFO *tmp_cs= cs[0]; - if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) || + if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) || (tmp_cs->state & MY_CS_HIDDEN) || !(tmp_cs->state & MY_CS_PRIMARY)) continue; @@ -4839,7 +4844,7 @@ static my_bool run_hton_fill_schema_files(THD *thd, st_plugin_int *plugin, { struct run_hton_fill_schema_files_args *args= (run_hton_fill_schema_files_args *) arg; - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; if(hton->fill_files_table) hton->fill_files_table(thd, args->tables, args->cond); return false; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 37506d11867..f06554979db 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -5085,7 +5085,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, } old_db_type= table->s->db_type; - if (create_info->db_type == (handlerton*) &default_hton) + if (!create_info->db_type) create_info->db_type= old_db_type; #ifdef WITH_PARTITION_STORAGE_ENGINE @@ -6398,7 +6398,7 @@ bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, lex->col_list.empty(); lex->alter_info.reset(); bzero((char*) &create_info,sizeof(create_info)); - create_info.db_type= (handlerton*) &default_hton; + create_info.db_type= 0; create_info.row_type=ROW_TYPE_NOT_USED; create_info.default_table_charset=default_charset_info; /* Force alter table to recreate table */ @@ -6542,7 +6542,7 @@ static bool check_engine(THD *thd, const char *table_name, no_substitution, 1))) return TRUE; - if (req_engine != (handlerton*) &default_hton && req_engine != *new_engine) + if (req_engine && req_engine != *new_engine) { push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_USING_OTHER_HANDLER, @@ -6555,7 +6555,8 @@ static bool check_engine(THD *thd, const char *table_name, { if (create_info->used_fields & HA_CREATE_USED_ENGINE) { - my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0), (*new_engine)->name, "TEMPORARY"); + my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0), + hton2plugin[(*new_engine)->slot]->name, "TEMPORARY"); *new_engine= 0; return TRUE; } diff --git a/sql/sql_tablespace.cc b/sql/sql_tablespace.cc index 8bc39ec82c6..84e2b9c7d04 100644 --- a/sql/sql_tablespace.cc +++ b/sql/sql_tablespace.cc @@ -28,16 +28,16 @@ int mysql_alter_tablespace(THD *thd, st_alter_tablespace *ts_info) If the user haven't defined an engine, this will fallback to using the default storage engine. */ - if (hton == NULL || hton == &default_hton || hton->state != SHOW_OPTION_YES) + if (hton == NULL || hton->state != SHOW_OPTION_YES) { hton= ha_resolve_by_legacy_type(thd, DB_TYPE_DEFAULT); if (ts_info->storage_engine != 0) push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_WARN_USING_OTHER_HANDLER, ER(ER_WARN_USING_OTHER_HANDLER), - hton->name, - ts_info->tablespace_name - ? ts_info->tablespace_name : ts_info->logfile_group_name); + hton2plugin[hton->slot]->name, + ts_info->tablespace_name ? ts_info->tablespace_name + : ts_info->logfile_group_name); } if (hton->alter_tablespace) @@ -64,7 +64,7 @@ int mysql_alter_tablespace(THD *thd, st_alter_tablespace *ts_info) push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_ILLEGAL_HA_CREATE_OPTION, ER(ER_ILLEGAL_HA_CREATE_OPTION), - hton->name, + hton2plugin[hton->slot]->name, "TABLESPACE or LOGFILE GROUP"); } if (mysql_bin_log.is_open()) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 31ef2d8907e..8cced1c47f8 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3099,11 +3099,11 @@ opt_ts_engine: "STORAGE ENGINE"); YYABORT; } - lex->alter_tablespace_info->storage_engine= $4 ? $4 : &default_hton; + lex->alter_tablespace_info->storage_engine= $4; }; opt_ts_wait: - /* empty */ + /* empty */ | ts_wait ; @@ -3939,12 +3939,18 @@ storage_engines: ident_or_text { $$ = ha_resolve_by_name(YYTHD, &$1); - if ($$ == NULL && - test(YYTHD->variables.sql_mode & MODE_NO_ENGINE_SUBSTITUTION)) + if ($$ == NULL) + if (YYTHD->variables.sql_mode & MODE_NO_ENGINE_SUBSTITUTION) { my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str); YYABORT; } + else + { + push_warning_printf(YYTHD, MYSQL_ERROR::WARN_LEVEL_ERROR, + ER_UNKNOWN_STORAGE_ENGINE, + ER(ER_UNKNOWN_STORAGE_ENGINE), $1.str); + } }; row_types: @@ -4621,7 +4627,7 @@ alter: lex->select_lex.db=lex->name= 0; lex->like_name= 0; bzero((char*) &lex->create_info,sizeof(lex->create_info)); - lex->create_info.db_type= (handlerton*) &default_hton; + lex->create_info.db_type= 0; lex->create_info.default_table_charset= NULL; lex->create_info.row_type= ROW_TYPE_NOT_USED; lex->alter_info.reset(); diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc index e39ee976eb1..dad51c1a512 100644 --- a/storage/archive/ha_archive.cc +++ b/storage/archive/ha_archive.cc @@ -145,49 +145,7 @@ static handler *archive_create_handler(TABLE_SHARE *table); */ #define ARCHIVE_MIN_ROWS_TO_USE_BULK_INSERT 2 - -static const char archive_hton_name[]= "ARCHIVE"; -static const char archive_hton_comment[]= "Archive storage engine"; - -/* dummy handlerton - only to have something to return from archive_db_init */ -handlerton archive_hton = { - MYSQL_HANDLERTON_INTERFACE_VERSION, - archive_hton_name, - SHOW_OPTION_YES, - archive_hton_comment, - DB_TYPE_ARCHIVE_DB, - archive_db_init, - 0, /* slot */ - 0, /* savepoint size. */ - NULL, /* close_connection */ - NULL, /* savepoint */ - NULL, /* rollback to savepoint */ - NULL, /* releas savepoint */ - NULL, /* commit */ - NULL, /* rollback */ - NULL, /* prepare */ - NULL, /* recover */ - NULL, /* commit_by_xid */ - NULL, /* rollback_by_xid */ - NULL, /* create_cursor_read_view */ - NULL, /* set_cursor_read_view */ - NULL, /* close_cursor_read_view */ - archive_create_handler, /* Create a new handler */ - NULL, /* Drop a database */ - archive_db_end, /* Panic call */ - NULL, /* Start Consistent Snapshot */ - NULL, /* Flush logs */ - NULL, /* Show status */ - NULL, /* Partition flags */ - NULL, /* Alter table flags */ - NULL, /* Alter interface */ - NULL, /* fill_files_table */ - HTON_NO_FLAGS, - NULL, /* binlog_func */ - NULL, /* binlog_log_query */ - NULL /* release_temporary_latches */ - -}; +handlerton archive_hton; static handler *archive_create_handler(TABLE_SHARE *table) { @@ -217,11 +175,18 @@ static byte* archive_get_key(ARCHIVE_SHARE *share,uint *length, TRUE Error */ -bool archive_db_init() +int archive_db_init() { DBUG_ENTER("archive_db_init"); if (archive_inited) DBUG_RETURN(FALSE); + + archive_hton.state=SHOW_OPTION_YES; + archive_hton.db_type=DB_TYPE_ARCHIVE_DB; + archive_hton.create=archive_create_handler; + archive_hton.panic=archive_db_end; + archive_hton.flags=HTON_NO_FLAGS; + if (pthread_mutex_init(&archive_mutex, MY_MUTEX_INIT_FAST)) goto error; if (hash_init(&archive_open_tables, system_charset_info, 32, 0, 0, @@ -1575,16 +1540,19 @@ bool ha_archive::check_and_repair(THD *thd) DBUG_RETURN(repair(thd, &check_opt)); } +struct st_mysql_storage_engine archive_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION, &archive_hton }; mysql_declare_plugin(archive) { MYSQL_STORAGE_ENGINE_PLUGIN, - &archive_hton, - archive_hton_name, + &archive_storage_engine, + "ARCHIVE", "Brian Aker, MySQL AB", - archive_hton_comment, - NULL, /* Plugin Init */ + "Archive storage engine", + archive_db_init, /* Plugin Init */ archive_db_done, /* Plugin Deinit */ 0x0100 /* 1.0 */, } mysql_declare_plugin_end; + diff --git a/storage/archive/ha_archive.h b/storage/archive/ha_archive.h index 4663531b674..4c53c5c4064 100644 --- a/storage/archive/ha_archive.h +++ b/storage/archive/ha_archive.h @@ -136,6 +136,6 @@ public: bool check_and_repair(THD *thd); }; -bool archive_db_init(void); +int archive_db_init(void); int archive_db_end(ha_panic_function type); diff --git a/storage/blackhole/ha_blackhole.cc b/storage/blackhole/ha_blackhole.cc index 098e44f39ee..3ee784c201f 100644 --- a/storage/blackhole/ha_blackhole.cc +++ b/storage/blackhole/ha_blackhole.cc @@ -22,57 +22,9 @@ #include "mysql_priv.h" #include "ha_blackhole.h" -#include - /* Static declarations for handlerton */ -static handler *blackhole_create_handler(TABLE_SHARE *table); - - -static const char blackhole_hton_name[]= "BLACKHOLE"; -static const char blackhole_hton_comment[]= - "/dev/null storage engine (anything you write to it disappears)"; - -/* Blackhole storage engine handlerton */ - -handlerton blackhole_hton= { - MYSQL_HANDLERTON_INTERFACE_VERSION, - blackhole_hton_name, - SHOW_OPTION_YES, - blackhole_hton_comment, - DB_TYPE_BLACKHOLE_DB, - NULL, - 0, /* slot */ - 0, /* savepoint size. */ - NULL, /* close_connection */ - NULL, /* savepoint */ - NULL, /* rollback to savepoint */ - NULL, /* release savepoint */ - NULL, /* commit */ - NULL, /* rollback */ - NULL, /* prepare */ - NULL, /* recover */ - NULL, /* commit_by_xid */ - NULL, /* rollback_by_xid */ - NULL, /* create_cursor_read_view */ - NULL, /* set_cursor_read_view */ - NULL, /* close_cursor_read_view */ - blackhole_create_handler, /* Create a new handler */ - NULL, /* Drop a database */ - NULL, /* Panic call */ - NULL, /* Start Consistent Snapshot */ - NULL, /* Flush logs */ - NULL, /* Show status */ - NULL, /* Partition flags */ - NULL, /* Alter table flags */ - NULL, /* Alter Tablespace */ - NULL, /* Fill FILES table */ - HTON_CAN_RECREATE | HTON_ALTER_CANNOT_CREATE, - NULL, /* binlog_func */ - NULL, /* binlog_log_query */ - NULL /* release_temporary_latches */ -}; - +handlerton blackhole_hton; static handler *blackhole_create_handler(TABLE_SHARE *table) { @@ -256,14 +208,26 @@ int ha_blackhole::index_last(byte * buf) DBUG_RETURN(HA_ERR_END_OF_FILE); } +static int blackhole_init() +{ + blackhole_hton.state= SHOW_OPTION_YES; + blackhole_hton.db_type= DB_TYPE_BLACKHOLE_DB; + blackhole_hton.create= blackhole_create_handler; + blackhole_hton.flags= HTON_CAN_RECREATE | HTON_ALTER_CANNOT_CREATE; + return 0; +} + +struct st_mysql_storage_engine blackhole_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION, &blackhole_hton }; + mysql_declare_plugin(blackhole) { MYSQL_STORAGE_ENGINE_PLUGIN, - &blackhole_hton, - blackhole_hton_name, + &blackhole_storage_engine, + "BLACKHOLE", "MySQL AB", - blackhole_hton_comment, - NULL, /* Plugin Init */ + "/dev/null storage engine (anything you write to it disappears)", + blackhole_init, /* Plugin Init */ NULL, /* Plugin Deinit */ 0x0100 /* 1.0 */, } diff --git a/storage/csv/ha_tina.cc b/storage/csv/ha_tina.cc index de69df90ed5..b343a8739c9 100644 --- a/storage/csv/ha_tina.cc +++ b/storage/csv/ha_tina.cc @@ -77,45 +77,7 @@ static int tina_init= 0; static handler *tina_create_handler(TABLE_SHARE *table); static int tina_init_func(); -static const char tina_hton_name[]= "CSV"; -static const char tina_hton_comment[]= "CSV storage engine"; - -handlerton tina_hton= { - MYSQL_HANDLERTON_INTERFACE_VERSION, - tina_hton_name, - SHOW_OPTION_YES, - tina_hton_comment, - DB_TYPE_CSV_DB, - (bool (*)()) tina_init_func, - 0, /* slot */ - 0, /* savepoint size. */ - NULL, /* close_connection */ - NULL, /* savepoint */ - NULL, /* rollback to savepoint */ - NULL, /* release savepoint */ - NULL, /* commit */ - NULL, /* rollback */ - NULL, /* prepare */ - NULL, /* recover */ - NULL, /* commit_by_xid */ - NULL, /* rollback_by_xid */ - NULL, /* create_cursor_read_view */ - NULL, /* set_cursor_read_view */ - NULL, /* close_cursor_read_view */ - tina_create_handler, /* Create a new handler */ - NULL, /* Drop a database */ - tina_end, /* Panic call */ - NULL, /* Start Consistent Snapshot */ - NULL, /* Flush logs */ - NULL, /* Show status */ - NULL, /* Partition flags */ - NULL, /* Alter table flags */ - NULL, /* Alter Tablespace */ - NULL, /* Fill FILES Table */ - HTON_CAN_RECREATE, - NULL, /* binlog_func */ - NULL /* binlog_log_query */ -}; +handlerton tina_hton; /***************************************************************************** ** TINA tables @@ -191,6 +153,11 @@ static int tina_init_func() VOID(pthread_mutex_init(&tina_mutex,MY_MUTEX_INIT_FAST)); (void) hash_init(&tina_open_tables,system_charset_info,32,0,0, (hash_get_key) tina_get_key,0,0); + tina_hton.state= SHOW_OPTION_YES; + tina_hton.db_type= DB_TYPE_CSV_DB; + tina_hton.create= tina_create_handler; + tina_hton.panic= tina_end; + tina_hton.flags= HTON_CAN_RECREATE; } return 0; } @@ -1401,14 +1368,16 @@ bool ha_tina::check_if_incompatible_data(HA_CREATE_INFO *info, return COMPATIBLE_DATA_YES; } +struct st_mysql_storage_engine csv_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION, &tina_hton }; mysql_declare_plugin(csv) { MYSQL_STORAGE_ENGINE_PLUGIN, - &tina_hton, - tina_hton_name, + &csv_storage_engine, + "CSV", "Brian Aker, MySQL AB", - tina_hton_comment, + "CSV storage engine", tina_init_func, /* Plugin Init */ tina_done_func, /* Plugin Deinit */ 0x0100 /* 1.0 */, diff --git a/storage/example/ha_example.cc b/storage/example/ha_example.cc index 2ce543dfbb0..28bccc7df2d 100644 --- a/storage/example/ha_example.cc +++ b/storage/example/ha_example.cc @@ -77,46 +77,7 @@ static int example_init_func(); static bool example_init_func_for_handlerton(); static int example_panic(enum ha_panic_function flag); -static const char example_hton_name[]= "EXAMPLE"; -static const char example_hton_comment[]= "Example storage engine"; - -handlerton example_hton= { - MYSQL_HANDLERTON_INTERFACE_VERSION, - example_hton_name, - SHOW_OPTION_YES, - example_hton_comment, - DB_TYPE_EXAMPLE_DB, - example_init_func_for_handlerton, - 0, /* slot */ - 0, /* savepoint size. */ - NULL, /* close_connection */ - NULL, /* savepoint */ - NULL, /* rollback to savepoint */ - NULL, /* release savepoint */ - NULL, /* commit */ - NULL, /* rollback */ - NULL, /* prepare */ - NULL, /* recover */ - NULL, /* commit_by_xid */ - NULL, /* rollback_by_xid */ - NULL, /* create_cursor_read_view */ - NULL, /* set_cursor_read_view */ - NULL, /* close_cursor_read_view */ - example_create_handler, /* Create a new handler */ - NULL, /* Drop a database */ - example_panic, /* Panic call */ - NULL, /* Start Consistent Snapshot */ - NULL, /* Flush logs */ - NULL, /* Show status */ - NULL, /* Partition flags */ - NULL, /* Alter table flags */ - NULL, /* Alter tablespace */ - NULL, /* Fill Files table */ - HTON_CAN_RECREATE, - NULL, - NULL, - NULL, -}; +handlerton example_hton; /* Variables for example share methods */ static HASH example_open_tables; // Hash used to track open tables @@ -143,6 +104,11 @@ static int example_init_func() VOID(pthread_mutex_init(&example_mutex,MY_MUTEX_INIT_FAST)); (void) hash_init(&example_open_tables,system_charset_info,32,0,0, (hash_get_key) example_get_key,0,0); + + example_hton.state= SHOW_OPTION_YES; + example_hton.db_type= DB_TYPE_EXAMPLE_DB; + example_hton.create= example_create_handler; + example_hton.flags= HTON_CAN_RECREATE; } DBUG_RETURN(0); } @@ -163,17 +129,6 @@ static int example_done_func() DBUG_RETURN(0); } -static bool example_init_func_for_handlerton() -{ - return example_init_func(); -} - -static int example_panic(enum ha_panic_function flag) -{ - return example_done_func(); -} - - /* Example of simple lock controls. The "share" it creates is structure we will pass to each example handler. Do you have to have one of these? Well, you have @@ -741,18 +696,21 @@ int ha_example::create(const char *name, TABLE *table_arg, HA_CREATE_INFO *create_info) { DBUG_ENTER("ha_example::create"); - /* This is not implemented but we want someone to be able that it works. */ + /* This is not implemented but we want someone to be able to see that it works. */ DBUG_RETURN(0); } +struct st_mysql_storage_engine example_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION, &example_hton }; + mysql_declare_plugin(example) { MYSQL_STORAGE_ENGINE_PLUGIN, - &example_hton, - example_hton_name, + &example_storage_engine, + "EXAMPLE", "Brian Aker, MySQL AB", - example_hton_comment, + "Example storage engine", example_init_func, /* Plugin Init */ example_done_func, /* Plugin Deinit */ 0x0001 /* 0.1 */, From f1bb09e777427145f614c52488ead02a62e062e2 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 28 May 2006 17:02:50 +0200 Subject: [PATCH 09/32] Incompatible ftparser plugin API change. mysql_parse() and mysql_add_word() now take a MYSQL_FTPARSER_PARAM*, not a mysql_ftparam. client/Makefile.am: don't fail when rm cannot delete from read-only dir sql/sql_plugin.cc: fix min_plugin_info_interface_version to be less error-prone --- client/Makefile.am | 14 +++++----- include/mysql/plugin.h | 31 ++++++++++++---------- plugin/fulltext/plugin_example.c | 5 +--- sql/sql_plugin.cc | 5 ++-- storage/myisam/ft_boolean_search.c | 42 +++++++++++++++--------------- storage/myisam/ft_parser.c | 17 ++++++------ storage/myisam/ft_static.c | 2 +- 7 files changed, 59 insertions(+), 57 deletions(-) diff --git a/client/Makefile.am b/client/Makefile.am index aa78f825c87..be2888367a6 100644 --- a/client/Makefile.am +++ b/client/Makefile.am @@ -83,13 +83,13 @@ link_sources: for f in $(sql_src) ; do \ rm -f $$f; \ @LN_CP_F@ $(top_srcdir)/sql/$$f $$f; \ - done; \ - for f in $(strings_src) ; do \ - rm -f $(srcdir)/$$f; \ - @LN_CP_F@ $(top_srcdir)/strings/$$f $$f; \ - done; \ - rm -f $(srcdir)/my_user.c; \ - @LN_CP_F@ $(top_srcdir)/sql-common/my_user.c my_user.c + done; + for f in $(strings_src) ; do \ + rm -f $(srcdir)/$$f; \ + @LN_CP_F@ $(top_srcdir)/strings/$$f $$f; \ + done; + -rm -f $(srcdir)/my_user.c; + @LN_CP_F@ $(top_srcdir)/sql-common/my_user.c my_user.c # Don't update the files from bitkeeper diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h index ab5ca6e7be4..a47b1099eef 100644 --- a/include/mysql/plugin.h +++ b/include/mysql/plugin.h @@ -98,9 +98,11 @@ struct st_mysql_plugin API for Full-text [pre]parser plugin. (MYSQL_FTPARSER_PLUGIN) */ -#define MYSQL_FTPARSER_INTERFACE_VERSION 0x0000 +#define MYSQL_FTPARSER_INTERFACE_VERSION 0x0100 /* Parsing modes. Set in MYSQL_FTPARSER_PARAM::mode */ +enum enum_ftparser_mode +{ /* Fast and simple mode. This mode is used for indexing, and natural language queries. @@ -109,7 +111,7 @@ struct st_mysql_plugin index. Stopwords or too short/long words should not be returned. The 'boolean_info' argument of mysql_add_word() does not have to be set. */ -#define MYSQL_FTPARSER_SIMPLE_MODE 0 + MYSQL_FTPARSER_SIMPLE_MODE= 0, /* Parse with stopwords mode. This mode is used in boolean searches for @@ -120,7 +122,7 @@ struct st_mysql_plugin or long. The 'boolean_info' argument of mysql_add_word() does not have to be set. */ -#define MYSQL_FTPARSER_WITH_STOPWORDS 1 + MYSQL_FTPARSER_WITH_STOPWORDS= 1, /* Parse in boolean mode. This mode is used to parse a boolean query string. @@ -133,7 +135,8 @@ struct st_mysql_plugin MYSQL_FTPARSER_WITH_STOPWORDS mode, no word should be ignored. Instead, use FT_TOKEN_STOPWORD for the token type of such a word. */ -#define MYSQL_FTPARSER_FULL_BOOLEAN_INFO 2 + MYSQL_FTPARSER_FULL_BOOLEAN_INFO= 2 +}; /* Token types for boolean mode searching (used for the type member of @@ -209,22 +212,20 @@ typedef struct st_mysql_ftparser_boolean_info to invoke the MySQL default parser. If plugin's role is to extract textual data from .doc, .pdf or .xml content, it might extract plaintext from the content, and then pass the text to the default - MySQL parser to be parsed. When mysql_parser is called, its param - argument should be given as the mysql_ftparam value. + MySQL parser to be parsed. mysql_add_word: A server callback to add a new word. When parsing a document, the server sets this to point at a function that adds the word to MySQL full-text index. When parsing a search query, this function will add the new word to the list of words to search - for. When mysql_add_word is called, its param argument should be - given as the mysql_ftparam value. boolean_info can be NULL for all - cases except when mode is MYSQL_FTPARSER_FULL_BOOLEAN_INFO. + for. The boolean_info argument can be NULL for all cases except + when mode is MYSQL_FTPARSER_FULL_BOOLEAN_INFO. ftparser_state: A generic pointer. The plugin can set it to point to information to be used internally for its own purposes. - mysql_ftparam: This is set by the server. It is passed as the first - argument to the mysql_parse or mysql_add_word callback. The plugin + mysql_ftparam: This is set by the server. It is used by MySQL functions + called via mysql_parse() and mysql_add_word() callback. The plugin should not modify it. cs: Information about the character set of the document or query string. @@ -239,15 +240,17 @@ typedef struct st_mysql_ftparser_boolean_info typedef struct st_mysql_ftparser_param { - int (*mysql_parse)(void *param, char *doc, int doc_len); - int (*mysql_add_word)(void *param, char *word, int word_len, + int (*mysql_parse)(struct st_mysql_ftparser_param *, + char *doc, int doc_len); + int (*mysql_add_word)(struct st_mysql_ftparser_param *, + char *word, int word_len, MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info); void *ftparser_state; void *mysql_ftparam; struct charset_info_st *cs; char *doc; int length; - int mode; + enum enum_ftparser_mode mode; } MYSQL_FTPARSER_PARAM; /* diff --git a/plugin/fulltext/plugin_example.c b/plugin/fulltext/plugin_example.c index 9b937453ce4..eefb10bd26b 100644 --- a/plugin/fulltext/plugin_example.c +++ b/plugin/fulltext/plugin_example.c @@ -144,10 +144,7 @@ static void add_word(MYSQL_FTPARSER_PARAM *param, char *word, size_t len) MYSQL_FTPARSER_BOOLEAN_INFO bool_info= { FT_TOKEN_WORD, 0, 0, 0, 0, ' ', 0 }; - if (param->mode == MYSQL_FTPARSER_FULL_BOOLEAN_INFO) - param->mysql_add_word(param->mysql_ftparam, word, len, &bool_info); - else - param->mysql_add_word(param->mysql_ftparam, word, len, 0); + param->mysql_add_word(param, word, len, &bool_info); } /* diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 01faae22c57..00dbdcf84a2 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -41,8 +41,8 @@ static int min_plugin_interface_version= 0x0000; static int min_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]= { 0x0000, - 0x0000, - 0x0000 + MYSQL_HANDLERTON_INTERFACE_VERSION, + MYSQL_FTPARSER_INTERFACE_VERSION }; static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]= { @@ -50,6 +50,7 @@ static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]= MYSQL_HANDLERTON_INTERFACE_VERSION, MYSQL_FTPARSER_INTERFACE_VERSION }; + static DYNAMIC_ARRAY plugin_dl_array; static DYNAMIC_ARRAY plugin_array; static HASH plugin_hash[MYSQL_MAX_PLUGIN_TYPE_NUM]; diff --git a/storage/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c index 8d48f533203..940bf8e3433 100644 --- a/storage/myisam/ft_boolean_search.c +++ b/storage/myisam/ft_boolean_search.c @@ -160,7 +160,6 @@ static int FTB_WORD_cmp_list(CHARSET_INFO *cs, FTB_WORD **a, FTB_WORD **b) typedef struct st_my_ftb_param { - MYSQL_FTPARSER_PARAM *up; FTB *ftb; FTB_EXPR *ftbe; byte *up_quot; @@ -168,10 +167,11 @@ typedef struct st_my_ftb_param } MY_FTB_PARAM; -static int ftb_query_add_word(void *param, char *word, int word_len, +static int ftb_query_add_word(MYSQL_FTPARSER_PARAM *param, + char *word, int word_len, MYSQL_FTPARSER_BOOLEAN_INFO *info) { - MY_FTB_PARAM *ftb_param= (MY_FTB_PARAM *)param; + MY_FTB_PARAM *ftb_param= param->mysql_ftparam; FTB_WORD *ftbw; FTB_EXPR *ftbe, *tmp_expr; FT_WORD *phrase_word; @@ -269,9 +269,10 @@ static int ftb_query_add_word(void *param, char *word, int word_len, } -static int ftb_parse_query_internal(void *param, char *query, int len) +static int ftb_parse_query_internal(MYSQL_FTPARSER_PARAM *param, + char *query, int len) { - MY_FTB_PARAM *ftb_param= (MY_FTB_PARAM *)param; + MY_FTB_PARAM *ftb_param= param->mysql_ftparam; MYSQL_FTPARSER_BOOLEAN_INFO info; CHARSET_INFO *cs= ftb_param->ftb->charset; char **start= &query; @@ -281,7 +282,7 @@ static int ftb_parse_query_internal(void *param, char *query, int len) info.prev= ' '; info.quot= 0; while (ft_get_word(cs, start, end, &w, &info)) - ftb_param->up->mysql_add_word(param, w.pos, w.len, &info); + param->mysql_add_word(param, w.pos, w.len, &info); return(0); } @@ -299,7 +300,6 @@ static void _ftb_parse_query(FTB *ftb, byte *query, uint len, if (! (param= ftparser_call_initializer(ftb->info, ftb->keynr, 0))) DBUG_VOID_RETURN; - ftb_param.up= param; ftb_param.ftb= ftb; ftb_param.depth= 0; ftb_param.ftbe= ftb->root; @@ -571,7 +571,6 @@ err: typedef struct st_my_ftb_phrase_param { - MYSQL_FTPARSER_PARAM *up; LIST *phrase; LIST *document; CHARSET_INFO *cs; @@ -581,10 +580,11 @@ typedef struct st_my_ftb_phrase_param } MY_FTB_PHRASE_PARAM; -static int ftb_phrase_add_word(void *param, char *word, int word_len, +static int ftb_phrase_add_word(MYSQL_FTPARSER_PARAM *param, + char *word, int word_len, MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info __attribute__((unused))) { - MY_FTB_PHRASE_PARAM *phrase_param= (MY_FTB_PHRASE_PARAM *)param; + MY_FTB_PHRASE_PARAM *phrase_param= param->mysql_ftparam; FT_WORD *w= (FT_WORD *)phrase_param->document->data; LIST *phrase, *document; w->pos= word; @@ -611,14 +611,15 @@ static int ftb_phrase_add_word(void *param, char *word, int word_len, } -static int ftb_check_phrase_internal(void *param, char *document, int len) +static int ftb_check_phrase_internal(MYSQL_FTPARSER_PARAM *param, + char *document, int len) { FT_WORD word; - MY_FTB_PHRASE_PARAM *phrase_param= (MY_FTB_PHRASE_PARAM *)param; + MY_FTB_PHRASE_PARAM *phrase_param= param->mysql_ftparam; const char *docend= document + len; while (ft_simple_get_word(phrase_param->cs, &document, docend, &word, FALSE)) { - phrase_param->up->mysql_add_word(param, word.pos, word.len, 0); + param->mysql_add_word(param, word.pos, word.len, 0); if (phrase_param->match) return 1; } @@ -651,7 +652,6 @@ static int _ftb_check_phrase(FTB *ftb, const byte *document, uint len, if (! (param= ftparser_call_initializer(ftb->info, ftb->keynr, 1))) DBUG_RETURN(0); - ftb_param.up= param; ftb_param.phrase= ftbe->phrase; ftb_param.document= ftbe->document; ftb_param.cs= ftb->charset; @@ -820,16 +820,16 @@ err: typedef struct st_my_ftb_find_param { - MYSQL_FTPARSER_PARAM *up; FT_INFO *ftb; FT_SEG_ITERATOR *ftsi; } MY_FTB_FIND_PARAM; -static int ftb_find_relevance_add_word(void *param, char *word, int len, +static int ftb_find_relevance_add_word(MYSQL_FTPARSER_PARAM *param, + char *word, int len, MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info __attribute__((unused))) { - MY_FTB_FIND_PARAM *ftb_param= (MY_FTB_FIND_PARAM *)param; + MY_FTB_FIND_PARAM *ftb_param= param->mysql_ftparam; FT_INFO *ftb= ftb_param->ftb; FTB_WORD *ftbw; int a, b, c; @@ -859,14 +859,15 @@ static int ftb_find_relevance_add_word(void *param, char *word, int len, } -static int ftb_find_relevance_parse(void *param, char *doc, int len) +static int ftb_find_relevance_parse(MYSQL_FTPARSER_PARAM *param, + char *doc, int len) { - MY_FTB_FIND_PARAM *ftb_param=(MY_FTB_FIND_PARAM *)param; + MY_FTB_FIND_PARAM *ftb_param= param->mysql_ftparam; FT_INFO *ftb= ftb_param->ftb; char *end= doc + len; FT_WORD w; while (ft_simple_get_word(ftb->charset, &doc, end, &w, TRUE)) - ftb_param->up->mysql_add_word(param, w.pos, w.len, 0); + param->mysql_add_word(param, w.pos, w.len, 0); return(0); } @@ -910,7 +911,6 @@ float ft_boolean_find_relevance(FT_INFO *ftb, byte *record, uint length) _mi_ft_segiterator_init(ftb->info, ftb->keynr, record, &ftsi); memcpy(&ftsi2, &ftsi, sizeof(ftsi)); - ftb_param.up= param; ftb_param.ftb= ftb; ftb_param.ftsi= &ftsi2; param->mysql_parse= ftb_find_relevance_parse; diff --git a/storage/myisam/ft_parser.c b/storage/myisam/ft_parser.c index 89ede813a2b..7793546f3bb 100644 --- a/storage/myisam/ft_parser.c +++ b/storage/myisam/ft_parser.c @@ -27,7 +27,6 @@ typedef struct st_ft_docstat { typedef struct st_my_ft_parser_param { - MYSQL_FTPARSER_PARAM *up; TREE *wtree; my_bool with_alloc; } MY_FT_PARSER_PARAM; @@ -241,14 +240,16 @@ void ft_parse_init(TREE *wtree, CHARSET_INFO *cs) } -static int ft_add_word(void *param, byte *word, uint word_len, +static int ft_add_word(MYSQL_FTPARSER_PARAM *param, + char *word, int word_len, MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info __attribute__((unused))) { TREE *wtree; FT_WORD w; + MY_FT_PARSER_PARAM *ft_param=param->mysql_ftparam; DBUG_ENTER("ft_add_word"); - wtree= ((MY_FT_PARSER_PARAM *)param)->wtree; - if (((MY_FT_PARSER_PARAM *)param)->with_alloc) + wtree= ft_param->wtree; + if (ft_param->with_alloc) { byte *ptr; /* allocating the data in the tree - to avoid mallocs and frees */ @@ -269,16 +270,17 @@ static int ft_add_word(void *param, byte *word, uint word_len, } -static int ft_parse_internal(void *param, byte *doc, int doc_len) +static int ft_parse_internal(MYSQL_FTPARSER_PARAM *param, + byte *doc, int doc_len) { byte *end=doc+doc_len; - MY_FT_PARSER_PARAM *ft_param=(MY_FT_PARSER_PARAM *)param; + MY_FT_PARSER_PARAM *ft_param=param->mysql_ftparam; TREE *wtree= ft_param->wtree; FT_WORD w; DBUG_ENTER("ft_parse_internal"); while (ft_simple_get_word(wtree->custom_arg, &doc, end, &w, TRUE)) - if (ft_param->up->mysql_add_word(param, w.pos, w.len, 0)) + if (param->mysql_add_word(param, w.pos, w.len, 0)) DBUG_RETURN(1); DBUG_RETURN(0); } @@ -292,7 +294,6 @@ int ft_parse(TREE *wtree, byte *doc, int doclen, my_bool with_alloc, DBUG_ENTER("ft_parse"); DBUG_ASSERT(parser); - my_param.up= param; my_param.wtree= wtree; my_param.with_alloc= with_alloc; diff --git a/storage/myisam/ft_static.c b/storage/myisam/ft_static.c index 6cfb0d59e62..61bb7b3c1f7 100644 --- a/storage/myisam/ft_static.c +++ b/storage/myisam/ft_static.c @@ -629,7 +629,7 @@ const char *ft_precompiled_stopwords[] = { static int ft_default_parser_parse(MYSQL_FTPARSER_PARAM *param) { - return param->mysql_parse(param->mysql_ftparam, param->doc, param->length); + return param->mysql_parse(param, param->doc, param->length); } struct st_mysql_ftparser ft_default_parser= From 0146929f09969ce4c08556b756273ec4eb508ed7 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 29 May 2006 14:51:46 -0400 Subject: [PATCH 10/32] BUG#17310: Archive error for drop database mysql-test/r/partition.result: Added new test case mysql-test/t/partition.test: Added new test case storage/archive/ha_archive.cc: Moved some code to avoid that ha_archive::create leaves files after error in create There are still cases where this occurs but now only on file creation errors. --- mysql-test/r/partition.result | 12 ++++++++++++ mysql-test/t/partition.test | 17 +++++++++++++++++ storage/archive/ha_archive.cc | 17 +++++++++-------- 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index 3be9f3edee2..2fb7b6942de 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -936,4 +936,16 @@ OPTIMIZE TABLE t1; Table Op Msg_type Msg_text test.t1 optimize note The storage engine for the table doesn't support optimize drop table t1; +create database db99; +use db99; +create table t1 (a int not null) +engine=archive +partition by list (a) +(partition p0 values in (1), partition p1 values in (2)); +insert into t1 values (1), (2); +create index inx on t1 (a); +alter table t1 add partition (partition p2 values in (3)); +alter table t1 drop partition p2; +use test; +drop database db99; End of 5.1 tests diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index a24124d3fb5..f7676ca471a 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -1077,4 +1077,21 @@ OPTIMIZE TABLE t1; drop table t1; +# +# Bug 17310 Partitions: Bugs with archived partitioned tables +# +create database db99; +use db99; +create table t1 (a int not null) +engine=archive +partition by list (a) +(partition p0 values in (1), partition p1 values in (2)); +insert into t1 values (1), (2); +--error 0, 1005 +create index inx on t1 (a); +alter table t1 add partition (partition p2 values in (3)); +alter table t1 drop partition p2; +use test; +drop database db99; + --echo End of 5.1 tests diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc index f3f20f6b103..03710b7c380 100644 --- a/storage/archive/ha_archive.cc +++ b/storage/archive/ha_archive.cc @@ -701,14 +701,6 @@ int ha_archive::create(const char *name, TABLE *table_arg, create_info->auto_increment_value -1 : (ulonglong) 0); - if ((create_file= my_create(fn_format(name_buff,name,"",ARM, - MY_REPLACE_EXT|MY_UNPACK_FILENAME),0, - O_RDWR | O_TRUNC,MYF(MY_WME))) < 0) - { - error= my_errno; - goto error; - } - for (uint key= 0; key < table_arg->s->keys; key++) { KEY *pos= table_arg->key_info+key; @@ -722,11 +714,20 @@ int ha_archive::create(const char *name, TABLE *table_arg, if (!(field->flags & AUTO_INCREMENT_FLAG)) { error= -1; + DBUG_PRINT("info", ("Index error in creating archive table")); goto error; } } } + if ((create_file= my_create(fn_format(name_buff,name,"",ARM, + MY_REPLACE_EXT|MY_UNPACK_FILENAME),0, + O_RDWR | O_TRUNC,MYF(MY_WME))) < 0) + { + error= my_errno; + goto error; + } + write_meta_file(create_file, 0, auto_increment_value, 0, (char *)create_info->data_file_name, FALSE); From 2b0c9d8bdbfdf64106905e20abd104962a31955b Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 30 May 2006 13:55:25 +0200 Subject: [PATCH 11/32] Bug #20142 show engine ndb status may falsely return latest epoch == 0 --- storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp | 2 -- storage/ndb/src/ndbapi/NdbTransaction.cpp | 9 +++++++++ storage/ndb/src/ndbapi/Ndbif.cpp | 4 ---- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp index d2d8c43a064..b0235a28154 100644 --- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp +++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp @@ -56,7 +56,6 @@ DBUG_RETURN(b);\ } -extern Uint64 g_latest_trans_gci; int ndb_dictionary_is_mysqld = 0; bool @@ -4226,7 +4225,6 @@ NdbDictInterface::execWAIT_GCP_CONF(NdbApiSignal* signal, { const WaitGCPConf * const conf= CAST_CONSTPTR(WaitGCPConf, signal->getDataPtr()); - g_latest_trans_gci= conf->gcp; m_waiter.signal(NO_WAIT); } diff --git a/storage/ndb/src/ndbapi/NdbTransaction.cpp b/storage/ndb/src/ndbapi/NdbTransaction.cpp index 3158dca5c40..916135b12d5 100644 --- a/storage/ndb/src/ndbapi/NdbTransaction.cpp +++ b/storage/ndb/src/ndbapi/NdbTransaction.cpp @@ -32,6 +32,8 @@ #include #include +Uint64 g_latest_trans_gci = 0; + /***************************************************************************** NdbTransaction( Ndb* aNdb ); @@ -1568,6 +1570,9 @@ NdbTransaction::receiveTC_COMMITCONF(const TcCommitConf * commitConf) theCommitStatus = Committed; theCompletionStatus = CompletedSuccess; theGlobalCheckpointId = commitConf->gci; + // theGlobalCheckpointId == 0 if NoOp transaction + if (theGlobalCheckpointId) + g_latest_trans_gci = theGlobalCheckpointId; return 0; } else { #ifdef NDB_NO_DROPPED_SIGNAL @@ -1746,6 +1751,8 @@ from other transactions. if (tCommitFlag == 1) { theCommitStatus = Committed; theGlobalCheckpointId = tGCI; + assert(tGCI); + g_latest_trans_gci = tGCI; } else if ((tNoComp >= tNoSent) && (theLastExecOpInList->theCommitIndicator == 1)){ @@ -1922,6 +1929,8 @@ NdbTransaction::receiveTCINDXCONF(const TcIndxConf * indxConf, if (tCommitFlag == 1) { theCommitStatus = Committed; theGlobalCheckpointId = tGCI; + assert(tGCI); + g_latest_trans_gci = tGCI; } else if ((tNoComp >= tNoSent) && (theLastExecOpInList->theCommitIndicator == 1)){ /**********************************************************************/ diff --git a/storage/ndb/src/ndbapi/Ndbif.cpp b/storage/ndb/src/ndbapi/Ndbif.cpp index 7799a71749e..ecaf6a3f435 100644 --- a/storage/ndb/src/ndbapi/Ndbif.cpp +++ b/storage/ndb/src/ndbapi/Ndbif.cpp @@ -46,7 +46,6 @@ #include extern EventLogger g_eventLogger; -Uint64 g_latest_trans_gci= 0; /****************************************************************************** * int init( int aNrOfCon, int aNrOfOp ); @@ -367,7 +366,6 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) tCon = void2con(tFirstDataPtr); if ((tCon->checkMagicNumber() == 0) && (tCon->theSendStatus == NdbTransaction::sendTC_OP)) { - g_latest_trans_gci= keyConf->gci; tReturnCode = tCon->receiveTCKEYCONF(keyConf, tLen); if (tReturnCode != -1) { completedTransaction(tCon); @@ -520,7 +518,6 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) tCon = void2con(tFirstDataPtr); if ((tCon->checkMagicNumber() == 0) && (tCon->theSendStatus == NdbTransaction::sendTC_COMMIT)) { - g_latest_trans_gci= commitConf->gci; tReturnCode = tCon->receiveTC_COMMITCONF(commitConf); if (tReturnCode != -1) { completedTransaction(tCon); @@ -855,7 +852,6 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) tCon = void2con(tFirstDataPtr); if ((tCon->checkMagicNumber() == 0) && (tCon->theSendStatus == NdbTransaction::sendTC_OP)) { - g_latest_trans_gci= indxConf->gci; tReturnCode = tCon->receiveTCINDXCONF(indxConf, tLen); if (tReturnCode != -1) { completedTransaction(tCon); From 15a13203f198102a74462cc5ffb5bbb8dc652a3f Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 30 May 2006 18:15:18 +0200 Subject: [PATCH 12/32] Now ftparser does not need to bother about memory management - it can tell MySQL to make a copy of everything (bug#17123) include/mysql/plugin.h: Now ftparser does not need to bother about memory management - it can tell MySQL to make a copy of everything (bug#17123) MYSQL_FTFLAGS_NEED_COPY flag storage/myisam/ft_boolean_search.c: param->flags storage/myisam/ft_nlq_search.c: param->flags. ft_parse takes a mem_root as an argument storage/myisam/ft_parser.c: ftparser takes a memroot as an argument. words are copied there, if necessary. memroot is reset for every parsing and free'd at the end of the statement. storage/myisam/ft_update.c: ftparser takes a memroot as an argument. words are copied there, if necessary. memroot is reset for every parsing and free'd at the end of the statement. storage/myisam/ftdefs.h: ftparser takes a memroot as an argument. words are copied there, if necessary. memroot is reset for every parsing and free'd at the end of the statement. storage/myisam/mi_check.c: ftparser takes a memroot as an argument. words are copied there, if necessary storage/myisam/myisamdef.h: memroot for ftparser in MI_INFO and MI_SORT_PARAM storage/myisam/sort.c: free ftparser memroot --- include/mysql/plugin.h | 16 ++++++++- storage/myisam/ft_boolean_search.c | 3 ++ storage/myisam/ft_nlq_search.c | 8 +++-- storage/myisam/ft_parser.c | 25 +++++++------- storage/myisam/ft_update.c | 54 ++++++++++++++---------------- storage/myisam/ftdefs.h | 14 ++++---- storage/myisam/mi_check.c | 10 ++++-- storage/myisam/myisamdef.h | 16 +++++---- storage/myisam/sort.c | 1 + 9 files changed, 87 insertions(+), 60 deletions(-) diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h index a47b1099eef..728b62ab2f4 100644 --- a/include/mysql/plugin.h +++ b/include/mysql/plugin.h @@ -201,6 +201,17 @@ typedef struct st_mysql_ftparser_boolean_info char *quot; } MYSQL_FTPARSER_BOOLEAN_INFO; +/* + The following flag means that buffer with a string (document, word) + may be overwritten by the caller before the end of the parsing (that is + before st_mysql_ftparser::deinit() call). If one needs the string + to survive between two successive calls of the parsing function, she + needs to save a copy of it. The flag may be set by MySQL before calling + st_mysql_ftparser::parse(), or it may be set by a plugin before calling + st_mysql_ftparser_param::mysql_parse() or + st_mysql_ftparser_param::mysql_add_word(). +*/ +#define MYSQL_FTFLAGS_NEED_COPY 1 /* An argument of the full-text parser plugin. This structure is @@ -234,8 +245,10 @@ typedef struct st_mysql_ftparser_boolean_info length: Length of the document or query string, in bytes. + flags: See MYSQL_FTFLAGS_* constants above. + mode: The parsing mode. With boolean operators, with stopwords, or - nothing. See MYSQL_FTPARSER_* constants above. + nothing. See enum_ftparser_mode above. */ typedef struct st_mysql_ftparser_param @@ -250,6 +263,7 @@ typedef struct st_mysql_ftparser_param struct charset_info_st *cs; char *doc; int length; + int flags; enum enum_ftparser_mode mode; } MYSQL_FTPARSER_PARAM; diff --git a/storage/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c index 940bf8e3433..33c4dc705b4 100644 --- a/storage/myisam/ft_boolean_search.c +++ b/storage/myisam/ft_boolean_search.c @@ -311,6 +311,7 @@ static void _ftb_parse_query(FTB *ftb, byte *query, uint len, param->cs= ftb->charset; param->doc= query; param->length= len; + param->flags= 0; param->mode= MYSQL_FTPARSER_FULL_BOOLEAN_INFO; parser->parse(param); DBUG_VOID_RETURN; @@ -665,6 +666,7 @@ static int _ftb_check_phrase(FTB *ftb, const byte *document, uint len, param->cs= ftb->charset; param->doc= (byte *)document; param->length= len; + param->flags= 0; param->mode= MYSQL_FTPARSER_WITH_STOPWORDS; parser->parse(param); DBUG_RETURN(ftb_param.match ? 1 : 0); @@ -916,6 +918,7 @@ float ft_boolean_find_relevance(FT_INFO *ftb, byte *record, uint length) param->mysql_parse= ftb_find_relevance_parse; param->mysql_add_word= ftb_find_relevance_add_word; param->mysql_ftparam= (void *)&ftb_param; + param->flags= 0; param->cs= ftb->charset; param->mode= MYSQL_FTPARSER_SIMPLE_MODE; while (_mi_ft_segiterator(&ftsi)) diff --git a/storage/myisam/ft_nlq_search.c b/storage/myisam/ft_nlq_search.c index b8207c1c3d0..53a01003dcd 100644 --- a/storage/myisam/ft_nlq_search.c +++ b/storage/myisam/ft_nlq_search.c @@ -235,7 +235,9 @@ FT_INFO *ft_init_nlq_search(MI_INFO *info, uint keynr, byte *query, NULL, NULL); ft_parse_init(&wtree, aio.charset); - if (ft_parse(&wtree, query, query_len, 0, parser, ftparser_param)) + ftparser_param->flags= 0; + if (ft_parse(&wtree, query, query_len, parser, ftparser_param, + &wtree.mem_root)) goto err; if (tree_walk(&wtree, (tree_walk_action)&walk_and_match, &aio, @@ -255,7 +257,9 @@ FT_INFO *ft_init_nlq_search(MI_INFO *info, uint keynr, byte *query, if (!(*info->read_record)(info,docid,record)) { info->update|= HA_STATE_AKTIV; - _mi_ft_parse(&wtree, info, keynr, record, 1, ftparser_param); + ftparser_param->flags= MYSQL_FTFLAGS_NEED_COPY; + _mi_ft_parse(&wtree, info, keynr, record, ftparser_param, + &wtree.mem_root); } } delete_queue(&best); diff --git a/storage/myisam/ft_parser.c b/storage/myisam/ft_parser.c index 7793546f3bb..38ac744d4a8 100644 --- a/storage/myisam/ft_parser.c +++ b/storage/myisam/ft_parser.c @@ -24,14 +24,12 @@ typedef struct st_ft_docstat { double sum; } FT_DOCSTAT; - typedef struct st_my_ft_parser_param { - TREE *wtree; - my_bool with_alloc; + TREE *wtree; + MEM_ROOT *mem_root; } MY_FT_PARSER_PARAM; - static int FT_WORD_cmp(CHARSET_INFO* cs, FT_WORD *w1, FT_WORD *w2) { return mi_compare_text(cs, (uchar*) w1->pos, w1->len, @@ -48,14 +46,14 @@ static int walk_and_copy(FT_WORD *word,uint32 count,FT_DOCSTAT *docstat) /* transforms tree of words into the array, applying normalization */ -FT_WORD * ft_linearize(TREE *wtree) +FT_WORD * ft_linearize(TREE *wtree, MEM_ROOT *mem_root) { FT_WORD *wlist,*p; FT_DOCSTAT docstat; DBUG_ENTER("ft_linearize"); - if ((wlist=(FT_WORD *) my_malloc(sizeof(FT_WORD)* - (1+wtree->elements_in_tree),MYF(0)))) + if ((wlist=(FT_WORD *) alloc_root(mem_root, sizeof(FT_WORD)* + (1+wtree->elements_in_tree)))) { docstat.list=wlist; docstat.uniq=wtree->elements_in_tree; @@ -249,12 +247,11 @@ static int ft_add_word(MYSQL_FTPARSER_PARAM *param, MY_FT_PARSER_PARAM *ft_param=param->mysql_ftparam; DBUG_ENTER("ft_add_word"); wtree= ft_param->wtree; - if (ft_param->with_alloc) + if (param->flags & MYSQL_FTFLAGS_NEED_COPY) { byte *ptr; - /* allocating the data in the tree - to avoid mallocs and frees */ DBUG_ASSERT(wtree->with_delete == 0); - ptr= (byte *)alloc_root(&wtree->mem_root, word_len); + ptr= (byte *)alloc_root(ft_param->mem_root, word_len); memcpy(ptr, word, word_len); w.pos= ptr; } @@ -286,16 +283,16 @@ static int ft_parse_internal(MYSQL_FTPARSER_PARAM *param, } -int ft_parse(TREE *wtree, byte *doc, int doclen, my_bool with_alloc, +int ft_parse(TREE *wtree, byte *doc, int doclen, struct st_mysql_ftparser *parser, - MYSQL_FTPARSER_PARAM *param) + MYSQL_FTPARSER_PARAM *param, MEM_ROOT *mem_root) { MY_FT_PARSER_PARAM my_param; DBUG_ENTER("ft_parse"); DBUG_ASSERT(parser); my_param.wtree= wtree; - my_param.with_alloc= with_alloc; + my_param.mem_root= mem_root; param->mysql_parse= ft_parse_internal; param->mysql_add_word= ft_add_word; @@ -357,6 +354,7 @@ MYSQL_FTPARSER_PARAM *ftparser_call_initializer(MI_INFO *info, info->ftparser_param= (MYSQL_FTPARSER_PARAM *) my_malloc(MAX_PARAM_NR * sizeof(MYSQL_FTPARSER_PARAM) * info->s->ftparsers, MYF(MY_WME|MY_ZEROFILL)); + init_alloc_root(&info->ft_memroot, FTPARSER_MEMROOT_ALLOC_SIZE, 0); if (! info->ftparser_param) return 0; } @@ -388,6 +386,7 @@ MYSQL_FTPARSER_PARAM *ftparser_call_initializer(MI_INFO *info, void ftparser_call_deinitializer(MI_INFO *info) { uint i, j, keys= info->s->state.header.keys; + free_root(&info->ft_memroot, MYF(0)); if (! info->ftparser_param) return; for (i= 0; i < keys; i++) diff --git a/storage/myisam/ft_update.c b/storage/myisam/ft_update.c index f5501792dcd..08d605dbcc2 100644 --- a/storage/myisam/ft_update.c +++ b/storage/myisam/ft_update.c @@ -77,7 +77,7 @@ uint _mi_ft_segiterator(register FT_SEG_ITERATOR *ftsi) { uint pack_length= (ftsi->seg->bit_start); ftsi->len= (pack_length == 1 ? (uint) *(uchar*) ftsi->pos : - uint2korr(ftsi->pos)); + uint2korr(ftsi->pos)); ftsi->pos+= pack_length; /* Skip VARCHAR length */ DBUG_RETURN(1); } @@ -95,9 +95,8 @@ uint _mi_ft_segiterator(register FT_SEG_ITERATOR *ftsi) /* parses a document i.e. calls ft_parse for every keyseg */ -uint _mi_ft_parse(TREE *parsed, MI_INFO *info, uint keynr, - const byte *record, my_bool with_alloc, - MYSQL_FTPARSER_PARAM *param) +uint _mi_ft_parse(TREE *parsed, MI_INFO *info, uint keynr, const byte *record, + MYSQL_FTPARSER_PARAM *param, MEM_ROOT *mem_root) { FT_SEG_ITERATOR ftsi; struct st_mysql_ftparser *parser; @@ -110,14 +109,14 @@ uint _mi_ft_parse(TREE *parsed, MI_INFO *info, uint keynr, while (_mi_ft_segiterator(&ftsi)) { if (ftsi.pos) - if (ft_parse(parsed, (byte *)ftsi.pos, ftsi.len, with_alloc, parser, - param)) + if (ft_parse(parsed, (byte *)ftsi.pos, ftsi.len, parser, param, mem_root)) DBUG_RETURN(1); } DBUG_RETURN(0); } -FT_WORD * _mi_ft_parserecord(MI_INFO *info, uint keynr, const byte *record) +FT_WORD *_mi_ft_parserecord(MI_INFO *info, uint keynr, const byte *record, + MEM_ROOT *mem_root) { TREE ptree; MYSQL_FTPARSER_PARAM *param; @@ -125,10 +124,11 @@ FT_WORD * _mi_ft_parserecord(MI_INFO *info, uint keynr, const byte *record) if (! (param= ftparser_call_initializer(info, keynr, 0))) DBUG_RETURN(NULL); bzero((char*) &ptree, sizeof(ptree)); - if (_mi_ft_parse(&ptree, info, keynr, record, 0, param)) + param->flags= 0; + if (_mi_ft_parse(&ptree, info, keynr, record, param, mem_root)) DBUG_RETURN(NULL); - DBUG_RETURN(ft_linearize(&ptree)); + DBUG_RETURN(ft_linearize(&ptree, mem_root)); } static int _mi_ft_store(MI_INFO *info, uint keynr, byte *keybuf, @@ -206,10 +206,11 @@ int _mi_ft_update(MI_INFO *info, uint keynr, byte *keybuf, int cmp, cmp2; DBUG_ENTER("_mi_ft_update"); - if (!(old_word=oldlist=_mi_ft_parserecord(info, keynr, oldrec))) - goto err0; - if (!(new_word=newlist=_mi_ft_parserecord(info, keynr, newrec))) - goto err1; + if (!(old_word=oldlist=_mi_ft_parserecord(info, keynr, oldrec, + &info->ft_memroot)) || + !(new_word=newlist=_mi_ft_parserecord(info, keynr, newrec, + &info->ft_memroot))) + goto err; error=0; while(old_word->pos && new_word->pos) @@ -222,13 +223,13 @@ int _mi_ft_update(MI_INFO *info, uint keynr, byte *keybuf, { key_length=_ft_make_key(info,keynr,keybuf,old_word,pos); if ((error=_mi_ck_delete(info,keynr,(uchar*) keybuf,key_length))) - goto err2; + goto err; } if (cmp > 0 || cmp2) { key_length=_ft_make_key(info,keynr,keybuf,new_word,pos); if ((error=_mi_ck_write(info,keynr,(uchar*) keybuf,key_length))) - goto err2; + goto err; } if (cmp<=0) old_word++; if (cmp>=0) new_word++; @@ -238,11 +239,8 @@ int _mi_ft_update(MI_INFO *info, uint keynr, byte *keybuf, else if (new_word->pos) error=_mi_ft_store(info,keynr,keybuf,new_word,pos); -err2: - my_free((char*) newlist,MYF(0)); -err1: - my_free((char*) oldlist,MYF(0)); -err0: +err: + free_root(&info->ft_memroot, MYF(MY_MARK_BLOCKS_FREE)); DBUG_RETURN(error); } @@ -255,12 +253,13 @@ int _mi_ft_add(MI_INFO *info, uint keynr, byte *keybuf, const byte *record, int error= -1; FT_WORD *wlist; DBUG_ENTER("_mi_ft_add"); + DBUG_PRINT("enter",("keynr: %d",keynr)); - if ((wlist=_mi_ft_parserecord(info, keynr, record))) - { + if ((wlist=_mi_ft_parserecord(info, keynr, record, &info->ft_memroot))) error=_mi_ft_store(info,keynr,keybuf,wlist,pos); - my_free((char*) wlist,MYF(0)); - } + + free_root(&info->ft_memroot, MYF(MY_MARK_BLOCKS_FREE)); + DBUG_PRINT("exit",("Return: %d",error)); DBUG_RETURN(error); } @@ -275,11 +274,10 @@ int _mi_ft_del(MI_INFO *info, uint keynr, byte *keybuf, const byte *record, DBUG_ENTER("_mi_ft_del"); DBUG_PRINT("enter",("keynr: %d",keynr)); - if ((wlist=_mi_ft_parserecord(info, keynr, record))) - { + if ((wlist=_mi_ft_parserecord(info, keynr, record, &info->ft_memroot))) error=_mi_ft_erase(info,keynr,keybuf,wlist,pos); - my_free((char*) wlist,MYF(0)); - } + + free_root(&info->ft_memroot, MYF(MY_MARK_BLOCKS_FREE)); DBUG_PRINT("exit",("Return: %d",error)); DBUG_RETURN(error); } diff --git a/storage/myisam/ftdefs.h b/storage/myisam/ftdefs.h index 2c4cfa1ffd6..108faf4f1a3 100644 --- a/storage/myisam/ftdefs.h +++ b/storage/myisam/ftdefs.h @@ -30,6 +30,8 @@ #define FT_MAX_WORD_LEN_FOR_SORT 31 +#define FTPARSER_MEMROOT_ALLOC_SIZE 65536 + #define COMPILE_STOPWORDS_IN /* Interested readers may consult SMART @@ -119,12 +121,12 @@ void _mi_ft_segiterator_dummy_init(const byte *, uint, FT_SEG_ITERATOR *); uint _mi_ft_segiterator(FT_SEG_ITERATOR *); void ft_parse_init(TREE *, CHARSET_INFO *); -int ft_parse(TREE *, byte *, int, my_bool, struct st_mysql_ftparser *parser, - MYSQL_FTPARSER_PARAM *param); -FT_WORD * ft_linearize(TREE *); -FT_WORD * _mi_ft_parserecord(MI_INFO *, uint, const byte *); -uint _mi_ft_parse(TREE *, MI_INFO *, uint, const byte *, my_bool, - MYSQL_FTPARSER_PARAM *param); +int ft_parse(TREE *, byte *, int, struct st_mysql_ftparser *parser, + MYSQL_FTPARSER_PARAM *, MEM_ROOT *); +FT_WORD * ft_linearize(TREE *, MEM_ROOT *); +FT_WORD * _mi_ft_parserecord(MI_INFO *, uint, const byte *, MEM_ROOT *); +uint _mi_ft_parse(TREE *, MI_INFO *, uint, const byte *, + MYSQL_FTPARSER_PARAM *, MEM_ROOT *); FT_INFO *ft_init_nlq_search(MI_INFO *, uint, byte *, uint, uint, byte *); FT_INFO *ft_init_boolean_search(MI_INFO *, uint, byte *, uint, CHARSET_INFO *); diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index 0fa095a21db..df0d363f7c3 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -2117,6 +2117,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, my_seek(param->read_cache.file,0L,MY_SEEK_END,MYF(0)); sort_param.wordlist=NULL; + init_alloc_root(&sort_param.wordroot, FTPARSER_MEMROOT_ALLOC_SIZE, 0); if (share->data_file_type == DYNAMIC_RECORD) length=max(share->base.min_pack_length+1,share->base.min_block_length); @@ -2200,6 +2201,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, goto err; } param->calc_checksum=0; /* No need to calc glob_crc */ + free_root(&sort_param.wordroot, MYF(0)); /* Set for next loop */ sort_info.max_records= (ha_rows) info->state->records; @@ -2589,6 +2591,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, uint ft_max_word_len_for_sort=FT_MAX_WORD_LEN_FOR_SORT* sort_param[i].keyinfo->seg->charset->mbmaxlen; sort_param[i].key_length+=ft_max_word_len_for_sort-HA_FT_MAXBYTELEN; + init_alloc_root(&sort_param[i].wordroot, FTPARSER_MEMROOT_ALLOC_SIZE, 0); } } sort_info.total_keys=i; @@ -2810,10 +2813,11 @@ static int sort_ft_key_read(MI_SORT_PARAM *sort_param, void *key) { for (;;) { - my_free((char*) wptr, MYF(MY_ALLOW_ZERO_PTR)); + free_root(&sort_param->wordroot, MYF(MY_MARK_BLOCKS_FREE)); if ((error=sort_get_next_record(sort_param))) DBUG_RETURN(error); - if (!(wptr=_mi_ft_parserecord(info,sort_param->key,sort_param->record))) + if (!(wptr=_mi_ft_parserecord(info,sort_param->key,sort_param->record, + &sort_param->wordroot))) DBUG_RETURN(1); if (wptr->pos) break; @@ -2837,7 +2841,7 @@ static int sort_ft_key_read(MI_SORT_PARAM *sort_param, void *key) #endif if (!wptr->pos) { - my_free((char*) sort_param->wordlist, MYF(0)); + free_root(&sort_param->wordroot, MYF(MY_MARK_BLOCKS_FREE)); sort_param->wordlist=0; error=sort_write_record(sort_param); } diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h index 0b450de9c03..a83fbe8f759 100644 --- a/storage/myisam/myisamdef.h +++ b/storage/myisam/myisamdef.h @@ -235,13 +235,14 @@ struct st_myisam_info { /* accumulate indexfile changes between write's */ TREE *bulk_insert; DYNAMIC_ARRAY *ft1_to_ft2; /* used only in ft1->ft2 conversion */ - MYSQL_FTPARSER_PARAM *ftparser_param; /* share info between init/deinit */ - char *filename; /* parameter to open filename */ - uchar *buff, /* Temp area for key */ - *lastkey,*lastkey2; /* Last used search key */ - uchar *first_mbr_key; /* Searhed spatial key */ - byte *rec_buff; /* Tempbuff for recordpack */ - uchar *int_keypos, /* Save position for next/previous */ + MEM_ROOT ft_memroot; /* used by the parser */ + MYSQL_FTPARSER_PARAM *ftparser_param; /* share info between init/deinit */ + char *filename; /* parameter to open filename */ + uchar *buff, /* Temp area for key */ + *lastkey,*lastkey2; /* Last used search key */ + uchar *first_mbr_key; /* Searhed spatial key */ + byte *rec_buff; /* Tempbuff for recordpack */ + uchar *int_keypos, /* Save position for next/previous */ *int_maxpos; /* -""- */ uint int_nod_flag; /* -""- */ uint32 int_keytree_version; /* -""- */ @@ -325,6 +326,7 @@ typedef struct st_mi_sort_param uchar **sort_keys; byte *rec_buff; void *wordlist, *wordptr; + MEM_ROOT wordroot; char *record; MY_TMPDIR *tmpdir; int (*key_cmp)(struct st_mi_sort_param *, const void *, const void *); diff --git a/storage/myisam/sort.c b/storage/myisam/sort.c index c9562461f56..44e7e8b464e 100644 --- a/storage/myisam/sort.c +++ b/storage/myisam/sort.c @@ -447,6 +447,7 @@ err: close_cached_file(&info->tempfile_for_exceptions); ok: + free_root(&info->wordroot, MYF(0)); remove_io_thread(&info->read_cache); pthread_mutex_lock(&info->sort_info->mutex); info->sort_info->threads_running--; From 26d192220d7ed9cdffeb2bbb70f0a3a78c7ab0fd Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 30 May 2006 18:18:13 +0200 Subject: [PATCH 13/32] reduce error log spamming by old privilege tables. If they're old, report it once, don't whine about every missing column. --- sql/table.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sql/table.cc b/sql/table.cc index d0caba7fe9e..5d7b788c755 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2355,12 +2355,23 @@ table_check_intact(TABLE *table, uint table_f_count, // previous MySQL version error= TRUE; if (MYSQL_VERSION_ID > table->s->mysql_version) + { my_error(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE, MYF(0), table->alias, table_f_count, table->s->fields, table->s->mysql_version, MYSQL_VERSION_ID); + sql_print_error(ER(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE), + table->alias, table_f_count, table->s->fields, + table->s->mysql_version, MYSQL_VERSION_ID); + DBUG_RETURN(error); + + } else if (MYSQL_VERSION_ID == table->s->mysql_version) + { my_error(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED,MYF(0), table->alias, table_f_count, table->s->fields); + sql_print_error(ER(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED), table->alias, + table_f_count, table->s->fields); + } else /* moving from newer mysql to older one -> let's say not an error but From e05bb63770495b9e5337538b1c98507d2648267a Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 30 May 2006 18:21:03 +0200 Subject: [PATCH 14/32] sql/Makefile.am: better mysqld dependencies sql/discover.cc: close(-1) bug sql/slave.cc: DBUG_ENTER/RETURN tags ha_archive.cc: double-close bug sql/Makefile.am: better mysqld dependencies sql/discover.cc: close(-1) bug sql/slave.cc: DBUG_ENTER/RETURN tags storage/archive/ha_archive.cc: double-close bug --- sql/Makefile.am | 2 +- sql/discover.cc | 2 +- sql/slave.cc | 243 ++++++++++++++++++++++++---------- storage/archive/ha_archive.cc | 17 +-- 4 files changed, 178 insertions(+), 86 deletions(-) diff --git a/sql/Makefile.am b/sql/Makefile.am index 7f711a1e212..d7a6eac72cc 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -35,7 +35,7 @@ LDADD = $(top_builddir)/vio/libvio.a \ $(top_builddir)/dbug/libdbug.a \ $(top_builddir)/regex/libregex.a \ $(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@ - +mysqld_DEPENDENCIES= @mysql_plugin_libs@ $(LDADD) mysqld_LDADD = @MYSQLD_EXTRA_LDFLAGS@ \ @pstack_libs@ \ @mysql_plugin_libs@ \ diff --git a/sql/discover.cc b/sql/discover.cc index 2a3da55f154..938a05ff4a7 100644 --- a/sql/discover.cc +++ b/sql/discover.cc @@ -119,8 +119,8 @@ int writefrm(const char *name, const void *frmdata, uint len) { if (my_write(file,(byte*)frmdata,len,MYF(MY_WME | MY_NABP))) error= 2; + VOID(my_close(file,MYF(0))); } - VOID(my_close(file,MYF(0))); DBUG_RETURN(error); } /* writefrm */ diff --git a/sql/slave.cc b/sql/slave.cc index 4ab9e951813..5ef91b1f0d4 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -95,6 +95,8 @@ void init_thread_mask(int* mask,MASTER_INFO* mi,bool inverse) { bool set_io = mi->slave_running, set_sql = mi->rli.slave_running; register int tmp_mask=0; + DBUG_ENTER("init_thread_mask"); + if (set_io) tmp_mask |= SLAVE_IO; if (set_sql) @@ -102,6 +104,7 @@ void init_thread_mask(int* mask,MASTER_INFO* mi,bool inverse) if (inverse) tmp_mask^= (SLAVE_IO | SLAVE_SQL); *mask = tmp_mask; + DBUG_VOID_RETURN; } @@ -111,9 +114,12 @@ void init_thread_mask(int* mask,MASTER_INFO* mi,bool inverse) void lock_slave_threads(MASTER_INFO* mi) { + DBUG_ENTER("lock_slave_threads"); + //TODO: see if we can do this without dual mutex pthread_mutex_lock(&mi->run_lock); pthread_mutex_lock(&mi->rli.run_lock); + DBUG_VOID_RETURN; } @@ -123,9 +129,12 @@ void lock_slave_threads(MASTER_INFO* mi) void unlock_slave_threads(MASTER_INFO* mi) { + DBUG_ENTER("unlock_slave_threads"); + //TODO: see if we can do this without dual mutex pthread_mutex_unlock(&mi->rli.run_lock); pthread_mutex_unlock(&mi->run_lock); + DBUG_VOID_RETURN; } @@ -423,6 +432,8 @@ err: void init_slave_skip_errors(const char* arg) { const char *p; + DBUG_ENTER("init_slave_skip_errors"); + if (bitmap_init(&slave_error_mask,0,MAX_SLAVE_ERROR,0)) { fprintf(stderr, "Badly out of memory, please check your system status\n"); @@ -434,7 +445,7 @@ void init_slave_skip_errors(const char* arg) if (!my_strnncoll(system_charset_info,(uchar*)arg,4,(const uchar*)"all",4)) { bitmap_set_all(&slave_error_mask); - return; + DBUG_VOID_RETURN; } for (p= arg ; *p; ) { @@ -446,12 +457,15 @@ void init_slave_skip_errors(const char* arg) while (!my_isdigit(system_charset_info,*p) && *p) p++; } + DBUG_VOID_RETURN; } void st_relay_log_info::inc_group_relay_log_pos(ulonglong log_pos, bool skip_lock) { + DBUG_ENTER("st_relay_log_info::inc_group_relay_log_pos"); + if (!skip_lock) pthread_mutex_lock(&data_lock); inc_event_relay_log_pos(); @@ -500,12 +514,14 @@ void st_relay_log_info::inc_group_relay_log_pos(ulonglong log_pos, pthread_cond_broadcast(&data_cond); if (!skip_lock) pthread_mutex_unlock(&data_lock); + DBUG_VOID_RETURN; } void st_relay_log_info::close_temporary_tables() { TABLE *table,*next; + DBUG_ENTER("st_relay_log_info::close_temporary_tables"); for (table=save_temporary_tables ; table ; table=next) { @@ -514,10 +530,12 @@ void st_relay_log_info::close_temporary_tables() Don't ask for disk deletion. For now, anyway they will be deleted when slave restarts, but it is a better intention to not delete them. */ + DBUG_PRINT("info", ("table: %p", table)); close_temporary(table, 1, 0); } save_temporary_tables= 0; slave_open_temp_tables= 0; + DBUG_VOID_RETURN; } /* @@ -613,12 +631,13 @@ err: int terminate_slave_threads(MASTER_INFO* mi,int thread_mask,bool skip_lock) { + DBUG_ENTER("terminate_slave_threads"); + if (!mi->inited) - return 0; /* successfully do nothing */ + DBUG_RETURN(0); /* successfully do nothing */ int error,force_all = (thread_mask & SLAVE_FORCE_ALL); pthread_mutex_t *sql_lock = &mi->rli.run_lock, *io_lock = &mi->run_lock; pthread_mutex_t *sql_cond_lock,*io_cond_lock; - DBUG_ENTER("terminate_slave_threads"); sql_cond_lock=sql_lock; io_cond_lock=io_lock; @@ -704,9 +723,10 @@ int start_slave_thread(pthread_handler h_func, pthread_mutex_t *start_lock, { pthread_t th; ulong start_id; - DBUG_ASSERT(mi->inited); DBUG_ENTER("start_slave_thread"); + DBUG_ASSERT(mi->inited); + if (start_lock) pthread_mutex_lock(start_lock); if (!server_id) @@ -810,8 +830,10 @@ int start_slave_threads(bool need_slave_mutex, bool wait_for_start, #ifdef NOT_USED_YET static int end_slave_on_walk(MASTER_INFO* mi, gptr /*unused*/) { + DBUG_ENTER("end_slave_on_walk"); + end_master_info(mi); - return 0; + DBUG_RETURN(0); } #endif @@ -825,6 +847,8 @@ static int end_slave_on_walk(MASTER_INFO* mi, gptr /*unused*/) void end_slave() { + DBUG_ENTER("end_slave"); + /* This is called when the server terminates, in close_connections(). It terminates slave threads. However, some CHANGE MASTER etc may still be @@ -846,19 +870,24 @@ void end_slave() active_mi= 0; } pthread_mutex_unlock(&LOCK_active_mi); + DBUG_VOID_RETURN; } static bool io_slave_killed(THD* thd, MASTER_INFO* mi) { + DBUG_ENTER("io_slave_killed"); + DBUG_ASSERT(mi->io_thd == thd); DBUG_ASSERT(mi->slave_running); // tracking buffer overrun - return mi->abort_slave || abort_loop || thd->killed; + DBUG_RETURN(mi->abort_slave || abort_loop || thd->killed); } static bool sql_slave_killed(THD* thd, RELAY_LOG_INFO* rli) { + DBUG_ENTER("sql_slave_killed"); + DBUG_ASSERT(rli->sql_thd == thd); DBUG_ASSERT(rli->slave_running == 1);// tracking buffer overrun if (abort_loop || thd->killed || rli->abort_slave) @@ -873,7 +902,7 @@ static bool sql_slave_killed(THD* thd, RELAY_LOG_INFO* rli) is actively working. */ if (!rli->unsafe_to_stop_at) - return 1; + DBUG_RETURN(1); DBUG_PRINT("info", ("Slave SQL thread is in an unsafe situation, giving " "it some grace period")); if (difftime(time(0), rli->unsafe_to_stop_at) > 60) @@ -885,10 +914,10 @@ static bool sql_slave_killed(THD* thd, RELAY_LOG_INFO* rli) "There is a risk of duplicate updates when the slave " "SQL thread is restarted. Please check your tables' " "contents after restart."); - return 1; + DBUG_RETURN(1); } } - return 0; + DBUG_RETURN(0); } @@ -917,6 +946,8 @@ void slave_print_msg(enum loglevel level, RELAY_LOG_INFO* rli, char buff[MAX_SLAVE_ERRMSG], *pbuff= buff; uint pbuffsize= sizeof(buff); va_list args; + DBUG_ENTER("slave_print_msg"); + va_start(args,msg); switch (level) { @@ -943,7 +974,7 @@ void slave_print_msg(enum loglevel level, RELAY_LOG_INFO* rli, break; default: DBUG_ASSERT(0); // should not come here - return; // don't crash production builds, just do nothing + DBUG_VOID_RETURN; // don't crash production builds, just do nothing } my_vsnprintf(pbuff, pbuffsize, msg, args); /* If the msg string ends with '.', do not add a ',' it would be ugly */ @@ -951,6 +982,7 @@ void slave_print_msg(enum loglevel level, RELAY_LOG_INFO* rli, (*report_function)("Slave: %s Error_code: %d", pbuff, err_code); else (*report_function)("Slave: %s, Error_code: %d", pbuff, err_code); + DBUG_VOID_RETURN; } /* @@ -962,9 +994,12 @@ void slave_print_msg(enum loglevel level, RELAY_LOG_INFO* rli, void skip_load_data_infile(NET *net) { + DBUG_ENTER("skip_load_data_infile"); + (void)net_request_file(net, "/dev/null"); (void)my_net_read(net); // discard response (void)net_write_command(net, 0, "", 0, "", 0); // Send ok + DBUG_VOID_RETURN; } @@ -983,13 +1018,17 @@ bool net_request_file(NET* net, const char* fname) const char *print_slave_db_safe(const char* db) { - return (db ? db : ""); + DBUG_ENTER("*print_slave_db_safe"); + + DBUG_RETURN((db ? db : "")); } static int init_strvar_from_file(char *var, int max_size, IO_CACHE *f, const char *default_val) { uint length; + DBUG_ENTER("init_strvar_from_file"); + if ((length=my_b_gets(f,var, max_size))) { char* last_p = var + length -1; @@ -1004,32 +1043,34 @@ static int init_strvar_from_file(char *var, int max_size, IO_CACHE *f, int c; while (((c=my_b_get(f)) != '\n' && c != my_b_EOF)); } - return 0; + DBUG_RETURN(0); } else if (default_val) { strmake(var, default_val, max_size-1); - return 0; + DBUG_RETURN(0); } - return 1; + DBUG_RETURN(1); } static int init_intvar_from_file(int* var, IO_CACHE* f, int default_val) { char buf[32]; + DBUG_ENTER("init_intvar_from_file"); + if (my_b_gets(f, buf, sizeof(buf))) { *var = atoi(buf); - return 0; + DBUG_RETURN(0); } else if (default_val) { *var = default_val; - return 0; + DBUG_RETURN(0); } - return 1; + DBUG_RETURN(1); } /* @@ -1049,6 +1090,7 @@ static int init_intvar_from_file(int* var, IO_CACHE* f, int default_val) static int get_master_version_and_clock(MYSQL* mysql, MASTER_INFO* mi) { const char* errmsg= 0; + DBUG_ENTER("get_master_version_and_clock"); /* Free old description_event_for_queue (that is needed if we are in @@ -1104,14 +1146,14 @@ static int get_master_version_and_clock(MYSQL* mysql, MASTER_INFO* mi) if (errmsg) { sql_print_error(errmsg); - return 1; + DBUG_RETURN(1); } /* as we are here, we tried to allocate the event */ if (!mi->rli.relay_log.description_event_for_queue) { sql_print_error("Slave I/O thread failed to create a default Format_description_log_event"); - return 1; + DBUG_RETURN(1); } /* @@ -1227,10 +1269,10 @@ err: if (errmsg) { sql_print_error(errmsg); - return 1; + DBUG_RETURN(1); } - return 0; + DBUG_RETURN(0); } /* @@ -1257,7 +1299,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db, handler *file; ulong save_options; NET *net= &mysql->net; - DBUG_ENTER("create_table_from_dump"); + DBUG_ENTER("create_table_from_dump"); packet_len= my_net_read(net); // read create table statement if (packet_len == packet_error) @@ -1666,7 +1708,6 @@ static bool wait_for_relay_log_space(RELAY_LOG_INFO* rli) MASTER_INFO* mi = rli->mi; const char *save_proc_info; THD* thd = mi->io_thd; - DBUG_ENTER("wait_for_relay_log_space"); pthread_mutex_lock(&rli->log_space_lock); @@ -1725,6 +1766,8 @@ static void write_ignored_events_info_to_relay_log(THD *thd, MASTER_INFO *mi) { RELAY_LOG_INFO *rli= &mi->rli; pthread_mutex_t *log_lock= rli->relay_log.get_log_lock(); + DBUG_ENTER("write_ignored_events_info_to_relay_log"); + DBUG_ASSERT(thd == mi->io_thd); pthread_mutex_lock(log_lock); if (rli->ign_master_log_name_end[0]) @@ -1755,11 +1798,14 @@ static void write_ignored_events_info_to_relay_log(THD *thd, MASTER_INFO *mi) } else pthread_mutex_unlock(log_lock); + DBUG_VOID_RETURN; } void init_master_info_with_options(MASTER_INFO* mi) { + DBUG_ENTER("init_master_info_with_options"); + mi->master_log_name[0] = 0; mi->master_log_pos = BIN_LOG_HEADER_SIZE; // skip magic number @@ -1783,13 +1829,17 @@ void init_master_info_with_options(MASTER_INFO* mi) strmake(mi->ssl_cipher, master_ssl_cipher, sizeof(mi->ssl_cipher)-1); if (master_ssl_key) strmake(mi->ssl_key, master_ssl_key, sizeof(mi->ssl_key)-1); + DBUG_VOID_RETURN; } void clear_slave_error(RELAY_LOG_INFO* rli) { + DBUG_ENTER("clear_slave_error"); + /* Clear the errors displayed by SHOW SLAVE STATUS */ rli->last_slave_error[0]= 0; rli->last_slave_errno= 0; + DBUG_VOID_RETURN; } /* @@ -1800,9 +1850,12 @@ void clear_slave_error(RELAY_LOG_INFO* rli) */ void clear_until_condition(RELAY_LOG_INFO* rli) { + DBUG_ENTER("clear_until_condition"); + rli->until_condition= RELAY_LOG_INFO::UNTIL_NONE; rli->until_log_name[0]= 0; rli->until_log_pos= 0; + DBUG_VOID_RETURN; } @@ -2031,9 +2084,10 @@ int register_slave_on_master(MYSQL* mysql) { char buf[1024], *pos= buf; uint report_host_len, report_user_len=0, report_password_len=0; + DBUG_ENTER("register_slave_on_master"); if (!report_host) - return 0; + DBUG_RETURN(0); report_host_len= strlen(report_host); if (report_user) report_user_len= strlen(report_user); @@ -2042,7 +2096,7 @@ int register_slave_on_master(MYSQL* mysql) /* 30 is a good safety margin */ if (report_host_len + report_user_len + report_password_len + 30 > sizeof(buf)) - return 0; // safety + DBUG_RETURN(0); // safety int4store(pos, server_id); pos+= 4; pos= net_store_data(pos, report_host, report_host_len); @@ -2059,9 +2113,9 @@ int register_slave_on_master(MYSQL* mysql) sql_print_error("Error on COM_REGISTER_SLAVE: %d '%s'", mysql_errno(mysql), mysql_error(mysql)); - return 1; + DBUG_RETURN(1); } - return 0; + DBUG_RETURN(0); } @@ -2313,6 +2367,8 @@ st_relay_log_info::st_relay_log_info() m_reload_flags(RELOAD_NONE_F), unsafe_to_stop_at(0) { + DBUG_ENTER("st_relay_log_info::st_relay_log_info"); + group_relay_log_name[0]= event_relay_log_name[0]= group_master_log_name[0]= 0; last_slave_error[0]= until_log_name[0]= ign_master_log_name_end[0]= 0; @@ -2327,11 +2383,14 @@ st_relay_log_info::st_relay_log_info() pthread_cond_init(&stop_cond, NULL); pthread_cond_init(&log_space_cond, NULL); relay_log.init_pthread_objects(); + DBUG_VOID_RETURN; } st_relay_log_info::~st_relay_log_info() { + DBUG_ENTER("st_relay_log_info::~st_relay_log_info"); + pthread_mutex_destroy(&run_lock); pthread_mutex_destroy(&data_lock); pthread_mutex_destroy(&log_space_lock); @@ -2340,6 +2399,7 @@ st_relay_log_info::~st_relay_log_info() pthread_cond_destroy(&stop_cond); pthread_cond_destroy(&log_space_cond); relay_log.cleanup(); + DBUG_VOID_RETURN; } /* @@ -2371,14 +2431,16 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name, longlong log_pos, longlong timeout) { - if (!inited) - return -1; int event_count = 0; ulong init_abort_pos_wait; int error=0; struct timespec abstime; // for timeout checking const char *msg; - DBUG_ENTER("wait_for_pos"); + DBUG_ENTER("st_relay_log_info::wait_for_pos"); + + if (!inited) + DBUG_RETURN(-1); + DBUG_PRINT("enter",("log_name: '%s' log_pos: %lu timeout: %lu", log_name->c_ptr(), (ulong) log_pos, (ulong) timeout)); @@ -2546,13 +2608,18 @@ improper_arguments: %d timed_out: %d", void set_slave_thread_options(THD* thd) { + DBUG_ENTER("set_slave_thread_options"); + thd->options = ((opt_log_slave_updates) ? OPTION_BIN_LOG:0) | OPTION_AUTO_IS_NULL; thd->variables.completion_type= 0; + DBUG_VOID_RETURN; } void set_slave_thread_default_charset(THD* thd, RELAY_LOG_INFO *rli) { + DBUG_ENTER("set_slave_thread_default_charset"); + thd->variables.character_set_client= global_system_variables.character_set_client; thd->variables.collation_connection= @@ -2561,6 +2628,7 @@ void set_slave_thread_default_charset(THD* thd, RELAY_LOG_INFO *rli) global_system_variables.collation_server; thd->update_charset(); rli->cached_charset_invalidate(); + DBUG_VOID_RETURN; } /* @@ -2622,6 +2690,8 @@ static int safe_sleep(THD* thd, int sec, CHECK_KILLED_FUNC thread_killed, { int nap_time; thr_alarm_t alarmed; + DBUG_ENTER("safe_sleep"); + thr_alarm_init(&alarmed); time_t start_time= time((time_t*) 0); time_t end_time= start_time+sec; @@ -2639,10 +2709,10 @@ static int safe_sleep(THD* thd, int sec, CHECK_KILLED_FUNC thread_killed, thr_end_alarm(&alarmed); if ((*thread_killed)(thd,thread_killed_arg)) - return 1; + DBUG_RETURN(1); start_time=time((time_t*) 0); } - return 0; + DBUG_RETURN(0); } @@ -2684,13 +2754,15 @@ static int request_dump(MYSQL* mysql, MASTER_INFO* mi, static int request_table_dump(MYSQL* mysql, const char* db, const char* table) { char buf[1024]; + DBUG_ENTER("request_table_dump"); + char * p = buf; uint table_len = (uint) strlen(table); uint db_len = (uint) strlen(db); if (table_len + db_len > sizeof(buf) - 2) { sql_print_error("request_table_dump: Buffer overrun"); - return 1; + DBUG_RETURN(1); } *p++ = db_len; @@ -2703,10 +2775,10 @@ static int request_table_dump(MYSQL* mysql, const char* db, const char* table) { sql_print_error("request_table_dump: Error sending the table dump \ command"); - return 1; + DBUG_RETURN(1); } - return 0; + DBUG_RETURN(0); } @@ -2730,6 +2802,7 @@ command"); static ulong read_event(MYSQL* mysql, MASTER_INFO *mi, bool* suppress_warnings) { ulong len; + DBUG_ENTER("read_event"); *suppress_warnings= 0; /* @@ -2738,7 +2811,7 @@ static ulong read_event(MYSQL* mysql, MASTER_INFO *mi, bool* suppress_warnings) */ #ifndef DBUG_OFF if (disconnect_slave_event_count && !(mi->events_till_disconnect--)) - return packet_error; + DBUG_RETURN(packet_error); #endif len = net_safe_read(mysql); @@ -2756,7 +2829,7 @@ static ulong read_event(MYSQL* mysql, MASTER_INFO *mi, bool* suppress_warnings) else sql_print_error("Error reading packet from server: %s ( server_errno=%d)", mysql_error(mysql), mysql_errno(mysql)); - return packet_error; + DBUG_RETURN(packet_error); } /* Check if eof packet */ @@ -2765,25 +2838,27 @@ static ulong read_event(MYSQL* mysql, MASTER_INFO *mi, bool* suppress_warnings) sql_print_information("Slave: received end packet from server, apparent " "master shutdown: %s", mysql_error(mysql)); - return packet_error; + DBUG_RETURN(packet_error); } DBUG_PRINT("info",( "len=%u, net->read_pos[4] = %d\n", len, mysql->net.read_pos[4])); - return len - 1; + DBUG_RETURN(len - 1); } int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int expected_error) { + DBUG_ENTER("check_expected_error"); + switch (expected_error) { case ER_NET_READ_ERROR: case ER_NET_ERROR_ON_WRITE: case ER_SERVER_SHUTDOWN: case ER_NEW_ABORTING_CONNECTION: - return 1; + DBUG_RETURN(1); default: - return 0; + DBUG_RETURN(0); } } @@ -2819,6 +2894,7 @@ bool st_relay_log_info::is_until_satisfied() { const char *log_name; ulonglong log_pos; + DBUG_ENTER("st_relay_log_info::is_until_satisfied"); DBUG_ASSERT(until_condition != UNTIL_NONE); @@ -2865,34 +2941,39 @@ bool st_relay_log_info::is_until_satisfied() /* Probably error so we aborting */ sql_print_error("Slave SQL thread is stopped because UNTIL " "condition is bad."); - return TRUE; + DBUG_RETURN(TRUE); } } else - return until_log_pos == 0; + DBUG_RETURN(until_log_pos == 0); } - return ((until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_EQUAL && + DBUG_RETURN(((until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_EQUAL && log_pos >= until_log_pos) || - until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_GREATER); + until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_GREATER)); } void st_relay_log_info::cached_charset_invalidate() { + DBUG_ENTER("st_relay_log_info::cached_charset_invalidate"); + /* Full of zeroes means uninitialized. */ bzero(cached_charset, sizeof(cached_charset)); + DBUG_VOID_RETURN; } bool st_relay_log_info::cached_charset_compare(char *charset) { + DBUG_ENTER("st_relay_log_info::cached_charset_compare"); + if (bcmp(cached_charset, charset, sizeof(cached_charset))) { memcpy(cached_charset, charset, sizeof(cached_charset)); - return 1; + DBUG_RETURN(1); } - return 0; + DBUG_RETURN(0); } /* @@ -2904,8 +2985,10 @@ bool st_relay_log_info::cached_charset_compare(char *charset) */ static int has_temporary_error(THD *thd) { + DBUG_ENTER("has_temporary_error"); + if (thd->is_fatal_error) - return 0; + DBUG_RETURN(0); /* Temporary error codes: @@ -2914,7 +2997,7 @@ static int has_temporary_error(THD *thd) */ if (thd->net.last_errno == ER_LOCK_DEADLOCK || thd->net.last_errno == ER_LOCK_WAIT_TIMEOUT) - return 1; + DBUG_RETURN(1); #ifdef HAVE_NDB_BINLOG /* @@ -2928,17 +3011,19 @@ static int has_temporary_error(THD *thd) switch (err->code) { case ER_GET_TEMPORARY_ERRMSG: - return 1; + DBUG_RETURN(1); default: break; } } #endif - return 0; + DBUG_RETURN(0); } static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) { + DBUG_ENTER("exec_relay_log_event"); + /* We acquire this mutex since we need it for all operations except event execution. But we will release it in places where we will @@ -2965,7 +3050,7 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) */ rli->abort_slave= 1; pthread_mutex_unlock(&rli->data_lock); - return 1; + DBUG_RETURN(1); } Log_event * ev = next_event(rli); @@ -2976,7 +3061,7 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) { pthread_mutex_unlock(&rli->data_lock); delete ev; - return 1; + DBUG_RETURN(1); } if (ev) { @@ -3044,7 +3129,7 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) --rli->slave_skip_counter; pthread_mutex_unlock(&rli->data_lock); delete ev; - return 0; // avoid infinite update loops + DBUG_RETURN(0); // avoid infinite update loops } pthread_mutex_unlock(&rli->data_lock); @@ -3125,13 +3210,11 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) */ rli->trans_retries= 0; // restart from fresh } - } - return exec_res; + } + DBUG_RETURN(exec_res); } - else - { - pthread_mutex_unlock(&rli->data_lock); - slave_print_msg(ERROR_LEVEL, rli, 0, "\ + pthread_mutex_unlock(&rli->data_lock); + slave_print_msg(ERROR_LEVEL, rli, 0, "\ Could not parse relay log event entry. The possible reasons are: the master's \ binary log is corrupted (you can check this by running 'mysqlbinlog' on the \ binary log), the slave's relay log is corrupted (you can check this by running \ @@ -3140,8 +3223,7 @@ or slave's MySQL code. If you want to check the master's binary log or slave's \ relay log, you will be able to know their names by issuing 'SHOW SLAVE STATUS' \ on this slave.\ "); - return 1; - } + DBUG_RETURN(1); } @@ -3461,6 +3543,7 @@ pthread_handler_t handle_slave_sql(void *arg) { THD *thd; /* needs to be first for thread_stack */ char llbuff[22],llbuff1[22]; + RELAY_LOG_INFO* rli = &((MASTER_INFO*)arg)->rli; const char *errmsg; @@ -4060,16 +4143,18 @@ err: static int queue_old_event(MASTER_INFO *mi, const char *buf, ulong event_len) { + DBUG_ENTER("queue_old_event"); + switch (mi->rli.relay_log.description_event_for_queue->binlog_version) { case 1: - return queue_binlog_ver_1_event(mi,buf,event_len); + DBUG_RETURN(queue_binlog_ver_1_event(mi,buf,event_len)); case 3: - return queue_binlog_ver_3_event(mi,buf,event_len); + DBUG_RETURN(queue_binlog_ver_3_event(mi,buf,event_len)); default: /* unsupported format; eg version 2 */ DBUG_PRINT("info",("unsupported binlog format %d in queue_old_event()", mi->rli.relay_log.description_event_for_queue->binlog_version)); - return 1; + DBUG_RETURN(1); } } @@ -4282,7 +4367,9 @@ void end_relay_log_info(RELAY_LOG_INFO* rli) static int safe_connect(THD* thd, MYSQL* mysql, MASTER_INFO* mi) { - return connect_to_master(thd, mysql, mi, 0, 0); + DBUG_ENTER("safe_connect"); + + DBUG_RETURN(connect_to_master(thd, mysql, mi, 0, 0)); } @@ -4439,9 +4526,10 @@ static int safe_reconnect(THD* thd, MYSQL* mysql, MASTER_INFO* mi, bool flush_relay_log_info(RELAY_LOG_INFO* rli) { bool error=0; + DBUG_ENTER("flush_relay_log_info"); if (unlikely(rli->no_storage)) - return 0; + DBUG_RETURN(0); IO_CACHE *file = &rli->info_file; char buff[FN_REFLEN*2+22*2+4], *pos; @@ -4461,7 +4549,7 @@ bool flush_relay_log_info(RELAY_LOG_INFO* rli) error=1; /* Flushing the relay log is done by the slave I/O thread */ - return error; + DBUG_RETURN(error); } @@ -4471,9 +4559,9 @@ bool flush_relay_log_info(RELAY_LOG_INFO* rli) static IO_CACHE *reopen_relay_log(RELAY_LOG_INFO *rli, const char **errmsg) { + DBUG_ENTER("reopen_relay_log"); DBUG_ASSERT(rli->cur_log != &rli->cache_buf); DBUG_ASSERT(rli->cur_log_fd == -1); - DBUG_ENTER("reopen_relay_log"); IO_CACHE *cur_log = rli->cur_log=&rli->cache_buf; if ((rli->cur_log_fd=open_binlog(cur_log,rli->event_relay_log_name, @@ -4494,11 +4582,11 @@ static Log_event* next_event(RELAY_LOG_INFO* rli) { Log_event* ev; IO_CACHE* cur_log = rli->cur_log; - pthread_mutex_t *log_lock = rli->relay_log.get_log_lock(); + pthread_mutex_t *log_lock = rli->relay_log.get_log_lock(); const char* errmsg=0; THD* thd = rli->sql_thd; - DBUG_ENTER("next_event"); + DBUG_ASSERT(thd != 0); #ifndef DBUG_OFF @@ -4909,12 +4997,16 @@ static int reload_entry_compare(const void *lhs, const void *rhs) { const char *lstr = static_cast(lhs); const char *rstr = static_cast(rhs)->table; - return strcmp(lstr, rstr); + DBUG_ENTER("reload_entry_compare"); + + DBUG_RETURN(strcmp(lstr, rstr)); } void st_relay_log_info::touching_table(char const* db, char const* table, ulong table_id) { + DBUG_ENTER("st_relay_log_info::touching_table"); + if (strcmp(db,"mysql") == 0) { #if defined(HAVE_BSEARCH) && defined(HAVE_SIZE_T) @@ -4935,10 +5027,13 @@ void st_relay_log_info::touching_table(char const* db, char const* table, if (entry) m_reload_flags|= entry->flag; } + DBUG_VOID_RETURN; } void st_relay_log_info::transaction_end(THD* thd) { + DBUG_ENTER("st_relay_log_info::transaction_end"); + if (m_reload_flags != RELOAD_NONE_F) { if (m_reload_flags & RELOAD_ACCESS_F) @@ -4949,11 +5044,14 @@ void st_relay_log_info::transaction_end(THD* thd) m_reload_flags= RELOAD_NONE_F; } + DBUG_VOID_RETURN; } #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) void st_relay_log_info::cleanup_context(THD *thd, bool error) { + DBUG_ENTER("st_relay_log_info::cleanup_context"); + DBUG_ASSERT(sql_thd == thd); /* 1) Instances of Table_map_log_event, if ::exec_event() was called on them, @@ -4976,6 +5074,7 @@ void st_relay_log_info::cleanup_context(THD *thd, bool error) close_thread_tables(thd); clear_tables_to_lock(); unsafe_to_stop_at= 0; + DBUG_VOID_RETURN; } #endif diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc index b151c61c267..739acffeb0d 100644 --- a/storage/archive/ha_archive.cc +++ b/storage/archive/ha_archive.cc @@ -1320,25 +1320,18 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt) we don't check rc here because we want to open the file back up even if the optimize failed but we will return rc below so that we will know it failed. + We also need to reopen our read descriptor since it has changed. */ DBUG_PRINT("info", ("Reopening archive data file")); - if (!(azopen(&(share->archive_write), share->data_file_name, - O_WRONLY|O_APPEND|O_BINARY))) + if (!azopen(&(share->archive_write), share->data_file_name, + O_WRONLY|O_APPEND|O_BINARY) || + !azopen(&archive, share->data_file_name, O_RDONLY|O_BINARY)) { DBUG_PRINT("info", ("Could not open archive write file")); rc= HA_ERR_CRASHED_ON_USAGE; - goto error; - } - - /* - Now we need to reopen our read descriptor since it has changed. - */ - if (!(azopen(&archive, share->data_file_name, O_RDONLY|O_BINARY))) - { - rc= HA_ERR_CRASHED_ON_USAGE; - goto error; } + DBUG_RETURN(rc); error: azclose(&writer); From fc03eef11652a1f40d40812b686cef80fd03a4b9 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 30 May 2006 20:06:29 +0200 Subject: [PATCH 15/32] don't try to "estimate" a number of words that a plugin parser can produce --- storage/myisam/mi_check.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index df0d363f7c3..ef7b1e6fde3 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -2180,12 +2180,36 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, { uint ft_max_word_len_for_sort=FT_MAX_WORD_LEN_FOR_SORT* sort_param.keyinfo->seg->charset->mbmaxlen; - sort_info.max_records= - (ha_rows) (sort_info.filelength/ft_min_word_len+1); + sort_param.key_length+=ft_max_word_len_for_sort-HA_FT_MAXBYTELEN; + /* + fulltext indexes may have much more entries than the + number of rows in the table. We estimate the number here. + + Note, built-in parser is always nr. 0 - see ftparser_call_initializer() + */ + if (sort_param.keyinfo->ftparser_nr == 0) + { + /* + for built-in parser the number of generated index entries + cannot be larger than the size of the data file divided + by the minimal word's length + */ + sort_info.max_records= + (ha_rows) (sort_info.filelength/ft_min_word_len+1); + } + else + { + /* + for external plugin parser we cannot tell anything at all :( + so, we'll use all the sort memory and start from ~10 buffpeks. + (see _create_index_by_sort) + */ + sort_info.max_records= + 10*param->sort_buffer_length/sort_param.key_length; + } sort_param.key_read=sort_ft_key_read; sort_param.key_write=sort_ft_key_write; - sort_param.key_length+=ft_max_word_len_for_sort-HA_FT_MAXBYTELEN; } else { From 78d3a4f214ab17eb60cc60343ab6aee348760bd2 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 30 May 2006 23:21:44 +0200 Subject: [PATCH 16/32] disabled.def with ndb_dd_backuprestore test disabled --- mysql-test/t/disabled.def | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index d6083ab8bfe..552827c47f9 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -38,3 +38,4 @@ rpl_sp : BUG#16456 2006-02-16 jmiller # the below testcase have been reworked to avoid the bug, test contains comment, keep bug open #ndb_binlog_ddl_multi : BUG#18976 2006-04-10 kent CRBR: multiple binlog, second binlog may miss schema log events +ndb_dd_backuprestore : Nikolay: removed partitions from the test. Review pending. From 49c664d360fb3aee8596f8b29f29600e0f957073 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 31 May 2006 01:52:14 +0200 Subject: [PATCH 17/32] ndb: release LOCK_open during mysqld schema sync and mysqld sync with binlog (create/drop/rename table) + increase timeout for sync... which now should never occur --- sql/ha_ndbcluster.cc | 12 ++++++------ sql/ha_ndbcluster_binlog.cc | 36 ++++++++++++++++++++++++++++++++---- sql/ha_ndbcluster_binlog.h | 5 +++-- 3 files changed, 41 insertions(+), 12 deletions(-) diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index f46a5eccabf..8b3ff56a847 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -4649,7 +4649,7 @@ int ha_ndbcluster::create(const char *name, share->db, share->table_name, m_table->getObjectId(), m_table->getObjectVersion(), - SOT_CREATE_TABLE); + SOT_CREATE_TABLE, 0, 0, 1); break; } } @@ -5031,7 +5031,7 @@ int ha_ndbcluster::rename_table(const char *from, const char *to) old_dbname, m_tabname, ndb_table_id, ndb_table_version, SOT_RENAME_TABLE, - m_dbname, new_tabname); + m_dbname, new_tabname, 1); } if (share) free_share(&share); @@ -5155,7 +5155,7 @@ ha_ndbcluster::delete_table(ha_ndbcluster *h, Ndb *ndb, current_thd->query, current_thd->query_length, share->db, share->table_name, ndb_table_id, ndb_table_version, - SOT_DROP_TABLE); + SOT_DROP_TABLE, 0, 0, 1); } else if (table_dropped && share && share->op) /* ndbcluster_log_schema_op will do a force GCP */ @@ -5752,7 +5752,7 @@ static void ndbcluster_drop_database(char *path) ha_ndbcluster::set_dbname(path, db); ndbcluster_log_schema_op(current_thd, 0, current_thd->query, current_thd->query_length, - db, "", 0, 0, SOT_DROP_DB); + db, "", 0, 0, SOT_DROP_DB, 0, 0, 0); #endif DBUG_VOID_RETURN; } @@ -9941,13 +9941,13 @@ int ndbcluster_alter_tablespace(THD* thd, st_alter_tablespace *info) thd->query, thd->query_length, "", info->tablespace_name, 0, 0, - SOT_TABLESPACE); + SOT_TABLESPACE, 0, 0, 0); else ndbcluster_log_schema_op(thd, 0, thd->query, thd->query_length, "", info->logfile_group_name, 0, 0, - SOT_LOGFILE_GROUP); + SOT_LOGFILE_GROUP, 0, 0, 0); #endif DBUG_RETURN(FALSE); diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index 144c073d565..452be961235 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -39,6 +39,12 @@ #define NDB_APPLY_TABLE_FILE "./" NDB_REP_DB "/" NDB_APPLY_TABLE #define NDB_SCHEMA_TABLE_FILE "./" NDB_REP_DB "/" NDB_SCHEMA_TABLE +/* + Timeout for syncing schema events between + mysql servers, and between mysql server and the binlog +*/ +const int opt_ndb_sync_timeout= 120; + /* Flag showing if the ndb injector thread is running, if so == 1 -1 if it was started but later stopped for some reason @@ -498,6 +504,7 @@ ndbcluster_binlog_log_query(THD *thd, enum_binlog_command binlog_command, { case LOGCOM_CREATE_TABLE: type= SOT_CREATE_TABLE; + DBUG_ASSERT(FALSE); break; case LOGCOM_ALTER_TABLE: type= SOT_ALTER_TABLE; @@ -505,9 +512,11 @@ ndbcluster_binlog_log_query(THD *thd, enum_binlog_command binlog_command, break; case LOGCOM_RENAME_TABLE: type= SOT_RENAME_TABLE; + DBUG_ASSERT(FALSE); break; case LOGCOM_DROP_TABLE: type= SOT_DROP_TABLE; + DBUG_ASSERT(FALSE); break; case LOGCOM_CREATE_DB: type= SOT_CREATE_DB; @@ -519,12 +528,14 @@ ndbcluster_binlog_log_query(THD *thd, enum_binlog_command binlog_command, break; case LOGCOM_DROP_DB: type= SOT_DROP_DB; + DBUG_ASSERT(FALSE); break; } if (log) { ndbcluster_log_schema_op(thd, 0, query, query_length, - db, table_name, 0, 0, type); + db, table_name, 0, 0, type, + 0, 0, 0); } DBUG_VOID_RETURN; } @@ -995,7 +1006,8 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share, uint32 ndb_table_id, uint32 ndb_table_version, enum SCHEMA_OP_TYPE type, - const char *new_db, const char *new_table_name) + const char *new_db, const char *new_table_name, + int have_lock_open) { DBUG_ENTER("ndbcluster_log_schema_op"); Thd_ndb *thd_ndb= get_thd_ndb(thd); @@ -1254,8 +1266,13 @@ end: if (ndb_error == 0 && !bitmap_is_clear_all(&schema_subscribers)) { - int max_timeout= 10; + int max_timeout= opt_ndb_sync_timeout; (void) pthread_mutex_lock(&ndb_schema_object->mutex); + if (have_lock_open) + { + safe_mutex_assert_owner(&LOCK_open); + (void) pthread_mutex_unlock(&LOCK_open); + } while (1) { struct timespec abstime; @@ -1300,6 +1317,10 @@ end: "distributing", ndb_schema_object->key); } } + if (have_lock_open) + { + (void) pthread_mutex_lock(&LOCK_open); + } (void) pthread_mutex_unlock(&ndb_schema_object->mutex); } @@ -2698,6 +2719,7 @@ ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name, NDB_SHARE *share, const char *type_str) { DBUG_ENTER("ndbcluster_handle_drop_table"); + THD *thd= current_thd; NDBDICT *dict= ndb->getDictionary(); if (event_name && dict->dropEvent(event_name)) @@ -2743,10 +2765,14 @@ ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name, these out of order, thus we are keeping the SYNC_DROP_ defined for now. */ + const char *save_proc_info= thd->proc_info; #define SYNC_DROP_ #ifdef SYNC_DROP_ + thd->proc_info= "Syncing ndb table schema operation and binlog"; (void) pthread_mutex_lock(&share->mutex); - int max_timeout= 10; + safe_mutex_assert_owner(&LOCK_open); + (void) pthread_mutex_unlock(&LOCK_open); + int max_timeout= opt_ndb_sync_timeout; while (share->op) { struct timespec abstime; @@ -2770,6 +2796,7 @@ ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name, type_str, share->key); } } + (void) pthread_mutex_lock(&LOCK_open); (void) pthread_mutex_unlock(&share->mutex); #else (void) pthread_mutex_lock(&share->mutex); @@ -2777,6 +2804,7 @@ ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name, share->op= 0; (void) pthread_mutex_unlock(&share->mutex); #endif + thd->proc_info= save_proc_info; DBUG_RETURN(0); } diff --git a/sql/ha_ndbcluster_binlog.h b/sql/ha_ndbcluster_binlog.h index d82cdccb1b9..7c45dee59d0 100644 --- a/sql/ha_ndbcluster_binlog.h +++ b/sql/ha_ndbcluster_binlog.h @@ -138,8 +138,9 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share, uint32 ndb_table_id, uint32 ndb_table_version, enum SCHEMA_OP_TYPE type, - const char *new_db= 0, - const char *new_table_name= 0); + const char *new_db, + const char *new_table_name, + int have_lock_open); int ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name, NDB_SHARE *share, const char *type_str); From bf6d480aab57f01be4749eeb73cb5ea6be552e06 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 31 May 2006 10:28:42 +0200 Subject: [PATCH 18/32] Bug #16997 Table rename that changes database does not rename indexes: Moved index tables to system database --- mysql-test/r/ndb_rename.result | 24 +++++++++ mysql-test/t/ndb_rename.test | 36 +++++++++++++ sql/ha_ndbcluster.cc | 35 +++++++++++++ storage/ndb/include/ndbapi/Ndb.hpp | 5 ++ storage/ndb/include/ndbapi/NdbDictionary.hpp | 10 ++++ storage/ndb/src/ndbapi/Ndb.cpp | 33 +++++++++++- storage/ndb/src/ndbapi/NdbDictionary.cpp | 8 +++ storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp | 14 ++++- storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp | 55 +++++++++++++++++++- storage/ndb/src/ndbapi/NdbImpl.hpp | 2 + storage/ndb/src/ndbapi/Ndbinit.cpp | 3 ++ 11 files changed, 220 insertions(+), 5 deletions(-) create mode 100644 mysql-test/r/ndb_rename.result create mode 100644 mysql-test/t/ndb_rename.test diff --git a/mysql-test/r/ndb_rename.result b/mysql-test/r/ndb_rename.result new file mode 100644 index 00000000000..2cc2dfb3ff1 --- /dev/null +++ b/mysql-test/r/ndb_rename.result @@ -0,0 +1,24 @@ +DROP TABLE IF EXISTS t1,t2; +drop database if exists mysqltest; +CREATE TABLE t1 ( +pk1 INT NOT NULL PRIMARY KEY, +attr1 INT NOT NULL, +attr2 INT, +attr3 VARCHAR(10), +INDEX i1(attr1) +) ENGINE=ndbcluster; +INSERT INTO t1 VALUES (0,0,0,"zero"),(1,1,1,"one"),(2,2,2,"two"); +SELECT * FROM t1 WHERE attr1 = 1; +pk1 attr1 attr2 attr3 +1 1 1 one +alter table t1 rename t2; +SELECT * FROM t2 WHERE attr1 = 1; +pk1 attr1 attr2 attr3 +1 1 1 one +create database ndbtest; +alter table t2 rename ndbtest.t2; +SELECT * FROM ndbtest.t2 WHERE attr1 = 1; +pk1 attr1 attr2 attr3 +1 1 1 one +drop table ndbtest.t2; +drop database ndbtest; diff --git a/mysql-test/t/ndb_rename.test b/mysql-test/t/ndb_rename.test new file mode 100644 index 00000000000..7f9fd0e6984 --- /dev/null +++ b/mysql-test/t/ndb_rename.test @@ -0,0 +1,36 @@ +-- source include/have_ndb.inc +-- source include/not_embedded.inc + +--disable_warnings +DROP TABLE IF EXISTS t1,t2; +drop database if exists mysqltest; +--enable_warnings + +# +# Table rename tests +# + +# +# Create a normal table with primary key +# +CREATE TABLE t1 ( + pk1 INT NOT NULL PRIMARY KEY, + attr1 INT NOT NULL, + attr2 INT, + attr3 VARCHAR(10), + INDEX i1(attr1) +) ENGINE=ndbcluster; + +INSERT INTO t1 VALUES (0,0,0,"zero"),(1,1,1,"one"),(2,2,2,"two"); +SELECT * FROM t1 WHERE attr1 = 1; +alter table t1 rename t2; +SELECT * FROM t2 WHERE attr1 = 1; + +create database ndbtest; +alter table t2 rename ndbtest.t2; +SELECT * FROM ndbtest.t2 WHERE attr1 = 1; + +drop table ndbtest.t2; +drop database ndbtest; + +# End of 4.1 tests diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index f46a5eccabf..8634a30eae9 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -4922,13 +4922,17 @@ int ha_ndbcluster::rename_table(const char *from, const char *to) { NDBDICT *dict; char old_dbname[FN_HEADLEN]; + char new_dbname[FN_HEADLEN]; char new_tabname[FN_HEADLEN]; const NDBTAB *orig_tab; int result; + bool recreate_indexes= FALSE; + NDBDICT::List index_list; DBUG_ENTER("ha_ndbcluster::rename_table"); DBUG_PRINT("info", ("Renaming %s to %s", from, to)); set_dbname(from, old_dbname); + set_dbname(to, new_dbname); set_tabname(from); set_tabname(to, new_tabname); @@ -4953,6 +4957,11 @@ int ha_ndbcluster::rename_table(const char *from, const char *to) DBUG_ASSERT(r == 0); } #endif + if (my_strcasecmp(system_charset_info, new_dbname, old_dbname)) + { + dict->listIndexes(index_list, *orig_tab); + recreate_indexes= TRUE; + } // Change current database to that of target table set_dbname(to); ndb->setDatabaseName(m_dbname); @@ -5033,6 +5042,32 @@ int ha_ndbcluster::rename_table(const char *from, const char *to) SOT_RENAME_TABLE, m_dbname, new_tabname); } + + // If we are moving tables between databases, we need to recreate + // indexes + if (recreate_indexes) + { + for (unsigned i = 0; i < index_list.count; i++) + { + NDBDICT::List::Element& index_el = index_list.elements[i]; + // Recreate any indexes not stored in the system database + if (my_strcasecmp(system_charset_info, + index_el.database, NDB_SYSTEM_DATABASE)) + { + set_dbname(from); + ndb->setDatabaseName(m_dbname); + const NDBINDEX * index= dict->getIndexGlobal(index_el.name, new_tab); + DBUG_PRINT("info", ("Creating index %s/%s", + index_el.database, index->getName())); + dict->createIndex(*index, new_tab); + DBUG_PRINT("info", ("Dropping index %s/%s", + index_el.database, index->getName())); + set_dbname(from); + ndb->setDatabaseName(m_dbname); + dict->dropIndexGlobal(*index); + } + } + } if (share) free_share(&share); #endif diff --git a/storage/ndb/include/ndbapi/Ndb.hpp b/storage/ndb/include/ndbapi/Ndb.hpp index f6f313e9224..5c7a0cf30a9 100644 --- a/storage/ndb/include/ndbapi/Ndb.hpp +++ b/storage/ndb/include/ndbapi/Ndb.hpp @@ -1001,6 +1001,9 @@ typedef void (* NdbEventCallback)(NdbEventOperation*, Ndb*, void*); #define WAITFOR_RESPONSE_TIMEOUT 120000 // Milliseconds #endif +#define NDB_SYSTEM_DATABASE "sys" +#define NDB_SYSTEM_SCHEMA "def" + /** * @class Ndb * @brief Represents the NDB kernel and is the main class of the NDB API. @@ -1648,6 +1651,8 @@ private: const char * externalizeIndexName(const char * internalIndexName, bool fullyQualifiedNames); const char * externalizeIndexName(const char * internalIndexName); + const BaseString old_internalize_index_name(const NdbTableImpl * table, + const char * external_name) const; const BaseString internalize_index_name(const NdbTableImpl * table, const char * external_name) const; diff --git a/storage/ndb/include/ndbapi/NdbDictionary.hpp b/storage/ndb/include/ndbapi/NdbDictionary.hpp index 865fb506f05..27e0aede36d 100644 --- a/storage/ndb/include/ndbapi/NdbDictionary.hpp +++ b/storage/ndb/include/ndbapi/NdbDictionary.hpp @@ -1635,6 +1635,16 @@ public: int listIndexes(List & list, const char * tableName); int listIndexes(List & list, const char * tableName) const; +#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL + /** + * Fetch list of indexes of given table. + * @param list Reference to list where to store the listed indexes + * @param table Reference to table that index belongs to. + * @return 0 if successful, otherwise -1 + */ + int listIndexes(List & list, const Table &table) const; +#endif + /** @} *******************************************************************/ /** * @name Events diff --git a/storage/ndb/src/ndbapi/Ndb.cpp b/storage/ndb/src/ndbapi/Ndb.cpp index 0b0749c835e..ee121708cea 100644 --- a/storage/ndb/src/ndbapi/Ndb.cpp +++ b/storage/ndb/src/ndbapi/Ndb.cpp @@ -1196,6 +1196,35 @@ Ndb::internalize_table_name(const char *external_name) const DBUG_RETURN(ret); } +const BaseString +Ndb::old_internalize_index_name(const NdbTableImpl * table, + const char * external_name) const +{ + BaseString ret; + DBUG_ENTER("old_internalize_index_name"); + DBUG_PRINT("enter", ("external_name: %s, table_id: %d", + external_name, table ? table->m_id : ~0)); + if (!table) + { + DBUG_PRINT("error", ("!table")); + DBUG_RETURN(ret); + } + + if (fullyQualifiedNames) + { + /* Internal index name format /// */ + ret.assfmt("%s%d%c%s", + theImpl->m_prefix.c_str(), + table->m_id, + table_name_separator, + external_name); + } + else + ret.assign(external_name); + + DBUG_PRINT("exit", ("internal_name: %s", ret.c_str())); + DBUG_RETURN(ret); +} const BaseString Ndb::internalize_index_name(const NdbTableImpl * table, @@ -1213,9 +1242,9 @@ Ndb::internalize_index_name(const NdbTableImpl * table, if (fullyQualifiedNames) { - /* Internal index name format ///
*/ + /* Internal index name format sys/def//
*/ ret.assfmt("%s%d%c%s", - theImpl->m_prefix.c_str(), + theImpl->m_systemPrefix.c_str(), table->m_id, table_name_separator, external_name); diff --git a/storage/ndb/src/ndbapi/NdbDictionary.cpp b/storage/ndb/src/ndbapi/NdbDictionary.cpp index e844dc3369e..c71689d2e81 100644 --- a/storage/ndb/src/ndbapi/NdbDictionary.cpp +++ b/storage/ndb/src/ndbapi/NdbDictionary.cpp @@ -1618,6 +1618,14 @@ NdbDictionary::Dictionary::listIndexes(List& list, return m_impl.listIndexes(list, tab->getTableId()); } +int +NdbDictionary::Dictionary::listIndexes(List& list, + const NdbDictionary::Table &table) const +{ + return m_impl.listIndexes(list, table.getTableId()); +} + + const struct NdbError & NdbDictionary::Dictionary::getNdbError() const { return m_impl.getNdbError(); diff --git a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp index d2d8c43a064..250e7207ee7 100644 --- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp +++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp @@ -1512,9 +1512,21 @@ NdbTableImpl * NdbDictionaryImpl::getIndexTable(NdbIndexImpl * index, NdbTableImpl * table) { + const char *current_db= m_ndb.getDatabaseName(); + NdbTableImpl *index_table; const BaseString internalName( m_ndb.internalize_index_name(table, index->getName())); - return getTable(m_ndb.externalizeTableName(internalName.c_str())); + // Get index table in system database + m_ndb.setDatabaseName(NDB_SYSTEM_DATABASE); + index_table= getTable(m_ndb.externalizeTableName(internalName.c_str())); + m_ndb.setDatabaseName(current_db); + if (!index_table) + { + // Index table not found + // Try geting index table in current database (old format) + index_table= getTable(m_ndb.externalizeTableName(internalName.c_str())); + } + return index_table; } #if 0 diff --git a/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp b/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp index cf30abc6c3f..41647cea10d 100644 --- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp +++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp @@ -1022,6 +1022,33 @@ NdbDictionaryImpl::getIndexGlobal(const char * index_name, } break; } + { + // Index not found, try old format + const BaseString + old_internal_indexname(m_ndb.old_internalize_index_name(&ndbtab, + index_name)); + retry= 2; + while (retry) + { + NdbTableImpl *tab= + fetchGlobalTableImplRef(InitIndex(old_internal_indexname, + index_name, ndbtab)); + if (tab) + { + // tab->m_index sould be set. otherwise tab == 0 + NdbIndexImpl *idx= tab->m_index; + if (idx->m_table_id != (unsigned)ndbtab.getObjectId() || + idx->m_table_version != (unsigned)ndbtab.getObjectVersion()) + { + releaseIndexGlobal(*idx, 1); + retry--; + continue; + } + DBUG_RETURN(idx); + } + break; + } + } m_error.code= 4243; DBUG_RETURN(0); } @@ -1088,17 +1115,41 @@ NdbDictionaryImpl::getIndex(const char* index_name, index_name, prim)); if (!tab) - goto err; + goto retry; info= Ndb_local_table_info::create(tab, 0); if (!info) - goto err; + goto retry; m_localHash.put(internal_indexname.c_str(), info); } else tab= info->m_table_impl; return tab->m_index; + +retry: + // Index not found, try fetching it from current database + const BaseString + old_internal_indexname(m_ndb.old_internalize_index_name(&prim, index_name)); + + info= m_localHash.get(old_internal_indexname.c_str()); + if (info == 0) + { + tab= fetchGlobalTableImplRef(InitIndex(old_internal_indexname, + index_name, + prim)); + if (!tab) + goto err; + + info= Ndb_local_table_info::create(tab, 0); + if (!info) + goto err; + m_localHash.put(old_internal_indexname.c_str(), info); + } + else + tab= info->m_table_impl; + + return tab->m_index; err: m_error.code= 4243; diff --git a/storage/ndb/src/ndbapi/NdbImpl.hpp b/storage/ndb/src/ndbapi/NdbImpl.hpp index 82795550381..3b7b8cf44fb 100644 --- a/storage/ndb/src/ndbapi/NdbImpl.hpp +++ b/storage/ndb/src/ndbapi/NdbImpl.hpp @@ -93,6 +93,8 @@ public: m_schemaname.c_str(), table_name_separator); } + BaseString m_systemPrefix; // Buffer for preformatted for // + /** * NOTE free lists must be _after_ theNdbObjectIdMap take * assure that destructors are run in correct order diff --git a/storage/ndb/src/ndbapi/Ndbinit.cpp b/storage/ndb/src/ndbapi/Ndbinit.cpp index e41380e6484..a21f82676d9 100644 --- a/storage/ndb/src/ndbapi/Ndbinit.cpp +++ b/storage/ndb/src/ndbapi/Ndbinit.cpp @@ -223,6 +223,9 @@ NdbImpl::NdbImpl(Ndb_cluster_connection *ndb_cluster_connection, } m_optimized_node_selection= m_ndb_cluster_connection.m_optimized_node_selection; + + m_systemPrefix.assfmt("%s%c%s%c", NDB_SYSTEM_DATABASE, table_name_separator, + NDB_SYSTEM_SCHEMA, table_name_separator); } NdbImpl::~NdbImpl() From 3925a56ee009d6b9034c7f83af79ca818d75047d Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 31 May 2006 10:30:48 +0200 Subject: [PATCH 19/32] proper cleanup after the test --- mysql-test/r/ndb_dd_backuprestore.result | 7 +++++++ mysql-test/t/ndb_dd_backuprestore.test | 10 ++++++++++ 2 files changed, 17 insertions(+) diff --git a/mysql-test/r/ndb_dd_backuprestore.result b/mysql-test/r/ndb_dd_backuprestore.result index 8c39c8c582f..33edf6783e6 100644 --- a/mysql-test/r/ndb_dd_backuprestore.result +++ b/mysql-test/r/ndb_dd_backuprestore.result @@ -155,3 +155,10 @@ DROP TABLE test.t1; DROP TABLE test.t2; DROP TABLE test.t3; DROP TABLE test.t4; +ALTER TABLESPACE table_space1 +DROP DATAFILE './table_space1/datafile.dat' +ENGINE = NDB; +DROP TABLESPACE table_space1 +ENGINE = NDB; +DROP LOGFILE GROUP log_group1 +ENGINE =NDB; diff --git a/mysql-test/t/ndb_dd_backuprestore.test b/mysql-test/t/ndb_dd_backuprestore.test index 65f141288e7..1508cccb46d 100644 --- a/mysql-test/t/ndb_dd_backuprestore.test +++ b/mysql-test/t/ndb_dd_backuprestore.test @@ -160,4 +160,14 @@ DROP TABLE test.t2; DROP TABLE test.t3; DROP TABLE test.t4; +ALTER TABLESPACE table_space1 +DROP DATAFILE './table_space1/datafile.dat' +ENGINE = NDB; + +DROP TABLESPACE table_space1 +ENGINE = NDB; + +DROP LOGFILE GROUP log_group1 +ENGINE =NDB; + #End 5.1 test case From 50ddc348d3a3ce85724c09907c2a0dee1507daaf Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 31 May 2006 09:33:10 -0400 Subject: [PATCH 20/32] BUG#20161: LINEAR keyword on subpartitions not displayed in information schema for partitions and in SHOW CREATE TABLE mysql-test/r/information_schema_part.result: Added new test cases mysql-test/t/information_schema_part.test: Added new test cases sql/sql_partition.cc: Added missing check for LINEAR keyword on subpartitions sql/sql_show.cc: Added missing check for LINEAR keyword on subpartitions Small remove of duplicate code --- mysql-test/r/information_schema_part.result | 29 +++++++++++++++++++++ mysql-test/t/information_schema_part.test | 22 ++++++++++++++++ sql/sql_partition.cc | 2 ++ sql/sql_show.cc | 21 ++++++++------- 4 files changed, 65 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/information_schema_part.result b/mysql-test/r/information_schema_part.result index cf49abf888a..e1bc6ef8700 100644 --- a/mysql-test/r/information_schema_part.result +++ b/mysql-test/r/information_schema_part.result @@ -111,3 +111,32 @@ NULL test t1 p0 NULL 1 NULL LINEAR HASH NULL month(f1) NULL NULL 0 0 0 # 1024 0 NULL test t1 p1 NULL 2 NULL LINEAR HASH NULL month(f1) NULL NULL 0 0 0 # 1024 0 # # NULL NULL default 0 default NULL test t1 p2 NULL 3 NULL LINEAR HASH NULL month(f1) NULL NULL 0 0 0 # 1024 0 # # NULL NULL default 0 default drop table t1; +create table t1 (a int) +PARTITION BY RANGE (a) +SUBPARTITION BY LINEAR HASH (a) +(PARTITION p0 VALUES LESS THAN (10)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY RANGE (a) SUBPARTITION BY LINEAR HASH (a) (PARTITION p0 VALUES LESS THAN (10) ) +select SUBPARTITION_METHOD FROM information_schema.partitions WHERE +table_schema="test" AND table_name="t1"; +SUBPARTITION_METHOD +LINEAR HASH +drop table t1; +create table t1 (a int) +PARTITION BY LIST (a) +(PARTITION p0 VALUES IN +(10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, +32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY LIST (a) (PARTITION p0 VALUES IN (10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53) ENGINE = MyISAM) +SELECT PARTITION_DESCRIPTION FROM information_schema.partitions WHERE +table_schema = "test" AND table_name = "t1"; +PARTITION_DESCRIPTION +10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53 +drop table t1; diff --git a/mysql-test/t/information_schema_part.test b/mysql-test/t/information_schema_part.test index 163b04248b8..4cbf21ca1d3 100644 --- a/mysql-test/t/information_schema_part.test +++ b/mysql-test/t/information_schema_part.test @@ -99,3 +99,25 @@ select * from information_schema.partitions where table_schema="test" and table_name="t1"; drop table t1; +# +# Bug 20161 Partitions: SUBPARTITION METHOD doesn't show LINEAR keyword +# +create table t1 (a int) +PARTITION BY RANGE (a) +SUBPARTITION BY LINEAR HASH (a) +(PARTITION p0 VALUES LESS THAN (10)); + +SHOW CREATE TABLE t1; +select SUBPARTITION_METHOD FROM information_schema.partitions WHERE +table_schema="test" AND table_name="t1"; +drop table t1; + +create table t1 (a int) +PARTITION BY LIST (a) +(PARTITION p0 VALUES IN +(10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, + 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53)); +SHOW CREATE TABLE t1; +SELECT PARTITION_DESCRIPTION FROM information_schema.partitions WHERE +table_schema = "test" AND table_name = "t1"; +drop table t1; diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index e946e972968..f6346821be2 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1843,6 +1843,8 @@ char *generate_partition_syntax(partition_info *part_info, { err+= add_subpartition_by(fptr); /* Must be hash partitioning for subpartitioning */ + if (part_info->linear_hash_ind) + err+= add_string(fptr, partition_keywords[PKW_LINEAR].str); if (part_info->list_of_subpart_fields) err+= add_key_partition(fptr, part_info->subpart_field_list); else diff --git a/sql/sql_show.cc b/sql/sql_show.cc index ac1825d7c84..c2d4904eb1b 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -3911,24 +3911,28 @@ static int get_schema_partitions_record(THD *thd, struct st_table_list *tables, { table->field[9]->store(part_info->part_func_string, part_info->part_func_len, cs); - table->field[9]->set_notnull(); } else if (part_info->list_of_part_fields) { collect_partition_expr(part_info->part_field_list, &tmp_str); table->field[9]->store(tmp_str.ptr(), tmp_str.length(), cs); - table->field[9]->set_notnull(); } + table->field[9]->set_notnull(); if (part_info->is_sub_partitioned()) { /* Subpartition method */ + tmp_res.length(0); + if (part_info->linear_hash_ind) + tmp_res.append(partition_keywords[PKW_LINEAR].str, + partition_keywords[PKW_LINEAR].length); if (part_info->list_of_subpart_fields) - table->field[8]->store(partition_keywords[PKW_KEY].str, - partition_keywords[PKW_KEY].length, cs); + tmp_res.append(partition_keywords[PKW_KEY].str, + partition_keywords[PKW_KEY].length); else - table->field[8]->store(partition_keywords[PKW_HASH].str, - partition_keywords[PKW_HASH].length, cs); + tmp_res.append(partition_keywords[PKW_HASH].str, + partition_keywords[PKW_HASH].length); + table->field[8]->store(tmp_res.ptr(), tmp_res.length(), cs); table->field[8]->set_notnull(); /* Subpartition expression */ @@ -3936,14 +3940,13 @@ static int get_schema_partitions_record(THD *thd, struct st_table_list *tables, { table->field[10]->store(part_info->subpart_func_string, part_info->subpart_func_len, cs); - table->field[10]->set_notnull(); } else if (part_info->list_of_subpart_fields) { collect_partition_expr(part_info->subpart_field_list, &tmp_str); table->field[10]->store(tmp_str.ptr(), tmp_str.length(), cs); - table->field[10]->set_notnull(); } + table->field[10]->set_notnull(); } while ((part_elem= part_it++)) @@ -5241,7 +5244,7 @@ ST_FIELD_INFO partitions_fields_info[]= {"PARTITION_ORDINAL_POSITION", 21 , MYSQL_TYPE_LONG, 0, 1, 0}, {"SUBPARTITION_ORDINAL_POSITION", 21 , MYSQL_TYPE_LONG, 0, 1, 0}, {"PARTITION_METHOD", 12, MYSQL_TYPE_STRING, 0, 1, 0}, - {"SUBPARTITION_METHOD", 5, MYSQL_TYPE_STRING, 0, 1, 0}, + {"SUBPARTITION_METHOD", 12, MYSQL_TYPE_STRING, 0, 1, 0}, {"PARTITION_EXPRESSION", 65535, MYSQL_TYPE_STRING, 0, 1, 0}, {"SUBPARTITION_EXPRESSION", 65535, MYSQL_TYPE_STRING, 0, 1, 0}, {"PARTITION_DESCRIPTION", 65535, MYSQL_TYPE_STRING, 0, 1, 0}, From 2f333aae1fd2045b5c11d37995bd1346d887c171 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 31 May 2006 16:16:03 +0200 Subject: [PATCH 21/32] Bug #18947 CRBR: order in binlog of create table and insert (on different table) not determ - wait for schema event also if mysqld is a single one in cluster to ensure serialization with data events + some current_thd removals + enabling kill of sql thread during shema sync wait mysql-test/r/rpl_ndb_log.result: Bug #18947 CRBR: order in binlog of create table and insert (on different table) not determ mysql-test/t/disabled.def: Bug #18947 CRBR: order in binlog of create table and insert (on different table) not determ --- mysql-test/r/rpl_ndb_log.result | 4 + mysql-test/t/disabled.def | 2 +- sql/ha_ndbcluster.cc | 15 +- sql/ha_ndbcluster_binlog.cc | 816 ++++++++++++++++---------------- 4 files changed, 434 insertions(+), 403 deletions(-) diff --git a/mysql-test/r/rpl_ndb_log.result b/mysql-test/r/rpl_ndb_log.result index 5f6f040b715..c435fb37531 100644 --- a/mysql-test/r/rpl_ndb_log.result +++ b/mysql-test/r/rpl_ndb_log.result @@ -47,6 +47,10 @@ master-bin.000001 # Table_map 1 # table_id: # (test.t1) flush logs; create table t3 (a int)ENGINE=NDB; start slave; + +let $result_pattern= '%127.0.0.1%root%master-bin.000002%slave-relay-bin.000005%Yes%Yes%0%0%None%' ; + +--source include/wait_slave_status.inc flush logs; stop slave; create table t2 (n int)ENGINE=NDB; diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 562006c7687..b4e37825326 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -29,7 +29,7 @@ rpl_ndb_commit_afterflush : BUG#19328 2006-05-04 tomas Slave timeout with COM_RE rpl_ndb_dd_partitions : BUG#19259 2006-04-21 rpl_ndb_dd_partitions fails on s/AMD rpl_ndb_ddl : BUG#18946 result file needs update + test needs to checked rpl_ndb_innodb2ndb : Bug #19710 Cluster replication to partition table fails on DELETE FROM statement -rpl_ndb_log : BUG#18947 2006-03-21 tomas CRBR: order in binlog of create table and insert (on different table) not determ +#rpl_ndb_log : BUG#18947 2006-03-21 tomas CRBR: order in binlog of create table and insert (on different table) not determ rpl_ndb_myisam2ndb : Bug #19710 Cluster replication to partition table fails on DELETE FROM statement rpl_switch_stm_row_mixed : BUG#18590 2006-03-28 brian rpl_row_blob_innodb : BUG#18980 2006-04-10 kent Test fails randomly diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 8b3ff56a847..787bc07f1f7 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -5054,6 +5054,7 @@ ha_ndbcluster::delete_table(ha_ndbcluster *h, Ndb *ndb, const char *db, const char *table_name) { + THD *thd= current_thd; DBUG_ENTER("ha_ndbcluster::ndbcluster_delete_table"); NDBDICT *dict= ndb->getDictionary(); #ifdef HAVE_NDB_BINLOG @@ -5085,7 +5086,7 @@ ha_ndbcluster::delete_table(ha_ndbcluster *h, Ndb *ndb, ndb_table_version= h->m_table->getObjectVersion(); } #endif - h->release_metadata(current_thd, ndb); + h->release_metadata(thd, ndb); } else { @@ -5151,8 +5152,8 @@ ha_ndbcluster::delete_table(ha_ndbcluster *h, Ndb *ndb, if (!IS_TMP_PREFIX(table_name) && share) { - ndbcluster_log_schema_op(current_thd, share, - current_thd->query, current_thd->query_length, + ndbcluster_log_schema_op(thd, share, + thd->query, thd->query_length, share->db, share->table_name, ndb_table_id, ndb_table_version, SOT_DROP_TABLE, 0, 0, 1); @@ -5733,6 +5734,7 @@ int ndbcluster_drop_database_impl(const char *path) static void ndbcluster_drop_database(char *path) { + THD *thd= current_thd; DBUG_ENTER("ndbcluster_drop_database"); #ifdef HAVE_NDB_BINLOG /* @@ -5750,8 +5752,8 @@ static void ndbcluster_drop_database(char *path) #ifdef HAVE_NDB_BINLOG char db[FN_REFLEN]; ha_ndbcluster::set_dbname(path, db); - ndbcluster_log_schema_op(current_thd, 0, - current_thd->query, current_thd->query_length, + ndbcluster_log_schema_op(thd, 0, + thd->query, thd->query_length, db, "", 0, 0, SOT_DROP_DB, 0, 0, 0); #endif DBUG_VOID_RETURN; @@ -6827,6 +6829,7 @@ static void dbug_print_open_tables() */ int handle_trailing_share(NDB_SHARE *share) { + THD *thd= current_thd; static ulong trailing_share_id= 0; DBUG_ENTER("handle_trailing_share"); @@ -6837,7 +6840,7 @@ int handle_trailing_share(NDB_SHARE *share) bzero((char*) &table_list,sizeof(table_list)); table_list.db= share->db; table_list.alias= table_list.table_name= share->table_name; - close_cached_tables(current_thd, 0, &table_list, TRUE); + close_cached_tables(thd, 0, &table_list, TRUE); pthread_mutex_lock(&ndbcluster_mutex); if (!--share->use_count) diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index 452be961235..48273320cc0 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -972,364 +972,6 @@ static char *ndb_pack_varchar(const NDBCOL *col, char *buf, return buf; } -/* - log query in schema table -*/ -static void ndb_report_waiting(const char *key, - int the_time, - const char *op, - const char *obj) -{ - ulonglong ndb_latest_epoch= 0; - const char *proc_info= ""; - pthread_mutex_lock(&injector_mutex); - if (injector_ndb) - ndb_latest_epoch= injector_ndb->getLatestGCI(); - if (injector_thd) - proc_info= injector_thd->proc_info; - pthread_mutex_unlock(&injector_mutex); - sql_print_information("NDB %s:" - " waiting max %u sec for %s %s." - " epochs: (%u,%u,%u)" - " injector proc_info: %s" - ,key, the_time, op, obj - ,(uint)ndb_latest_handled_binlog_epoch - ,(uint)ndb_latest_received_binlog_epoch - ,(uint)ndb_latest_epoch - ,proc_info - ); -} - -int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share, - const char *query, int query_length, - const char *db, const char *table_name, - uint32 ndb_table_id, - uint32 ndb_table_version, - enum SCHEMA_OP_TYPE type, - const char *new_db, const char *new_table_name, - int have_lock_open) -{ - DBUG_ENTER("ndbcluster_log_schema_op"); - Thd_ndb *thd_ndb= get_thd_ndb(thd); - if (!thd_ndb) - { - if (!(thd_ndb= ha_ndbcluster::seize_thd_ndb())) - { - sql_print_error("Could not allocate Thd_ndb object"); - DBUG_RETURN(1); - } - set_thd_ndb(thd, thd_ndb); - } - - DBUG_PRINT("enter", - ("query: %s db: %s table_name: %s thd_ndb->options: %d", - query, db, table_name, thd_ndb->options)); - if (!schema_share || thd_ndb->options & TNO_NO_LOG_SCHEMA_OP) - { - DBUG_RETURN(0); - } - - char tmp_buf2[FN_REFLEN]; - const char *type_str; - switch (type) - { - case SOT_DROP_TABLE: - /* drop database command, do not log at drop table */ - if (thd->lex->sql_command == SQLCOM_DROP_DB) - DBUG_RETURN(0); - /* redo the drop table query as is may contain several tables */ - query= tmp_buf2; - query_length= (uint) (strxmov(tmp_buf2, "drop table `", - table_name, "`", NullS) - tmp_buf2); - type_str= "drop table"; - break; - case SOT_RENAME_TABLE: - /* redo the rename table query as is may contain several tables */ - query= tmp_buf2; - query_length= (uint) (strxmov(tmp_buf2, "rename table `", - db, ".", table_name, "` to `", - new_db, ".", new_table_name, "`", NullS) - tmp_buf2); - type_str= "rename table"; - break; - case SOT_CREATE_TABLE: - type_str= "create table"; - break; - case SOT_ALTER_TABLE: - type_str= "create table"; - break; - case SOT_DROP_DB: - type_str= "drop db"; - break; - case SOT_CREATE_DB: - type_str= "create db"; - break; - case SOT_ALTER_DB: - type_str= "alter db"; - break; - case SOT_TABLESPACE: - type_str= "tablespace"; - break; - case SOT_LOGFILE_GROUP: - type_str= "logfile group"; - break; - default: - abort(); /* should not happen, programming error */ - } - - NDB_SCHEMA_OBJECT *ndb_schema_object; - { - char key[FN_REFLEN]; - build_table_filename(key, sizeof(key), db, table_name, ""); - ndb_schema_object= ndb_get_schema_object(key, TRUE, FALSE); - } - - const NdbError *ndb_error= 0; - uint32 node_id= g_ndb_cluster_connection->node_id(); - Uint64 epoch= 0; - MY_BITMAP schema_subscribers; - uint32 bitbuf[sizeof(ndb_schema_object->slock)/4]; - uint32 bitbuf_e[sizeof(bitbuf)]; - bzero((char *)bitbuf_e, sizeof(bitbuf_e)); - { - int i, updated= 0; - int no_storage_nodes= g_ndb_cluster_connection->no_db_nodes(); - bitmap_init(&schema_subscribers, bitbuf, sizeof(bitbuf)*8, false); - bitmap_set_all(&schema_subscribers); - (void) pthread_mutex_lock(&schema_share->mutex); - for (i= 0; i < no_storage_nodes; i++) - { - MY_BITMAP *table_subscribers= &schema_share->subscriber_bitmap[i]; - if (!bitmap_is_clear_all(table_subscribers)) - { - bitmap_intersect(&schema_subscribers, - table_subscribers); - updated= 1; - } - } - (void) pthread_mutex_unlock(&schema_share->mutex); - if (updated) - bitmap_clear_bit(&schema_subscribers, node_id); - else - bitmap_clear_all(&schema_subscribers); - - if (ndb_schema_object) - { - (void) pthread_mutex_lock(&ndb_schema_object->mutex); - memcpy(ndb_schema_object->slock, schema_subscribers.bitmap, - sizeof(ndb_schema_object->slock)); - (void) pthread_mutex_unlock(&ndb_schema_object->mutex); - } - - DBUG_DUMP("schema_subscribers", (char*)schema_subscribers.bitmap, - no_bytes_in_map(&schema_subscribers)); - DBUG_PRINT("info", ("bitmap_is_clear_all(&schema_subscribers): %d", - bitmap_is_clear_all(&schema_subscribers))); - } - - Ndb *ndb= thd_ndb->ndb; - char save_db[FN_REFLEN]; - strcpy(save_db, ndb->getDatabaseName()); - - char tmp_buf[FN_REFLEN]; - NDBDICT *dict= ndb->getDictionary(); - ndb->setDatabaseName(NDB_REP_DB); - Ndb_table_guard ndbtab_g(dict, NDB_SCHEMA_TABLE); - const NDBTAB *ndbtab= ndbtab_g.get_table(); - NdbTransaction *trans= 0; - int retries= 100; - const NDBCOL *col[SCHEMA_SIZE]; - unsigned sz[SCHEMA_SIZE]; - - if (ndbtab == 0) - { - if (strcmp(NDB_REP_DB, db) != 0 || - strcmp(NDB_SCHEMA_TABLE, table_name)) - { - ndb_error= &dict->getNdbError(); - } - goto end; - } - - { - uint i; - for (i= 0; i < SCHEMA_SIZE; i++) - { - col[i]= ndbtab->getColumn(i); - if (i != SCHEMA_QUERY_I) - { - sz[i]= col[i]->getLength(); - DBUG_ASSERT(sz[i] <= sizeof(tmp_buf)); - } - } - } - - while (1) - { - const char *log_db= db; - const char *log_tab= table_name; - const char *log_subscribers= (char*)schema_subscribers.bitmap; - uint32 log_type= (uint32)type; - if ((trans= ndb->startTransaction()) == 0) - goto err; - while (1) - { - NdbOperation *op= 0; - int r= 0; - r|= (op= trans->getNdbOperation(ndbtab)) == 0; - DBUG_ASSERT(r == 0); - r|= op->writeTuple(); - DBUG_ASSERT(r == 0); - - /* db */ - ndb_pack_varchar(col[SCHEMA_DB_I], tmp_buf, log_db, strlen(log_db)); - r|= op->equal(SCHEMA_DB_I, tmp_buf); - DBUG_ASSERT(r == 0); - /* name */ - ndb_pack_varchar(col[SCHEMA_NAME_I], tmp_buf, log_tab, - strlen(log_tab)); - r|= op->equal(SCHEMA_NAME_I, tmp_buf); - DBUG_ASSERT(r == 0); - /* slock */ - DBUG_ASSERT(sz[SCHEMA_SLOCK_I] == sizeof(bitbuf)); - r|= op->setValue(SCHEMA_SLOCK_I, log_subscribers); - DBUG_ASSERT(r == 0); - /* query */ - { - NdbBlob *ndb_blob= op->getBlobHandle(SCHEMA_QUERY_I); - DBUG_ASSERT(ndb_blob != 0); - uint blob_len= query_length; - const char* blob_ptr= query; - r|= ndb_blob->setValue(blob_ptr, blob_len); - DBUG_ASSERT(r == 0); - } - /* node_id */ - r|= op->setValue(SCHEMA_NODE_ID_I, node_id); - DBUG_ASSERT(r == 0); - /* epoch */ - r|= op->setValue(SCHEMA_EPOCH_I, epoch); - DBUG_ASSERT(r == 0); - /* id */ - r|= op->setValue(SCHEMA_ID_I, ndb_table_id); - DBUG_ASSERT(r == 0); - /* version */ - r|= op->setValue(SCHEMA_VERSION_I, ndb_table_version); - DBUG_ASSERT(r == 0); - /* type */ - r|= op->setValue(SCHEMA_TYPE_I, log_type); - DBUG_ASSERT(r == 0); - if (log_db != new_db && new_db && new_table_name) - { - log_db= new_db; - log_tab= new_table_name; - log_subscribers= (const char *)bitbuf_e; // no ack expected on this - log_type= (uint32)SOT_RENAME_TABLE_NEW; - continue; - } - break; - } - if (trans->execute(NdbTransaction::Commit) == 0) - { - dict->forceGCPWait(); - DBUG_PRINT("info", ("logged: %s", query)); - break; - } -err: - const NdbError *this_error= trans ? - &trans->getNdbError() : &ndb->getNdbError(); - if (this_error->status == NdbError::TemporaryError) - { - if (retries--) - { - if (trans) - ndb->closeTransaction(trans); - continue; // retry - } - } - ndb_error= this_error; - break; - } -end: - if (ndb_error) - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, - ER_GET_ERRMSG, ER(ER_GET_ERRMSG), - ndb_error->code, - ndb_error->message, - "Could not log query '%s' on other mysqld's"); - - if (trans) - ndb->closeTransaction(trans); - ndb->setDatabaseName(save_db); - - /* - Wait for other mysqld's to acknowledge the table operation - */ - if (ndb_error == 0 && - !bitmap_is_clear_all(&schema_subscribers)) - { - int max_timeout= opt_ndb_sync_timeout; - (void) pthread_mutex_lock(&ndb_schema_object->mutex); - if (have_lock_open) - { - safe_mutex_assert_owner(&LOCK_open); - (void) pthread_mutex_unlock(&LOCK_open); - } - while (1) - { - struct timespec abstime; - int i; - int no_storage_nodes= g_ndb_cluster_connection->no_db_nodes(); - set_timespec(abstime, 1); - int ret= pthread_cond_timedwait(&injector_cond, - &ndb_schema_object->mutex, - &abstime); - - (void) pthread_mutex_lock(&schema_share->mutex); - for (i= 0; i < no_storage_nodes; i++) - { - /* remove any unsubscribed from schema_subscribers */ - MY_BITMAP *tmp= &schema_share->subscriber_bitmap[i]; - if (!bitmap_is_clear_all(tmp)) - bitmap_intersect(&schema_subscribers, tmp); - } - (void) pthread_mutex_unlock(&schema_share->mutex); - - /* remove any unsubscribed from ndb_schema_object->slock */ - bitmap_intersect(&ndb_schema_object->slock_bitmap, &schema_subscribers); - - DBUG_DUMP("ndb_schema_object->slock_bitmap.bitmap", - (char*)ndb_schema_object->slock_bitmap.bitmap, - no_bytes_in_map(&ndb_schema_object->slock_bitmap)); - - if (bitmap_is_clear_all(&ndb_schema_object->slock_bitmap)) - break; - - if (ret) - { - max_timeout--; - if (max_timeout == 0) - { - sql_print_error("NDB %s: distributing %s timed out. Ignoring...", - type_str, ndb_schema_object->key); - break; - } - if (ndb_extra_logging) - ndb_report_waiting(type_str, max_timeout, - "distributing", ndb_schema_object->key); - } - } - if (have_lock_open) - { - (void) pthread_mutex_lock(&LOCK_open); - } - (void) pthread_mutex_unlock(&ndb_schema_object->mutex); - } - - if (ndb_schema_object) - ndb_free_schema_object(&ndb_schema_object, FALSE); - - DBUG_RETURN(0); -} - /* acknowledge handling of schema operation */ @@ -1466,7 +1108,7 @@ ndbcluster_update_slock(THD *thd, } end: if (ndb_error) - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_GET_ERRMSG, ER(ER_GET_ERRMSG), ndb_error->code, ndb_error->message, @@ -1478,6 +1120,383 @@ end: DBUG_RETURN(0); } +/* + log query in schema table +*/ +static void ndb_report_waiting(const char *key, + int the_time, + const char *op, + const char *obj) +{ + ulonglong ndb_latest_epoch= 0; + const char *proc_info= ""; + pthread_mutex_lock(&injector_mutex); + if (injector_ndb) + ndb_latest_epoch= injector_ndb->getLatestGCI(); + if (injector_thd) + proc_info= injector_thd->proc_info; + pthread_mutex_unlock(&injector_mutex); + sql_print_information("NDB %s:" + " waiting max %u sec for %s %s." + " epochs: (%u,%u,%u)" + " injector proc_info: %s" + ,key, the_time, op, obj + ,(uint)ndb_latest_handled_binlog_epoch + ,(uint)ndb_latest_received_binlog_epoch + ,(uint)ndb_latest_epoch + ,proc_info + ); +} + +int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share, + const char *query, int query_length, + const char *db, const char *table_name, + uint32 ndb_table_id, + uint32 ndb_table_version, + enum SCHEMA_OP_TYPE type, + const char *new_db, const char *new_table_name, + int have_lock_open) +{ + DBUG_ENTER("ndbcluster_log_schema_op"); + Thd_ndb *thd_ndb= get_thd_ndb(thd); + if (!thd_ndb) + { + if (!(thd_ndb= ha_ndbcluster::seize_thd_ndb())) + { + sql_print_error("Could not allocate Thd_ndb object"); + DBUG_RETURN(1); + } + set_thd_ndb(thd, thd_ndb); + } + + DBUG_PRINT("enter", + ("query: %s db: %s table_name: %s thd_ndb->options: %d", + query, db, table_name, thd_ndb->options)); + if (!schema_share || thd_ndb->options & TNO_NO_LOG_SCHEMA_OP) + { + DBUG_RETURN(0); + } + + char tmp_buf2[FN_REFLEN]; + const char *type_str; + switch (type) + { + case SOT_DROP_TABLE: + /* drop database command, do not log at drop table */ + if (thd->lex->sql_command == SQLCOM_DROP_DB) + DBUG_RETURN(0); + /* redo the drop table query as is may contain several tables */ + query= tmp_buf2; + query_length= (uint) (strxmov(tmp_buf2, "drop table `", + table_name, "`", NullS) - tmp_buf2); + type_str= "drop table"; + break; + case SOT_RENAME_TABLE: + /* redo the rename table query as is may contain several tables */ + query= tmp_buf2; + query_length= (uint) (strxmov(tmp_buf2, "rename table `", + db, ".", table_name, "` to `", + new_db, ".", new_table_name, "`", NullS) - tmp_buf2); + type_str= "rename table"; + break; + case SOT_CREATE_TABLE: + type_str= "create table"; + break; + case SOT_ALTER_TABLE: + type_str= "create table"; + break; + case SOT_DROP_DB: + type_str= "drop db"; + break; + case SOT_CREATE_DB: + type_str= "create db"; + break; + case SOT_ALTER_DB: + type_str= "alter db"; + break; + case SOT_TABLESPACE: + type_str= "tablespace"; + break; + case SOT_LOGFILE_GROUP: + type_str= "logfile group"; + break; + default: + abort(); /* should not happen, programming error */ + } + + NDB_SCHEMA_OBJECT *ndb_schema_object; + { + char key[FN_REFLEN]; + build_table_filename(key, sizeof(key), db, table_name, ""); + ndb_schema_object= ndb_get_schema_object(key, TRUE, FALSE); + } + + const NdbError *ndb_error= 0; + uint32 node_id= g_ndb_cluster_connection->node_id(); + Uint64 epoch= 0; + MY_BITMAP schema_subscribers; + uint32 bitbuf[sizeof(ndb_schema_object->slock)/4]; + char bitbuf_e[sizeof(bitbuf)]; + bzero(bitbuf_e, sizeof(bitbuf_e)); + { + int i, updated= 0; + int no_storage_nodes= g_ndb_cluster_connection->no_db_nodes(); + bitmap_init(&schema_subscribers, bitbuf, sizeof(bitbuf)*8, false); + bitmap_set_all(&schema_subscribers); + (void) pthread_mutex_lock(&schema_share->mutex); + for (i= 0; i < no_storage_nodes; i++) + { + MY_BITMAP *table_subscribers= &schema_share->subscriber_bitmap[i]; + if (!bitmap_is_clear_all(table_subscribers)) + { + bitmap_intersect(&schema_subscribers, + table_subscribers); + updated= 1; + } + } + (void) pthread_mutex_unlock(&schema_share->mutex); + if (updated) + { + bitmap_clear_bit(&schema_subscribers, node_id); + /* + if setting own acknowledge bit it is important that + no other mysqld's are registred, as subsequent code + will cause the original event to be hidden (by blob + merge event code) + */ + if (bitmap_is_clear_all(&schema_subscribers)) + bitmap_set_bit(&schema_subscribers, node_id); + } + else + bitmap_clear_all(&schema_subscribers); + + if (ndb_schema_object) + { + (void) pthread_mutex_lock(&ndb_schema_object->mutex); + memcpy(ndb_schema_object->slock, schema_subscribers.bitmap, + sizeof(ndb_schema_object->slock)); + (void) pthread_mutex_unlock(&ndb_schema_object->mutex); + } + + DBUG_DUMP("schema_subscribers", (char*)schema_subscribers.bitmap, + no_bytes_in_map(&schema_subscribers)); + DBUG_PRINT("info", ("bitmap_is_clear_all(&schema_subscribers): %d", + bitmap_is_clear_all(&schema_subscribers))); + } + + Ndb *ndb= thd_ndb->ndb; + char save_db[FN_REFLEN]; + strcpy(save_db, ndb->getDatabaseName()); + + char tmp_buf[FN_REFLEN]; + NDBDICT *dict= ndb->getDictionary(); + ndb->setDatabaseName(NDB_REP_DB); + Ndb_table_guard ndbtab_g(dict, NDB_SCHEMA_TABLE); + const NDBTAB *ndbtab= ndbtab_g.get_table(); + NdbTransaction *trans= 0; + int retries= 100; + const NDBCOL *col[SCHEMA_SIZE]; + unsigned sz[SCHEMA_SIZE]; + + if (ndbtab == 0) + { + if (strcmp(NDB_REP_DB, db) != 0 || + strcmp(NDB_SCHEMA_TABLE, table_name)) + { + ndb_error= &dict->getNdbError(); + } + goto end; + } + + { + uint i; + for (i= 0; i < SCHEMA_SIZE; i++) + { + col[i]= ndbtab->getColumn(i); + if (i != SCHEMA_QUERY_I) + { + sz[i]= col[i]->getLength(); + DBUG_ASSERT(sz[i] <= sizeof(tmp_buf)); + } + } + } + + while (1) + { + const char *log_db= db; + const char *log_tab= table_name; + const char *log_subscribers= (char*)schema_subscribers.bitmap; + uint32 log_type= (uint32)type; + if ((trans= ndb->startTransaction()) == 0) + goto err; + while (1) + { + NdbOperation *op= 0; + int r= 0; + r|= (op= trans->getNdbOperation(ndbtab)) == 0; + DBUG_ASSERT(r == 0); + r|= op->writeTuple(); + DBUG_ASSERT(r == 0); + + /* db */ + ndb_pack_varchar(col[SCHEMA_DB_I], tmp_buf, log_db, strlen(log_db)); + r|= op->equal(SCHEMA_DB_I, tmp_buf); + DBUG_ASSERT(r == 0); + /* name */ + ndb_pack_varchar(col[SCHEMA_NAME_I], tmp_buf, log_tab, + strlen(log_tab)); + r|= op->equal(SCHEMA_NAME_I, tmp_buf); + DBUG_ASSERT(r == 0); + /* slock */ + DBUG_ASSERT(sz[SCHEMA_SLOCK_I] == sizeof(bitbuf)); + r|= op->setValue(SCHEMA_SLOCK_I, log_subscribers); + DBUG_ASSERT(r == 0); + /* query */ + { + NdbBlob *ndb_blob= op->getBlobHandle(SCHEMA_QUERY_I); + DBUG_ASSERT(ndb_blob != 0); + uint blob_len= query_length; + const char* blob_ptr= query; + r|= ndb_blob->setValue(blob_ptr, blob_len); + DBUG_ASSERT(r == 0); + } + /* node_id */ + r|= op->setValue(SCHEMA_NODE_ID_I, node_id); + DBUG_ASSERT(r == 0); + /* epoch */ + r|= op->setValue(SCHEMA_EPOCH_I, epoch); + DBUG_ASSERT(r == 0); + /* id */ + r|= op->setValue(SCHEMA_ID_I, ndb_table_id); + DBUG_ASSERT(r == 0); + /* version */ + r|= op->setValue(SCHEMA_VERSION_I, ndb_table_version); + DBUG_ASSERT(r == 0); + /* type */ + r|= op->setValue(SCHEMA_TYPE_I, log_type); + DBUG_ASSERT(r == 0); + if (log_db != new_db && new_db && new_table_name) + { + log_db= new_db; + log_tab= new_table_name; + log_subscribers= bitbuf_e; // no ack expected on this + log_type= (uint32)SOT_RENAME_TABLE_NEW; + continue; + } + break; + } + if (trans->execute(NdbTransaction::Commit) == 0) + { + DBUG_PRINT("info", ("logged: %s", query)); + break; + } +err: + const NdbError *this_error= trans ? + &trans->getNdbError() : &ndb->getNdbError(); + if (this_error->status == NdbError::TemporaryError) + { + if (retries--) + { + if (trans) + ndb->closeTransaction(trans); + continue; // retry + } + } + ndb_error= this_error; + break; + } +end: + if (ndb_error) + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + ER_GET_ERRMSG, ER(ER_GET_ERRMSG), + ndb_error->code, + ndb_error->message, + "Could not log query '%s' on other mysqld's"); + + if (trans) + ndb->closeTransaction(trans); + ndb->setDatabaseName(save_db); + + /* + Wait for other mysqld's to acknowledge the table operation + */ + if (ndb_error == 0 && + !bitmap_is_clear_all(&schema_subscribers)) + { + /* + if own nodeid is set we are a single mysqld registred + as an optimization we update the slock directly + */ + if (bitmap_is_set(&schema_subscribers, node_id)) + ndbcluster_update_slock(thd, db, table_name); + else + dict->forceGCPWait(); + + int max_timeout= opt_ndb_sync_timeout; + (void) pthread_mutex_lock(&ndb_schema_object->mutex); + if (have_lock_open) + { + safe_mutex_assert_owner(&LOCK_open); + (void) pthread_mutex_unlock(&LOCK_open); + } + while (1) + { + struct timespec abstime; + int i; + int no_storage_nodes= g_ndb_cluster_connection->no_db_nodes(); + set_timespec(abstime, 1); + int ret= pthread_cond_timedwait(&injector_cond, + &ndb_schema_object->mutex, + &abstime); + if (thd->killed) + break; + (void) pthread_mutex_lock(&schema_share->mutex); + for (i= 0; i < no_storage_nodes; i++) + { + /* remove any unsubscribed from schema_subscribers */ + MY_BITMAP *tmp= &schema_share->subscriber_bitmap[i]; + if (!bitmap_is_clear_all(tmp)) + bitmap_intersect(&schema_subscribers, tmp); + } + (void) pthread_mutex_unlock(&schema_share->mutex); + + /* remove any unsubscribed from ndb_schema_object->slock */ + bitmap_intersect(&ndb_schema_object->slock_bitmap, &schema_subscribers); + + DBUG_DUMP("ndb_schema_object->slock_bitmap.bitmap", + (char*)ndb_schema_object->slock_bitmap.bitmap, + no_bytes_in_map(&ndb_schema_object->slock_bitmap)); + + if (bitmap_is_clear_all(&ndb_schema_object->slock_bitmap)) + break; + + if (ret) + { + max_timeout--; + if (max_timeout == 0) + { + sql_print_error("NDB %s: distributing %s timed out. Ignoring...", + type_str, ndb_schema_object->key); + break; + } + if (ndb_extra_logging) + ndb_report_waiting(type_str, max_timeout, + "distributing", ndb_schema_object->key); + } + } + if (have_lock_open) + { + (void) pthread_mutex_lock(&LOCK_open); + } + (void) pthread_mutex_unlock(&ndb_schema_object->mutex); + } + + if (ndb_schema_object) + ndb_free_schema_object(&ndb_schema_object, FALSE); + + DBUG_RETURN(0); +} + /* Handle _non_ data events from the storage nodes */ @@ -1701,16 +1720,36 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, bitmap_init(&slock, schema->slock, 8*SCHEMA_SLOCK_SIZE, false); uint node_id= g_ndb_cluster_connection->node_id(); ndbcluster_get_schema(tmp_share, schema); + DBUG_PRINT("info", + ("%s.%s: log query_length: %d query: '%s' type: %d", + schema->db, schema->name, + schema->query_length, schema->query, + schema->type)); + char key[FN_REFLEN]; + build_table_filename(key, sizeof(key), schema->db, schema->name, ""); + if ((enum SCHEMA_OP_TYPE)schema->type == SOT_CLEAR_SLOCK) + { + pthread_mutex_lock(&ndbcluster_mutex); + NDB_SCHEMA_OBJECT *ndb_schema_object= + (NDB_SCHEMA_OBJECT*) hash_search(&ndb_schema_objects, + (byte*) key, strlen(key)); + if (ndb_schema_object) + { + pthread_mutex_lock(&ndb_schema_object->mutex); + memcpy(ndb_schema_object->slock, schema->slock, + sizeof(ndb_schema_object->slock)); + DBUG_DUMP("ndb_schema_object->slock_bitmap.bitmap", + (char*)ndb_schema_object->slock_bitmap.bitmap, + no_bytes_in_map(&ndb_schema_object->slock_bitmap)); + pthread_mutex_unlock(&ndb_schema_object->mutex); + pthread_cond_signal(&injector_cond); + } + pthread_mutex_unlock(&ndbcluster_mutex); + DBUG_RETURN(0); + } if (schema->node_id != node_id) { int log_query= 0, post_epoch_unlock= 0; - DBUG_PRINT("info", - ("%s.%s: log query_length: %d query: '%s' type: %d", - schema->db, schema->name, - schema->query_length, schema->query, - schema->type)); - char key[FN_REFLEN]; - build_table_filename(key, sizeof(key), schema->db, schema->name, ""); switch ((enum SCHEMA_OP_TYPE)schema->type) { case SOT_DROP_TABLE: @@ -1759,30 +1798,12 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, TRUE, /* print error */ FALSE); /* binlog the query */ break; - case SOT_CLEAR_SLOCK: - { - pthread_mutex_lock(&ndbcluster_mutex); - NDB_SCHEMA_OBJECT *ndb_schema_object= - (NDB_SCHEMA_OBJECT*) hash_search(&ndb_schema_objects, - (byte*) key, strlen(key)); - if (ndb_schema_object) - { - pthread_mutex_lock(&ndb_schema_object->mutex); - memcpy(ndb_schema_object->slock, schema->slock, - sizeof(ndb_schema_object->slock)); - DBUG_DUMP("ndb_schema_object->slock_bitmap.bitmap", - (char*)ndb_schema_object->slock_bitmap.bitmap, - no_bytes_in_map(&ndb_schema_object->slock_bitmap)); - pthread_mutex_unlock(&ndb_schema_object->mutex); - pthread_cond_signal(&injector_cond); - } - pthread_mutex_unlock(&ndbcluster_mutex); - DBUG_RETURN(0); - } case SOT_TABLESPACE: case SOT_LOGFILE_GROUP: log_query= 1; break; + case SOT_CLEAR_SLOCK: + abort(); } if (log_query && ndb_binlog_running) { @@ -2349,6 +2370,7 @@ ndbcluster_create_event(Ndb *ndb, const NDBTAB *ndbtab, const char *event_name, NDB_SHARE *share, int push_warning) { + THD *thd= current_thd; DBUG_ENTER("ndbcluster_create_event"); DBUG_PRINT("info", ("table=%s version=%d event=%s share=%s", ndbtab->getName(), ndbtab->getObjectVersion(), @@ -2378,7 +2400,7 @@ ndbcluster_create_event(Ndb *ndb, const NDBTAB *ndbtab, "with BLOB attribute and no PK is not supported", share->key); if (push_warning) - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_ILLEGAL_HA_CREATE_OPTION, ER(ER_ILLEGAL_HA_CREATE_OPTION), ndbcluster_hton.name, @@ -2422,7 +2444,7 @@ ndbcluster_create_event(Ndb *ndb, const NDBTAB *ndbtab, failed, print a warning */ if (push_warning) - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_GET_ERRMSG, ER(ER_GET_ERRMSG), dict->getNdbError().code, dict->getNdbError().message, "NDB"); @@ -2450,7 +2472,7 @@ ndbcluster_create_event(Ndb *ndb, const NDBTAB *ndbtab, dict->dropEvent(my_event.getName())) { if (push_warning) - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_GET_ERRMSG, ER(ER_GET_ERRMSG), dict->getNdbError().code, dict->getNdbError().message, "NDB"); @@ -2469,7 +2491,7 @@ ndbcluster_create_event(Ndb *ndb, const NDBTAB *ndbtab, if (dict->createEvent(my_event)) { if (push_warning) - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_GET_ERRMSG, ER(ER_GET_ERRMSG), dict->getNdbError().code, dict->getNdbError().message, "NDB"); @@ -2482,7 +2504,7 @@ ndbcluster_create_event(Ndb *ndb, const NDBTAB *ndbtab, DBUG_RETURN(-1); } #ifdef NDB_BINLOG_EXTRA_WARNINGS - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_GET_ERRMSG, ER(ER_GET_ERRMSG), 0, "NDB Binlog: Removed trailing event", "NDB"); @@ -2511,6 +2533,7 @@ int ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab, const char *event_name) { + THD *thd= current_thd; /* we are in either create table or rename table so table should be locked, hence we can work with the share without locks @@ -2584,7 +2607,7 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab, { sql_print_error("NDB Binlog: Creating NdbEventOperation failed for" " %s",event_name); - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_GET_ERRMSG, ER(ER_GET_ERRMSG), ndb->getNdbError().code, ndb->getNdbError().message, @@ -2634,7 +2657,7 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab, sql_print_error("NDB Binlog: Creating NdbEventOperation" " blob field %u handles failed (code=%d) for %s", j, op->getNdbError().code, event_name); - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_GET_ERRMSG, ER(ER_GET_ERRMSG), op->getNdbError().code, op->getNdbError().message, @@ -2671,7 +2694,7 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab, retries= 0; if (retries == 0) { - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_GET_ERRMSG, ER(ER_GET_ERRMSG), op->getNdbError().code, op->getNdbError().message, "NDB"); @@ -2727,7 +2750,7 @@ ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name, if (dict->getNdbError().code != 4710) { /* drop event failed for some reason, issue a warning */ - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_GET_ERRMSG, ER(ER_GET_ERRMSG), dict->getNdbError().code, dict->getNdbError().message, "NDB"); @@ -2780,7 +2803,8 @@ ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name, int ret= pthread_cond_timedwait(&injector_cond, &share->mutex, &abstime); - if (share->op == 0) + if (thd->killed || + share->op == 0) break; if (ret) { From 0de72ae91f3101ca4e41d3f9e0a960a3babbb56e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 31 May 2006 18:07:32 +0200 Subject: [PATCH 22/32] after review fixes mysql-test/t/disabled.def: enable test --- mysql-test/t/disabled.def | 1 - sql/handler.cc | 77 +++++++++++++++++++-------------------- sql/handler.h | 4 +- sql/set_var.cc | 2 +- sql/sql_partition.cc | 10 ++--- sql/sql_plugin.h | 3 +- sql/sql_show.cc | 14 +++---- sql/sql_table.cc | 2 +- sql/sql_tablespace.cc | 4 +- 9 files changed, 58 insertions(+), 59 deletions(-) diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 552827c47f9..d6083ab8bfe 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -38,4 +38,3 @@ rpl_sp : BUG#16456 2006-02-16 jmiller # the below testcase have been reworked to avoid the bug, test contains comment, keep bug open #ndb_binlog_ddl_multi : BUG#18976 2006-04-10 kent CRBR: multiple binlog, second binlog may miss schema log events -ndb_dd_backuprestore : Nikolay: removed partitions from the test. Review pending. diff --git a/sql/handler.cc b/sql/handler.cc index ebfcc8f7a13..261925a3a60 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -48,7 +48,7 @@ check for dups and to find handlerton from legacy_db_type. Remove when legacy_db_type is finally gone */ static handlerton *installed_htons[128]; -st_mysql_plugin *hton2plugin[MAX_HA]; +st_plugin_int *hton2plugin[MAX_HA]; #define BITMAP_STACKBUF_SIZE (128/8) @@ -102,7 +102,7 @@ handlerton *ha_resolve_by_name(THD *thd, LEX_STRING *name) if ((plugin= plugin_lock(name, MYSQL_STORAGE_ENGINE_PLUGIN))) { - handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; + handlerton *hton= (handlerton *)plugin->data; if (!(hton->flags & HTON_NOT_USER_SELECTABLE)) return hton; plugin_unlock(plugin); @@ -135,7 +135,7 @@ const char *ha_get_storage_engine(enum legacy_db_type db_type) default: if (db_type > DB_TYPE_UNKNOWN && db_type < DB_TYPE_DEFAULT && installed_htons[db_type]) - return hton2plugin[installed_htons[db_type]->slot]->name; + return hton2plugin[installed_htons[db_type]->slot]->name.str; return "*NONE*"; } } @@ -351,22 +351,19 @@ static int ha_finish_errors(void) int ha_finalize_handlerton(st_plugin_int *plugin) { - handlerton *hton; + handlerton *hton= (handlerton *)plugin->data; DBUG_ENTER("ha_finalize_handlerton"); - if (!(hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton)) - DBUG_RETURN(1); - switch (hton->state) { case SHOW_OPTION_NO: case SHOW_OPTION_DISABLED: break; case SHOW_OPTION_YES: - if (hton->panic && hton->panic(HA_PANIC_CLOSE)) - DBUG_RETURN(1); if (installed_htons[hton->db_type] == hton) installed_htons[hton->db_type]= NULL; + if (hton->panic && hton->panic(HA_PANIC_CLOSE)) + DBUG_RETURN(1); break; }; DBUG_RETURN(0); @@ -376,9 +373,10 @@ int ha_finalize_handlerton(st_plugin_int *plugin) int ha_initialize_handlerton(st_plugin_int *plugin) { handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; - DBUG_ENTER("ha_initialize_handlerton"); + plugin->data= hton; // shortcut for the future + /* the switch below and hton->state should be removed when command-line options for plugins will be implemented @@ -388,6 +386,7 @@ int ha_initialize_handlerton(st_plugin_int *plugin) break; case SHOW_OPTION_YES: { + uint tmp; /* now check the db_type for conflict */ if (hton->db_type <= DB_TYPE_UNKNOWN || hton->db_type >= DB_TYPE_DEFAULT || @@ -409,11 +408,11 @@ int ha_initialize_handlerton(st_plugin_int *plugin) hton->db_type= (enum legacy_db_type) idx; } installed_htons[hton->db_type]= hton; - uint tmp= hton->savepoint_offset; + tmp= hton->savepoint_offset; hton->savepoint_offset= savepoint_alloc_size; savepoint_alloc_size+= tmp; hton->slot= total_ha++; - hton2plugin[hton->slot]=plugin->plugin; + hton2plugin[hton->slot]=plugin; if (hton->prepare) total_ha_2pc++; break; @@ -445,16 +444,14 @@ int ha_init() DBUG_RETURN(error); } +/* + close, flush or restart databases + Ignore this for other databases than ours +*/ - - - /* close, flush or restart databases */ - /* Ignore this for other databases than ours */ - -static my_bool panic_handlerton(THD *unused1, st_plugin_int *plugin, - void *arg) +static my_bool panic_handlerton(THD *unused1, st_plugin_int *plugin, void *arg) { - handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; + handlerton *hton= (handlerton *)plugin->data; if (hton->state == SHOW_OPTION_YES && hton->panic) ((int*)arg)[0]|= hton->panic((enum ha_panic_function)((int*)arg)[1]); return FALSE; @@ -476,7 +473,7 @@ int ha_panic(enum ha_panic_function flag) static my_bool dropdb_handlerton(THD *unused1, st_plugin_int *plugin, void *path) { - handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; + handlerton *hton= (handlerton *)plugin->data; if (hton->state == SHOW_OPTION_YES && hton->drop_database) hton->drop_database((char *)path); return FALSE; @@ -492,9 +489,11 @@ void ha_drop_database(char* path) static my_bool closecon_handlerton(THD *thd, st_plugin_int *plugin, void *unused) { - handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; - /* there's no need to rollback here as all transactions must - be rolled back already */ + handlerton *hton= (handlerton *)plugin->data; + /* + there's no need to rollback here as all transactions must + be rolled back already + */ if (hton->state == SHOW_OPTION_YES && hton->close_connection && thd->ha_data[hton->slot]) hton->close_connection(thd); @@ -585,7 +584,7 @@ int ha_prepare(THD *thd) { push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA), - hton2plugin[(*ht)->slot]->name); + hton2plugin[(*ht)->slot]->name.str); } } } @@ -824,7 +823,7 @@ struct xahton_st { static my_bool xacommit_handlerton(THD *unused1, st_plugin_int *plugin, void *arg) { - handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; + handlerton *hton= (handlerton *)plugin->data; if (hton->state == SHOW_OPTION_YES && hton->recover) { hton->commit_by_xid(((struct xahton_st *)arg)->xid); @@ -836,7 +835,7 @@ static my_bool xacommit_handlerton(THD *unused1, st_plugin_int *plugin, static my_bool xarollback_handlerton(THD *unused1, st_plugin_int *plugin, void *arg) { - handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; + handlerton *hton= (handlerton *)plugin->data; if (hton->state == SHOW_OPTION_YES && hton->recover) { hton->rollback_by_xid(((struct xahton_st *)arg)->xid); @@ -851,7 +850,7 @@ int ha_commit_or_rollback_by_xid(XID *xid, bool commit) struct xahton_st xaop; xaop.xid= xid; xaop.result= 1; - + plugin_foreach(NULL, commit ? xacommit_handlerton : xarollback_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, &xaop); @@ -943,7 +942,7 @@ struct xarecover_st static my_bool xarecover_handlerton(THD *unused, st_plugin_int *plugin, void *arg) { - handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; + handlerton *hton= (handlerton *)plugin->data; struct xarecover_st *info= (struct xarecover_st *) arg; int got; @@ -952,7 +951,7 @@ static my_bool xarecover_handlerton(THD *unused, st_plugin_int *plugin, while ((got= hton->recover(info->list, info->len)) > 0 ) { sql_print_information("Found %d prepared transaction(s) in %s", - got, hton2plugin[hton->slot]->name); + got, hton2plugin[hton->slot]->name.str); for (int i=0; i < got; i ++) { my_xid x=info->list[i].get_my_xid(); @@ -1132,7 +1131,7 @@ bool mysql_xa_recover(THD *thd) static my_bool release_temporary_latches(THD *thd, st_plugin_int *plugin, void *unused) { - handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; + handlerton *hton= (handlerton *)plugin->data; if (hton->state == SHOW_OPTION_YES && hton->release_temporary_latches) hton->release_temporary_latches(thd); @@ -1257,7 +1256,7 @@ int ha_release_savepoint(THD *thd, SAVEPOINT *sv) static my_bool snapshot_handlerton(THD *thd, st_plugin_int *plugin, void *arg) { - handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; + handlerton *hton= (handlerton *)plugin->data; if (hton->state == SHOW_OPTION_YES && hton->start_consistent_snapshot) { @@ -1288,7 +1287,7 @@ int ha_start_consistent_snapshot(THD *thd) static my_bool flush_handlerton(THD *thd, st_plugin_int *plugin, void *arg) { - handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; + handlerton *hton= (handlerton *)plugin->data; if (hton->state == SHOW_OPTION_YES && hton->flush_logs && hton->flush_logs()) return TRUE; return FALSE; @@ -2599,7 +2598,7 @@ struct binlog_func_st static my_bool binlog_func_list(THD *thd, st_plugin_int *plugin, void *arg) { hton_list_st *hton_list= (hton_list_st *)arg; - handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; + handlerton *hton= (handlerton *)plugin->data; if (hton->state == SHOW_OPTION_YES && hton->binlog_func) { uint sz= hton_list->sz; @@ -2689,7 +2688,7 @@ static my_bool binlog_log_query_handlerton(THD *thd, st_plugin_int *plugin, void *args) { - return binlog_log_query_handlerton2(thd, (const handlerton *) plugin->plugin->info, args); + return binlog_log_query_handlerton2(thd, (const handlerton *)plugin->data, args); } void ha_binlog_log_query(THD *thd, const handlerton *hton, @@ -2984,7 +2983,7 @@ static my_bool exts_handlerton(THD *unused, st_plugin_int *plugin, void *arg) { List *found_exts= (List *) arg; - handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; + handlerton *hton= (handlerton *)plugin->data; handler *file; if (hton->state == SHOW_OPTION_YES && hton->create && (file= hton->create((TABLE_SHARE*) 0))) @@ -3060,7 +3059,7 @@ static my_bool showstat_handlerton(THD *thd, st_plugin_int *plugin, void *arg) { enum ha_stat_type stat= *(enum ha_stat_type *) arg; - handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; + handlerton *hton= (handlerton *)plugin->data; if (hton->state == SHOW_OPTION_YES && hton->show_status && hton->show_status(thd, stat_print, stat)) return TRUE; @@ -3090,8 +3089,8 @@ bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat) { if (db_type->state != SHOW_OPTION_YES) { - const char *name=hton2plugin[db_type->slot]->name; - result= stat_print(thd, name, strlen(name), + const LEX_STRING *name=&hton2plugin[db_type->slot]->name; + result= stat_print(thd, name->str, name->length, "", 0, "DISABLED", 8) ? 1 : 0; } else diff --git a/sql/handler.h b/sql/handler.h index ba5344b19c7..564f391ce2d 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -461,7 +461,7 @@ typedef bool (stat_print_fn)(THD *thd, const char *type, uint type_len, const char *file, uint file_len, const char *status, uint status_len); enum ha_stat_type { HA_ENGINE_STATUS, HA_ENGINE_LOGS, HA_ENGINE_MUTEX }; -extern st_mysql_plugin *hton2plugin[MAX_HA]; +extern st_plugin_int *hton2plugin[MAX_HA]; /* handlerton is a singleton structure - one instance per storage engine - @@ -1530,7 +1530,7 @@ static inline enum legacy_db_type ha_legacy_type(const handlerton *db_type) static inline const char *ha_resolve_storage_engine_name(const handlerton *db_type) { - return db_type == NULL ? "UNKNOWN" : hton2plugin[db_type->slot]->name; + return db_type == NULL ? "UNKNOWN" : hton2plugin[db_type->slot]->name.str; } static inline bool ha_check_storage_engine_flag(const handlerton *db_type, uint32 flag) diff --git a/sql/set_var.cc b/sql/set_var.cc index e53d94d635a..3dbbd243ee4 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -3307,7 +3307,7 @@ byte *sys_var_thd_storage_engine::value_ptr(THD *thd, enum_var_type type, handlerton *val; val= (type == OPT_GLOBAL) ? global_system_variables.*offset : thd->variables.*offset; - return (byte *) hton2plugin[val->slot]->name; + return (byte *) hton2plugin[val->slot]->name.str; } diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 03dfe378ec2..733287f8359 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1665,8 +1665,8 @@ static int add_keyword_int(File fptr, const char *keyword, longlong num) static int add_engine(File fptr, handlerton *engine_type) { - const char *engine_str= hton2plugin[engine_type->slot]->name; - DBUG_PRINT("info", ("ENGINE = %s", engine_str)); + const char *engine_str= hton2plugin[engine_type->slot]->name.str; + DBUG_PRINT("info", ("ENGINE: %s", engine_str)); int err= add_string(fptr, "ENGINE = "); return err + add_string(fptr, engine_str); } @@ -1676,7 +1676,7 @@ static int add_partition_options(File fptr, partition_element *p_elem) int err= 0; if (p_elem->tablespace_name) - err+= add_keyword_string(fptr,"TABLESPACE", FALSE, + err+= add_keyword_string(fptr,"TABLESPACE", FALSE, p_elem->tablespace_name); if (p_elem->nodegroup_id != UNDEF_NODEGROUP) err+= add_keyword_int(fptr,"NODEGROUP",(longlong)p_elem->nodegroup_id); @@ -4515,8 +4515,8 @@ the generated partition syntax in a correct manner. DBUG_PRINT("info", ("No explicit engine used")); create_info->db_type= table->part_info->default_engine_type; } - DBUG_PRINT("info", ("New engine type = %s", - hton2plugin[create_info->db_type->slot]->name)); + DBUG_PRINT("info", ("New engine type: %s", + hton2plugin[create_info->db_type->slot]->name.str)); thd->work_part_info= NULL; *partition_changed= TRUE; } diff --git a/sql/sql_plugin.h b/sql/sql_plugin.h index 8459346fb53..b013beaba1f 100644 --- a/sql/sql_plugin.h +++ b/sql/sql_plugin.h @@ -58,7 +58,8 @@ struct st_plugin_int struct st_mysql_plugin *plugin; struct st_plugin_dl *plugin_dl; enum enum_plugin_state state; - uint ref_count; /* number of threads using the plugin */ + uint ref_count; /* number of threads using the plugin */ + void *data; /* plugin type specific, e.g. handlerton */ }; typedef int (*plugin_type_init)(struct st_plugin_int *); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 8693e805826..8c492e9457b 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -55,12 +55,13 @@ static my_bool show_handlerton(THD *thd, st_plugin_int *plugin, { handlerton *default_type= (handlerton *) arg; Protocol *protocol= thd->protocol; - handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; + handlerton *hton= (handlerton *)plugin->data; if (!(hton->flags & HTON_HIDDEN)) { protocol->prepare_for_resend(); - protocol->store(plugin->plugin->name, system_charset_info); + protocol->store(plugin->name.str, plugin->name.length, + system_charset_info); const char *option_name= show_comp_option_name[(int) hton->state]; if (hton->state == SHOW_OPTION_YES && default_type == hton) @@ -3091,7 +3092,7 @@ static my_bool iter_schema_engines(THD *thd, st_plugin_int *plugin, void *ptable) { TABLE *table= (TABLE *) ptable; - handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; + handlerton *hton= (handlerton *)plugin->data; const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS; CHARSET_INFO *scs= system_charset_info; DBUG_ENTER("iter_schema_engines"); @@ -3099,7 +3100,7 @@ static my_bool iter_schema_engines(THD *thd, st_plugin_int *plugin, if (!(hton->flags & HTON_HIDDEN)) { if (!(wild && wild[0] && - wild_case_compare(scs, plugin->plugin->name,wild))) + wild_case_compare(scs, plugin->name.str,wild))) { LEX_STRING state[2]={{STRING_WITH_LEN("ENABLED")}, {STRING_WITH_LEN("DISABLED")}}; @@ -3107,8 +3108,7 @@ static my_bool iter_schema_engines(THD *thd, st_plugin_int *plugin, LEX_STRING *tmp; restore_record(table, s->default_values); - table->field[0]->store(plugin->plugin->name, - strlen(plugin->plugin->name), scs); + table->field[0]->store(plugin->name.str, plugin->name.length, scs); tmp= &state[test(hton->state)]; table->field[1]->store(tmp->str, tmp->length, scs); table->field[2]->store(plugin->plugin->descr, @@ -5008,7 +5008,7 @@ static my_bool run_hton_fill_schema_files(THD *thd, st_plugin_int *plugin, { struct run_hton_fill_schema_files_args *args= (run_hton_fill_schema_files_args *) arg; - handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; + handlerton *hton= (handlerton *)plugin->data; if(hton->fill_files_table) hton->fill_files_table(thd, args->tables, args->cond); return false; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 3975d5724c4..21dee4d3f2f 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -6465,7 +6465,7 @@ static bool check_engine(THD *thd, const char *table_name, if (create_info->used_fields & HA_CREATE_USED_ENGINE) { my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0), - hton2plugin[(*new_engine)->slot]->name, "TEMPORARY"); + hton2plugin[(*new_engine)->slot]->name.str, "TEMPORARY"); *new_engine= 0; return TRUE; } diff --git a/sql/sql_tablespace.cc b/sql/sql_tablespace.cc index 84e2b9c7d04..94318a67575 100644 --- a/sql/sql_tablespace.cc +++ b/sql/sql_tablespace.cc @@ -35,7 +35,7 @@ int mysql_alter_tablespace(THD *thd, st_alter_tablespace *ts_info) push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_WARN_USING_OTHER_HANDLER, ER(ER_WARN_USING_OTHER_HANDLER), - hton2plugin[hton->slot]->name, + hton2plugin[hton->slot]->name.str, ts_info->tablespace_name ? ts_info->tablespace_name : ts_info->logfile_group_name); } @@ -64,7 +64,7 @@ int mysql_alter_tablespace(THD *thd, st_alter_tablespace *ts_info) push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_ILLEGAL_HA_CREATE_OPTION, ER(ER_ILLEGAL_HA_CREATE_OPTION), - hton2plugin[hton->slot]->name, + hton2plugin[hton->slot]->name.str, "TABLESPACE or LOGFILE GROUP"); } if (mysql_bin_log.is_open()) From eb67ecef898433461ac9251541188fd9e1e945d4 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 31 May 2006 18:37:16 +0200 Subject: [PATCH 23/32] classes that are compiled conditionally in log_event.cc must be defined conditionally in log_event.h BitKeeper/deleted/.del-client_priv.h.rej~915a5a16fe10ef0: Delete: client/client_priv.h.rej --- client/client_priv.h.rej | 15 --------------- sql/log_event.h | 5 ++++- 2 files changed, 4 insertions(+), 16 deletions(-) delete mode 100644 client/client_priv.h.rej diff --git a/client/client_priv.h.rej b/client/client_priv.h.rej deleted file mode 100644 index ac3818bb1e1..00000000000 --- a/client/client_priv.h.rej +++ /dev/null @@ -1,15 +0,0 @@ -*************** -*** 50,55 **** - OPT_NDBCLUSTER, OPT_NDB_CONNECTSTRING, - #endif - OPT_TRIGGERS, - OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_SHOW_WARNINGS,OPT_DROP_DATABASE, -! OPT_TZ_UTC, OPT_AUTO_CLOSE - }; ---- 50,55 ---- - OPT_NDBCLUSTER, OPT_NDB_CONNECTSTRING, - #endif - OPT_TRIGGERS, - OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_SHOW_WARNINGS,OPT_DROP_DATABASE, -! OPT_TZ_UTC, OPT_AUTO_CLOSE, OPT_SSL_VERIFY_SERVER_CERT - }; diff --git a/sql/log_event.h b/sql/log_event.h index b24686514e3..d9a9d93a1e5 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -1635,6 +1635,8 @@ public: #endif char *str_to_hex(char *to, const char *from, uint len); +#ifdef HAVE_ROW_BASED_REPLICATION + /***************************************************************************** Table map log event class @@ -1643,7 +1645,6 @@ char *str_to_hex(char *to, const char *from, uint len); identifier (an integer number). ****************************************************************************/ - class Table_map_log_event : public Log_event { public: @@ -1750,6 +1751,7 @@ private: ****************************************************************************/ + class Rows_log_event : public Log_event { public: @@ -2121,5 +2123,6 @@ private: #endif }; +#endif /* HAVE_ROW_BASED_REPLICATION */ #endif /* _log_event_h */ From 8b4581778036c95072438630884ad810b512815a Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 31 May 2006 18:44:09 +0200 Subject: [PATCH 24/32] WL#2595 - atomic operations BitKeeper/etc/ignore: Added mysys/test_atomic to the ignore list --- .bzrignore | 1 + configure.in | 56 ++++--------- include/atomic/nolock.h | 169 ++++++++++++++++++++++++++++++++++++++ include/atomic/rwlock.h | 161 ++++++++++++++++++++++++++++++++++++ include/atomic/x86-gcc.h | 56 +++++++++++++ include/atomic/x86-msvc.h | 85 +++++++++++++++++++ include/my_atomic.h | 46 +++++++++++ include/my_global.h | 13 +++ mysys/Makefile.am | 9 +- mysys/my_atomic.c | 46 +++++++++++ mysys/my_getncpus.c | 40 +++++++++ mysys/test_atomic.c | 133 ++++++++++++++++++++++++++++++ 12 files changed, 768 insertions(+), 47 deletions(-) create mode 100644 include/atomic/nolock.h create mode 100644 include/atomic/rwlock.h create mode 100644 include/atomic/x86-gcc.h create mode 100644 include/atomic/x86-msvc.h create mode 100644 include/my_atomic.h create mode 100644 mysys/my_atomic.c create mode 100644 mysys/my_getncpus.c create mode 100644 mysys/test_atomic.c diff --git a/.bzrignore b/.bzrignore index 57fcbdd8f73..27e8cb3c79d 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1771,3 +1771,4 @@ vio/viotest.cpp zlib/*.ds? zlib/*.vcproj libmysqld/event_scheduler.cc +mysys/test_atomic diff --git a/configure.in b/configure.in index 0f0649fd3bc..1e332e390e1 100644 --- a/configure.in +++ b/configure.in @@ -778,48 +778,6 @@ struct request_info *req; AC_SUBST(WRAPLIBS) if test "$TARGET_LINUX" = "true"; then - AC_MSG_CHECKING([for atomic operations]) - - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - - atom_ops= - AC_TRY_RUN([ -#include -int main() -{ - atomic_t v; - - atomic_set(&v, 23); - atomic_add(5, &v); - return atomic_read(&v) == 28 ? 0 : -1; -} - ], - [AC_DEFINE([HAVE_ATOMIC_ADD], [1], - [atomic_add() from (Linux only)]) - atom_ops="${atom_ops}atomic_add "], - ) - AC_TRY_RUN([ -#include -int main() -{ - atomic_t v; - - atomic_set(&v, 23); - atomic_sub(5, &v); - return atomic_read(&v) == 18 ? 0 : -1; -} - ], - [AC_DEFINE([HAVE_ATOMIC_SUB], [1], - [atomic_sub() from (Linux only)]) - atom_ops="${atom_ops}atomic_sub "], - ) - - if test -z "$atom_ops"; then atom_ops="no"; fi - AC_MSG_RESULT($atom_ops) - - AC_LANG_RESTORE - AC_ARG_WITH(pstack, [ --with-pstack Use the pstack backtrace library], [ USE_PSTACK=$withval ], @@ -1631,6 +1589,20 @@ then fi fi +AC_ARG_WITH([atomic-ops], + AC_HELP_STRING([--with-atomic-ops=rwlocks|smp|up], + [Implement atomic operations using pthread rwlocks or atomic CPU + instructions for multi-processor (default) or uniprocessor + configuration]), , [with_atomic_ops=smp]) +case "$with_atomic_ops" in + "up") AC_DEFINE([MY_ATOMIC_MODE_DUMMY], [1], + [Assume single-CPU mode, no concurrency]) ;; + "rwlocks") AC_DEFINE([MY_ATOMIC_MODE_RWLOCKS], [1], + [Use pthread rwlocks for atomic ops]) ;; + "smp") ;; + *) AC_MSG_ERROR(["$with_atomic_ops" is not a valid value for --with-atomic-ops]) ;; +esac + # Force static compilation to avoid linking problems/get more speed AC_ARG_WITH(mysqld-ldflags, [ --with-mysqld-ldflags Extra linking arguments for mysqld], diff --git a/include/atomic/nolock.h b/include/atomic/nolock.h new file mode 100644 index 00000000000..cf21a94c7de --- /dev/null +++ b/include/atomic/nolock.h @@ -0,0 +1,169 @@ +/* Copyright (C) 2006 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#if defined(__i386__) || defined(_M_IX86) +#ifdef MY_ATOMIC_MODE_DUMMY +# define LOCK "" +#else +# define LOCK "lock " +#endif +#ifdef __GNUC__ +#include "x86-gcc.h" +#elif defined(_MSC_VER) +#include "x86-msvc.h" +#endif +#endif + +#ifdef make_atomic_add_body8 + +#ifdef HAVE_INLINE + +#define make_atomic_add(S) \ +static inline uint ## S _my_atomic_add ## S( \ + my_atomic_ ## S ## _t *a, uint ## S v) \ +{ \ + make_atomic_add_body ## S; \ + return v; \ +} + +#define make_atomic_swap(S) \ +static inline uint ## S _my_atomic_swap ## S( \ + my_atomic_ ## S ## _t *a, uint ## S v) \ +{ \ + make_atomic_swap_body ## S; \ + return v; \ +} + +#define make_atomic_cas(S) \ +static inline uint _my_atomic_cas ## S(my_atomic_ ## S ## _t *a,\ + uint ## S *cmp, uint ## S set) \ +{ \ + uint8 ret; \ + make_atomic_cas_body ## S; \ + return ret; \ +} + +#define make_atomic_load(S) \ +static inline uint ## S _my_atomic_load ## S( \ + my_atomic_ ## S ## _t *a) \ +{ \ + uint ## S ret; \ + make_atomic_load_body ## S; \ + return ret; \ +} + +#define make_atomic_store(S) \ +static inline void _my_atomic_store ## S( \ + my_atomic_ ## S ## _t *a, uint ## S v) \ +{ \ + make_atomic_store_body ## S; \ +} + +#else /* no inline functions */ + +#define make_atomic_add(S) \ +extern uint ## S _my_atomic_add ## S( \ + my_atomic_ ## S ## _t *a, uint ## S v); + +#define make_atomic_swap(S) \ +extern uint ## S _my_atomic_swap ## S( \ + my_atomic_ ## S ## _t *a, uint ## S v); + +#define make_atomic_cas(S) \ +extern uint _my_atomic_cas ## S(my_atomic_ ## S ## _t *a, \ + uint ## S *cmp, uint ## S set); + +#define make_atomic_load(S) \ +extern uint ## S _my_atomic_load ## S( \ + my_atomic_ ## S ## _t *a); + +#define make_atomic_store(S) \ +extern void _my_atomic_store ## S( \ + my_atomic_ ## S ## _t *a, uint ## S v); + +#endif + +make_atomic_add( 8) +make_atomic_add(16) +make_atomic_add(32) + +make_atomic_cas( 8) +make_atomic_cas(16) +make_atomic_cas(32) + +make_atomic_load( 8) +make_atomic_load(16) +make_atomic_load(32) + +make_atomic_store( 8) +make_atomic_store(16) +make_atomic_store(32) + +make_atomic_swap( 8) +make_atomic_swap(16) +make_atomic_swap(32) + +#undef make_atomic_add_body8 +#undef make_atomic_cas_body8 +#undef make_atomic_load_body8 +#undef make_atomic_store_body8 +#undef make_atomic_swap_body8 +#undef make_atomic_add_body16 +#undef make_atomic_cas_body16 +#undef make_atomic_load_body16 +#undef make_atomic_store_body16 +#undef make_atomic_swap_body16 +#undef make_atomic_add_body32 +#undef make_atomic_cas_body32 +#undef make_atomic_load_body32 +#undef make_atomic_store_body32 +#undef make_atomic_swap_body32 +#undef make_atomic_add +#undef make_atomic_cas +#undef make_atomic_load +#undef make_atomic_store +#undef make_atomic_swap + +#define my_atomic_add8(a,v,L) _my_atomic_add8(a,v) +#define my_atomic_add16(a,v,L) _my_atomic_add16(a,v) +#define my_atomic_add32(a,v,L) _my_atomic_add32(a,v) + +#define my_atomic_cas8(a,c,v,L) _my_atomic_cas8(a,c,v) +#define my_atomic_cas16(a,c,v,L) _my_atomic_cas16(a,c,v) +#define my_atomic_cas32(a,c,v,L) _my_atomic_cas32(a,c,v) + +#define my_atomic_load8(a,L) _my_atomic_load8(a) +#define my_atomic_load16(a,L) _my_atomic_load16(a) +#define my_atomic_load32(a,L) _my_atomic_load32(a) + +#define my_atomic_store8(a,v,L) _my_atomic_store8(a,v) +#define my_atomic_store16(a,v,L) _my_atomic_store16(a,v) +#define my_atomic_store32(a,v,L) _my_atomic_store32(a,v) + +#define my_atomic_swap8(a,v,L) _my_atomic_swap8(a,v) +#define my_atomic_swap16(a,v,L) _my_atomic_swap16(a,v) +#define my_atomic_swap32(a,v,L) _my_atomic_swap32(a,v) + +#define my_atomic_rwlock_t typedef int +#define my_atomic_rwlock_destroy(name) +#define my_atomic_rwlock_init(name) +#define my_atomic_rwlock_rdlock(name) +#define my_atomic_rwlock_wrlock(name) +#define my_atomic_rwlock_rdunlock(name) +#define my_atomic_rwlock_wrunlock(name) + +#endif + diff --git a/include/atomic/rwlock.h b/include/atomic/rwlock.h new file mode 100644 index 00000000000..ca5be29ab9b --- /dev/null +++ b/include/atomic/rwlock.h @@ -0,0 +1,161 @@ +/* Copyright (C) 2006 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +typedef struct {pthread_rwlock_t rw;} my_atomic_rwlock_t; + +#ifdef MY_ATOMIC_EXTRA_DEBUG +#define CHECK_RW if (rw) if (a->rw) assert(rw == a->rw); else a->rw=rw; +#else +#define CHECK_RW +#endif + +#ifdef MY_ATOMIC_MODE_DUMMY +/* + the following can never be enabled by ./configure, one need to put #define in + a source to trigger the following warning. The resulting code will be broken, + it only makes sense to do it to see now test_atomic detects broken + implementations (another way is to run a UP build on an SMP box). +*/ +#warning MY_ATOMIC_MODE_DUMMY and MY_ATOMIC_MODE_RWLOCKS are incompatible +#define my_atomic_rwlock_destroy(name) +#define my_atomic_rwlock_init(name) +#define my_atomic_rwlock_rdlock(name) +#define my_atomic_rwlock_wrlock(name) +#define my_atomic_rwlock_rdunlock(name) +#define my_atomic_rwlock_wrunlock(name) +#else +#define my_atomic_rwlock_destroy(name) pthread_rwlock_destroy(& (name)->rw) +#define my_atomic_rwlock_init(name) pthread_rwlock_init(& (name)->rw, 0) +#define my_atomic_rwlock_rdlock(name) pthread_rwlock_rdlock(& (name)->rw) +#define my_atomic_rwlock_wrlock(name) pthread_rwlock_wrlock(& (name)->rw) +#define my_atomic_rwlock_rdunlock(name) pthread_rwlock_unlock(& (name)->rw) +#define my_atomic_rwlock_wrunlock(name) pthread_rwlock_unlock(& (name)->rw) +#endif + +#ifdef HAVE_INLINE + +#define make_atomic_add(S) \ +static inline uint ## S my_atomic_add ## S( \ + my_atomic_ ## S ## _t *a, uint ## S v, my_atomic_rwlock_t *rw) \ +{ \ + uint ## S ret; \ + CHECK_RW; \ + if (rw) my_atomic_rwlock_wrlock(rw); \ + ret= a->val; \ + a->val+= v; \ + if (rw) my_atomic_rwlock_wrunlock(rw); \ + return ret; \ +} + +#define make_atomic_swap(S) \ +static inline uint ## S my_atomic_swap ## S( \ + my_atomic_ ## S ## _t *a, uint ## S v, my_atomic_rwlock_t *rw) \ +{ \ + uint ## S ret; \ + CHECK_RW; \ + if (rw) my_atomic_rwlock_wrlock(rw); \ + ret= a->val; \ + a->val= v; \ + if (rw) my_atomic_rwlock_wrunlock(rw); \ + return ret; \ +} + +#define make_atomic_cas(S) \ +static inline uint my_atomic_cas ## S(my_atomic_ ## S ## _t *a, \ + uint ## S *cmp, uint ## S set, my_atomic_rwlock_t *rw) \ +{ \ + uint ret; \ + CHECK_RW; \ + if (rw) my_atomic_rwlock_wrlock(rw); \ + if (ret= (a->val == *cmp)) a->val= set; else *cmp=a->val; \ + if (rw) my_atomic_rwlock_wrunlock(rw); \ + return ret; \ +} + +#define make_atomic_load(S) \ +static inline uint ## S my_atomic_load ## S( \ + my_atomic_ ## S ## _t *a, my_atomic_rwlock_t *rw) \ +{ \ + uint ## S ret; \ + CHECK_RW; \ + if (rw) my_atomic_rwlock_wrlock(rw); \ + ret= a->val; \ + if (rw) my_atomic_rwlock_wrunlock(rw); \ + return ret; \ +} + +#define make_atomic_store(S) \ +static inline void my_atomic_store ## S( \ + my_atomic_ ## S ## _t *a, uint ## S v, my_atomic_rwlock_t *rw) \ +{ \ + CHECK_RW; \ + if (rw) my_atomic_rwlock_rdlock(rw); \ + (a)->val= (v); \ + if (rw) my_atomic_rwlock_rdunlock(rw); \ +} + +#else /* no inline functions */ + +#define make_atomic_add(S) \ +extern uint ## S my_atomic_add ## S( \ + my_atomic_ ## S ## _t *a, uint ## S v, my_atomic_rwlock_t *rw); + +#define make_atomic_swap(S) \ +extern uint ## S my_atomic_swap ## S( \ + my_atomic_ ## S ## _t *a, uint ## S v, my_atomic_rwlock_t *rw); + +#define make_atomic_cas(S) \ +extern uint my_atomic_cas ## S(my_atomic_ ## S ## _t *a, \ + uint ## S *cmp, uint ## S set, my_atomic_rwlock_t *rw); + +#define make_atomic_load(S) \ +extern uint ## S my_atomic_load ## S( \ + my_atomic_ ## S ## _t *a, my_atomic_rwlock_t *rw); + +#define make_atomic_store(S) \ +extern void my_atomic_store ## S( \ + my_atomic_ ## S ## _t *a, uint ## S v, my_atomic_rwlock_t *rw); + +#endif + +make_atomic_add( 8) +make_atomic_add(16) +make_atomic_add(32) +make_atomic_add(64) +make_atomic_cas( 8) +make_atomic_cas(16) +make_atomic_cas(32) +make_atomic_cas(64) +make_atomic_load( 8) +make_atomic_load(16) +make_atomic_load(32) +make_atomic_load(64) +make_atomic_store( 8) +make_atomic_store(16) +make_atomic_store(32) +make_atomic_store(64) +make_atomic_swap( 8) +make_atomic_swap(16) +make_atomic_swap(32) +make_atomic_swap(64) +#undef make_atomic_add +#undef make_atomic_cas +#undef make_atomic_load +#undef make_atomic_store +#undef make_atomic_swap +#undef CHECK_RW + + diff --git a/include/atomic/x86-gcc.h b/include/atomic/x86-gcc.h new file mode 100644 index 00000000000..b06d80d37e5 --- /dev/null +++ b/include/atomic/x86-gcc.h @@ -0,0 +1,56 @@ +/* Copyright (C) 2006 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + XXX 64-bit atomic operations can be implemented using + cmpxchg8b, if necessary +*/ + +#define make_atomic_add_body8 \ + asm volatile (LOCK "xadd %0, %1;" : "+r" (v) , "+m" (a->val)) +#define make_atomic_swap_body8 \ + asm volatile ("xchg %0, %1;" : "+r" (v) , "+m" (a->val)) +#define make_atomic_cas_body8 \ + asm volatile (LOCK "cmpxchg %3, %0; setz %2;" \ + : "+m" (a->val), "+a" (*cmp), "=q" (ret): "r" (set)) + +#ifdef MY_ATOMIC_MODE_DUMMY +#define make_atomic_load_body8 ret=a->val +#define make_atomic_store_body8 a->val=v +#else +/* + Actually 32-bit reads/writes are always atomic on x86 + But we add LOCK here anyway to force memory barriers +*/ +#define make_atomic_load_body8 \ + ret=0; \ + asm volatile (LOCK "cmpxchg %2, %0" \ + : "+m" (a->val), "+a" (ret): "r" (ret)) +#define make_atomic_store_body8 \ + asm volatile ("xchg %0, %1;" : "+m" (a->val) : "r" (v)) +#endif + +#define make_atomic_add_body16 make_atomic_add_body8 +#define make_atomic_add_body32 make_atomic_add_body8 +#define make_atomic_cas_body16 make_atomic_cas_body8 +#define make_atomic_cas_body32 make_atomic_cas_body8 +#define make_atomic_load_body16 make_atomic_load_body8 +#define make_atomic_load_body32 make_atomic_load_body8 +#define make_atomic_store_body16 make_atomic_store_body8 +#define make_atomic_store_body32 make_atomic_store_body8 +#define make_atomic_swap_body16 make_atomic_swap_body8 +#define make_atomic_swap_body32 make_atomic_swap_body8 + diff --git a/include/atomic/x86-msvc.h b/include/atomic/x86-msvc.h new file mode 100644 index 00000000000..19645551196 --- /dev/null +++ b/include/atomic/x86-msvc.h @@ -0,0 +1,85 @@ +/* Copyright (C) 2006 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + XXX 64-bit atomic operations can be implemented using + cmpxchg8b, if necessary +*/ + +// Would it be better to use intrinsics ? +// (InterlockedCompareExchange, InterlockedCompareExchange16 +// InterlockedExchangeAdd, InterlockedExchange) + +#define make_atomic_add_body(REG) \ + _asm { \ + _asm mov REG, v \ + _asm LOCK xadd a->val, REG \ + _asm movzx v, REG \ + } +#define make_atomic_cas_body(AREG,REG2) \ + _asm { \ + _asm mov AREG, *cmp \ + _asm mov REG2, set \ + _asm LOCK cmpxchg a->val, REG2 \ + _asm mov *cmp, AREG \ + _asm setz al \ + _asm movzx ret, al \ + } +#define make_atomic_swap_body(REG) \ + _asm { \ + _asm mov REG, v \ + _asm xchg a->val, REG \ + _asm mov v, REG \ + } + +#ifdef MY_ATOMIC_MODE_DUMMY +#define make_atomic_load_body(AREG,REG) ret=a->val +#define make_atomic_store_body(REG) a->val=v +#else +/* + Actually 32-bit reads/writes are always atomic on x86 + But we add LOCK here anyway to force memory barriers +*/ +#define make_atomic_load_body(AREG,REG2) \ + _asm { \ + _asm mov AREG, 0 \ + _asm mov REG2, AREG \ + _asm LOCK cmpxchg a->val, REG2 \ + _asm mov ret, AREG \ + } +#define make_atomic_store_body(REG) \ + _asm { \ + _asm mov REG, v \ + _asm xchg a->val, REG \ + } +#endif + +#define make_atomic_add_body8 make_atomic_add_body(al) +#define make_atomic_add_body16 make_atomic_add_body(ax) +#define make_atomic_add_body32 make_atomic_add_body(eax) +#define make_atomic_cas_body8 make_atomic_cas_body(al, bl) +#define make_atomic_cas_body16 make_atomic_cas_body(ax, bx) +#define make_atomic_cas_body32 make_atomic_cas_body(eax, ebx) +#define make_atomic_load_body8 make_atomic_load_body(al, bl) +#define make_atomic_load_body16 make_atomic_load_body(ax, bx) +#define make_atomic_load_body32 make_atomic_load_body(eax, ebx) +#define make_atomic_store_body8 make_atomic_store_body(al) +#define make_atomic_store_body16 make_atomic_store_body(ax) +#define make_atomic_store_body32 make_atomic_store_body(eax) +#define make_atomic_swap_body8 make_atomic_swap_body(al) +#define make_atomic_swap_body16 make_atomic_swap_body(ax) +#define make_atomic_swap_body32 make_atomic_swap_body(eax) + diff --git a/include/my_atomic.h b/include/my_atomic.h new file mode 100644 index 00000000000..091edc0f57b --- /dev/null +++ b/include/my_atomic.h @@ -0,0 +1,46 @@ +/* Copyright (C) 2006 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef atomic_rwlock_init + +#ifdef MY_ATOMIC_EXTRA_DEBUG +#ifndef MY_ATOMIC_MODE_RWLOCKS +#error MY_ATOMIC_EXTRA_DEBUG can be only used with MY_ATOMIC_MODE_RWLOCKS +#endif +#define LOCK_PTR void *rw; +#else +#define LOCK_PTR +#endif + +typedef volatile struct {uint8 val; LOCK_PTR} my_atomic_8_t; +typedef volatile struct {uint16 val; LOCK_PTR} my_atomic_16_t; +typedef volatile struct {uint32 val; LOCK_PTR} my_atomic_32_t; +typedef volatile struct {uint64 val; LOCK_PTR} my_atomic_64_t; + +#ifndef MY_ATOMIC_MODE_RWLOCKS +#include "atomic/nolock.h" +#endif + +#ifndef my_atomic_rwlock_init +#include "atomic/rwlock.h" +#endif + +#define MY_ATOMIC_OK 0 +#define MY_ATOMIC_NOT_1CPU 1 +extern int my_atomic_initialize(); + +#endif + diff --git a/include/my_global.h b/include/my_global.h index 100e695a0de..81fa5225c3b 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -181,6 +181,17 @@ #define HOT_DATA #endif +/* + now let's figure out if inline functions are supported + autoconf defines 'inline' to be empty, if not +*/ +#define inline_test_1(X) X ## 1 +#define inline_test_2(X) inline_test_1(X) +#if inline_test_2(inline) != 1 +#define HAVE_INLINE +#endif +#undef inline_test_2 +#undef inline_test_1 /* The following macros are used to control inlining a bit more than @@ -889,6 +900,8 @@ typedef unsigned long ulonglong; /* ulong or unsigned long long */ typedef long longlong; #endif #endif +typedef longlong int64; +typedef ulonglong uint64; #if defined(NO_CLIENT_LONG_LONG) typedef unsigned long my_ulonglong; diff --git a/mysys/Makefile.am b/mysys/Makefile.am index 1241e8cdded..93d0e896874 100644 --- a/mysys/Makefile.am +++ b/mysys/Makefile.am @@ -20,8 +20,7 @@ MYSQLBASEdir= $(prefix) INCLUDES = @ZLIB_INCLUDES@ -I$(top_builddir)/include \ -I$(top_srcdir)/include -I$(srcdir) pkglib_LIBRARIES = libmysys.a -LDADD = libmysys.a ../dbug/libdbug.a \ - ../strings/libmystrings.a +LDADD = libmysys.a $(top_builddir)/strings/libmystrings.a noinst_HEADERS = mysys_priv.h my_static.h libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \ mf_path.c mf_loadpath.c my_file.c \ @@ -32,7 +31,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \ mf_tempdir.c my_lock.c mf_brkhant.c my_alarm.c \ my_malloc.c my_realloc.c my_once.c mulalloc.c \ my_alloc.c safemalloc.c my_new.cc \ - my_vle.c \ + my_vle.c my_atomic.c \ my_fopen.c my_fstream.c my_getsystime.c \ my_error.c errors.c my_div.c my_messnc.c \ mf_format.c mf_same.c mf_dirname.c mf_fn_ext.c \ @@ -40,7 +39,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \ mf_pack.c mf_unixpath.c mf_strip.c \ mf_wcomp.c mf_wfile.c my_gethwaddr.c \ mf_qsort.c mf_qsort2.c mf_sort.c \ - ptr_cmp.c mf_radix.c queues.c \ + ptr_cmp.c mf_radix.c queues.c my_getncpus.c \ tree.c trie.c list.c hash.c array.c string.c typelib.c \ my_copy.c my_append.c my_lib.c \ my_delete.c my_rename.c my_redel.c \ @@ -64,7 +63,7 @@ libmysys_a_LIBADD = @THREAD_LOBJECTS@ # testhash_DEPENDENCIES= $(LIBRARIES) # test_charset_DEPENDENCIES= $(LIBRARIES) # charset2html_DEPENDENCIES= $(LIBRARIES) -EXTRA_PROGRAMS = +noinst_PROGRAMS= test_atomic$(EXEEXT) DEFS = -DDEFAULT_BASEDIR=\"$(prefix)\" \ -DDATADIR="\"$(MYSQLDATAdir)\"" \ -DDEFAULT_CHARSET_HOME="\"$(MYSQLBASEdir)\"" \ diff --git a/mysys/my_atomic.c b/mysys/my_atomic.c new file mode 100644 index 00000000000..21b80f0f6a1 --- /dev/null +++ b/mysys/my_atomic.c @@ -0,0 +1,46 @@ +/* Copyright (C) 2006 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include +#include + +#ifndef HAVE_INLINE +/* + the following will cause all inline functions to be instantiated +*/ +#define HAVE_INLINE +#define static extern +#endif + +#include + +/* + checks that the current build of atomic ops + can run on this machine + + RETURN + ATOMIC_xxx values, see my_atomic.h +*/ +int my_atomic_initialize() +{ + /* currently the only thing worth checking is SMP/UP issue */ +#ifdef MY_ATOMIC_MODE_DUMMY + return my_getncpus() == 1 ? MY_ATOMIC_OK : MY_ATOMIC_NOT_1CPU; +#else + return MY_ATOMIC_OK; +#endif +} + diff --git a/mysys/my_getncpus.c b/mysys/my_getncpus.c new file mode 100644 index 00000000000..6c45617e496 --- /dev/null +++ b/mysys/my_getncpus.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2006 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* get the number of (online) CPUs */ + +#include "mysys_priv.h" +#include + +static int ncpus=0; + +#ifdef _SC_NPROCESSORS_ONLN +int my_getncpus() +{ + if (!ncpus) + ncpus= sysconf(_SC_NPROCESSORS_ONLN); + return ncpus; +} + +#else +/* unknown */ +int my_getncpus() +{ + return 2; +} + +#endif + diff --git a/mysys/test_atomic.c b/mysys/test_atomic.c new file mode 100644 index 00000000000..21315bc13a4 --- /dev/null +++ b/mysys/test_atomic.c @@ -0,0 +1,133 @@ +#include +#include +#include + +my_atomic_32_t a32,b32,c32; +my_atomic_rwlock_t rwl; + +pthread_attr_t thr_attr; +pthread_mutex_t mutex; +pthread_cond_t cond; +int N; + +/* add and sub a random number in a loop. Must get 0 at the end */ +pthread_handler_t test_atomic_add_handler(void *arg) +{ + int m=*(int *)arg; + int32 x; + for (x=((int)(&m)); m ; m--) + { + x=x*m+0x87654321; + my_atomic_add32(&a32, x, &rwl); + my_atomic_add32(&a32, -x, &rwl); + } + pthread_mutex_lock(&mutex); + N--; + if (!N) pthread_cond_signal(&cond); + pthread_mutex_unlock(&mutex); +} + +/* + 1. generate thread number 0..N-1 from b32 + 2. add it to a32 + 3. swap thread numbers in c32 + 4. (optionally) one more swap to avoid 0 as a result + 5. subtract result from a32 + must get 0 in a32 at the end +*/ +pthread_handler_t test_atomic_swap_handler(void *arg) +{ + int m=*(int *)arg; + uint32 x=my_atomic_add32(&b32, 1, &rwl); + + my_atomic_add32(&a32, x, &rwl); + + for (; m ; m--) + x=my_atomic_swap32(&c32, x,&rwl); + + if (!x) + x=my_atomic_swap32(&c32, x,&rwl); + + my_atomic_add32(&a32, -x, &rwl); + + pthread_mutex_lock(&mutex); + N--; + if (!N) pthread_cond_signal(&cond); + pthread_mutex_unlock(&mutex); +} + +/* + same as test_atomic_add_handler, but my_atomic_add32 is emulated with + (slower) my_atomic_cas32 +*/ +pthread_handler_t test_atomic_cas_handler(void *arg) +{ + int m=*(int *)arg; + int32 x; + for (x=((int)(&m)); m ; m--) + { + uint32 y=my_atomic_load32(&a32, &rwl); + x=x*m+0x87654321; + while (!my_atomic_cas32(&a32, &y, y+x, &rwl)) ; + while (!my_atomic_cas32(&a32, &y, y-x, &rwl)) ; + } + pthread_mutex_lock(&mutex); + N--; + if (!N) pthread_cond_signal(&cond); + pthread_mutex_unlock(&mutex); +} + +void test_atomic(const char *test, pthread_handler handler, int n, int m) +{ + pthread_t t; + ulonglong now=my_getsystime(); + + my_atomic_store32(&a32, 0, &rwl); + my_atomic_store32(&b32, 0, &rwl); + my_atomic_store32(&c32, 0, &rwl); + + printf("Testing %s with %d threads, %d iterations... ", test, n, m); + for (N=n ; n ; n--) + pthread_create(&t, &thr_attr, handler, &m); + + pthread_mutex_lock(&mutex); + while (N) + pthread_cond_wait(&cond, &mutex); + pthread_mutex_unlock(&mutex); + now=my_getsystime()-now; + printf("got %lu in %g secs\n", my_atomic_load32(&a32, &rwl), + ((double)now)/1e7); +} + +int main() +{ + int err; + +#ifdef _IONBF + setvbuf(stdout, 0, _IONBF, 0); +#endif + printf("N CPUs: %d\n", my_getncpus()); + + if ((err= my_atomic_initialize())) + { + printf("my_atomic_initialize() failed. Error=%d\n", err); + return 1; + } + + pthread_attr_init(&thr_attr); + pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); + pthread_mutex_init(&mutex, 0); + pthread_cond_init(&cond, 0); + my_atomic_rwlock_init(&rwl); + + test_atomic("my_atomic_add32", test_atomic_add_handler, 100,1000000); + test_atomic("my_atomic_swap32", test_atomic_swap_handler, 100,1000000); + test_atomic("my_atomic_cas32", test_atomic_cas_handler, 100,1000000); + + pthread_mutex_destroy(&mutex); + pthread_cond_destroy(&cond); + pthread_attr_destroy(&thr_attr); + my_atomic_rwlock_destroy(&rwl); + return 0; +} + From 591294d0ef8fd19655ebc2ba922a99aaead48d67 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 31 May 2006 19:12:17 +0200 Subject: [PATCH 25/32] correct type for federated_db_init() --- sql/ha_federated.cc | 2 +- sql/ha_federated.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index 30988c6c8d0..76fa9715ef0 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -399,7 +399,7 @@ static byte *federated_get_key(FEDERATED_SHARE *share, uint *length, TRUE Error */ -bool federated_db_init() +int federated_db_init() { DBUG_ENTER("federated_db_init"); diff --git a/sql/ha_federated.h b/sql/ha_federated.h index 458ef42ebda..de7f7c4f178 100644 --- a/sql/ha_federated.h +++ b/sql/ha_federated.h @@ -307,6 +307,6 @@ public: int execute_simple_query(const char *query, int len); }; -bool federated_db_init(void); +int federated_db_init(void); int federated_db_end(ha_panic_function type); From a706b2a33a8450f8ce8b3da728d39eb72271d0a3 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 31 May 2006 13:32:14 -0400 Subject: [PATCH 26/32] BUG#18198: Many strange partition functions were allowed, now only strictly allowed functions are ok mysql-test/r/partition_error.result: New test cases mysql-test/t/partition_error.test: New test cases sql/item.h: Added method check_partition_func_processor for check if item tree is valid sql/item_cmpfunc.h: Added method check_partition_func_processor for check if item tree is valid sql/item_func.h: Added method check_partition_func_processor for check if item tree is valid sql/item_strfunc.h: Added method check_partition_func_processor for check if item tree is valid sql/item_timefunc.h: Added method check_partition_func_processor for check if item tree is valid sql/item_xmlfunc.h: Added method check_partition_func_processor for check if item tree is valid --- mysql-test/r/partition_error.result | 23 +++++++++++ mysql-test/t/partition_error.test | 28 +++++++++++++ sql/item.h | 31 +++++++++------ sql/item_cmpfunc.h | 28 ++++++------- sql/item_func.h | 62 ++++++++++++++--------------- sql/item_strfunc.h | 48 +++++++++++----------- sql/item_timefunc.h | 60 ++++++++++++++-------------- sql/item_xmlfunc.h | 2 +- 8 files changed, 170 insertions(+), 112 deletions(-) diff --git a/mysql-test/r/partition_error.result b/mysql-test/r/partition_error.result index 1a0b1dd9b3a..a7ca3d9b2fa 100644 --- a/mysql-test/r/partition_error.result +++ b/mysql-test/r/partition_error.result @@ -554,3 +554,26 @@ PARTITION BY RANGE (a) (PARTITION p1 VALUES LESS THAN(5)); insert into t1 values (10); ERROR HY000: Table has no partition for value 10 drop table t1; +create table t1 (v varchar(12)) +partition by range (ascii(v)) +(partition p0 values less than (10)); +drop table t1; +create table t1 (a int) +partition by hash (rand(a)); +ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ')' at line 2 +create table t1 (a int) +partition by hash(CURTIME() + a); +ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ')' at line 2 +create table t1 (a int) +partition by hash (NOW()+a); +ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ')' at line 2 +create table t1 (a int) +partition by hash (extract(hour from convert_tz(a, '+00:00', '+00:00'))); +ERROR HY000: This partition function is not allowed +create table t1 (a int) +partition by range (a + (select count(*) from t1)) +(partition p1 values less than (1)); +ERROR HY000: This partition function is not allowed +create table t1 (a char(10)) +partition by hash (extractvalue(a,'a')); +ERROR HY000: The PARTITION function returns the wrong type diff --git a/mysql-test/t/partition_error.test b/mysql-test/t/partition_error.test index 03a2ab41807..659f0b8cef4 100644 --- a/mysql-test/t/partition_error.test +++ b/mysql-test/t/partition_error.test @@ -747,3 +747,31 @@ CREATE TABLE t1(a int) --error ER_NO_PARTITION_FOR_GIVEN_VALUE insert into t1 values (10); drop table t1; + +# +# Bug 18198 Partitions: Verify that erroneus partition functions doesn't work +# +create table t1 (v varchar(12)) +partition by range (ascii(v)) +(partition p0 values less than (10)); +drop table t1; + +-- error 1064 +create table t1 (a int) +partition by hash (rand(a)); +-- error 1064 +create table t1 (a int) +partition by hash(CURTIME() + a); +-- error 1064 +create table t1 (a int) +partition by hash (NOW()+a); +-- error ER_PARTITION_FUNCTION_IS_NOT_ALLOWED +create table t1 (a int) +partition by hash (extract(hour from convert_tz(a, '+00:00', '+00:00'))); +-- error ER_PARTITION_FUNCTION_IS_NOT_ALLOWED +create table t1 (a int) +partition by range (a + (select count(*) from t1)) +(partition p1 values less than (1)); +-- error ER_PARTITION_FUNC_NOT_ALLOWED_ERROR +create table t1 (a char(10)) +partition by hash (extractvalue(a,'a')); diff --git a/sql/item.h b/sql/item.h index d5cddaa7177..ea68bfa9a17 100644 --- a/sql/item.h +++ b/sql/item.h @@ -745,6 +745,13 @@ public: virtual bool change_context_processor(byte *context) { return 0; } virtual bool reset_query_id_processor(byte *query_id) { return 0; } /* + Check if a partition function is allowed + SYNOPSIS + check_partition_func_processor() + bool_arg Return argument + RETURN VALUE + 0 + DESCRIPTION check_partition_func_processor is used to check if a partition function uses an allowed function. The default is that an item is not allowed in a partition function. However all mathematical functions, string @@ -1031,7 +1038,7 @@ public: Item::maybe_null= TRUE; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0; } + bool check_partition_func_processor(byte *bool_arg) { return 0; } bool fix_fields(THD *, Item **); enum Type type() const; @@ -1078,7 +1085,7 @@ public: Item_num() {} /* Remove gcc warning */ virtual Item_num *neg()= 0; Item *safe_charset_converter(CHARSET_INFO *tocs); - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; #define NO_CACHED_FIELD_INDEX ((uint)(-1)) @@ -1264,7 +1271,7 @@ public: bool is_null() { return 1; } void print(String *str) { str->append(STRING_WITH_LEN("NULL")); } Item *safe_charset_converter(CHARSET_INFO *tocs); - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_null_result :public Item_null @@ -1277,7 +1284,7 @@ public: { save_in_field(result_field, no_conversions); } - virtual bool check_partition_func_processor(byte *bool_arg) + bool check_partition_func_processor(byte *bool_arg) { *(bool *)bool_arg= FALSE; return 0; } }; @@ -1462,7 +1469,7 @@ public: {} Item *safe_charset_converter(CHARSET_INFO *tocs); void print(String *str) { str->append(func_name); } - virtual bool check_partition_func_processor(byte *bool_arg) + bool check_partition_func_processor(byte *bool_arg) { *(bool *)bool_arg= FALSE; return 0; } }; @@ -1582,7 +1589,7 @@ public: {} void print(String *str) { str->append(func_name); } Item *safe_charset_converter(CHARSET_INFO *tocs); - virtual bool check_partition_func_processor(byte *bool_arg) + bool check_partition_func_processor(byte *bool_arg) { *(bool *)bool_arg= FALSE; return 0; } }; @@ -1661,7 +1668,7 @@ public: void print(String *str); // to prevent drop fixed flag (no need parent cleanup call) void cleanup() {} - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -1676,7 +1683,7 @@ public: {} Item *safe_charset_converter(CHARSET_INFO *tocs); void print(String *str) { str->append(func_name); } - virtual bool check_partition_func_processor(byte *bool_arg) + bool check_partition_func_processor(byte *bool_arg) { *(bool *)bool_arg= FALSE; return 0; } }; @@ -1690,7 +1697,7 @@ public: &my_charset_bin) { max_length=19;} enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; } - virtual bool check_partition_func_processor(byte *bool_arg) + bool check_partition_func_processor(byte *bool_arg) { *(bool *)bool_arg= FALSE; return 0; } }; @@ -1714,7 +1721,7 @@ public: unsigned_flag=1; } enum_field_types field_type() const { return int_field_type; } - virtual bool check_partition_func_processor(byte *bool_arg) + bool check_partition_func_processor(byte *bool_arg) { *(bool *)bool_arg= FALSE; return 0; } }; @@ -1739,7 +1746,7 @@ public: void cleanup() {} bool eq(const Item *item, bool binary_cmp) const; virtual Item *safe_charset_converter(CHARSET_INFO *tocs); - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -1977,7 +1984,7 @@ public: } Item *new_item(); virtual Item *real_item() { return ref; } - virtual bool check_partition_func_processor(byte *bool_arg) + bool check_partition_func_processor(byte *bool_arg) { *(bool *)bool_arg= FALSE; return 0; } }; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 0472fe17975..1a289c05006 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -239,7 +239,7 @@ public: } Item *neg_transformer(THD *thd); virtual Item *negated_item(); - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_not :public Item_bool_func @@ -250,7 +250,7 @@ public: enum Functype functype() const { return NOT_FUNC; } const char *func_name() const { return "not"; } Item *neg_transformer(THD *thd); - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_maxmin_subselect; @@ -465,7 +465,7 @@ public: bool is_bool_func() { return 1; } CHARSET_INFO *compare_collation() { return cmp_collation.collation; } uint decimal_precision() const { return 1; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -477,7 +477,7 @@ public: optimize_type select_optimize() const { return OPTIMIZE_NONE; } const char *func_name() const { return "strcmp"; } void print(String *str) { Item_func::print(str); } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -540,7 +540,7 @@ public: const char *func_name() const { return "ifnull"; } Field *tmp_table_field(TABLE *table); uint decimal_precision() const; - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -581,7 +581,7 @@ public: void print(String *str) { Item_func::print(str); } table_map not_null_tables() const { return 0; } bool is_null(); - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -624,7 +624,7 @@ public: void print(String *str); Item *find_item(String *str); CHARSET_INFO *compare_collation() { return cmp_collation.collation; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -904,7 +904,7 @@ class Item_func_in :public Item_func_opt_neg bool nulls_in_row(); bool is_bool_func() { return 1; } CHARSET_INFO *compare_collation() { return cmp_collation.collation; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; /* Functions used by where clause */ @@ -946,7 +946,7 @@ public: optimize_type select_optimize() const { return OPTIMIZE_NULL; } Item *neg_transformer(THD *thd); CHARSET_INFO *compare_collation() { return args[0]->collation.collation; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; /* Functions used by HAVING for rewriting IN subquery */ @@ -968,7 +968,7 @@ public: */ table_map used_tables() const { return used_tables_cache | RAND_TABLE_BIT; } - virtual bool check_partition_func_processor(byte *bool_arg) + bool check_partition_func_processor(byte *bool_arg) { *(bool *)bool_arg= FALSE; return 0; } }; @@ -992,7 +992,7 @@ public: void print(String *str); CHARSET_INFO *compare_collation() { return args[0]->collation.collation; } void top_level_item() { abort_on_null=1; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -1031,7 +1031,7 @@ public: const char *func_name() const { return "like"; } bool fix_fields(THD *thd, Item **ref); void cleanup(); - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; #ifdef USE_REGEX @@ -1054,7 +1054,7 @@ public: const char *func_name() const { return "regexp"; } void print(String *str) { print_op(str); } CHARSET_INFO *compare_collation() { return cmp_collation.collation; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; #else @@ -1111,7 +1111,7 @@ public: Item *transform(Item_transformer transformer, byte *arg); void traverse_cond(Cond_traverser, void *arg, traverse_order order); void neg_arguments(THD *thd); - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; diff --git a/sql/item_func.h b/sql/item_func.h index 58ac28aeb9d..4d942bf8775 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -247,7 +247,7 @@ public: void fix_num_length_and_dec(); void find_num_type(); String *str_op(String *str) { DBUG_ASSERT(0); return 0; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -260,7 +260,7 @@ class Item_num_op :public Item_func_numhybrid void print(String *str) { print_op(str); } void find_num_type(); String *str_op(String *str) { DBUG_ASSERT(0); return 0; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -298,7 +298,7 @@ public: { max_length=args[0]->max_length; unsigned_flag=0; } void print(String *str); uint decimal_precision() const { return args[0]->decimal_precision(); } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -332,7 +332,7 @@ public: void fix_length_and_dec() {}; const char *func_name() const { return "decimal_typecast"; } void print(String *); - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -401,7 +401,7 @@ public: const char *func_name() const { return "DIV"; } void fix_length_and_dec(); void print(String *str) { print_op(str); } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -474,7 +474,7 @@ public: Item_func_exp(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "exp"; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -484,7 +484,7 @@ public: Item_func_ln(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "ln"; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -495,7 +495,7 @@ public: Item_func_log(Item *a,Item *b) :Item_dec_func(a,b) {} double val_real(); const char *func_name() const { return "log"; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -505,7 +505,7 @@ public: Item_func_log2(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "log2"; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -515,7 +515,7 @@ public: Item_func_log10(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "log10"; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -525,7 +525,7 @@ public: Item_func_sqrt(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "sqrt"; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -535,7 +535,7 @@ public: Item_func_pow(Item *a,Item *b) :Item_dec_func(a,b) {} double val_real(); const char *func_name() const { return "pow"; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -545,7 +545,7 @@ public: Item_func_acos(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "acos"; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_asin :public Item_dec_func @@ -554,7 +554,7 @@ public: Item_func_asin(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "asin"; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_atan :public Item_dec_func @@ -564,7 +564,7 @@ public: Item_func_atan(Item *a,Item *b) :Item_dec_func(a,b) {} double val_real(); const char *func_name() const { return "atan"; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_cos :public Item_dec_func @@ -573,7 +573,7 @@ public: Item_func_cos(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "cos"; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_sin :public Item_dec_func @@ -582,7 +582,7 @@ public: Item_func_sin(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "sin"; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_tan :public Item_dec_func @@ -591,7 +591,7 @@ public: Item_func_tan(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "tan"; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_integer :public Item_int_func @@ -668,7 +668,7 @@ public: Item_func_sign(Item *a) :Item_int_func(a) {} const char *func_name() const { return "sign"; } longlong val_int(); - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -683,7 +683,7 @@ public: const char *func_name() const { return name; } void fix_length_and_dec() { decimals= NOT_FIXED_DEC; max_length= float_length(decimals); } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -701,7 +701,7 @@ public: my_decimal *val_decimal(my_decimal *); void fix_length_and_dec(); enum Item_result result_type () const { return cmp_type; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_min :public Item_func_min_max @@ -727,7 +727,7 @@ public: longlong val_int(); const char *func_name() const { return "length"; } void fix_length_and_dec() { max_length=10; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_bit_length :public Item_func_length @@ -747,7 +747,7 @@ public: longlong val_int(); const char *func_name() const { return "char_length"; } void fix_length_and_dec() { max_length=10; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_coercibility :public Item_int_func @@ -758,7 +758,7 @@ public: const char *func_name() const { return "coercibility"; } void fix_length_and_dec() { max_length=10; maybe_null= 0; } table_map not_null_tables() const { return 0; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_locate :public Item_int_func @@ -772,7 +772,7 @@ public: longlong val_int(); void fix_length_and_dec(); void print(String *str); - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -797,7 +797,7 @@ public: longlong val_int(); const char *func_name() const { return "ascii"; } void fix_length_and_dec() { max_length=3; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_ord :public Item_int_func @@ -807,7 +807,7 @@ public: Item_func_ord(Item *a) :Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "ord"; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_find_in_set :public Item_int_func @@ -821,7 +821,7 @@ public: longlong val_int(); const char *func_name() const { return "find_in_set"; } void fix_length_and_dec(); - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; /* Base class for all bit functions: '~', '|', '^', '&', '>>', '<<' */ @@ -833,7 +833,7 @@ public: Item_func_bit(Item *a) :Item_int_func(a) {} void fix_length_and_dec() { unsigned_flag= 1; } void print(String *str) { print_op(str); } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_bit_or :public Item_func_bit @@ -859,7 +859,7 @@ public: longlong val_int(); const char *func_name() const { return "bit_count"; } void fix_length_and_dec() { max_length=2; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_shift_left :public Item_func_bit @@ -1286,7 +1286,7 @@ public: longlong val_int(); const char *func_name() const { return "inet_aton"; } void fix_length_and_dec() { decimals = 0; max_length = 21; maybe_null=1;} - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 5e4fe49e281..2b244347876 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -46,7 +46,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "md5"; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -57,7 +57,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "sha"; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_aes_encrypt :public Item_str_func @@ -88,7 +88,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "concat"; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_concat_ws :public Item_str_func @@ -109,7 +109,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "reverse"; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -147,7 +147,7 @@ protected: public: Item_str_conv(Item *item) :Item_str_func(item) {} String *val_str(String *); - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -211,7 +211,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "substr"; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -223,7 +223,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "substring_index"; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -238,7 +238,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "trim"; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -418,7 +418,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "soundex"; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -526,7 +526,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "rpad"; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -539,7 +539,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "lpad"; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -554,7 +554,7 @@ public: collation.set(default_charset()); decimals=0; max_length=64; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -571,7 +571,7 @@ public: decimals=0; max_length=args[0]->max_length*2*collation.collation->mbmaxlen; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_unhex :public Item_str_func @@ -587,7 +587,7 @@ public: decimals=0; max_length=(1+args[0]->max_length)/2; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -611,7 +611,7 @@ public: } void print(String *str); const char *func_name() const { return "cast_as_binary"; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -651,7 +651,7 @@ public: String* val_str(String* str); const char *func_name() const { return "inet_ntoa"; } void fix_length_and_dec() { decimals = 0; max_length=3*8+7; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_quote :public Item_str_func @@ -666,7 +666,7 @@ public: collation.set(args[0]->collation); max_length= args[0]->max_length * 2 + 2; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_conv_charset :public Item_str_func @@ -709,7 +709,7 @@ public: void fix_length_and_dec(); const char *func_name() const { return "convert"; } void print(String *str); - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_set_collation :public Item_str_func @@ -742,7 +742,7 @@ public: maybe_null= 0; }; table_map not_null_tables() const { return 0; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_collation :public Item_str_func @@ -758,7 +758,7 @@ public: maybe_null= 0; }; table_map not_null_tables() const { return 0; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_crc32 :public Item_int_func @@ -769,7 +769,7 @@ public: const char *func_name() const { return "crc32"; } void fix_length_and_dec() { max_length=10; } longlong val_int(); - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_uncompressed_length : public Item_int_func @@ -780,7 +780,7 @@ public: const char *func_name() const{return "uncompressed_length";} void fix_length_and_dec() { max_length=10; } longlong val_int(); - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; #ifdef HAVE_COMPRESS @@ -797,7 +797,7 @@ public: void fix_length_and_dec(){max_length= (args[0]->max_length*120)/100+12;} const char *func_name() const{return "compress";} String *val_str(String *) ZLIB_DEPENDED_FUNCTION - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_uncompress: public Item_str_func @@ -808,7 +808,7 @@ public: void fix_length_and_dec(){max_length= MAX_BLOB_WIDTH;} const char *func_name() const{return "uncompress";} String *val_str(String *) ZLIB_DEPENDED_FUNCTION - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; #define UUID_LENGTH (8+1+4+1+4+1+4+1+12) diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index a42232fd0fc..cbac0564faf 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -39,7 +39,7 @@ public: { max_length=6*MY_CHARSET_BIN_MB_MAXLEN; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -54,7 +54,7 @@ public: decimals=0; max_length=6*MY_CHARSET_BIN_MB_MAXLEN; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -71,7 +71,7 @@ public: maybe_null=1; } enum_monotonicity_info get_monotonicity_info() const; - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -87,7 +87,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -112,7 +112,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -145,7 +145,7 @@ public: max_length=3*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -161,7 +161,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -177,7 +177,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -193,7 +193,7 @@ public: max_length=1*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -209,7 +209,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -225,7 +225,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_yearweek :public Item_int_func @@ -240,7 +240,7 @@ public: max_length=6*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -257,7 +257,7 @@ public: max_length=4*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -287,7 +287,7 @@ public: max_length=1*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_dayname :public Item_func_weekday @@ -320,7 +320,7 @@ public: decimals=0; max_length=10*MY_CHARSET_BIN_MB_MAXLEN; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -335,7 +335,7 @@ public: decimals=0; max_length=10*MY_CHARSET_BIN_MB_MAXLEN; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -542,7 +542,7 @@ public: Item_func_from_days(Item *a) :Item_date(a) {} const char *func_name() const { return "from_days"; } bool get_date(TIME *res, uint fuzzy_date); - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -560,7 +560,7 @@ public: void fix_length_and_dec(); uint format_length(const String *format); bool eq(const Item *item, bool binary_cmp) const; - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -579,7 +579,7 @@ class Item_func_from_unixtime :public Item_date_func const char *func_name() const { return "from_unixtime"; } void fix_length_and_dec(); bool get_date(TIME *res, uint fuzzy_date); - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -646,7 +646,7 @@ public: { return tmp_table_field_from_field_type(table, 0); } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -669,7 +669,7 @@ public: bool get_date(TIME *res, uint fuzzy_date); bool eq(const Item *item, bool binary_cmp) const; void print(String *str); - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -687,7 +687,7 @@ class Item_extract :public Item_int_func void fix_length_and_dec(); bool eq(const Item *item, bool binary_cmp) const; void print(String *str); - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -724,7 +724,7 @@ public: max_length=args[0]->max_length; maybe_null= 1; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -744,7 +744,7 @@ public: String *val_str(String *a); void fix_length_and_dec(); void print(String *str); - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -816,7 +816,7 @@ public: { return tmp_table_field_from_field_type(table, 0); } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -839,7 +839,7 @@ public: } void print(String *str); const char *func_name() const { return "add_time"; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_timediff :public Item_str_func @@ -879,7 +879,7 @@ public: { return tmp_table_field_from_field_type(table, 0); } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_microsecond :public Item_int_func @@ -893,7 +893,7 @@ public: decimals=0; maybe_null=1; } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -911,7 +911,7 @@ public: maybe_null=1; } void print(String *str); - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -958,7 +958,7 @@ public: { return tmp_table_field_from_field_type(table, 1); } - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; diff --git a/sql/item_xmlfunc.h b/sql/item_xmlfunc.h index 53302283296..e11b4eac1e2 100644 --- a/sql/item_xmlfunc.h +++ b/sql/item_xmlfunc.h @@ -42,7 +42,7 @@ public: Item_func_xml_extractvalue(Item *a,Item *b) :Item_xml_str_func(a,b) {} const char *func_name() const { return "extractvalue"; } String *val_str(String *); - virtual bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; From 0d55b2ea8786d77a13667c9f27232d5d0d3a8a69 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 31 May 2006 23:24:25 +0200 Subject: [PATCH 27/32] Bug #18947 CRBR: order in binlog of create table and insert (on different table) not determ - move clear of slock until after completion of data events on the binlog --- sql/ha_ndbcluster_binlog.cc | 53 ++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index 48273320cc0..b85d03ca888 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -1720,37 +1720,26 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, bitmap_init(&slock, schema->slock, 8*SCHEMA_SLOCK_SIZE, false); uint node_id= g_ndb_cluster_connection->node_id(); ndbcluster_get_schema(tmp_share, schema); + enum SCHEMA_OP_TYPE schema_type= (enum SCHEMA_OP_TYPE)schema->type; DBUG_PRINT("info", ("%s.%s: log query_length: %d query: '%s' type: %d", schema->db, schema->name, schema->query_length, schema->query, - schema->type)); - char key[FN_REFLEN]; - build_table_filename(key, sizeof(key), schema->db, schema->name, ""); - if ((enum SCHEMA_OP_TYPE)schema->type == SOT_CLEAR_SLOCK) + schema_type)); + if (schema_type == SOT_CLEAR_SLOCK) { - pthread_mutex_lock(&ndbcluster_mutex); - NDB_SCHEMA_OBJECT *ndb_schema_object= - (NDB_SCHEMA_OBJECT*) hash_search(&ndb_schema_objects, - (byte*) key, strlen(key)); - if (ndb_schema_object) - { - pthread_mutex_lock(&ndb_schema_object->mutex); - memcpy(ndb_schema_object->slock, schema->slock, - sizeof(ndb_schema_object->slock)); - DBUG_DUMP("ndb_schema_object->slock_bitmap.bitmap", - (char*)ndb_schema_object->slock_bitmap.bitmap, - no_bytes_in_map(&ndb_schema_object->slock_bitmap)); - pthread_mutex_unlock(&ndb_schema_object->mutex); - pthread_cond_signal(&injector_cond); - } - pthread_mutex_unlock(&ndbcluster_mutex); + /* + handle slock after epoch is completed to ensure that + schema events get inserted in the binlog after any data + events + */ + post_epoch_log_list->push_back(schema, mem_root); DBUG_RETURN(0); } if (schema->node_id != node_id) { int log_query= 0, post_epoch_unlock= 0; - switch ((enum SCHEMA_OP_TYPE)schema->type) + switch (schema_type) { case SOT_DROP_TABLE: // fall through @@ -1944,10 +1933,30 @@ ndb_binlog_thread_handle_schema_event_post_epoch(THD *thd, schema->type)); int log_query= 0; { + enum SCHEMA_OP_TYPE schema_type= (enum SCHEMA_OP_TYPE)schema->type; char key[FN_REFLEN]; build_table_filename(key, sizeof(key), schema->db, schema->name, ""); + if (schema_type == SOT_CLEAR_SLOCK) + { + pthread_mutex_lock(&ndbcluster_mutex); + NDB_SCHEMA_OBJECT *ndb_schema_object= + (NDB_SCHEMA_OBJECT*) hash_search(&ndb_schema_objects, + (byte*) key, strlen(key)); + if (ndb_schema_object) + { + pthread_mutex_lock(&ndb_schema_object->mutex); + memcpy(ndb_schema_object->slock, schema->slock, + sizeof(ndb_schema_object->slock)); + DBUG_DUMP("ndb_schema_object->slock_bitmap.bitmap", + (char*)ndb_schema_object->slock_bitmap.bitmap, + no_bytes_in_map(&ndb_schema_object->slock_bitmap)); + pthread_mutex_unlock(&ndb_schema_object->mutex); + pthread_cond_signal(&injector_cond); + } + pthread_mutex_unlock(&ndbcluster_mutex); + continue; + } NDB_SHARE *share= get_share(key, 0, false, false); - enum SCHEMA_OP_TYPE schema_type= (enum SCHEMA_OP_TYPE)schema->type; switch (schema_type) { case SOT_DROP_DB: From 5c27329565ef1dc72e6ca127af0a7ca000862970 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Jun 2006 00:03:05 +0200 Subject: [PATCH 28/32] mention new files in Makefile --- include/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/Makefile.am b/include/Makefile.am index e1ddadb933a..27b359bb6a3 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -31,7 +31,8 @@ noinst_HEADERS = config-win.h config-netware.h \ my_aes.h my_tree.h my_trie.h hash.h thr_alarm.h \ thr_lock.h t_ctype.h violite.h md5.h base64.h \ mysql_version.h.in my_handler.h my_time.h decimal.h \ - my_vle.h my_user.h + my_vle.h my_user.h my_atomic.h atomic/nolock.h \ + atomic/rwlock.h atomic/x86-gcc.h atomic/x86-msvc.h # mysql_version.h are generated CLEANFILES = mysql_version.h my_config.h readline openssl From 49a4c85bdf4e0b00243197c660b398ed4233cb9d Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Jun 2006 08:24:05 +0200 Subject: [PATCH 29/32] ndb - bug#20185 Dont be too aggressive in Dbtc::nodeFailCheckTransaction let it timeout by 1, so that it does not assert that it has waited too long old impl. set timeotu value to 0, making timeout = (ctcTimer - 0) which could be quite big. ndb/src/kernel/blocks/ERROR_codes.txt: error codes ndb/src/kernel/blocks/dbdih/DbdihMain.cpp: 2 new error inserts 7030 - delay in GCP_PREPARE until checkLocalNodefailComplete is true 7031 - delay in GCP_PREPARE and die ndb/src/kernel/blocks/dbtc/DbtcMain.cpp: Dont set api con timer to 0, as this might trigger asserion in timeoutfound lab if state == PREPARE_TO_COMMIT ndb/test/ndbapi/testNodeRestart.cpp: testcase ndb/test/run-test/daily-basic-tests.txt: autotest --- ndb/src/kernel/blocks/ERROR_codes.txt | 3 ++ ndb/src/kernel/blocks/dbdih/DbdihMain.cpp | 24 ++++++++++ ndb/src/kernel/blocks/dbtc/DbtcMain.cpp | 8 ++-- ndb/test/ndbapi/testNodeRestart.cpp | 56 +++++++++++++++++++++++ ndb/test/run-test/daily-basic-tests.txt | 4 ++ 5 files changed, 92 insertions(+), 3 deletions(-) diff --git a/ndb/src/kernel/blocks/ERROR_codes.txt b/ndb/src/kernel/blocks/ERROR_codes.txt index 4887b6a7ea5..20f03e7ea69 100644 --- a/ndb/src/kernel/blocks/ERROR_codes.txt +++ b/ndb/src/kernel/blocks/ERROR_codes.txt @@ -63,6 +63,9 @@ Delay GCP_SAVEREQ by 10 secs 7165: Delay INCL_NODE_REQ in starting node yeilding error in GCP_PREPARE +7030: Delay in GCP_PREPARE until node has completed a node failure +7031: Delay in GCP_PREPARE and die 3s later + ERROR CODES FOR TESTING NODE FAILURE, LOCAL CHECKPOINT HANDLING: ----------------------------------------------------------------- diff --git a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp index 3bbf1c76644..65c864bd853 100644 --- a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp +++ b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp @@ -5417,6 +5417,12 @@ Dbdih::checkLocalNodefailComplete(Signal* signal, Uint32 failedNodeId, return; } + if (ERROR_INSERTED(7030)) + { + ndbout_c("Reenable GCP_PREPARE"); + CLEAR_ERROR_INSERT_VALUE; + } + NFCompleteRep * const nf = (NFCompleteRep *)&signal->theData[0]; nf->blockNo = DBDIH; nf->nodeId = cownNodeId; @@ -7459,6 +7465,16 @@ void Dbdih::execGCP_PREPARE(Signal* signal) { jamEntry(); CRASH_INSERTION(7005); + + if (ERROR_INSERTED(7030)) + { + cgckptflag = true; + ndbout_c("Delayed GCP_PREPARE 5s"); + sendSignalWithDelay(reference(), GSN_GCP_PREPARE, signal, 5000, + signal->getLength()); + return; + } + Uint32 masterNodeId = signal->theData[0]; Uint32 gci = signal->theData[1]; BlockReference retRef = calcDihBlockRef(masterNodeId); @@ -7471,6 +7487,14 @@ void Dbdih::execGCP_PREPARE(Signal* signal) cgcpParticipantState = GCP_PARTICIPANT_PREPARE_RECEIVED; cnewgcp = gci; + if (ERROR_INSERTED(7031)) + { + ndbout_c("Crashing delayed in GCP_PREPARE 3s"); + signal->theData[0] = 9999; + sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 3000, 1); + return; + } + signal->theData[0] = cownNodeId; signal->theData[1] = gci; sendSignal(retRef, GSN_GCP_PREPARECONF, signal, 2, JBA); diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp index 7982fe82e45..2bd61296554 100644 --- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp +++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp @@ -7002,18 +7002,20 @@ Dbtc::nodeFailCheckTransactions(Signal* signal, { jam(); Ptr transPtr; + Uint32 TtcTimer = ctcTimer; + Uint32 TapplTimeout = c_appl_timeout_value; for (transPtr.i = transPtrI; transPtr.i < capiConnectFilesize; transPtr.i++) { ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord); if (transPtr.p->m_transaction_nodes.get(failedNodeId)) { jam(); + // Force timeout regardless of state - Uint32 save = c_appl_timeout_value; c_appl_timeout_value = 1; - setApiConTimer(transPtr.i, 0, __LINE__); + setApiConTimer(transPtr.i, TtcTimer - 2, __LINE__); timeOutFoundLab(signal, transPtr.i, ZNODEFAIL_BEFORE_COMMIT); - c_appl_timeout_value = save; + c_appl_timeout_value = TapplTimeout; } // Send CONTINUEB to continue later diff --git a/ndb/test/ndbapi/testNodeRestart.cpp b/ndb/test/ndbapi/testNodeRestart.cpp index 7017aac0ade..68f101442c5 100644 --- a/ndb/test/ndbapi/testNodeRestart.cpp +++ b/ndb/test/ndbapi/testNodeRestart.cpp @@ -868,6 +868,56 @@ runBug18612SR(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_OK; } +int runBug20185(NDBT_Context* ctx, NDBT_Step* step){ + int result = NDBT_OK; + int loops = ctx->getNumLoops(); + int records = ctx->getNumRecords(); + NdbRestarter restarter; + HugoOperations hugoOps(*ctx->getTab()); + Ndb* pNdb = GETNDB(step); + + int dump[] = { 7090, 20 } ; + if (restarter.dumpStateAllNodes(dump, 2)) + return NDBT_FAILED; + + NdbSleep_MilliSleep(3000); + + if(hugoOps.startTransaction(pNdb) != 0) + return NDBT_FAILED; + + if(hugoOps.pkUpdateRecord(pNdb, 1, 1) != 0) + return NDBT_FAILED; + + if (hugoOps.execute_NoCommit(pNdb) != 0) + return NDBT_FAILED; + + int nodeId; + const int node = hugoOps.getTransaction()->getConnectedNodeId(); + do { + nodeId = restarter.getDbNodeId(rand() % restarter.getNumDbNodes()); + } while (nodeId == node); + + if (restarter.insertErrorInAllNodes(7030)) + return NDBT_FAILED; + + if (restarter.insertErrorInNode(nodeId, 7031)) + return NDBT_FAILED; + + NdbSleep_MilliSleep(500); + + if (hugoOps.execute_Commit(pNdb) == 0) + return NDBT_FAILED; + + NdbSleep_MilliSleep(3000); + + restarter.waitClusterStarted(); + + if (restarter.dumpStateAllNodes(dump, 1)) + return NDBT_FAILED; + + return NDBT_OK; +} + NDBT_TESTSUITE(testNodeRestart); TESTCASE("NoLoad", @@ -1175,6 +1225,12 @@ TESTCASE("Bug18612SR", STEP(runBug18612SR); FINALIZER(runClearTable); } +TESTCASE("Bug20185", + ""){ + INITIALIZER(runLoadTable); + STEP(runBug20185); + FINALIZER(runClearTable); +} NDBT_TESTSUITE_END(testNodeRestart); int main(int argc, const char** argv){ diff --git a/ndb/test/run-test/daily-basic-tests.txt b/ndb/test/run-test/daily-basic-tests.txt index 508bf4c3d1e..e70dcafb249 100644 --- a/ndb/test/run-test/daily-basic-tests.txt +++ b/ndb/test/run-test/daily-basic-tests.txt @@ -470,6 +470,10 @@ max-time: 1000 cmd: testNodeRestart args: -n Bug18612SR T1 +max-time: 1000 +cmd: testNodeRestart +args: -n Bug20185 T1 + # OLD FLEX max-time: 500 cmd: flexBench From 740077bdc58a20faf66fab159f56626b8acf3662 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Jun 2006 12:25:47 +0200 Subject: [PATCH 30/32] unittest: rename *.t* to *-t* to be automake-friendly simplify Makefiles test_atomic.c: move to unittest, add GPL comment, fix warnings, convert to tap framework. configure: remove custom tests for available types, use AC_CHECK_TYPE instead x86-gcc.h: fix gcc -ansi errors while maintaining readability ignore: added *-t unittest/mysys/base64-t.c: Rename: unittest/mysys/base64.t.c -> unittest/mysys/base64-t.c unittest/mysys/bitmap-t.c: Rename: unittest/mysys/bitmap.t.c -> unittest/mysys/bitmap-t.c unittest/mytap/t/basic-t.c: Rename: unittest/mytap/t/basic.t.c -> unittest/mytap/t/basic-t.c unittest/examples/no_plan-t.c: Rename: unittest/examples/no_plan.t.c -> unittest/examples/no_plan-t.c unittest/examples/simple-t.c: Rename: unittest/examples/simple.t.c -> unittest/examples/simple-t.c unittest/examples/skip-t.c: Rename: unittest/examples/skip.t.c -> unittest/examples/skip-t.c unittest/examples/skip_all-t.c: Rename: unittest/examples/skip_all.t.c -> unittest/examples/skip_all-t.c unittest/examples/todo-t.c: Rename: unittest/examples/todo.t.c -> unittest/examples/todo-t.c BitKeeper/etc/ignore: added *-t config/ac-macros/misc.m4: remove custom AC_TRY_RUN tests for available types, use AC_CHECK_TYPE instead configure.in: remove custom tests for available types, use AC_CHECK_TYPE instead include/atomic/x86-gcc.h: fix gcc -ansi errors while maintaining readability include/my_global.h: remove custom tests for available types, use AC_CHECK_TYPE instead include/my_sys.h: add missing declaration mysys/Makefile.am: move test_atomic to unittest unittest/Makefile.am: simplifications, correct permissions in chmod unittest/README.txt: rename *.t* to *-t* to be automake-friendly unittest/examples/Makefile.am: rename *.t* to *-t* to be automake-friendly simplify Makefile unittest/mysys/Makefile.am: rename *.t* to *-t* to be automake-friendly simplify Makefile unittest/mysys/my_atomic-t.c: move mysys/test_atomic.c to unittest, add GPL comment, fix warnings, convert to tap framework. unittest/mytap/t/Makefile.am: rename *.t* to *-t* to be automake-friendly simplify Makefile unittest/unit.pl: rename *.t* to *-t* to be automake-friendly --- .bzrignore | 1 + config/ac-macros/misc.m4 | 97 ------------------- configure.in | 54 +++-------- include/atomic/x86-gcc.h | 3 + include/my_global.h | 38 +++++--- include/my_sys.h | 5 +- mysys/Makefile.am | 1 - unittest/Makefile.am | 25 ++--- unittest/README.txt | 23 +++-- unittest/examples/Makefile.am | 11 +-- .../examples/{no_plan.t.c => no_plan-t.c} | 0 unittest/examples/{simple.t.c => simple-t.c} | 0 unittest/examples/{skip.t.c => skip-t.c} | 0 .../examples/{skip_all.t.c => skip_all-t.c} | 0 unittest/examples/{todo.t.c => todo-t.c} | 0 unittest/mysys/Makefile.am | 6 +- unittest/mysys/{base64.t.c => base64-t.c} | 0 unittest/mysys/{bitmap.t.c => bitmap-t.c} | 0 .../mysys/my_atomic-t.c | 42 +++++--- unittest/mytap/t/Makefile.am | 5 +- unittest/mytap/t/{basic.t.c => basic-t.c} | 0 unittest/unit.pl | 2 +- 22 files changed, 98 insertions(+), 215 deletions(-) rename unittest/examples/{no_plan.t.c => no_plan-t.c} (100%) rename unittest/examples/{simple.t.c => simple-t.c} (100%) rename unittest/examples/{skip.t.c => skip-t.c} (100%) rename unittest/examples/{skip_all.t.c => skip_all-t.c} (100%) rename unittest/examples/{todo.t.c => todo-t.c} (100%) rename unittest/mysys/{base64.t.c => base64-t.c} (100%) rename unittest/mysys/{bitmap.t.c => bitmap-t.c} (100%) rename mysys/test_atomic.c => unittest/mysys/my_atomic-t.c (71%) rename unittest/mytap/t/{basic.t.c => basic-t.c} (100%) diff --git a/.bzrignore b/.bzrignore index 27e8cb3c79d..b3bc5760f59 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1772,3 +1772,4 @@ zlib/*.ds? zlib/*.vcproj libmysqld/event_scheduler.cc mysys/test_atomic +*-t diff --git a/config/ac-macros/misc.m4 b/config/ac-macros/misc.m4 index a2f70071e2d..3ed64b5625b 100644 --- a/config/ac-macros/misc.m4 +++ b/config/ac-macros/misc.m4 @@ -155,84 +155,6 @@ fi ]) -#---START: Used in for client configure -AC_DEFUN([MYSQL_CHECK_ULONG], -[AC_MSG_CHECKING(for type ulong) -AC_CACHE_VAL(ac_cv_ulong, -[AC_TRY_RUN([#include -#include -main() -{ - ulong foo; - foo++; - exit(0); -}], ac_cv_ulong=yes, ac_cv_ulong=no, ac_cv_ulong=no)]) -AC_MSG_RESULT($ac_cv_ulong) -if test "$ac_cv_ulong" = "yes" -then - AC_DEFINE([HAVE_ULONG], [1], [system headers define ulong]) -fi -]) - -AC_DEFUN([MYSQL_CHECK_UCHAR], -[AC_MSG_CHECKING(for type uchar) -AC_CACHE_VAL(ac_cv_uchar, -[AC_TRY_RUN([#include -#include -main() -{ - uchar foo; - foo++; - exit(0); -}], ac_cv_uchar=yes, ac_cv_uchar=no, ac_cv_uchar=no)]) -AC_MSG_RESULT($ac_cv_uchar) -if test "$ac_cv_uchar" = "yes" -then - AC_DEFINE([HAVE_UCHAR], [1], [system headers define uchar]) -fi -]) - -AC_DEFUN([MYSQL_CHECK_UINT], -[AC_MSG_CHECKING(for type uint) -AC_CACHE_VAL(ac_cv_uint, -[AC_TRY_RUN([#include -#include -main() -{ - uint foo; - foo++; - exit(0); -}], ac_cv_uint=yes, ac_cv_uint=no, ac_cv_uint=no)]) -AC_MSG_RESULT($ac_cv_uint) -if test "$ac_cv_uint" = "yes" -then - AC_DEFINE([HAVE_UINT], [1], [system headers define uint]) -fi -]) - - -AC_DEFUN([MYSQL_CHECK_IN_ADDR_T], -[AC_MSG_CHECKING(for type in_addr_t) -AC_CACHE_VAL(ac_cv_in_addr_t, -[AC_TRY_RUN([#include -#include -#include -#include -#include - -int main(int argc, char **argv) -{ - in_addr_t foo; - exit(0); -}], ac_cv_in_addr_t=yes, ac_cv_in_addr_t=no, ac_cv_in_addr_t=no)]) -AC_MSG_RESULT($ac_cv_in_addr_t) -if test "$ac_cv_in_addr_t" = "yes" -then - AC_DEFINE([HAVE_IN_ADDR_T], [1], [system headers define in_addr_t]) -fi -]) - - AC_DEFUN([MYSQL_PTHREAD_YIELD], [AC_CACHE_CHECK([if pthread_yield takes zero arguments], ac_cv_pthread_yield_zero_arg, [AC_TRY_LINK([#define _GNU_SOURCE @@ -272,25 +194,6 @@ fi #---END: -AC_DEFUN([MYSQL_CHECK_FP_EXCEPT], -[AC_MSG_CHECKING(for type fp_except) -AC_CACHE_VAL(ac_cv_fp_except, -[AC_TRY_RUN([#include -#include -#include -main() -{ - fp_except foo; - foo++; - exit(0); -}], ac_cv_fp_except=yes, ac_cv_fp_except=no, ac_cv_fp_except=no)]) -AC_MSG_RESULT($ac_cv_fp_except) -if test "$ac_cv_fp_except" = "yes" -then - AC_DEFINE([HAVE_FP_EXCEPT], [1], [fp_except from ieeefp.h]) -fi -]) - # From fileutils-3.14/aclocal.m4 # @defmac AC_PROG_CC_STDC diff --git a/configure.in b/configure.in index 1e332e390e1..be6f3c8eaec 100644 --- a/configure.in +++ b/configure.in @@ -829,38 +829,20 @@ fi # Later in this script LIBS will be augmented with a threads library. NON_THREADED_LIBS="$LIBS" -AC_MSG_CHECKING([for int8]) -case $SYSTEM_TYPE in - *netware) - AC_MSG_RESULT([no]) - ;; - *) -AC_TRY_RUN([ -#ifdef HAVE_STDLIB_H -#include -#endif - -#ifdef HAVE_STDDEF_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H +AC_CHECK_TYPES([int8, uint8, int16, uint16, int32, uint32, int64, uint64, + uchar, uint, ulong],[],[], [ #include -#endif - -int main() -{ - int8 i; - return 0; -} -], -[AC_DEFINE([HAVE_INT_8_16_32], [1], - [whether int8, int16 and int32 types exist]) -AC_MSG_RESULT([yes])], -[AC_MSG_RESULT([no])] -) - ;; -esac +]) +AC_CHECK_TYPES([in_addr_t], [], [], [ +#include +#include +#include +#include +]) +AC_CHECK_TYPES([fp_except], [], [], [ +#include +#include +]) # # Some system specific hacks @@ -1734,16 +1716,6 @@ MYSQL_FUNC_ALLOCA MYSQL_TIMESPEC_TS # Do we have the tzname variable MYSQL_TZNAME -# Do the system files define ulong -MYSQL_CHECK_ULONG -# Do the system files define uchar -MYSQL_CHECK_UCHAR -# Do the system files define uint -MYSQL_CHECK_UINT -# Check for fp_except in ieeefp.h -MYSQL_CHECK_FP_EXCEPT -# Check for IN_ADDR_T -MYSQL_CHECK_IN_ADDR_T # Do the c++ compiler have a bool type MYSQL_CXX_BOOL # Check some common bugs with gcc 2.8.# on sparc diff --git a/include/atomic/x86-gcc.h b/include/atomic/x86-gcc.h index b06d80d37e5..7576db54d69 100644 --- a/include/atomic/x86-gcc.h +++ b/include/atomic/x86-gcc.h @@ -19,6 +19,9 @@ cmpxchg8b, if necessary */ +/* fix -ansi errors while maintaining readability */ +#define asm __asm__ + #define make_atomic_add_body8 \ asm volatile (LOCK "xadd %0, %1;" : "+r" (v) , "+m" (a->val)) #define make_atomic_swap_body8 \ diff --git a/include/my_global.h b/include/my_global.h index 81fa5225c3b..f2ad3af0b6f 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -864,26 +864,36 @@ typedef void *gptr; /* Generic pointer */ #else typedef char *gptr; /* Generic pointer */ #endif -#ifndef HAVE_INT_8_16_32 -typedef signed char int8; /* Signed integer >= 8 bits */ -typedef short int16; /* Signed integer >= 16 bits */ -#endif #ifndef HAVE_UCHAR typedef unsigned char uchar; /* Short for unsigned char */ #endif -typedef unsigned char uint8; /* Short for unsigned integer >= 8 bits */ -typedef unsigned short uint16; /* Short for unsigned integer >= 16 bits */ +#ifndef HAVE_INT8 +typedef signed char int8; /* Signed integer >= 8 bits */ +#endif +#ifndef HAVE_UINT8 +typedef unsigned char uint8; /* Unsigned integer >= 8 bits */ +#endif +#ifndef HAVE_INT16 +typedef short int16; +#endif +#ifndef HAVE_UINT16 +typedef unsigned short uint16; +#endif #if SIZEOF_INT == 4 -#ifndef HAVE_INT_8_16_32 -typedef int int32; +#ifndef HAVE_INT32 +typedef int int32; +#endif +#ifndef HAVE_UINT32 +typedef unsigned int uint32; #endif -typedef unsigned int uint32; /* Short for unsigned integer >= 32 bits */ #elif SIZEOF_LONG == 4 -#ifndef HAVE_INT_8_16_32 -typedef long int32; +#ifndef HAVE_INT32 +typedef long int32; +#endif +#ifndef HAVE_UINT32 +typedef unsigned long uint32; #endif -typedef unsigned long uint32; /* Short for unsigned integer >= 32 bits */ #else #error "Neither int or long is of 4 bytes width" #endif @@ -900,8 +910,12 @@ typedef unsigned long ulonglong; /* ulong or unsigned long long */ typedef long longlong; #endif #endif +#ifndef HAVE_INT64 typedef longlong int64; +#endif +#ifndef HAVE_UINT64 typedef ulonglong uint64; +#endif #if defined(NO_CLIENT_LONG_LONG) typedef unsigned long my_ulonglong; diff --git a/include/my_sys.h b/include/my_sys.h index 5024505a821..4ea7cecf0a1 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -821,8 +821,9 @@ extern ulong crc32(ulong crc, const uchar *buf, uint len); extern uint my_set_max_open_files(uint files); void my_free_open_file_info(void); -ulonglong my_getsystime(void); -my_bool my_gethwaddr(uchar *to); +extern ulonglong my_getsystime(void); +extern my_bool my_gethwaddr(uchar *to); +extern int my_getncpus(); #ifdef HAVE_SYS_MMAN_H #include diff --git a/mysys/Makefile.am b/mysys/Makefile.am index 93d0e896874..2838427e9e0 100644 --- a/mysys/Makefile.am +++ b/mysys/Makefile.am @@ -63,7 +63,6 @@ libmysys_a_LIBADD = @THREAD_LOBJECTS@ # testhash_DEPENDENCIES= $(LIBRARIES) # test_charset_DEPENDENCIES= $(LIBRARIES) # charset2html_DEPENDENCIES= $(LIBRARIES) -noinst_PROGRAMS= test_atomic$(EXEEXT) DEFS = -DDEFAULT_BASEDIR=\"$(prefix)\" \ -DDATADIR="\"$(MYSQLDATAdir)\"" \ -DDEFAULT_CHARSET_HOME="\"$(MYSQLBASEdir)\"" \ diff --git a/unittest/Makefile.am b/unittest/Makefile.am index bfa9f40f8ce..dc778aada1c 100644 --- a/unittest/Makefile.am +++ b/unittest/Makefile.am @@ -1,27 +1,14 @@ SUBDIRS = mytap . mysys examples noinst_SCRIPTS = unit +#EXTRA_DIST = unit.pl -EXTRA_DIST = unit.pl +unittests = mytap mysys -DISTCLEANFILES = unit - -unittests = mysys examples - -.PHONY: all mytap mysys examples test - -test: unit all - @./unit run $(unittests) - -mytap: - cd mytap && $(MAKE) - -mysys: - cd mysys && $(MAKE) - -examples: - cd examples && $(MAKE) +test: unit + ./unit run $(unittests) unit: $(srcdir)/unit.pl cp $(srcdir)/unit.pl $@ - chmod +x $@ + chmod 700 $@ + diff --git a/unittest/README.txt b/unittest/README.txt index fd9641665c7..0d8bb9025d8 100644 --- a/unittest/README.txt +++ b/unittest/README.txt @@ -7,14 +7,14 @@ will be added over time. mytap Source for the MyTAP library mysys Tests for mysys components - bitmap.t.c Unit test for MY_BITMAP - base64.t.c Unit test for base64 encoding functions + bitmap-t.c Unit test for MY_BITMAP + base64-t.c Unit test for base64 encoding functions examples Example unit tests - simple.t.c Example of a standard TAP unit test - skip.t.c Example where some test points are skipped - skip_all.t.c Example of a test where the entire test is skipped - todo.t.c Example where test contain test points that are TODO - no_plan.t.c Example of a test with no plan (avoid this) + simple-t.c Example of a standard TAP unit test + skip-t.c Example where some test points are skipped + skip_all-t.c Example of a test where the entire test is skipped + todo-t.c Example where test contain test points that are TODO + no_plan-t.c Example of a test with no plan (avoid this) Executing unit tests @@ -28,9 +28,12 @@ To make and execute all unit tests in the directory: Adding unit tests ----------------- -Add a file with a name of the format "foo.t.c" to the appropriate +Add a file with a name of the format "foo-t.c" to the appropriate directory and add the following to the Makefile.am in that directory (where ... denotes stuff already there): - noinst_PROGRAMS = ... foo.t - foo_t_c_SOURCES = foo.t.c + noinst_PROGRAMS = ... foo-t + +Note, it's important to have "-t" at the end of the filename, otherwise the +test won't be executed by 'make test' ! + diff --git a/unittest/examples/Makefile.am b/unittest/examples/Makefile.am index 94a67927d12..f3c70b654a1 100644 --- a/unittest/examples/Makefile.am +++ b/unittest/examples/Makefile.am @@ -5,14 +5,5 @@ AM_LDFLAGS = -L$(top_builddir)/unittest/mytap LDADD = -lmytap -noinst_PROGRAMS = simple.t skip.t todo.t skip_all.t no_plan.t +noinst_PROGRAMS = simple-t skip-t todo-t skip_all-t no_plan-t -simple_t_SOURCES = simple.t.c - -skip_t_SOURCES = skip.t.c - -todo_t_SOURCES = todo.t.c - -skip_all_t_SOURCES = skip_all.t.c - -no_plan_t_SOURCES = no_plan.t.c diff --git a/unittest/examples/no_plan.t.c b/unittest/examples/no_plan-t.c similarity index 100% rename from unittest/examples/no_plan.t.c rename to unittest/examples/no_plan-t.c diff --git a/unittest/examples/simple.t.c b/unittest/examples/simple-t.c similarity index 100% rename from unittest/examples/simple.t.c rename to unittest/examples/simple-t.c diff --git a/unittest/examples/skip.t.c b/unittest/examples/skip-t.c similarity index 100% rename from unittest/examples/skip.t.c rename to unittest/examples/skip-t.c diff --git a/unittest/examples/skip_all.t.c b/unittest/examples/skip_all-t.c similarity index 100% rename from unittest/examples/skip_all.t.c rename to unittest/examples/skip_all-t.c diff --git a/unittest/examples/todo.t.c b/unittest/examples/todo-t.c similarity index 100% rename from unittest/examples/todo.t.c rename to unittest/examples/todo-t.c diff --git a/unittest/mysys/Makefile.am b/unittest/mysys/Makefile.am index 010a7845339..b1e0356bac6 100644 --- a/unittest/mysys/Makefile.am +++ b/unittest/mysys/Makefile.am @@ -7,9 +7,5 @@ AM_LDFLAGS += -L$(top_builddir)/strings -L$(top_builddir)/dbug LDADD = -lmytap -lmysys -ldbug -lmystrings -noinst_PROGRAMS = bitmap.t base64.t - -bitmap_t_SOURCES = bitmap.t.c - -base64_t_SOURCES = base64.t.c +noinst_PROGRAMS = bitmap-t base64-t my_atomic-t diff --git a/unittest/mysys/base64.t.c b/unittest/mysys/base64-t.c similarity index 100% rename from unittest/mysys/base64.t.c rename to unittest/mysys/base64-t.c diff --git a/unittest/mysys/bitmap.t.c b/unittest/mysys/bitmap-t.c similarity index 100% rename from unittest/mysys/bitmap.t.c rename to unittest/mysys/bitmap-t.c diff --git a/mysys/test_atomic.c b/unittest/mysys/my_atomic-t.c similarity index 71% rename from mysys/test_atomic.c rename to unittest/mysys/my_atomic-t.c index 21315bc13a4..8a3fe129b07 100644 --- a/mysys/test_atomic.c +++ b/unittest/mysys/my_atomic-t.c @@ -1,3 +1,21 @@ +/* Copyright (C) 2006 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include + #include #include #include @@ -25,6 +43,7 @@ pthread_handler_t test_atomic_add_handler(void *arg) N--; if (!N) pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); + return 0; } /* @@ -54,6 +73,7 @@ pthread_handler_t test_atomic_swap_handler(void *arg) N--; if (!N) pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); + return 0; } /* @@ -75,6 +95,7 @@ pthread_handler_t test_atomic_cas_handler(void *arg) N--; if (!N) pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); + return 0; } void test_atomic(const char *test, pthread_handler handler, int n, int m) @@ -86,7 +107,7 @@ void test_atomic(const char *test, pthread_handler handler, int n, int m) my_atomic_store32(&b32, 0, &rwl); my_atomic_store32(&c32, 0, &rwl); - printf("Testing %s with %d threads, %d iterations... ", test, n, m); + diag("Testing %s with %d threads, %d iterations... ", test, n, m); for (N=n ; n ; n--) pthread_create(&t, &thr_attr, handler, &m); @@ -95,24 +116,19 @@ void test_atomic(const char *test, pthread_handler handler, int n, int m) pthread_cond_wait(&cond, &mutex); pthread_mutex_unlock(&mutex); now=my_getsystime()-now; - printf("got %lu in %g secs\n", my_atomic_load32(&a32, &rwl), - ((double)now)/1e7); + ok(my_atomic_load32(&a32, &rwl) == 0, + "tested %s in %g secs", test, ((double)now)/1e7); } int main() { int err; -#ifdef _IONBF - setvbuf(stdout, 0, _IONBF, 0); -#endif - printf("N CPUs: %d\n", my_getncpus()); + diag("N CPUs: %d", my_getncpus()); + err= my_atomic_initialize(); - if ((err= my_atomic_initialize())) - { - printf("my_atomic_initialize() failed. Error=%d\n", err); - return 1; - } + plan(4); + ok(err == 0, "my_atomic_initialize() returned %d", err); pthread_attr_init(&thr_attr); pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); @@ -128,6 +144,6 @@ int main() pthread_cond_destroy(&cond); pthread_attr_destroy(&thr_attr); my_atomic_rwlock_destroy(&rwl); - return 0; + return exit_status(); } diff --git a/unittest/mytap/t/Makefile.am b/unittest/mytap/t/Makefile.am index 88c31cfeb7f..b685ae7dc1c 100644 --- a/unittest/mytap/t/Makefile.am +++ b/unittest/mytap/t/Makefile.am @@ -5,8 +5,5 @@ AM_LDFLAGS = -L$(top_builddir)/unittest/mytap LDADD = -lmytap -noinst_PROGRAMS = basic.t +noinst_PROGRAMS = basic-t -basic_t_SOURCES = basic.t.c - -all: $(noinst_PROGRAMS) diff --git a/unittest/mytap/t/basic.t.c b/unittest/mytap/t/basic-t.c similarity index 100% rename from unittest/mytap/t/basic.t.c rename to unittest/mytap/t/basic-t.c diff --git a/unittest/unit.pl b/unittest/unit.pl index cae394cf9b6..3092a874192 100644 --- a/unittest/unit.pl +++ b/unittest/unit.pl @@ -59,7 +59,7 @@ sub _find_test_files (@) { my @files; find sub { $File::Find::prune = 1 if /^SCCS$/; - push(@files, $File::Find::name) if -x _ && /\.t\z/; + push(@files, $File::Find::name) if -x _ && /-t\z/; }, @dirs; return @files; } From 6e20d34b170895a01a8990254d89ab19c44864e3 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Jun 2006 12:59:39 +0200 Subject: [PATCH 31/32] this should not occur now after some other fixes w.r.t LOCK_open handeling in ndb and binlog --- mysql-test/t/disabled.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 42155e94154..77ca2e29669 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -24,7 +24,7 @@ ps_7ndb : BUG#18950 2006-02-16 jmiller create table like does n rpl_ndb_2innodb : BUG#19227 2006-04-20 pekka pk delete apparently not replicated rpl_ndb_2myisam : BUG#19227 2006-04-20 pekka pk delete apparently not replicated rpl_ndb_auto_inc : BUG#17086 2006-02-16 jmiller CR: auto_increment_increment and auto_increment_offset produce duplicate key er -rpl_ndb_commit_afterflush : BUG#19328 2006-05-04 tomas Slave timeout with COM_REGISTER_SLAVE error causing stop +#rpl_ndb_commit_afterflush : BUG#19328 2006-05-04 tomas Slave timeout with COM_REGISTER_SLAVE error causing stop rpl_ndb_dd_partitions : BUG#19259 2006-04-21 rpl_ndb_dd_partitions fails on s/AMD rpl_ndb_ddl : BUG#18946 result file needs update + test needs to checked rpl_ndb_innodb2ndb : Bug #19710 Cluster replication to partition table fails on DELETE FROM statement From 73977d11f3cd10e15ee6187691e6b73930561044 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Jun 2006 14:51:58 +0200 Subject: [PATCH 32/32] Bug #18483 Cannot create table with FK constraint - remove error set for auto partitioned tables --- mysql-test/r/ndb_basic.result | 8 ++++++++ mysql-test/t/ndb_basic.test | 14 ++++++++++++++ sql/sql_table.cc | 3 ++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/ndb_basic.result b/mysql-test/r/ndb_basic.result index b8bafd398fe..631165d9fc8 100644 --- a/mysql-test/r/ndb_basic.result +++ b/mysql-test/r/ndb_basic.result @@ -748,3 +748,11 @@ f1 f2 f3 111111 aaaaaa 1 222222 bbbbbb 2 drop table t1; +CREATE TABLE t1 (a VARCHAR(255) NOT NULL, +CONSTRAINT pk_a PRIMARY KEY (a))engine=ndb; +CREATE TABLE t2(a VARCHAR(255) NOT NULL, +b VARCHAR(255) NOT NULL, +c VARCHAR(255) NOT NULL, +CONSTRAINT pk_b_c_id PRIMARY KEY (b,c), +CONSTRAINT fk_a FOREIGN KEY(a) REFERENCES t1(a))engine=ndb; +drop table t1, t2; diff --git a/mysql-test/t/ndb_basic.test b/mysql-test/t/ndb_basic.test index d11e30ae97d..c7fa5aeee1e 100644 --- a/mysql-test/t/ndb_basic.test +++ b/mysql-test/t/ndb_basic.test @@ -713,3 +713,17 @@ select * from t1 order by f1; select * from t1 order by f2; select * from t1 order by f3; drop table t1; + +# +# Bug #18483 Cannot create table with FK constraint +# ndb does not support foreign key constraint, it is silently ignored +# in line with other storage engines +# +CREATE TABLE t1 (a VARCHAR(255) NOT NULL, + CONSTRAINT pk_a PRIMARY KEY (a))engine=ndb; +CREATE TABLE t2(a VARCHAR(255) NOT NULL, + b VARCHAR(255) NOT NULL, + c VARCHAR(255) NOT NULL, + CONSTRAINT pk_b_c_id PRIMARY KEY (b,c), + CONSTRAINT fk_a FOREIGN KEY(a) REFERENCES t1(a))engine=ndb; +drop table t1, t2; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 21dee4d3f2f..64523ec6310 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3106,7 +3106,8 @@ bool mysql_create_table_internal(THD *thd, } while ((key= key_iterator++)) { - if (key->type == Key::FOREIGN_KEY) + if (key->type == Key::FOREIGN_KEY && + !part_info->is_auto_partitioned) { my_error(ER_CANNOT_ADD_FOREIGN, MYF(0)); goto err;