From d35c7f2f502a9636df6fd32dedd1161f6477c0a1 Mon Sep 17 00:00:00 2001 From: "mikael@dator5.(none)" <> Date: Tue, 20 Jun 2006 10:57:02 -0400 Subject: [PATCH 01/21] BUG#18198: Too flexible partition functions --- mysql-test/r/partition_error.result | 17 +++++++++++++++++ mysql-test/t/partition_error.test | 22 ++++++++++++++++++++++ sql/sql_yacc.yy | 11 +++++++++-- 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/partition_error.result b/mysql-test/r/partition_error.result index 39f0cf9ca55..38ea8e860a1 100644 --- a/mysql-test/r/partition_error.result +++ b/mysql-test/r/partition_error.result @@ -1,5 +1,22 @@ drop table if exists t1; create table t1 (a int) +partition by range (a) +(partition p0 values less than ((select count(*) from t1))); +ERROR HY000: This partition function is not allowed +create table t1 (a int) +partition by range (a) +(partition p0 values less than (a); +ERROR 42S22: Unknown column 'a' in 'partition function' +create table t1 (a int) +partition by range (a) +(partition p0 values less than (1)); +alter table t1 add partition (partition p1 values less than (a)); +ERROR 42S22: Unknown column 'a' in 'partition function' +alter table t1 add partition +(partition p1 values less than ((select count(*) from t1))); +ERROR HY000: This partition function is not allowed +drop table t1; +create table t1 (a int) engine = x partition by key (a); Warnings: diff --git a/mysql-test/t/partition_error.test b/mysql-test/t/partition_error.test index 076c5c5773b..d7f71c02571 100644 --- a/mysql-test/t/partition_error.test +++ b/mysql-test/t/partition_error.test @@ -8,6 +8,28 @@ drop table if exists t1; --enable_warnings +# +# Bug 18198: Partitions: Too flexible functions +# +-- error ER_PARTITION_FUNCTION_IS_NOT_ALLOWED +create table t1 (a int) +partition by range (a) +(partition p0 values less than ((select count(*) from t1))); +-- error 1054 +create table t1 (a int) +partition by range (a) +(partition p0 values less than (a); + +create table t1 (a int) +partition by range (a) +(partition p0 values less than (1)); +-- error 1054 +alter table t1 add partition (partition p1 values less than (a)); +-- error ER_PARTITION_FUNCTION_IS_NOT_ALLOWED +alter table t1 add partition +(partition p1 values less than ((select count(*) from t1))); +drop table t1; + # # Bug 20397: Partitions: Crash when using non-existing engine # diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 32fdcfe45bd..9bf4b2df1fc 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3616,6 +3616,7 @@ part_bit_expr: { Item *part_expr= $1; bool not_corr_func; + bool part_expression_ok= TRUE; LEX *lex= Lex; THD *thd= YYTHD; longlong item_value; @@ -3633,13 +3634,19 @@ part_bit_expr: mem_alloc_error(sizeof(part_elem_value)); YYABORT; } - + part_expr->walk(&Item::check_partition_func_processor, 0, + (byte*)(&part_expression_ok)); + if (!part_expression_ok) + { + my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0)); + YYABORT; + } if (part_expr->fix_fields(YYTHD, (Item**)0) || ((context->table_list= save_list), FALSE) || (!part_expr->const_item()) || (!lex->safe_to_cache_query)) { - yyerror(ER(ER_NO_CONST_EXPR_IN_RANGE_OR_LIST_ERROR)); + my_error(ER_NO_CONST_EXPR_IN_RANGE_OR_LIST_ERROR, MYF(0)); YYABORT; } thd->where= save_where; From 5771a711f070d94e315641a6bcbe770ac8791c15 Mon Sep 17 00:00:00 2001 From: "mikael@dator5.(none)" <> Date: Fri, 23 Jun 2006 01:21:26 -0400 Subject: [PATCH 02/21] BUG#18198: Less flexibility in defining partition functions Changed test for functions if they are supported. 3 categories: 1) Fully supported 2) Supported for single character collations 3) Supported for binary collations --- mysql-test/r/partition.result | 2 +- mysql-test/t/partition.test | 2 +- sql/item.h | 64 ++++++++++++++++++++++----------- sql/item_cmpfunc.h | 39 ++++++++++++-------- sql/item_func.h | 67 +++++++++++++++++++---------------- sql/item_strfunc.h | 64 ++++++++++++++++++++------------- sql/item_timefunc.h | 62 ++++++++++++++++---------------- sql/item_xmlfunc.h | 3 +- sql/partition_info.cc | 39 ++++++++++++++------ sql/partition_info.h | 9 +++-- sql/sql_partition.cc | 49 +++++++++++++++++++++++-- sql/sql_table.cc | 2 +- 12 files changed, 262 insertions(+), 140 deletions(-) diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index fa1baaec07e..b1d6347c84c 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -742,7 +742,7 @@ t2 CREATE TABLE `t2` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='no comment' PARTITION BY KEY (a) drop table t2; create table t1 (s1 char(2) character set utf8) -partition by list (case when s1 > 'cz' then 1 else 2 end) +partition by list (cast(s1 as signed)) (partition p1 values in (1), partition p2 values in (2)); drop table t1; diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index f62bb2dcd01..b0b4f644c23 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -867,7 +867,7 @@ drop table t2; # Bug#14367: Partitions: crash if utf8 column # create table t1 (s1 char(2) character set utf8) -partition by list (case when s1 > 'cz' then 1 else 2 end) +partition by list (cast(s1 as signed)) (partition p1 values in (1), partition p2 values in (2)); drop table t1; diff --git a/sql/item.h b/sql/item.h index a6132aba8b0..7b93db6301a 100644 --- a/sql/item.h +++ b/sql/item.h @@ -789,7 +789,7 @@ public: Check if a partition function is allowed SYNOPSIS check_partition_func_processor() - bool_arg Return argument + int_arg Return argument RETURN VALUE 0 DESCRIPTION @@ -806,8 +806,28 @@ public: 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; } + +#define PF_SAFE_BINARY_COLLATION 3 +#define PF_SAFE_SINGLE_CHAR_COLLATION 2 +#define PF_SAFE 1 +#define PF_UNSAFE 0 + bool safe_for_binary_collation(byte *int_arg) + { + if (*(int *)int_arg != PF_UNSAFE) + *(int*)int_arg= PF_SAFE_BINARY_COLLATION; + return 0; + } + bool safe_for_single_char_collation(byte *int_arg) + { + if (*(int*)int_arg == PF_SAFE) + *(int*)int_arg= PF_SAFE_SINGLE_CHAR_COLLATION; + return 0; + } + virtual bool check_partition_func_processor(byte *int_arg) + { + *(int *)int_arg= PF_UNSAFE; + return 0; + } virtual Item *equal_fields_propagator(byte * arg) { return this; } virtual Item *set_no_const_sub(byte *arg) { return this; } @@ -1106,7 +1126,8 @@ public: Item::maybe_null= TRUE; } - bool check_partition_func_processor(byte *bool_arg) { return 0; } + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg); } bool fix_fields(THD *, Item **); enum Type type() const; @@ -1153,7 +1174,7 @@ public: Item_num() {} /* Remove gcc warning */ virtual Item_num *neg()= 0; Item *safe_charset_converter(CHARSET_INFO *tocs); - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; #define NO_CACHED_FIELD_INDEX ((uint)(-1)) @@ -1289,7 +1310,7 @@ public: bool collect_item_field_processor(byte * arg); bool find_item_in_field_list_processor(byte *arg); bool register_field_in_read_map(byte *arg); - bool check_partition_func_processor(byte *bool_arg) { return 0; } + bool check_partition_func_processor(byte *int_arg) { return 0; } void cleanup(); bool result_as_longlong() { @@ -1337,7 +1358,7 @@ public: bool is_null() { return 1; } void print(String *str) { str->append(STRING_WITH_LEN("NULL")); } Item *safe_charset_converter(CHARSET_INFO *tocs); - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; class Item_null_result :public Item_null @@ -1350,8 +1371,8 @@ public: { save_in_field(result_field, no_conversions); } - bool check_partition_func_processor(byte *bool_arg) - { *(bool *)bool_arg= FALSE; return 0; } + bool check_partition_func_processor(byte *int_arg) + { *(int *)int_arg= PF_UNSAFE; return 0; } }; /* Item represents one placeholder ('?') of prepared statement */ @@ -1642,8 +1663,8 @@ public: {} void print(String *str) { str->append(func_name); } Item *safe_charset_converter(CHARSET_INFO *tocs); - bool check_partition_func_processor(byte *bool_arg) - { *(bool *)bool_arg= FALSE; return 0; } + bool check_partition_func_processor(byte *int_arg) + { *(int *)int_arg= PF_UNSAFE; return 0; } }; @@ -1721,7 +1742,7 @@ public: void print(String *str); // to prevent drop fixed flag (no need parent cleanup call) void cleanup() {} - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -1736,8 +1757,8 @@ public: {} Item *safe_charset_converter(CHARSET_INFO *tocs); void print(String *str) { str->append(func_name); } - bool check_partition_func_processor(byte *bool_arg) - { *(bool *)bool_arg= FALSE; return 0; } + bool check_partition_func_processor(byte *int_arg) + { *(int *)int_arg= PF_UNSAFE; return 0; } }; @@ -1750,8 +1771,8 @@ public: &my_charset_bin) { max_length=19;} enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; } - bool check_partition_func_processor(byte *bool_arg) - { *(bool *)bool_arg= FALSE; return 0; } + bool check_partition_func_processor(byte *int_arg) + { *(int *)int_arg= PF_UNSAFE; return 0; } }; class Item_empty_string :public Item_string @@ -1774,8 +1795,8 @@ public: unsigned_flag=1; } enum_field_types field_type() const { return int_field_type; } - bool check_partition_func_processor(byte *bool_arg) - { *(bool *)bool_arg= FALSE; return 0; } + bool check_partition_func_processor(byte *int_arg) + { *(int *)int_arg= PF_UNSAFE; return 0; } }; @@ -1799,7 +1820,8 @@ public: void cleanup() {} bool eq(const Item *item, bool binary_cmp) const; virtual Item *safe_charset_converter(CHARSET_INFO *tocs); - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_binary_collation(int_arg);} }; @@ -2026,8 +2048,8 @@ public: } Item *new_item(); virtual Item *real_item() { return ref; } - bool check_partition_func_processor(byte *bool_arg) - { *(bool *)bool_arg= FALSE; return 0; } + bool check_partition_func_processor(byte *int_arg) + { *(int *)int_arg= PF_UNSAFE; return 0; } }; #ifdef MYSQL_SERVER diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 82cb5febe7d..08b8d4a4d99 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -240,7 +240,8 @@ public: } Item *neg_transformer(THD *thd); virtual Item *negated_item(); - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg); } }; class Item_func_not :public Item_bool_func @@ -251,7 +252,8 @@ public: enum Functype functype() const { return NOT_FUNC; } const char *func_name() const { return "not"; } Item *neg_transformer(THD *thd); - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg); } }; class Item_maxmin_subselect; @@ -466,7 +468,8 @@ public: bool is_bool_func() { return 1; } CHARSET_INFO *compare_collation() { return cmp_collation.collation; } uint decimal_precision() const { return 1; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg); } }; @@ -478,7 +481,8 @@ public: optimize_type select_optimize() const { return OPTIMIZE_NONE; } const char *func_name() const { return "strcmp"; } void print(String *str) { Item_func::print(str); } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg); } }; @@ -541,7 +545,7 @@ public: const char *func_name() const { return "ifnull"; } Field *tmp_table_field(TABLE *table); uint decimal_precision() const; - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -582,7 +586,7 @@ public: void print(String *str) { Item_func::print(str); } table_map not_null_tables() const { return 0; } bool is_null(); - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -625,7 +629,8 @@ public: void print(String *str); Item *find_item(String *str); CHARSET_INFO *compare_collation() { return cmp_collation.collation; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg); } }; @@ -976,7 +981,8 @@ public: bool nulls_in_row(); bool is_bool_func() { return 1; } CHARSET_INFO *compare_collation() { return cmp_collation.collation; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg); } }; /* Functions used by where clause */ @@ -1018,7 +1024,7 @@ public: optimize_type select_optimize() const { return OPTIMIZE_NULL; } Item *neg_transformer(THD *thd); CHARSET_INFO *compare_collation() { return args[0]->collation.collation; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; /* Functions used by HAVING for rewriting IN subquery */ @@ -1040,8 +1046,8 @@ public: */ table_map used_tables() const { return used_tables_cache | RAND_TABLE_BIT; } - bool check_partition_func_processor(byte *bool_arg) - { *(bool *)bool_arg= FALSE; return 0; } + bool check_partition_func_processor(byte *int_arg) + { *(int *)int_arg= PF_UNSAFE; return 0; } }; @@ -1064,7 +1070,7 @@ public: void print(String *str); CHARSET_INFO *compare_collation() { return args[0]->collation.collation; } void top_level_item() { abort_on_null=1; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -1103,7 +1109,8 @@ public: const char *func_name() const { return "like"; } bool fix_fields(THD *thd, Item **ref); void cleanup(); - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg); } }; #ifdef USE_REGEX @@ -1126,7 +1133,8 @@ public: const char *func_name() const { return "regexp"; } void print(String *str) { print_op(str); } CHARSET_INFO *compare_collation() { return cmp_collation.collation; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg); } }; #else @@ -1183,7 +1191,8 @@ public: Item *transform(Item_transformer transformer, byte *arg); void traverse_cond(Cond_traverser, void *arg, traverse_order order); void neg_arguments(THD *thd); - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg); } }; diff --git a/sql/item_func.h b/sql/item_func.h index 0aedae73bdc..763b05db02a 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; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_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; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -311,7 +311,7 @@ public: { max_length=args[0]->max_length; unsigned_flag=0; } void print(String *str); uint decimal_precision() const { return args[0]->decimal_precision(); } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -345,7 +345,7 @@ public: void fix_length_and_dec() {}; const char *func_name() const { return "decimal_typecast"; } void print(String *); - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -414,7 +414,7 @@ public: const char *func_name() const { return "DIV"; } void fix_length_and_dec(); void print(String *str) { print_op(str); } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -487,7 +487,7 @@ public: Item_func_exp(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "exp"; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -497,7 +497,7 @@ public: Item_func_ln(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "ln"; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -508,7 +508,7 @@ public: Item_func_log(Item *a,Item *b) :Item_dec_func(a,b) {} double val_real(); const char *func_name() const { return "log"; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -518,7 +518,7 @@ public: Item_func_log2(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "log2"; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -528,7 +528,7 @@ public: Item_func_log10(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "log10"; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -538,7 +538,7 @@ public: Item_func_sqrt(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "sqrt"; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -548,7 +548,7 @@ public: Item_func_pow(Item *a,Item *b) :Item_dec_func(a,b) {} double val_real(); const char *func_name() const { return "pow"; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -558,7 +558,7 @@ public: Item_func_acos(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "acos"; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; class Item_func_asin :public Item_dec_func @@ -567,7 +567,7 @@ public: Item_func_asin(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "asin"; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; class Item_func_atan :public Item_dec_func @@ -577,7 +577,7 @@ public: Item_func_atan(Item *a,Item *b) :Item_dec_func(a,b) {} double val_real(); const char *func_name() const { return "atan"; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; class Item_func_cos :public Item_dec_func @@ -586,7 +586,7 @@ public: Item_func_cos(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "cos"; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; class Item_func_sin :public Item_dec_func @@ -595,7 +595,7 @@ public: Item_func_sin(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "sin"; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; class Item_func_tan :public Item_dec_func @@ -604,7 +604,7 @@ public: Item_func_tan(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "tan"; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; class Item_func_integer :public Item_int_func @@ -681,7 +681,7 @@ public: Item_func_sign(Item *a) :Item_int_func(a) {} const char *func_name() const { return "sign"; } longlong val_int(); - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -696,7 +696,7 @@ public: const char *func_name() const { return name; } void fix_length_and_dec() { decimals= NOT_FIXED_DEC; max_length= float_length(decimals); } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -714,7 +714,7 @@ public: my_decimal *val_decimal(my_decimal *); void fix_length_and_dec(); enum Item_result result_type () const { return cmp_type; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; class Item_func_min :public Item_func_min_max @@ -740,7 +740,8 @@ public: longlong val_int(); const char *func_name() const { return "length"; } void fix_length_and_dec() { max_length=10; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg);} }; class Item_func_bit_length :public Item_func_length @@ -760,7 +761,8 @@ public: longlong val_int(); const char *func_name() const { return "char_length"; } void fix_length_and_dec() { max_length=10; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg);} }; class Item_func_coercibility :public Item_int_func @@ -771,7 +773,6 @@ 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; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_locate :public Item_int_func @@ -785,7 +786,8 @@ public: longlong val_int(); void fix_length_and_dec(); void print(String *str); - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg);} }; @@ -810,7 +812,8 @@ public: longlong val_int(); const char *func_name() const { return "ascii"; } void fix_length_and_dec() { max_length=3; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg);} }; class Item_func_ord :public Item_int_func @@ -820,7 +823,8 @@ public: Item_func_ord(Item *a) :Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "ord"; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg);} }; class Item_func_find_in_set :public Item_int_func @@ -834,7 +838,8 @@ public: longlong val_int(); const char *func_name() const { return "find_in_set"; } void fix_length_and_dec(); - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg);} }; /* Base class for all bit functions: '~', '|', '^', '&', '>>', '<<' */ @@ -846,7 +851,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); } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; class Item_func_bit_or :public Item_func_bit @@ -872,7 +877,7 @@ public: longlong val_int(); const char *func_name() const { return "bit_count"; } void fix_length_and_dec() { max_length=2; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; class Item_func_shift_left :public Item_func_bit @@ -1309,7 +1314,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;} - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index b2e63deed92..bf822a87406 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -47,7 +47,8 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "md5"; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg);} }; @@ -58,7 +59,8 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "sha"; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg);} }; class Item_func_aes_encrypt :public Item_str_func @@ -89,7 +91,8 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "concat"; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg);} }; class Item_func_concat_ws :public Item_str_func @@ -110,7 +113,8 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "reverse"; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg);} }; @@ -148,7 +152,8 @@ protected: public: Item_str_conv(Item *item) :Item_str_func(item) {} String *val_str(String *); - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_binary_collation(int_arg);} }; @@ -212,7 +217,8 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "substr"; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg);} }; @@ -224,7 +230,8 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "substring_index"; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg);} }; @@ -239,7 +246,8 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "trim"; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg);} }; @@ -419,7 +427,8 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "soundex"; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg);} }; @@ -527,7 +536,8 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "rpad"; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg);} }; @@ -540,7 +550,8 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "lpad"; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg);} }; @@ -555,7 +566,8 @@ public: collation.set(default_charset()); max_length= 64; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg);} }; @@ -572,7 +584,8 @@ public: decimals=0; max_length=args[0]->max_length*2*collation.collation->mbmaxlen; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_binary_collation(int_arg);} }; class Item_func_unhex :public Item_str_func @@ -588,7 +601,8 @@ public: decimals=0; max_length=(1+args[0]->max_length)/2; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_binary_collation(int_arg);} }; @@ -612,7 +626,8 @@ public: } void print(String *str); const char *func_name() const { return "cast_as_binary"; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg);} }; @@ -652,7 +667,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; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; class Item_func_quote :public Item_str_func @@ -667,7 +682,7 @@ public: collation.set(args[0]->collation); max_length= args[0]->max_length * 2 + 2; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; class Item_func_conv_charset :public Item_str_func @@ -711,7 +726,6 @@ public: void fix_length_and_dec(); const char *func_name() const { return "convert"; } void print(String *str); - bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_set_collation :public Item_str_func @@ -744,7 +758,6 @@ public: maybe_null= 0; }; table_map not_null_tables() const { return 0; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_collation :public Item_str_func @@ -760,7 +773,6 @@ public: maybe_null= 0; }; table_map not_null_tables() const { return 0; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_crc32 :public Item_int_func @@ -771,7 +783,8 @@ public: const char *func_name() const { return "crc32"; } void fix_length_and_dec() { max_length=10; } longlong val_int(); - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg);} }; class Item_func_uncompressed_length : public Item_int_func @@ -782,7 +795,8 @@ public: const char *func_name() const{return "uncompressed_length";} void fix_length_and_dec() { max_length=10; } longlong val_int(); - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg);} }; #ifdef HAVE_COMPRESS @@ -799,7 +813,8 @@ 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 - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg);} }; class Item_func_uncompress: public Item_str_func @@ -810,7 +825,8 @@ 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 - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg);} }; #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 e3f10c9716f..1bbead25d65 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -39,7 +39,7 @@ public: { max_length=6*MY_CHARSET_BIN_MB_MAXLEN; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -54,7 +54,7 @@ public: decimals=0; max_length=6*MY_CHARSET_BIN_MB_MAXLEN; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -71,7 +71,7 @@ public: maybe_null=1; } enum_monotonicity_info get_monotonicity_info() const; - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -87,7 +87,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -112,7 +112,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -145,7 +145,7 @@ public: max_length=3*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -161,7 +161,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -177,7 +177,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -193,7 +193,7 @@ public: max_length=1*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -209,7 +209,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -225,7 +225,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_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; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -257,7 +257,7 @@ public: max_length=4*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -287,7 +287,7 @@ public: max_length=1*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_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; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -335,7 +335,7 @@ public: decimals=0; max_length=10*MY_CHARSET_BIN_MB_MAXLEN; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -545,7 +545,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); - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -563,7 +563,7 @@ public: void fix_length_and_dec(); uint format_length(const String *format); bool eq(const Item *item, bool binary_cmp) const; - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -582,7 +582,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); - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -651,7 +651,7 @@ public: return tmp_table_field_from_field_type(table, 0); } bool result_as_longlong() { return TRUE; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -674,7 +674,7 @@ public: bool get_date(TIME *res, uint fuzzy_date); bool eq(const Item *item, bool binary_cmp) const; void print(String *str); - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -692,7 +692,8 @@ 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); - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg); } }; @@ -729,7 +730,7 @@ public: max_length=args[0]->max_length; maybe_null= 1; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -749,7 +750,8 @@ public: String *val_str(String *a); void fix_length_and_dec(); void print(String *str); - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg); } }; @@ -829,7 +831,7 @@ public: } bool result_as_longlong() { return TRUE; } longlong val_int(); - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -852,7 +854,7 @@ public: } void print(String *str); const char *func_name() const { return "add_time"; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; class Item_func_timediff :public Item_str_func @@ -892,7 +894,7 @@ public: { return tmp_table_field_from_field_type(table, 0); } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; class Item_func_microsecond :public Item_int_func @@ -906,7 +908,7 @@ public: decimals=0; maybe_null=1; } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -924,7 +926,7 @@ public: maybe_null=1; } void print(String *str); - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; @@ -971,7 +973,7 @@ public: { return tmp_table_field_from_field_type(table, 1); } - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return 0;} }; diff --git a/sql/item_xmlfunc.h b/sql/item_xmlfunc.h index e11b4eac1e2..4ce72777ca4 100644 --- a/sql/item_xmlfunc.h +++ b/sql/item_xmlfunc.h @@ -42,7 +42,8 @@ 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 *); - bool check_partition_func_processor(byte *bool_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) + { return safe_for_single_char_collation(int_arg);} }; diff --git a/sql/partition_info.cc b/sql/partition_info.cc index 39c8d976732..502a0fb4eef 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -694,6 +694,7 @@ end: file A reference to a handler of the table max_rows Maximum number of rows stored in the table engine_type Return value for used engine in partitions + check_partition_function Should we check the partition function RETURN VALUE TRUE Error, something went wrong @@ -708,26 +709,42 @@ end: */ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type, - handler *file, ulonglong max_rows) + handler *file, ulonglong max_rows, + bool check_partition_function) { handlerton **engine_array= NULL; uint part_count= 0; uint i, tot_partitions; bool result= TRUE; char *same_name; - bool part_expression_ok= TRUE; + int part_expression_ok= PF_SAFE; DBUG_ENTER("partition_info::check_partition_info"); - if (part_type != HASH_PARTITION || !list_of_part_fields) - part_expr->walk(&Item::check_partition_func_processor, 0, - (byte*)(&part_expression_ok)); - if (is_sub_partitioned() && !list_of_subpart_fields) - subpart_expr->walk(&Item::check_partition_func_processor, 0, - (byte*)(&part_expression_ok)); - if (!part_expression_ok) + pf_collation_allowed= PF_SAFE; + spf_collation_allowed= PF_SAFE; + if (check_partition_function) { - my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0)); - goto end; + if (part_type != HASH_PARTITION || !list_of_part_fields) + { + part_expr->walk(&Item::check_partition_func_processor, 0, + (byte*)(&part_expression_ok)); + pf_collation_allowed= (char)part_expression_ok; + part_expression_ok= PF_SAFE; + if (is_sub_partitioned() && !list_of_subpart_fields) + { + subpart_expr->walk(&Item::check_partition_func_processor, 0, + (byte*)(&part_expression_ok)); + } + spf_collation_allowed= (char)part_expression_ok; + } + else + multi_char_collation_allowed= TRUE; + if (!pf_collation_allowed || + !spf_collation_allowed) + { + my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0)); + goto end; + } } if (unlikely(!is_sub_partitioned() && !(use_default_subpartitions && use_default_no_subpartitions))) diff --git a/sql/partition_info.h b/sql/partition_info.h index 3d8c6a40221..e02b06991d3 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -188,6 +188,8 @@ public: bool is_auto_partitioned; bool from_openfrm; bool has_null_value; + char pf_collation_allowed; + char spf_collation_allowed; partition_info() @@ -217,7 +219,9 @@ public: list_of_part_fields(FALSE), list_of_subpart_fields(FALSE), linear_hash_ind(FALSE), fixed(FALSE), is_auto_partitioned(FALSE), from_openfrm(FALSE), - has_null_value(FALSE) + has_null_value(FALSE), + pf_collation_allowed(0), + spf_collation_allowed(0) { all_fields_in_PF.clear_all(); all_fields_in_PPF.clear_all(); @@ -250,7 +254,8 @@ public: bool check_range_constants(); bool check_list_constants(); bool check_partition_info(THD *thd, handlerton **eng_type, - handler *file, ulonglong max_rows); + handler *file, ulonglong max_rows, + bool check_partition_function); void print_no_partition_found(TABLE *table); private: static int list_part_cmp(const void* a, const void* b); diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 00c15c2dbca..e0e73dda2b5 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -525,6 +525,7 @@ static bool set_up_field_array(TABLE *table, } + /* Create a field array including all fields of both the partitioning and the subpartitioning functions. @@ -549,6 +550,7 @@ static bool create_full_part_field_array(TABLE *table, partition_info *part_info) { bool result= FALSE; + Field **ptr; DBUG_ENTER("create_full_part_field_array"); if (!part_info->is_sub_partitioned()) @@ -558,7 +560,7 @@ static bool create_full_part_field_array(TABLE *table, } else { - Field **ptr, *field, **field_array; + Field *field, **field_array; uint no_part_fields=0, size_field_array; ptr= table->field; while ((field= *(ptr++))) @@ -1369,6 +1371,38 @@ static uint32 get_part_id_from_linear_hash(longlong hash_value, uint mask, return part_id; } + +/* + Check that partition function do not contain any forbidden + character sets and collations. + SYNOPSIS + check_part_func_collation() + part_info Partition info + ptr Array of Field pointers + RETURN VALUES + FALSE Success + TRUE Error +*/ + +static bool check_part_func_collation(int collation_allowed, + Field **ptr) +{ + Field *field; + while ((field= *(ptr++))) + { + if (field->result_type() == STRING_RESULT) + { + CHARSET_INFO *cs= ((Field_str*)field)->charset(); + if (use_strnxfrm(cs) || + (collation_allowed == PF_SAFE_BINARY_COLLATION && + (!(cs->state & MY_CS_BINSORT)))) + return TRUE; + } + } + return FALSE; +} + + /* fix partition functions @@ -1514,6 +1548,17 @@ bool fix_partition_func(THD *thd, TABLE *table, goto end; } } + if (((part_info->pf_collation_allowed != PF_SAFE) && + check_part_func_collation(part_info->pf_collation_allowed, + part_info->part_field_array)) || + (part_info->is_sub_partitioned() && + part_info->spf_collation_allowed != PF_SAFE && + check_part_func_collation(part_info->spf_collation_allowed, + part_info->subpart_field_array))) + { + my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0)); + goto end; + } if (unlikely(create_full_part_field_array(table, part_info))) goto end; if (unlikely(check_primary_key(table))) @@ -4545,7 +4590,7 @@ the generated partition syntax in a correct manner. tab_part_info->use_default_no_subpartitions= FALSE; } if (tab_part_info->check_partition_info(thd, (handlerton**)NULL, - table->file, ULL(0))) + table->file, ULL(0), FALSE)) { DBUG_RETURN(TRUE); } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index bf0535567b4..41f345ad9f0 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3145,7 +3145,7 @@ bool mysql_create_table_internal(THD *thd, DBUG_PRINT("info", ("db_type = %d", ha_legacy_type(part_info->default_engine_type))); if (part_info->check_partition_info(thd, &engine_type, file, - create_info->max_rows)) + create_info->max_rows, TRUE)) goto err; part_info->default_engine_type= engine_type; From d6d6783b6a0e1131ab3c66513cc9dd56ba7f8b68 Mon Sep 17 00:00:00 2001 From: "mikael/pappa@dator5.(none)" <> Date: Wed, 12 Jul 2006 11:22:13 -0400 Subject: [PATCH 03/21] BUG#18198: Fix --- sql/partition_info.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/sql/partition_info.cc b/sql/partition_info.cc index 502a0fb4eef..7c9f71e254f 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -737,8 +737,6 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type, } spf_collation_allowed= (char)part_expression_ok; } - else - multi_char_collation_allowed= TRUE; if (!pf_collation_allowed || !spf_collation_allowed) { From 21f8aef468011654cd6f489289ee58ab06456fc9 Mon Sep 17 00:00:00 2001 From: "mikael/pappa@dator5.(none)" <> Date: Thu, 13 Jul 2006 20:37:17 -0400 Subject: [PATCH 04/21] BUG#18198: Partition function bug Review fixes --- sql/item_cmpfunc.h | 2 +- sql/item_strfunc.h | 14 -------------- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 08b8d4a4d99..b576f53ad2d 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1134,7 +1134,7 @@ public: void print(String *str) { print_op(str); } CHARSET_INFO *compare_collation() { return cmp_collation.collation; } bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg); } + { return safe_for_binary_collation(int_arg); } }; #else diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index bf822a87406..c42ba69c7b8 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -59,8 +59,6 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "sha"; } - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg);} }; class Item_func_aes_encrypt :public Item_str_func @@ -217,8 +215,6 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "substr"; } - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg);} }; @@ -230,8 +226,6 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "substring_index"; } - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg);} }; @@ -246,8 +240,6 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "trim"; } - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg);} }; @@ -795,8 +787,6 @@ public: const char *func_name() const{return "uncompressed_length";} void fix_length_and_dec() { max_length=10; } longlong val_int(); - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg);} }; #ifdef HAVE_COMPRESS @@ -813,8 +803,6 @@ 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 - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg);} }; class Item_func_uncompress: public Item_str_func @@ -825,8 +813,6 @@ 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 - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg);} }; #define UUID_LENGTH (8+1+4+1+4+1+4+1+12) From 032d208be21ad47671b86ec7bec14162883e7616 Mon Sep 17 00:00:00 2001 From: "mikael/pappa@dator5.(none)" <> Date: Fri, 21 Jul 2006 10:23:32 -0400 Subject: [PATCH 05/21] BUG#18198: Partition function handling Review fixes --- sql/item.h | 46 +++++++++--------------------- sql/item_cmpfunc.h | 37 +++++++++--------------- sql/item_func.h | 66 ++++++++++++++++++++----------------------- sql/item_strfunc.h | 40 +++++++++----------------- sql/item_timefunc.h | 62 ++++++++++++++++++++-------------------- sql/item_xmlfunc.h | 3 +- sql/partition_info.cc | 13 +++++---- sql/partition_info.h | 6 +--- sql/sql_partition.cc | 29 ++++++++++--------- sql/sql_yacc.yy | 2 +- 10 files changed, 127 insertions(+), 177 deletions(-) diff --git a/sql/item.h b/sql/item.h index 7b93db6301a..4dd2ad2c13c 100644 --- a/sql/item.h +++ b/sql/item.h @@ -807,26 +807,10 @@ public: below should be defined in the new Item class. */ -#define PF_SAFE_BINARY_COLLATION 3 -#define PF_SAFE_SINGLE_CHAR_COLLATION 2 -#define PF_SAFE 1 -#define PF_UNSAFE 0 - bool safe_for_binary_collation(byte *int_arg) - { - if (*(int *)int_arg != PF_UNSAFE) - *(int*)int_arg= PF_SAFE_BINARY_COLLATION; - return 0; - } - bool safe_for_single_char_collation(byte *int_arg) - { - if (*(int*)int_arg == PF_SAFE) - *(int*)int_arg= PF_SAFE_SINGLE_CHAR_COLLATION; - return 0; - } virtual bool check_partition_func_processor(byte *int_arg) { - *(int *)int_arg= PF_UNSAFE; - return 0; + *(int *)int_arg= 0; + return FALSE; } virtual Item *equal_fields_propagator(byte * arg) { return this; } @@ -1126,8 +1110,7 @@ public: Item::maybe_null= TRUE; } - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg); } + bool check_partition_func_processor(byte *int_arg) { return FALSE; } bool fix_fields(THD *, Item **); enum Type type() const; @@ -1174,7 +1157,7 @@ public: Item_num() {} /* Remove gcc warning */ virtual Item_num *neg()= 0; Item *safe_charset_converter(CHARSET_INFO *tocs); - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; #define NO_CACHED_FIELD_INDEX ((uint)(-1)) @@ -1310,7 +1293,7 @@ public: bool collect_item_field_processor(byte * arg); bool find_item_in_field_list_processor(byte *arg); bool register_field_in_read_map(byte *arg); - bool check_partition_func_processor(byte *int_arg) { return 0; } + bool check_partition_func_processor(byte *int_arg) { return FALSE; } void cleanup(); bool result_as_longlong() { @@ -1358,7 +1341,7 @@ public: bool is_null() { return 1; } void print(String *str) { str->append(STRING_WITH_LEN("NULL")); } Item *safe_charset_converter(CHARSET_INFO *tocs); - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; class Item_null_result :public Item_null @@ -1372,7 +1355,7 @@ public: save_in_field(result_field, no_conversions); } bool check_partition_func_processor(byte *int_arg) - { *(int *)int_arg= PF_UNSAFE; return 0; } + { *(int *)int_arg= 0; return FALSE; } }; /* Item represents one placeholder ('?') of prepared statement */ @@ -1664,7 +1647,7 @@ public: void print(String *str) { str->append(func_name); } Item *safe_charset_converter(CHARSET_INFO *tocs); bool check_partition_func_processor(byte *int_arg) - { *(int *)int_arg= PF_UNSAFE; return 0; } + { *(int *)int_arg= 0; return FALSE; } }; @@ -1742,7 +1725,7 @@ public: void print(String *str); // to prevent drop fixed flag (no need parent cleanup call) void cleanup() {} - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; @@ -1758,7 +1741,7 @@ public: Item *safe_charset_converter(CHARSET_INFO *tocs); void print(String *str) { str->append(func_name); } bool check_partition_func_processor(byte *int_arg) - { *(int *)int_arg= PF_UNSAFE; return 0; } + { *(int *)int_arg= 0; return FALSE; } }; @@ -1772,7 +1755,7 @@ public: { max_length=19;} enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; } bool check_partition_func_processor(byte *int_arg) - { *(int *)int_arg= PF_UNSAFE; return 0; } + { *(int *)int_arg= 0; return FALSE; } }; class Item_empty_string :public Item_string @@ -1796,7 +1779,7 @@ public: } enum_field_types field_type() const { return int_field_type; } bool check_partition_func_processor(byte *int_arg) - { *(int *)int_arg= PF_UNSAFE; return 0; } + { *(int *)int_arg= 0; return FALSE; } }; @@ -1820,8 +1803,7 @@ public: void cleanup() {} bool eq(const Item *item, bool binary_cmp) const; virtual Item *safe_charset_converter(CHARSET_INFO *tocs); - bool check_partition_func_processor(byte *int_arg) - { return safe_for_binary_collation(int_arg);} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -2049,7 +2031,7 @@ public: Item *new_item(); virtual Item *real_item() { return ref; } bool check_partition_func_processor(byte *int_arg) - { *(int *)int_arg= PF_UNSAFE; return 0; } + { *(int *)int_arg= 0; return FALSE; } }; #ifdef MYSQL_SERVER diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index b576f53ad2d..d84e73ff6a5 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -240,8 +240,7 @@ public: } Item *neg_transformer(THD *thd); virtual Item *negated_item(); - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg); } + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; class Item_func_not :public Item_bool_func @@ -252,8 +251,7 @@ public: enum Functype functype() const { return NOT_FUNC; } const char *func_name() const { return "not"; } Item *neg_transformer(THD *thd); - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg); } + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; class Item_maxmin_subselect; @@ -468,8 +466,7 @@ public: bool is_bool_func() { return 1; } CHARSET_INFO *compare_collation() { return cmp_collation.collation; } uint decimal_precision() const { return 1; } - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg); } + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -481,8 +478,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); } - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg); } + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -545,7 +541,7 @@ public: const char *func_name() const { return "ifnull"; } Field *tmp_table_field(TABLE *table); uint decimal_precision() const; - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -586,7 +582,7 @@ public: void print(String *str) { Item_func::print(str); } table_map not_null_tables() const { return 0; } bool is_null(); - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -629,8 +625,7 @@ public: void print(String *str); Item *find_item(String *str); CHARSET_INFO *compare_collation() { return cmp_collation.collation; } - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg); } + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -981,8 +976,7 @@ public: bool nulls_in_row(); bool is_bool_func() { return 1; } CHARSET_INFO *compare_collation() { return cmp_collation.collation; } - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg); } + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; /* Functions used by where clause */ @@ -1024,7 +1018,7 @@ public: optimize_type select_optimize() const { return OPTIMIZE_NULL; } Item *neg_transformer(THD *thd); CHARSET_INFO *compare_collation() { return args[0]->collation.collation; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; /* Functions used by HAVING for rewriting IN subquery */ @@ -1047,7 +1041,7 @@ public: table_map used_tables() const { return used_tables_cache | RAND_TABLE_BIT; } bool check_partition_func_processor(byte *int_arg) - { *(int *)int_arg= PF_UNSAFE; return 0; } + { *(int *)int_arg= 0; return FALSE; } }; @@ -1070,7 +1064,7 @@ public: void print(String *str); CHARSET_INFO *compare_collation() { return args[0]->collation.collation; } void top_level_item() { abort_on_null=1; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -1109,8 +1103,7 @@ public: const char *func_name() const { return "like"; } bool fix_fields(THD *thd, Item **ref); void cleanup(); - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg); } + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; #ifdef USE_REGEX @@ -1133,8 +1126,7 @@ public: const char *func_name() const { return "regexp"; } void print(String *str) { print_op(str); } CHARSET_INFO *compare_collation() { return cmp_collation.collation; } - bool check_partition_func_processor(byte *int_arg) - { return safe_for_binary_collation(int_arg); } + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; #else @@ -1191,8 +1183,7 @@ public: Item *transform(Item_transformer transformer, byte *arg); void traverse_cond(Cond_traverser, void *arg, traverse_order order); void neg_arguments(THD *thd); - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg); } + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; diff --git a/sql/item_func.h b/sql/item_func.h index 763b05db02a..43b16817f3c 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; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -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; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -311,7 +311,7 @@ public: { max_length=args[0]->max_length; unsigned_flag=0; } void print(String *str); uint decimal_precision() const { return args[0]->decimal_precision(); } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -345,7 +345,7 @@ public: void fix_length_and_dec() {}; const char *func_name() const { return "decimal_typecast"; } void print(String *); - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -414,7 +414,7 @@ public: const char *func_name() const { return "DIV"; } void fix_length_and_dec(); void print(String *str) { print_op(str); } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -487,7 +487,7 @@ public: Item_func_exp(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "exp"; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -497,7 +497,7 @@ public: Item_func_ln(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "ln"; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -508,7 +508,7 @@ public: Item_func_log(Item *a,Item *b) :Item_dec_func(a,b) {} double val_real(); const char *func_name() const { return "log"; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -518,7 +518,7 @@ public: Item_func_log2(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "log2"; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -528,7 +528,7 @@ public: Item_func_log10(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "log10"; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -538,7 +538,7 @@ public: Item_func_sqrt(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "sqrt"; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -548,7 +548,7 @@ public: Item_func_pow(Item *a,Item *b) :Item_dec_func(a,b) {} double val_real(); const char *func_name() const { return "pow"; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -558,7 +558,7 @@ public: Item_func_acos(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "acos"; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; class Item_func_asin :public Item_dec_func @@ -567,7 +567,7 @@ public: Item_func_asin(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "asin"; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; class Item_func_atan :public Item_dec_func @@ -577,7 +577,7 @@ public: Item_func_atan(Item *a,Item *b) :Item_dec_func(a,b) {} double val_real(); const char *func_name() const { return "atan"; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; class Item_func_cos :public Item_dec_func @@ -586,7 +586,7 @@ public: Item_func_cos(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "cos"; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; class Item_func_sin :public Item_dec_func @@ -595,7 +595,7 @@ public: Item_func_sin(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "sin"; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; class Item_func_tan :public Item_dec_func @@ -604,7 +604,7 @@ public: Item_func_tan(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "tan"; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; class Item_func_integer :public Item_int_func @@ -681,7 +681,7 @@ public: Item_func_sign(Item *a) :Item_int_func(a) {} const char *func_name() const { return "sign"; } longlong val_int(); - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -696,7 +696,7 @@ public: const char *func_name() const { return name; } void fix_length_and_dec() { decimals= NOT_FIXED_DEC; max_length= float_length(decimals); } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -714,7 +714,7 @@ public: my_decimal *val_decimal(my_decimal *); void fix_length_and_dec(); enum Item_result result_type () const { return cmp_type; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; class Item_func_min :public Item_func_min_max @@ -740,8 +740,7 @@ public: longlong val_int(); const char *func_name() const { return "length"; } void fix_length_and_dec() { max_length=10; } - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg);} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; class Item_func_bit_length :public Item_func_length @@ -761,8 +760,7 @@ public: longlong val_int(); const char *func_name() const { return "char_length"; } void fix_length_and_dec() { max_length=10; } - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg);} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; class Item_func_coercibility :public Item_int_func @@ -786,8 +784,7 @@ public: longlong val_int(); void fix_length_and_dec(); void print(String *str); - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg);} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -812,8 +809,7 @@ public: longlong val_int(); const char *func_name() const { return "ascii"; } void fix_length_and_dec() { max_length=3; } - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg);} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; class Item_func_ord :public Item_int_func @@ -823,8 +819,7 @@ public: Item_func_ord(Item *a) :Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "ord"; } - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg);} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; class Item_func_find_in_set :public Item_int_func @@ -838,8 +833,7 @@ public: longlong val_int(); const char *func_name() const { return "find_in_set"; } void fix_length_and_dec(); - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg);} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; /* Base class for all bit functions: '~', '|', '^', '&', '>>', '<<' */ @@ -851,7 +845,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); } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; class Item_func_bit_or :public Item_func_bit @@ -877,7 +871,7 @@ public: longlong val_int(); const char *func_name() const { return "bit_count"; } void fix_length_and_dec() { max_length=2; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; class Item_func_shift_left :public Item_func_bit @@ -1314,7 +1308,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;} - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index c42ba69c7b8..e66390c5f2b 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -47,8 +47,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "md5"; } - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg);} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -89,8 +88,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "concat"; } - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg);} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; class Item_func_concat_ws :public Item_str_func @@ -111,8 +109,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "reverse"; } - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg);} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -150,8 +147,7 @@ protected: public: Item_str_conv(Item *item) :Item_str_func(item) {} String *val_str(String *); - bool check_partition_func_processor(byte *int_arg) - { return safe_for_binary_collation(int_arg);} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -419,8 +415,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "soundex"; } - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg);} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -528,8 +523,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "rpad"; } - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg);} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -542,8 +536,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "lpad"; } - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg);} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -558,8 +551,7 @@ public: collation.set(default_charset()); max_length= 64; } - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg);} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -576,8 +568,7 @@ public: decimals=0; max_length=args[0]->max_length*2*collation.collation->mbmaxlen; } - bool check_partition_func_processor(byte *int_arg) - { return safe_for_binary_collation(int_arg);} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; class Item_func_unhex :public Item_str_func @@ -593,8 +584,7 @@ public: decimals=0; max_length=(1+args[0]->max_length)/2; } - bool check_partition_func_processor(byte *int_arg) - { return safe_for_binary_collation(int_arg);} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -618,8 +608,7 @@ public: } void print(String *str); const char *func_name() const { return "cast_as_binary"; } - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg);} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; @@ -659,7 +648,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; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; class Item_func_quote :public Item_str_func @@ -674,7 +663,7 @@ public: collation.set(args[0]->collation); max_length= args[0]->max_length * 2 + 2; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; class Item_func_conv_charset :public Item_str_func @@ -775,8 +764,7 @@ public: const char *func_name() const { return "crc32"; } void fix_length_and_dec() { max_length=10; } longlong val_int(); - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg);} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; class Item_func_uncompressed_length : public Item_int_func diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 1bbead25d65..6623f7ad418 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -39,7 +39,7 @@ public: { max_length=6*MY_CHARSET_BIN_MB_MAXLEN; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; @@ -54,7 +54,7 @@ public: decimals=0; max_length=6*MY_CHARSET_BIN_MB_MAXLEN; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; @@ -71,7 +71,7 @@ public: maybe_null=1; } enum_monotonicity_info get_monotonicity_info() const; - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; @@ -87,7 +87,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; @@ -112,7 +112,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; @@ -145,7 +145,7 @@ public: max_length=3*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; @@ -161,7 +161,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; @@ -177,7 +177,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; @@ -193,7 +193,7 @@ public: max_length=1*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; @@ -209,7 +209,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; @@ -225,7 +225,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; class Item_func_yearweek :public Item_int_func @@ -240,7 +240,7 @@ public: max_length=6*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; @@ -257,7 +257,7 @@ public: max_length=4*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; @@ -287,7 +287,7 @@ public: max_length=1*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; class Item_func_dayname :public Item_func_weekday @@ -320,7 +320,7 @@ public: decimals=0; max_length=10*MY_CHARSET_BIN_MB_MAXLEN; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; @@ -335,7 +335,7 @@ public: decimals=0; max_length=10*MY_CHARSET_BIN_MB_MAXLEN; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; @@ -545,7 +545,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); - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; @@ -563,7 +563,7 @@ public: void fix_length_and_dec(); uint format_length(const String *format); bool eq(const Item *item, bool binary_cmp) const; - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; @@ -582,7 +582,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); - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; @@ -651,7 +651,7 @@ public: return tmp_table_field_from_field_type(table, 0); } bool result_as_longlong() { return TRUE; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; @@ -674,7 +674,7 @@ public: bool get_date(TIME *res, uint fuzzy_date); bool eq(const Item *item, bool binary_cmp) const; void print(String *str); - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; @@ -692,8 +692,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); - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg); } + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; @@ -730,7 +729,7 @@ public: max_length=args[0]->max_length; maybe_null= 1; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; @@ -750,8 +749,7 @@ public: String *val_str(String *a); void fix_length_and_dec(); void print(String *str); - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg); } + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; @@ -831,7 +829,7 @@ public: } bool result_as_longlong() { return TRUE; } longlong val_int(); - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; @@ -854,7 +852,7 @@ public: } void print(String *str); const char *func_name() const { return "add_time"; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; class Item_func_timediff :public Item_str_func @@ -894,7 +892,7 @@ public: { return tmp_table_field_from_field_type(table, 0); } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; class Item_func_microsecond :public Item_int_func @@ -908,7 +906,7 @@ public: decimals=0; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; @@ -926,7 +924,7 @@ public: maybe_null=1; } void print(String *str); - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; @@ -973,7 +971,7 @@ public: { return tmp_table_field_from_field_type(table, 1); } - bool check_partition_func_processor(byte *int_arg) { return 0;} + bool check_partition_func_processor(byte *int_arg) { return FALSE;} }; diff --git a/sql/item_xmlfunc.h b/sql/item_xmlfunc.h index 4ce72777ca4..513a85aa665 100644 --- a/sql/item_xmlfunc.h +++ b/sql/item_xmlfunc.h @@ -42,8 +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 *); - bool check_partition_func_processor(byte *int_arg) - { return safe_for_single_char_collation(int_arg);} + bool check_partition_func_processor(byte *int_arg) { return FALSE; } }; diff --git a/sql/partition_info.cc b/sql/partition_info.cc index 94008e621c7..1afbb968547 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -718,25 +718,26 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type, uint i, tot_partitions; bool result= TRUE; char *same_name; - int part_expression_ok= PF_SAFE; DBUG_ENTER("partition_info::check_partition_info"); - pf_collation_allowed= PF_SAFE; - spf_collation_allowed= PF_SAFE; if (check_partition_function) { + int part_expression_ok= 1; + int pf_collation_allowed= 1; + int spf_collation_allowed= 1; + if (part_type != HASH_PARTITION || !list_of_part_fields) { part_expr->walk(&Item::check_partition_func_processor, 0, (byte*)(&part_expression_ok)); - pf_collation_allowed= (char)part_expression_ok; - part_expression_ok= PF_SAFE; + pf_collation_allowed= part_expression_ok; + part_expression_ok= 1; if (is_sub_partitioned() && !list_of_subpart_fields) { subpart_expr->walk(&Item::check_partition_func_processor, 0, (byte*)(&part_expression_ok)); } - spf_collation_allowed= (char)part_expression_ok; + spf_collation_allowed= part_expression_ok; } if (!pf_collation_allowed || !spf_collation_allowed) diff --git a/sql/partition_info.h b/sql/partition_info.h index a7dd7bcfab2..8cc989c0991 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -188,8 +188,6 @@ public: bool is_auto_partitioned; bool from_openfrm; bool has_null_value; - char pf_collation_allowed; - char spf_collation_allowed; partition_info() @@ -219,9 +217,7 @@ public: list_of_part_fields(FALSE), list_of_subpart_fields(FALSE), linear_hash_ind(FALSE), fixed(FALSE), is_auto_partitioned(FALSE), from_openfrm(FALSE), - has_null_value(FALSE), - pf_collation_allowed(0), - spf_collation_allowed(0) + has_null_value(FALSE) { all_fields_in_PF.clear_all(); all_fields_in_PPF.clear_all(); diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index db2307597ba..d11a7b8bccd 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1376,7 +1376,7 @@ static uint32 get_part_id_from_linear_hash(longlong hash_value, uint mask, Check that partition function do not contain any forbidden character sets and collations. SYNOPSIS - check_part_func_collation() + check_part_func_fields() part_info Partition info ptr Array of Field pointers RETURN VALUES @@ -1384,19 +1384,24 @@ static uint32 get_part_id_from_linear_hash(longlong hash_value, uint mask, TRUE Error */ -static bool check_part_func_collation(int collation_allowed, - Field **ptr) +static bool check_part_func_fields(Field **ptr) { Field *field; while ((field= *(ptr++))) { - if (field->result_type() == STRING_RESULT) + /* + For CHAR/VARCHAR fields we need to take special precautions. + Binary collation with CHAR is automatically supported. Other + types need some kind of standardisation function handling + */ + if (field->type() == MYSQL_TYPE_STRING || + field->type() == MYSQL_TYPE_VARCHAR) { CHARSET_INFO *cs= ((Field_str*)field)->charset(); - if (use_strnxfrm(cs) || - (collation_allowed == PF_SAFE_BINARY_COLLATION && - (!(cs->state & MY_CS_BINSORT)))) - return TRUE; + if (field->type() == MYSQL_TYPE_STRING && + cs->state & MY_CS_BINSORT) + return FALSE; + return TRUE; } } return FALSE; @@ -1548,13 +1553,9 @@ bool fix_partition_func(THD *thd, TABLE *table, goto end; } } - if (((part_info->pf_collation_allowed != PF_SAFE) && - check_part_func_collation(part_info->pf_collation_allowed, - part_info->part_field_array)) || + if ((check_part_func_fields(part_info->part_field_array)) || (part_info->is_sub_partitioned() && - part_info->spf_collation_allowed != PF_SAFE && - check_part_func_collation(part_info->spf_collation_allowed, - part_info->subpart_field_array))) + check_part_func_fields(part_info->subpart_field_array))) { my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0)); goto end; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index e12985faca8..57dceb7766b 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3619,7 +3619,7 @@ part_bit_expr: { Item *part_expr= $1; bool not_corr_func; - bool part_expression_ok= TRUE; + int part_expression_ok= 1; LEX *lex= Lex; THD *thd= YYTHD; longlong item_value; From 6abfac485972dc1faab5b72d1ae0fc85d1485ffb Mon Sep 17 00:00:00 2001 From: "mikael/pappa@dator5.(none)" <> Date: Mon, 31 Jul 2006 05:35:57 -0400 Subject: [PATCH 06/21] Fix --- sql/item.h | 1 - 1 file changed, 1 deletion(-) diff --git a/sql/item.h b/sql/item.h index 6d20d615d92..f7bae8d3d47 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1103,7 +1103,6 @@ public: Item::maybe_null= TRUE; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } bool fix_fields(THD *, Item **); enum Type type() const; From 23cb067aa2b8404b94013339990a7d639c7ea8a5 Mon Sep 17 00:00:00 2001 From: "mikael/pappa@dator5.(none)" <> Date: Mon, 31 Jul 2006 11:38:09 -0400 Subject: [PATCH 07/21] BUG#18198: More fixes --- mysql-test/r/partition.result | 5 ----- mysql-test/r/partition_error.result | 2 +- mysql-test/r/partition_pruning.result | 12 +++--------- mysql-test/t/partition.test | 12 +++++++----- mysql-test/t/partition_error.test | 2 +- mysql-test/t/partition_pruning.test | 18 +++++++++++------- sql/sql_partition.cc | 7 +++++-- 7 files changed, 28 insertions(+), 30 deletions(-) diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index 2b5b47aeedd..5605b4b6c2a 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -750,11 +750,6 @@ t2 CREATE TABLE `t2` ( PRIMARY KEY (`a`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='no comment' /*!50100 PARTITION BY KEY (a) */ drop table t2; -create table t1 (s1 char(2) character set utf8) -partition by list (cast(s1 as signed)) -(partition p1 values in (1), -partition p2 values in (2)); -drop table t1; create table t1 (f1 int) partition by hash (f1) as select 1; drop table t1; prepare stmt1 from 'create table t1 (s1 int) partition by hash (s1)'; diff --git a/mysql-test/r/partition_error.result b/mysql-test/r/partition_error.result index 6ded066c3ec..87ae1d62a04 100644 --- a/mysql-test/r/partition_error.result +++ b/mysql-test/r/partition_error.result @@ -641,7 +641,7 @@ ERROR HY000: Partition constant is out of partition function domain create table t1 (v varchar(12)) partition by range (ascii(v)) (partition p0 values less than (10)); -drop table t1; +ERROR HY000: This partition function is not allowed 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 diff --git a/mysql-test/r/partition_pruning.result b/mysql-test/r/partition_pruning.result index bf7888bfd99..8125ae91959 100644 --- a/mysql-test/r/partition_pruning.result +++ b/mysql-test/r/partition_pruning.result @@ -284,13 +284,6 @@ explain partitions select * from t9 where a <= '2004-12-19'; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t9 p0,p1 ALL NULL NULL NULL NULL 2 Using where drop table t5,t6,t7,t8,t9; -create table t1 (a enum('a','b','c','d') default 'a') -partition by hash (ascii(a)) partitions 2; -insert into t1 values ('a'),('b'),('c'); -explain partitions select * from t1 where a='b'; -id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 p0,p1 ALL NULL NULL NULL NULL 3 Using where -drop table t1; create table t1 ( a1 int not null ) @@ -643,8 +636,9 @@ f_int1 f_int2 8 8 9 9 drop table t1; -create table t1 (a char(10)) partition by list(length(a)) ( -partition p1 values in (1), +create table t1 (a char(10) binary) +partition by list(length(a)) +(partition p1 values in (1), partition p2 values in (2), partition p3 values in (3), partition p4 values in (4), diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index 4583c06e74f..6fe06dfc8af 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -883,11 +883,13 @@ drop table t2; # # Bug#14367: Partitions: crash if utf8 column # -create table t1 (s1 char(2) character set utf8) -partition by list (cast(s1 as signed)) -(partition p1 values in (1), - partition p2 values in (2)); -drop table t1; +# utf columns not supported after Bug #18198 is fixed +# +#create table t1 (s1 char(2) character set utf8) +#partition by list (cast(s1 as signed)) +#(partition p1 values in (1), +# partition p2 values in (2)); +#drop table t1; # # Bug#15336 Partitions: crash if create table as select diff --git a/mysql-test/t/partition_error.test b/mysql-test/t/partition_error.test index a9efbc587be..2c0706cb2cb 100644 --- a/mysql-test/t/partition_error.test +++ b/mysql-test/t/partition_error.test @@ -809,10 +809,10 @@ partition by range (a) # # Bug 18198 Partitions: Verify that erroneus partition functions doesn't work # +-- error ER_PARTITION_FUNCTION_IS_NOT_ALLOWED 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) diff --git a/mysql-test/t/partition_pruning.test b/mysql-test/t/partition_pruning.test index dd79e8d3acb..e0ed5c1c844 100644 --- a/mysql-test/t/partition_pruning.test +++ b/mysql-test/t/partition_pruning.test @@ -238,11 +238,14 @@ explain partitions select * from t9 where a <= '2004-12-19'; drop table t5,t6,t7,t8,t9; # Test the case where we can't create partitioning 'index' -create table t1 (a enum('a','b','c','d') default 'a') - partition by hash (ascii(a)) partitions 2; -insert into t1 values ('a'),('b'),('c'); -explain partitions select * from t1 where a='b'; -drop table t1; +# +# Not supported after bug#18198 is fixed +# +#create table t1 (a enum('a','b','c','d') default 'a') +# partition by hash (ascii(a)) partitions 2; +#insert into t1 values ('a'),('b'),('c'); +#explain partitions select * from t1 where a='b'; +#drop table t1; # # Test cases for bugs found in code review: @@ -519,8 +522,9 @@ select * from t1 where f_int1 between 5 and 15 order by f_int1; drop table t1; # part2: bug in pruning code -create table t1 (a char(10)) partition by list(length(a)) ( - partition p1 values in (1), +create table t1 (a char(10) binary) +partition by list(length(a)) + (partition p1 values in (1), partition p2 values in (2), partition p3 values in (3), partition p4 values in (4), diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 55eab215746..54610328694 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1553,8 +1553,11 @@ bool fix_partition_func(THD *thd, TABLE *table, goto end; } } - if ((check_part_func_fields(part_info->part_field_array)) || - (part_info->is_sub_partitioned() && + if (((part_info->part_type != HASH_PARTITION || + part_info->list_of_part_fields == FALSE) && + check_part_func_fields(part_info->part_field_array)) || + (part_info->list_of_part_fields == FALSE && + part_info->is_sub_partitioned() && check_part_func_fields(part_info->subpart_field_array))) { my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0)); From 6425e335304b50749ca9775b9c015d21417c9b73 Mon Sep 17 00:00:00 2001 From: "mikael/pappa@dator5.(none)" <> Date: Wed, 2 Aug 2006 06:40:25 -0400 Subject: [PATCH 08/21] BUG#18198: Fixes to handle VARCHAR strings properly New methods to handle VARCHAR strings and CHAR's which are not using a binary collation. Indentation fixes Now strings are run through strnxfrm before they are processed by the partition function We do not allow collations where strnxfrm expands the string since we want the resulting string to fit in the same value range as the original. --- mysql-test/r/partition_range.result | 42 +++ mysql-test/t/partition_range.test | 30 ++ sql/partition_info.h | 29 +- sql/sql_partition.cc | 435 +++++++++++++++++++++++++--- 4 files changed, 495 insertions(+), 41 deletions(-) diff --git a/mysql-test/r/partition_range.result b/mysql-test/r/partition_range.result index 9812c80040b..2fa40b44815 100644 --- a/mysql-test/r/partition_range.result +++ b/mysql-test/r/partition_range.result @@ -709,3 +709,45 @@ WHERE (a >= '2004-07-01' AND a <= '2004-09-30') OR id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 p407,p408,p409,p507,p508,p509 ALL NULL NULL NULL NULL 18 Using where DROP TABLE t1; +create table t1 (a varchar(20)) +partition by range (crc32(md5(a))) +(partition p0 values less than (100), +partition p1 values less than maxvalue); +insert into t1 values ("12345678901234567890"); +insert into t1 values ("A2345678901234567890"); +insert into t1 values ("B2345678901234567890"); +insert into t1 values ("1234567890123456789"); +insert into t1 values ("1234567890123456"); +select * from t1; +a +12345678901234567890 +A2345678901234567890 +B2345678901234567890 +1234567890123456789 +1234567890123456 +explain partitions select * from t1 where a = "12345678901234567890"; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p1 ALL NULL NULL NULL NULL 5 Using where +explain partitions select * from t1 where a = "12345678901234567890" OR +a = "A2345678901234567890" OR +a = "B2345678901234567890" OR +a = "C2345678901234567890"; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p1 ALL NULL NULL NULL NULL 5 Using where +explain partitions select * from t1 where a = "01234567890123456"; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p1 ALL NULL NULL NULL NULL 5 Using where +select * from t1 where a = "01234567890123456"; +a +select * from t1 where a = "12345678901234567890" OR +a = "A2345678901234567890" OR +a = "B2345678901234567890" OR +a = "C2345678901234567890"; +a +12345678901234567890 +A2345678901234567890 +B2345678901234567890 +select * from t1 where a = "12345678901234567890"; +a +12345678901234567890 +drop table t1; diff --git a/mysql-test/t/partition_range.test b/mysql-test/t/partition_range.test index 670b9333ab9..8cf2313e39c 100644 --- a/mysql-test/t/partition_range.test +++ b/mysql-test/t/partition_range.test @@ -686,3 +686,33 @@ EXPLAIN PARTITIONS SELECT * from t1 WHERE (a >= '2004-07-01' AND a <= '2004-09-30') OR (a >= '2005-07-01' AND a <= '2005-09-30'); DROP TABLE t1; + +# +# Bug 18198: Try with a couple of cases using VARCHAR fields in +# partition function. +create table t1 (a varchar(20)) +partition by range (crc32(md5(a))) +(partition p0 values less than (100), + partition p1 values less than maxvalue); + +insert into t1 values ("12345678901234567890"); +insert into t1 values ("A2345678901234567890"); +insert into t1 values ("B2345678901234567890"); +insert into t1 values ("1234567890123456789"); +insert into t1 values ("1234567890123456"); +select * from t1; +explain partitions select * from t1 where a = "12345678901234567890"; +explain partitions select * from t1 where a = "12345678901234567890" OR + a = "A2345678901234567890" OR + a = "B2345678901234567890" OR + a = "C2345678901234567890"; +explain partitions select * from t1 where a = "01234567890123456"; +select * from t1 where a = "01234567890123456"; +select * from t1 where a = "12345678901234567890" OR + a = "A2345678901234567890" OR + a = "B2345678901234567890" OR + a = "C2345678901234567890"; +select * from t1 where a = "12345678901234567890"; + + +drop table t1; diff --git a/sql/partition_info.h b/sql/partition_info.h index 8cc989c0991..91beaf569e0 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -60,7 +60,17 @@ public: same in all subpartitions */ get_subpart_id_func get_subpartition_id; - + + /* + When we have various string fields we might need some preparation + before and clean-up after calling the get_part_id_func's. We need + one such method for get_partition_id and one for + get_part_partition_id and one for get_subpartition_id. + */ + get_part_id_func get_partition_id_charset; + get_part_id_func get_part_partition_id_charset; + get_subpart_id_func get_subpartition_id_charset; + /* NULL-terminated array of fields used in partitioned expression */ Field **part_field_array; /* NULL-terminated array of fields used in subpartitioned expression */ @@ -72,6 +82,16 @@ public: */ Field **full_part_field_array; + /* + When we have a field that requires transformation before calling the + partition functions we must allocate field buffers for the field of + the fields in the partition function. + */ + char **part_field_buffers; + char **subpart_field_buffers; + char **restore_part_field_ptrs; + char **restore_subpart_field_ptrs; + Item *part_expr; Item *subpart_expr; @@ -188,6 +208,8 @@ public: bool is_auto_partitioned; bool from_openfrm; bool has_null_value; + bool includes_charset_field_part; + bool includes_charset_field_subpart; partition_info() @@ -195,6 +217,8 @@ public: get_subpartition_id(NULL), part_field_array(NULL), subpart_field_array(NULL), full_part_field_array(NULL), + part_field_buffers(NULL), subpart_field_buffers(NULL), + restore_part_field_ptrs(NULL), restore_subpart_field_ptrs(NULL), part_expr(NULL), subpart_expr(NULL), item_free_list(NULL), first_log_entry(NULL), exec_log_entry(NULL), frm_log_entry(NULL), list_array(NULL), @@ -217,7 +241,8 @@ public: list_of_part_fields(FALSE), list_of_subpart_fields(FALSE), linear_hash_ind(FALSE), fixed(FALSE), is_auto_partitioned(FALSE), from_openfrm(FALSE), - has_null_value(FALSE) + has_null_value(FALSE), includes_charset_field_part(FALSE), + includes_charset_field_subpart(FALSE) { all_fields_in_PF.clear_all(); all_fields_in_PPF.clear_all(); diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 54610328694..b2a6287ff81 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -62,48 +62,64 @@ static const char *end_paren_str= ")"; static const char *begin_paren_str= "("; static const char *comma_str= ","; -int get_partition_id_list(partition_info *part_info, - uint32 *part_id, - longlong *func_value); -int get_partition_id_range(partition_info *part_info, - uint32 *part_id, - longlong *func_value); -int get_partition_id_hash_nosub(partition_info *part_info, - uint32 *part_id, - longlong *func_value); -int get_partition_id_key_nosub(partition_info *part_info, - uint32 *part_id, - longlong *func_value); -int get_partition_id_linear_hash_nosub(partition_info *part_info, +static int get_part_id_charset_func_all(partition_info *part_info, uint32 *part_id, longlong *func_value); -int get_partition_id_linear_key_nosub(partition_info *part_info, - uint32 *part_id, - longlong *func_value); -int get_partition_id_range_sub_hash(partition_info *part_info, - uint32 *part_id, - longlong *func_value); -int get_partition_id_range_sub_key(partition_info *part_info, - uint32 *part_id, - longlong *func_value); -int get_partition_id_range_sub_linear_hash(partition_info *part_info, +static int get_part_id_charset_func_part(partition_info *part_info, + uint32 *part_id, + longlong *func_value); +static int get_part_id_charset_func_subpart(partition_info *part_info, uint32 *part_id, longlong *func_value); -int get_partition_id_range_sub_linear_key(partition_info *part_info, - uint32 *part_id, - longlong *func_value); -int get_partition_id_list_sub_hash(partition_info *part_info, +static int get_part_part_id_charset_func(partition_info *part_info, + uint32 *part_id, + longlong *func_value); +static uint32 get_subpart_id_charset_func(partition_info *part_info); +int get_partition_id_list(partition_info *part_info, + uint32 *part_id, + longlong *func_value); +int get_partition_id_list(partition_info *part_info, + uint32 *part_id, + longlong *func_value); +int get_partition_id_range(partition_info *part_info, + uint32 *part_id, + longlong *func_value); +int get_partition_id_hash_nosub(partition_info *part_info, + uint32 *part_id, + longlong *func_value); +int get_partition_id_key_nosub(partition_info *part_info, + uint32 *part_id, + longlong *func_value); +int get_partition_id_linear_hash_nosub(partition_info *part_info, + uint32 *part_id, + longlong *func_value); +int get_partition_id_linear_key_nosub(partition_info *part_info, + uint32 *part_id, + longlong *func_value); +int get_partition_id_range_sub_hash(partition_info *part_info, uint32 *part_id, longlong *func_value); -int get_partition_id_list_sub_key(partition_info *part_info, +int get_partition_id_range_sub_key(partition_info *part_info, uint32 *part_id, longlong *func_value); -int get_partition_id_list_sub_linear_hash(partition_info *part_info, +int get_partition_id_range_sub_linear_hash(partition_info *part_info, uint32 *part_id, longlong *func_value); -int get_partition_id_list_sub_linear_key(partition_info *part_info, +int get_partition_id_range_sub_linear_key(partition_info *part_info, uint32 *part_id, longlong *func_value); +int get_partition_id_list_sub_hash(partition_info *part_info, + uint32 *part_id, + longlong *func_value); +int get_partition_id_list_sub_key(partition_info *part_info, + uint32 *part_id, + longlong *func_value); +int get_partition_id_list_sub_linear_hash(partition_info *part_info, + uint32 *part_id, + longlong *func_value); +int get_partition_id_list_sub_linear_key(partition_info *part_info, + uint32 *part_id, + longlong *func_value); uint32 get_partition_id_hash_sub(partition_info *part_info); uint32 get_partition_id_key_sub(partition_info *part_info); uint32 get_partition_id_linear_hash_sub(partition_info *part_info); @@ -1311,6 +1327,34 @@ static void set_up_partition_func_pointers(partition_info *part_info) } } } + if (part_info->includes_charset_field_part || + part_info->includes_charset_field_subpart) + { + DBUG_ASSERT(part_info->get_partition_id); + part_info->get_partition_id_charset= part_info->get_partition_id; + if (part_info->includes_charset_field_part && + part_info->includes_charset_field_subpart) + part_info->get_partition_id= get_part_id_charset_func_all; + else if (part_info->includes_charset_field_part) + part_info->get_partition_id= get_part_id_charset_func_part; + else + part_info->get_partition_id= get_part_id_charset_func_subpart; + } + if (part_info->includes_charset_field_part && + part_info->is_sub_partitioned()) + { + DBUG_ASSERT(part_info->get_part_partition_id); + part_info->get_part_partition_id_charset= + part_info->get_part_partition_id; + part_info->get_part_partition_id= get_part_part_id_charset_func; + } + if (part_info->includes_charset_field_subpart) + { + DBUG_ASSERT(part_info->get_subpartition_id); + part_info->get_subpartition_id_charset= + part_info->get_subpartition_id; + part_info->get_subpartition_id= get_subpart_id_charset_func; + } DBUG_VOID_RETURN; } @@ -1377,16 +1421,24 @@ static uint32 get_part_id_from_linear_hash(longlong hash_value, uint mask, character sets and collations. SYNOPSIS check_part_func_fields() - part_info Partition info ptr Array of Field pointers + ok_with_charsets Will we report allowed charset + fields as ok RETURN VALUES FALSE Success TRUE Error + DESCRIPTION + We will check in this routine that the fields of the partition functions + do not contain unallowed parts. It can also be used to check if there + are fields that require special care by calling my_strnxfrm before + calling the functions to calculate partition id. */ -static bool check_part_func_fields(Field **ptr) +static bool check_part_func_fields(Field **ptr, bool ok_with_charsets) { Field *field; + DBUG_ENTER("check_part_func_field"); + while ((field= *(ptr++))) { /* @@ -1400,13 +1452,121 @@ static bool check_part_func_fields(Field **ptr) CHARSET_INFO *cs= ((Field_str*)field)->charset(); if (field->type() == MYSQL_TYPE_STRING && cs->state & MY_CS_BINSORT) - return FALSE; - return TRUE; + { + DBUG_RETURN(FALSE); + } + if (!ok_with_charsets || + cs->mbmaxlen > 1 || + cs->strxfrm_multiply > 1) + { + DBUG_RETURN(TRUE); + } + DBUG_RETURN(FALSE); } } - return FALSE; + DBUG_RETURN(FALSE); } +/* + Set up buffers and arrays for fields requiring preparation + SYNOPSIS + set_up_charset_field_preps() + part_info Partition info object + RETURN VALUES + TRUE Memory Allocation error + FALSE Success + DESCRIPTION + Set up arrays and buffers for fields that require special care for + calculation of partition id. This is used for string fields with + variable length or string fields with fixed length that isn't using + the binary collation. +*/ + +static bool set_up_charset_field_preps(partition_info *part_info) +{ + Field *field, **ptr; + char *field_buf; + char **char_ptrs; + unsigned i; + size_t size; + + DBUG_ENTER("set_up_charset_field_preps"); + if (check_part_func_fields(part_info->part_field_array, FALSE)) + { + ptr= part_info->part_field_array; + part_info->includes_charset_field_part= TRUE; + /* + Set up arrays and buffers for those fields + */ + i= 0; + while ((field= *(ptr++))) + i++; + size= i * sizeof(char*); + + if (!(char_ptrs= (char**)sql_calloc(size))) + goto error; + part_info->part_field_buffers= char_ptrs; + + if (!(char_ptrs= (char**)sql_calloc(size))) + goto error; + part_info->restore_part_field_ptrs= char_ptrs; + + ptr= part_info->part_field_array; + i= 0; + while ((field= *(ptr++))) + { + CHARSET_INFO *cs= ((Field_str*)field)->charset(); + size= field->pack_length(); + if (!(field_buf= sql_calloc(size))) + goto error; + part_info->part_field_buffers[i++]= field_buf; + } + } + if (part_info->is_sub_partitioned() && + check_part_func_fields(part_info->subpart_field_array, FALSE)) + { + /* + Set up arrays and buffers for those fields + */ + part_info->includes_charset_field_subpart= TRUE; + + ptr= part_info->subpart_field_array; + i= 0; + while ((field= *(ptr++))) + { + unsigned j= 0; + Field *part_field; + Field **part_ptr= part_info->part_field_array; + bool field_already_have_buffer= FALSE; + CHARSET_INFO *cs= ((Field_str*)field)->charset(); + size= field->pack_length(); + + while ((part_field= *(part_ptr++))) + { + field_buf= part_info->part_field_buffers[j++]; + if (field == part_field) + { + field_already_have_buffer= TRUE; + break; + } + } + if (!field_already_have_buffer) + { + if (!(field_buf= sql_calloc(size))) + goto error; + } + part_info->subpart_field_buffers[i++]= field_buf; + } + size= i * sizeof(char*); + if (!(char_ptrs= (char**)sql_calloc(i * sizeof(char*)))) + goto error; + part_info->restore_subpart_field_ptrs= char_ptrs; + } + DBUG_RETURN(FALSE); +error: + mem_alloc_error(size); + DBUG_RETURN(TRUE); +} /* fix partition functions @@ -1555,10 +1715,10 @@ bool fix_partition_func(THD *thd, TABLE *table, } if (((part_info->part_type != HASH_PARTITION || part_info->list_of_part_fields == FALSE) && - check_part_func_fields(part_info->part_field_array)) || + check_part_func_fields(part_info->part_field_array, TRUE)) || (part_info->list_of_part_fields == FALSE && part_info->is_sub_partitioned() && - check_part_func_fields(part_info->subpart_field_array))) + check_part_func_fields(part_info->subpart_field_array, TRUE))) { my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0)); goto end; @@ -1573,6 +1733,11 @@ bool fix_partition_func(THD *thd, TABLE *table, goto end; if (unlikely(set_up_partition_bitmap(thd, part_info))) goto end; + if (unlikely(set_up_charset_field_preps(part_info))) + { + my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0)); + goto end; + } check_range_capable_PF(table); set_up_partition_key_maps(table, part_info); set_up_partition_func_pointers(part_info); @@ -2289,6 +2454,86 @@ static uint32 get_part_id_linear_key(partition_info *part_info, no_parts)); } +/* + Copy to field buffers and set up field pointers + SYNOPSIS + copy_to_part_field_buffers() + ptr Array of fields to copy + RETURN VALUES + NONE + DESCRIPTION + This routine is used to take the data from field pointer, convert + it to a standard format and store this format in a field buffer + allocated for this purpose. Next the field pointers are moved to + point to the field buffers. There is a separate to restore the + field pointers after this call. +*/ + +static void copy_to_part_field_buffers(Field **ptr, + char **field_bufs, + char **restore_ptr) +{ + Field *field; + while ((field= *(ptr++))) + { + *restore_ptr= field->ptr; + restore_ptr++; + if ((field->type() == MYSQL_TYPE_VARCHAR || + (field->type() == MYSQL_TYPE_STRING && + (!(((Field_str*)field)->charset()->state & MY_CS_BINSORT))) && + ((!field->maybe_null()) || (!field->is_null())))) + { + CHARSET_INFO *cs= ((Field_str*)field)->charset(); + uint len= field->pack_length(); + char *field_buf= *field_bufs; + /* + We only use the field buffer for VARCHAR and CHAR strings + which isn't of a binary collation. We also only use the + field buffer for fields which are not currently NULL. + The field buffer will store a normalised string. We use + the strnxfrm method to normalise the string. + */ + if (field->type() == MYSQL_TYPE_VARCHAR) + { + uint len_bytes= ((Field_varstring*)field)->length_bytes; + my_strnxfrm(cs, (uchar*)(field_buf + len_bytes), (len - len_bytes), + (uchar*)(field->ptr + len_bytes), field->field_length); + if (len_bytes == 1) + *field_buf= (uchar)field->field_length; + else + int2store(field_buf, field->field_length); + } + else + { + my_strnxfrm(cs, (uchar*)field_buf, len, + (uchar*)field->ptr, field->field_length); + } + field->ptr= field_buf; + } + field_bufs++; + } + return; +} + +/* + Restore field pointers + SYNOPSIS + restore_part_field_pointers() + ptr Array of fields to restore + RETURN VALUES + NONE +*/ + +static void restore_part_field_pointers(Field **ptr, char **restore_ptr) +{ + Field *field; + while ((field= *(ptr++))) + { + field->ptr= *restore_ptr; + restore_ptr++; + } + return; +} /* This function is used to calculate the partition id where all partition fields have been prepared to point to a record where the partition field @@ -2299,6 +2544,7 @@ static uint32 get_part_id_linear_key(partition_info *part_info, part_info A reference to the partition_info struct where all the desired information is given out:part_id The partition id is returned through this pointer + out: func_value Value of partition function (longlong) RETURN VALUE part_id Partition id of partition that would contain @@ -2342,6 +2588,7 @@ static uint32 get_part_id_linear_key(partition_info *part_info, part_info A reference to the partition_info struct where all the desired information is given out:part_id The partition id is returned through this pointer + out: func_value The value calculated by partition function RETURN VALUE part_id Partition id of partition that would contain @@ -2363,6 +2610,78 @@ static uint32 get_part_id_linear_key(partition_info *part_info, get_partition_id_linear_key_nosub */ +static int get_part_id_charset_func_subpart(partition_info *part_info, + uint32 *part_id, + longlong *func_value) +{ + int res; + copy_to_part_field_buffers(part_info->subpart_field_array, + part_info->subpart_field_buffers, + part_info->restore_subpart_field_ptrs); + res= part_info->get_partition_id_charset(part_info, part_id, func_value); + restore_part_field_pointers(part_info->subpart_field_array, + part_info->restore_subpart_field_ptrs); + return res; +} +static int get_part_id_charset_func_part(partition_info *part_info, + uint32 *part_id, + longlong *func_value) +{ + int res; + copy_to_part_field_buffers(part_info->part_field_array, + part_info->part_field_buffers, + part_info->restore_part_field_ptrs); + res= part_info->get_partition_id_charset(part_info, part_id, func_value); + restore_part_field_pointers(part_info->part_field_array, + part_info->restore_part_field_ptrs); + return res; +} + +static int get_part_id_charset_func_all(partition_info *part_info, + uint32 *part_id, + longlong *func_value) +{ + int res; + copy_to_part_field_buffers(part_info->part_field_array, + part_info->part_field_buffers, + part_info->restore_part_field_ptrs); + copy_to_part_field_buffers(part_info->subpart_field_array, + part_info->subpart_field_buffers, + part_info->restore_subpart_field_ptrs); + res= part_info->get_partition_id_charset(part_info, part_id, func_value); + restore_part_field_pointers(part_info->part_field_array, + part_info->restore_part_field_ptrs); + restore_part_field_pointers(part_info->subpart_field_array, + part_info->restore_subpart_field_ptrs); + return res; +} + +static int get_part_part_id_charset_func(partition_info *part_info, + uint32 *part_id, + longlong *func_value) +{ + int res; + copy_to_part_field_buffers(part_info->part_field_array, + part_info->part_field_buffers, + part_info->restore_part_field_ptrs); + res= part_info->get_part_partition_id_charset(part_info, + part_id, func_value); + restore_part_field_pointers(part_info->part_field_array, + part_info->restore_part_field_ptrs); + return res; +} + +static uint32 get_subpart_id_charset_func(partition_info *part_info) +{ + int res; + copy_to_part_field_buffers(part_info->subpart_field_array, + part_info->subpart_field_buffers, + part_info->restore_subpart_field_ptrs); + res= part_info->get_subpartition_id_charset(part_info); + restore_part_field_pointers(part_info->subpart_field_array, + part_info->restore_subpart_field_ptrs); + return res; +} int get_partition_id_list(partition_info *part_info, uint32 *part_id, @@ -2451,6 +2770,21 @@ notfound: The edge of corresponding sub-array of part_info->list_array */ +uint32 get_list_array_idx_for_endpoint_charset(partition_info *part_info, + bool left_endpoint, + bool include_endpoint) +{ + uint32 res; + copy_to_part_field_buffers(part_info->part_field_array, + part_info->part_field_buffers, + part_info->restore_part_field_ptrs); + res= get_list_array_idx_for_endpoint(part_info, left_endpoint, + include_endpoint); + restore_part_field_pointers(part_info->part_field_array, + part_info->restore_part_field_ptrs); + return res; +} + uint32 get_list_array_idx_for_endpoint(partition_info *part_info, bool left_endpoint, bool include_endpoint) @@ -2580,6 +2914,22 @@ int get_partition_id_range(partition_info *part_info, The edge of corresponding part_info->range_int_array sub-array. */ +static uint32 +get_partition_id_range_for_endpoint_charset(partition_info *part_info, + bool left_endpoint, + bool include_endpoint) +{ + uint32 res; + copy_to_part_field_buffers(part_info->part_field_array, + part_info->part_field_buffers, + part_info->restore_part_field_ptrs); + res= get_partition_id_range_for_endpoint(part_info, left_endpoint, + include_endpoint); + restore_part_field_pointers(part_info->part_field_array, + part_info->restore_part_field_ptrs); + return res; +} + uint32 get_partition_id_range_for_endpoint(partition_info *part_info, bool left_endpoint, bool include_endpoint) @@ -6420,13 +6770,20 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info, if (part_info->part_type == RANGE_PARTITION) { - get_endpoint= get_partition_id_range_for_endpoint; + if (part_info->includes_charset_field_part) + get_endpoint= get_partition_id_range_for_endpoint_charset; + else + get_endpoint= get_partition_id_range_for_endpoint; max_endpoint_val= part_info->no_parts; part_iter->get_next= get_next_partition_id_range; } else if (part_info->part_type == LIST_PARTITION) { - get_endpoint= get_list_array_idx_for_endpoint; + + if (part_info->includes_charset_field_part) + get_endpoint= get_list_array_idx_for_endpoint_charset; + else + get_endpoint= get_list_array_idx_for_endpoint; max_endpoint_val= part_info->no_list_values; part_iter->get_next= get_next_partition_id_list; part_iter->part_info= part_info; From 9711ee848c85152227338ef578cad226e28f36fb Mon Sep 17 00:00:00 2001 From: "mikael/pappa@dator5.(none)" <> Date: Wed, 2 Aug 2006 08:06:46 -0400 Subject: [PATCH 09/21] BUG#18198: Fixes ascii on varchar now allowed --- mysql-test/r/partition_error.result | 2 +- mysql-test/t/partition_error.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/partition_error.result b/mysql-test/r/partition_error.result index 87ae1d62a04..6ded066c3ec 100644 --- a/mysql-test/r/partition_error.result +++ b/mysql-test/r/partition_error.result @@ -641,7 +641,7 @@ ERROR HY000: Partition constant is out of partition function domain create table t1 (v varchar(12)) partition by range (ascii(v)) (partition p0 values less than (10)); -ERROR HY000: This partition function is not allowed +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 diff --git a/mysql-test/t/partition_error.test b/mysql-test/t/partition_error.test index 2c0706cb2cb..a9efbc587be 100644 --- a/mysql-test/t/partition_error.test +++ b/mysql-test/t/partition_error.test @@ -809,10 +809,10 @@ partition by range (a) # # Bug 18198 Partitions: Verify that erroneus partition functions doesn't work # --- error ER_PARTITION_FUNCTION_IS_NOT_ALLOWED 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) From 814b81ad6b8583fdaa67fa2c6999feac0a5a0a26 Mon Sep 17 00:00:00 2001 From: "mikael/pappa@dator5.(none)" <> Date: Mon, 4 Sep 2006 11:18:34 -0400 Subject: [PATCH 10/21] BUG#21210: ALTER TABLE t1 REORGANIZE PARTITION crashes when using InnoDB Inserted wrong handlers into the new_file_array which later caused havoc in rename_partitions --- sql/ha_partition.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 30c64760c88..377f5dbc83c 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -1360,6 +1360,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, i= 0; part_count= 0; orig_count= 0; + first= TRUE; part_it.rewind(); do { @@ -1387,9 +1388,16 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, DBUG_RETURN(ER_OUTOFMEMORY); } } while (++j < no_subparts); + if (part_elem->part_state == PART_CHANGED) + orig_count+= no_subparts; + else if (temp_partitions && first) + { + orig_count+= (no_subparts * temp_partitions); + first= FALSE; + } } } while (++i < no_parts); - + first= FALSE; /* Step 5: Create the new partitions and also open, lock and call external_lock From 2b3a53e54ef71f1b4c9bc96c7d69224e1cdfc96e Mon Sep 17 00:00:00 2001 From: "mikael/pappa@dator5.(none)" <> Date: Fri, 8 Sep 2006 03:18:05 -0400 Subject: [PATCH 11/21] Rearranged test cases, move InnoDB test cases to partition_innodb --- mysql-test/r/partition.result | 37 --------------- mysql-test/r/partition_error.result | 24 ---------- mysql-test/r/partition_innodb.result | 71 ++++++++++++++++++++++++++++ mysql-test/r/partition_range.result | 10 ---- mysql-test/t/partition.test | 37 --------------- mysql-test/t/partition_error.test | 17 ------- mysql-test/t/partition_innodb.test | 68 ++++++++++++++++++++++++++ mysql-test/t/partition_range.test | 12 ----- 8 files changed, 139 insertions(+), 137 deletions(-) diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index 2e2af07bfdc..f89568e3780 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -21,32 +21,6 @@ partition by key(a) partitions 1e+300; ERROR 42000: Only normal integers allowed as number here near '1e+300' at line 3 create table t1 (a int) -engine = innodb -partition by key (a); -show table status; -Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 InnoDB 10 Compact 2 8192 16384 0 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL partitioned -insert into t1 values (0), (1), (2), (3); -show table status; -Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 InnoDB 10 Compact 4 4096 16384 0 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL partitioned -drop table t1; -create table t1 (a int auto_increment primary key) -engine = innodb -partition by key (a); -show table status; -Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 InnoDB 10 Compact 2 8192 16384 0 0 0 1 NULL NULL NULL latin1_swedish_ci NULL partitioned -insert into t1 values (NULL), (NULL), (NULL), (NULL); -show table status; -Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 InnoDB 10 Compact 4 4096 16384 0 0 0 5 NULL NULL NULL latin1_swedish_ci NULL partitioned -insert into t1 values (NULL), (NULL), (NULL), (NULL); -show table status; -Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 InnoDB 10 Compact 8 2048 16384 0 0 0 9 NULL NULL NULL latin1_swedish_ci NULL partitioned -drop table t1; -create table t1 (a int) partition by key (a) (partition p0 DATA DIRECTORY 'part-data' INDEX DIRECTORY 'part-data'); ERROR 42000: Incorrect table name 'part-data' @@ -1042,17 +1016,6 @@ set session sql_mode=''; drop table t1; create table t1 (a int) partition by key (a) -(partition p1 engine = innodb); -alter table t1 rebuild partition p1; -alter table t1 rebuild partition p1; -alter table t1 rebuild partition p1; -alter table t1 rebuild partition p1; -alter table t1 rebuild partition p1; -alter table t1 rebuild partition p1; -alter table t1 rebuild partition p1; -drop table t1; -create table t1 (a int) -partition by key (a) (partition p0 engine = MERGE); ERROR HY000: MyISAM Merge handler cannot be used in partitioned tables create table t1 (a varchar(1)) diff --git a/mysql-test/r/partition_error.result b/mysql-test/r/partition_error.result index a51aaf22f69..4b01b759902 100644 --- a/mysql-test/r/partition_error.result +++ b/mysql-test/r/partition_error.result @@ -1,28 +1,4 @@ drop table if exists t1; -create table t1 (a int) -engine = x -partition by key (a); -Warnings: -Error 1286 Unknown table engine 'x' -show create table t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `a` int(11) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY KEY (a) */ -drop table t1; -create table t1 (a int) -engine = innodb -partition by list (a) -(partition p0 values in (0)); -alter table t1 engine = x; -Warnings: -Error 1286 Unknown table engine 'x' -show create table t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `a` int(11) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1 /*!50100 PARTITION BY LIST (a) (PARTITION p0 VALUES IN (0) ENGINE = InnoDB) */ -drop table t1; partition by list (a) partitions 3 (partition x1 values in (1,2,9,4) tablespace ts1, diff --git a/mysql-test/r/partition_innodb.result b/mysql-test/r/partition_innodb.result index f4e75ccdb05..8619d0909ee 100644 --- a/mysql-test/r/partition_innodb.result +++ b/mysql-test/r/partition_innodb.result @@ -3,3 +3,74 @@ show table status like 't1'; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment t1 InnoDB 10 Compact 2 8192 16384 0 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL partitioned drop table t1; +create table t1 (a int) +engine = innodb +partition by key (a); +show table status; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment +t1 InnoDB 10 Compact 2 8192 16384 0 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL partitioned +insert into t1 values (0), (1), (2), (3); +show table status; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment +t1 InnoDB 10 Compact 4 4096 16384 0 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL partitioned +drop table t1; +create table t1 (a int auto_increment primary key) +engine = innodb +partition by key (a); +show table status; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment +t1 InnoDB 10 Compact 2 8192 16384 0 0 0 1 NULL NULL NULL latin1_swedish_ci NULL partitioned +insert into t1 values (NULL), (NULL), (NULL), (NULL); +show table status; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment +t1 InnoDB 10 Compact 4 4096 16384 0 0 0 5 NULL NULL NULL latin1_swedish_ci NULL partitioned +insert into t1 values (NULL), (NULL), (NULL), (NULL); +show table status; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment +t1 InnoDB 10 Compact 8 2048 16384 0 0 0 9 NULL NULL NULL latin1_swedish_ci NULL partitioned +drop table t1; +create table t1 (a int) +partition by key (a) +(partition p1 engine = innodb); +alter table t1 rebuild partition p1; +alter table t1 rebuild partition p1; +alter table t1 rebuild partition p1; +alter table t1 rebuild partition p1; +alter table t1 rebuild partition p1; +alter table t1 rebuild partition p1; +alter table t1 rebuild partition p1; +drop table t1; +create table t1 (a date) +engine = innodb +partition by range (year(a)) +(partition p0 values less than (2006), +partition p1 values less than (2007)); +explain partitions select * from t1 +where a between '2006-01-01' and '2007-06-01'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p1 ALL NULL NULL NULL NULL 2 Using where +drop table t1; +create table t1 (a int) +engine = x +partition by key (a); +Warnings: +Error 1286 Unknown table engine 'x' +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY KEY (a) */ +drop table t1; +create table t1 (a int) +engine = innodb +partition by list (a) +(partition p0 values in (0)); +alter table t1 engine = x; +Warnings: +Error 1286 Unknown table engine 'x' +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 /*!50100 PARTITION BY LIST (a) (PARTITION p0 VALUES IN (0) ENGINE = InnoDB) */ +drop table t1; diff --git a/mysql-test/r/partition_range.result b/mysql-test/r/partition_range.result index be88d9f6639..9812c80040b 100644 --- a/mysql-test/r/partition_range.result +++ b/mysql-test/r/partition_range.result @@ -1,14 +1,4 @@ drop table if exists t1; -create table t1 (a date) -engine = innodb -partition by range (year(a)) -(partition p0 values less than (2006), -partition p1 values less than (2007)); -explain partitions select * from t1 -where a between '2006-01-01' and '2007-06-01'; -id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 p1 ALL NULL NULL NULL NULL 2 Using where -drop table t1; create table t1 (a int unsigned) partition by range (a) (partition pnull values less than (0), diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index 532a63b0d24..96c4d4a4b1d 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -42,27 +42,6 @@ create table t1 (a int) partition by key(a) partitions 1e+300; -# -# Bug 21173: SHOW TABLE STATUS crashes server in InnoDB -# -create table t1 (a int) -engine = innodb -partition by key (a); -show table status; -insert into t1 values (0), (1), (2), (3); -show table status; -drop table t1; - -create table t1 (a int auto_increment primary key) -engine = innodb -partition by key (a); -show table status; -insert into t1 values (NULL), (NULL), (NULL), (NULL); -show table status; -insert into t1 values (NULL), (NULL), (NULL), (NULL); -show table status; -drop table t1; - # # Bug 21350: Data Directory problems # @@ -1193,22 +1172,6 @@ show create table t1; set session sql_mode=''; drop table t1; -# -# BUG 19122 Crash after ALTER TABLE t1 REBUILD PARTITION p1 -# -create table t1 (a int) -partition by key (a) -(partition p1 engine = innodb); - -alter table t1 rebuild partition p1; -alter table t1 rebuild partition p1; -alter table t1 rebuild partition p1; -alter table t1 rebuild partition p1; -alter table t1 rebuild partition p1; -alter table t1 rebuild partition p1; -alter table t1 rebuild partition p1; -drop table t1; - # # BUG 19304 Partitions: MERGE handler not allowed in partitioned tables # diff --git a/mysql-test/t/partition_error.test b/mysql-test/t/partition_error.test index d0e3f355292..5afed68d855 100644 --- a/mysql-test/t/partition_error.test +++ b/mysql-test/t/partition_error.test @@ -8,23 +8,6 @@ drop table if exists t1; --enable_warnings -# -# Bug 20397: Partitions: Crash when using non-existing engine -# -create table t1 (a int) -engine = x -partition by key (a); -show create table t1; -drop table t1; - -create table t1 (a int) -engine = innodb -partition by list (a) -(partition p0 values in (0)); - -alter table t1 engine = x; -show create table t1; -drop table t1; # # Partition by key stand-alone error diff --git a/mysql-test/t/partition_innodb.test b/mysql-test/t/partition_innodb.test index a110fb30a3b..782e204742f 100644 --- a/mysql-test/t/partition_innodb.test +++ b/mysql-test/t/partition_innodb.test @@ -8,3 +8,71 @@ create table t1 (a int) engine=innodb partition by hash(a) ; show table status like 't1'; drop table t1; +# +# Bug 21173: SHOW TABLE STATUS crashes server in InnoDB +# +create table t1 (a int) +engine = innodb +partition by key (a); +show table status; +insert into t1 values (0), (1), (2), (3); +show table status; +drop table t1; + +create table t1 (a int auto_increment primary key) +engine = innodb +partition by key (a); +show table status; +insert into t1 values (NULL), (NULL), (NULL), (NULL); +show table status; +insert into t1 values (NULL), (NULL), (NULL), (NULL); +show table status; +drop table t1; + +# +# BUG 19122 Crash after ALTER TABLE t1 REBUILD PARTITION p1 +# +create table t1 (a int) +partition by key (a) +(partition p1 engine = innodb); + +alter table t1 rebuild partition p1; +alter table t1 rebuild partition p1; +alter table t1 rebuild partition p1; +alter table t1 rebuild partition p1; +alter table t1 rebuild partition p1; +alter table t1 rebuild partition p1; +alter table t1 rebuild partition p1; +drop table t1; + +# +# Bug 21339: Crash in Explain Partitions +# +create table t1 (a date) +engine = innodb +partition by range (year(a)) +(partition p0 values less than (2006), + partition p1 values less than (2007)); +explain partitions select * from t1 +where a between '2006-01-01' and '2007-06-01'; +drop table t1; + +# +# Bug 20397: Partitions: Crash when using non-existing engine +# +create table t1 (a int) +engine = x +partition by key (a); +show create table t1; +drop table t1; + +create table t1 (a int) +engine = innodb +partition by list (a) +(partition p0 values in (0)); + +alter table t1 engine = x; +show create table t1; +drop table t1; + + diff --git a/mysql-test/t/partition_range.test b/mysql-test/t/partition_range.test index 8719cbd98c4..12495fdae73 100644 --- a/mysql-test/t/partition_range.test +++ b/mysql-test/t/partition_range.test @@ -9,18 +9,6 @@ drop table if exists t1; --enable_warnings -# -# Bug 21339: Crash in Explain Partitions -# -create table t1 (a date) -engine = innodb -partition by range (year(a)) -(partition p0 values less than (2006), - partition p1 values less than (2007)); -explain partitions select * from t1 -where a between '2006-01-01' and '2007-06-01'; -drop table t1; - # # More checks for partition pruning # From 89af58aa95e087be1dd70e8da07adeeefae1296c Mon Sep 17 00:00:00 2001 From: "mikael/pappa@dator5.(none)" <> Date: Fri, 8 Sep 2006 05:57:37 -0400 Subject: [PATCH 12/21] Need to set symbolic-links=1 for valgrind builds for the partition test --- mysql-test/t/partition-master.opt | 1 + 1 file changed, 1 insertion(+) create mode 100644 mysql-test/t/partition-master.opt diff --git a/mysql-test/t/partition-master.opt b/mysql-test/t/partition-master.opt new file mode 100644 index 00000000000..b1392bfd485 --- /dev/null +++ b/mysql-test/t/partition-master.opt @@ -0,0 +1 @@ +--symbolic-links=1 From 3b4ef2a9755328c9a510d31336792ba52d4555d3 Mon Sep 17 00:00:00 2001 From: "mikael/pappa@dator5.(none)" <> Date: Tue, 19 Sep 2006 02:56:02 -0400 Subject: [PATCH 13/21] BUG#22178: Scan ordered performed also on engines not supporting ordered scans Scan of ranges without start key should not use ordered scans unless it is requested. --- sql/ha_partition.cc | 17 ++++++++++++++++- sql/ha_partition.h | 7 ++++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index e435b356def..6b08d42edce 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -3655,7 +3655,10 @@ int ha_partition::read_range_first(const key_range *start_key, if (!start_key) // Read first record { - m_index_scan_type= partition_index_first; + if (m_ordered) + m_index_scan_type= partition_index_first; + else + m_index_scan_type= partition_index_first_unordered; error= common_first_last(m_rec0); } else @@ -3869,6 +3872,18 @@ int ha_partition::handle_unordered_scan_next_partition(byte * buf) DBUG_PRINT("info", ("index_first on partition %d", i)); error= file->index_first(buf); break; + case partition_index_first_unordered: + /* + We perform a scan without sorting and this means that we + should not use the index_first since not all handlers + support it and it is also unnecessary to restrict sort + order. + */ + DBUG_PRINT("info", ("read_range_first on partition %d", i)); + table->record[0]= buf; + error= file->read_range_first(0, end_range, eq_range, 0); + table->record[0]= m_rec0; + break; default: DBUG_ASSERT(FALSE); DBUG_RETURN(1); diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 97086d7b632..d76591b7514 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -45,9 +45,10 @@ private: { partition_index_read= 0, partition_index_first= 1, - partition_index_last= 2, - partition_index_read_last= 3, - partition_no_index_scan= 4 + partition_index_first_unordered= 2, + partition_index_last= 3, + partition_index_read_last= 4, + partition_no_index_scan= 5 }; /* Data for the partition handler */ int m_mode; // Open mode From ea9014043b3c809e210bc8a2c80fb253359ad7f3 Mon Sep 17 00:00:00 2001 From: "mikael/pappa@dator5.(none)" <> Date: Tue, 19 Sep 2006 11:40:21 -0400 Subject: [PATCH 14/21] Close the DDL log from 2 places => put into separate method Needed to close ddl log in recovery before deleting it --- sql/sql_table.cc | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 610771724e1..2500ea46c3e 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1132,6 +1132,26 @@ bool execute_ddl_log_entry(THD *thd, uint first_entry) } +/* + Close the ddl log + SYNOPSIS + close_ddl_log() + RETURN VALUES + NONE +*/ + +static void close_ddl_log() +{ + DBUG_ENTER("close_ddl_log"); + if (global_ddl_log.file_id >= 0) + { + VOID(my_close(global_ddl_log.file_id, MYF(MY_WME))); + global_ddl_log.file_id= (File) -1; + } + DBUG_VOID_RETURN; +} + + /* Execute the ddl log at recovery of MySQL Server SYNOPSIS @@ -1183,6 +1203,7 @@ void execute_ddl_log_recovery() } } } + close_ddl_log(); create_ddl_log_file_name(file_name); VOID(my_delete(file_name, MYF(0))); global_ddl_log.recovery_phase= FALSE; @@ -1220,11 +1241,7 @@ void release_ddl_log() my_free((char*)free_list, MYF(0)); free_list= tmp; } - if (global_ddl_log.file_id >= 0) - { - VOID(my_close(global_ddl_log.file_id, MYF(MY_WME))); - global_ddl_log.file_id= (File) -1; - } + close_ddl_log(); global_ddl_log.inited= 0; pthread_mutex_unlock(&LOCK_gdl); VOID(pthread_mutex_destroy(&LOCK_gdl)); From 0d4d06fd6c05abf2faca31c7c9bd5a4f71b5fbef Mon Sep 17 00:00:00 2001 From: "mikael/pappa@dator5.(none)" <> Date: Tue, 26 Sep 2006 01:38:17 -0400 Subject: [PATCH 15/21] Fixed bugs in check_part_func_fields --- sql/sql_partition.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index eedcdcb2083..d815fb1ac24 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1452,16 +1452,13 @@ static bool check_part_func_fields(Field **ptr, bool ok_with_charsets) CHARSET_INFO *cs= ((Field_str*)field)->charset(); if (field->type() == MYSQL_TYPE_STRING && cs->state & MY_CS_BINSORT) - { - DBUG_RETURN(FALSE); - } + continue; if (!ok_with_charsets || cs->mbmaxlen > 1 || cs->strxfrm_multiply > 1) { DBUG_RETURN(TRUE); } - DBUG_RETURN(FALSE); } } DBUG_RETURN(FALSE); From 58ee682e9d3daf27c771a34b0a465e29a29b2205 Mon Sep 17 00:00:00 2001 From: "mikael/pappa@dator5.(none)" <> Date: Tue, 26 Sep 2006 02:25:23 -0400 Subject: [PATCH 16/21] BUG#18198 Review comments --- sql/item.h | 51 +++++++++++++++++++++++++------------- sql/item_cmpfunc.h | 29 +++++++++++----------- sql/item_func.h | 60 ++++++++++++++++++++++----------------------- sql/item_strfunc.h | 28 ++++++++++----------- sql/item_timefunc.h | 60 ++++++++++++++++++++++----------------------- sql/item_xmlfunc.h | 2 +- 6 files changed, 123 insertions(+), 107 deletions(-) diff --git a/sql/item.h b/sql/item.h index 09722c62f2b..89c4ce8ff18 100644 --- a/sql/item.h +++ b/sql/item.h @@ -846,8 +846,31 @@ public: 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. + + The general behaviour is that most integer functions are allowed. + If the partition function contains any multi-byte collations then + the function check_part_func_fields will report an error on the + partition function independent of what functions are used. So the + only character sets allowed are single character collation and + even for those only a limited set of functions are allowed. The + problem with multi-byte collations is that almost every string + function has the ability to change things such that two strings + that are equal will not be equal after manipulated by a string + function. E.g. two strings one contains a double s, there is a + special german character that is equal to two s. Now assume a + string function removes one character at this place, then in + one the double s will be removed and in the other there will + still be one s remaining and the strings are no longer equal + and thus the partition function will not sort equal strings into + the same partitions. + + So the check if a partition function is valid is two steps. First + check that the field types are valid, next check that the partition + function is valid. The current set of partition functions valid + assumes that there are no multi-byte collations amongst the partition + fields. */ - virtual bool check_partition_func_processor(byte *bool_arg) { return FALSE; } + virtual bool check_partition_func_processor(byte *bool_arg) { return TRUE;} virtual bool subst_argument_checker(byte **arg) { if (*arg) @@ -1348,7 +1371,7 @@ public: bool collect_item_field_processor(byte * arg); bool find_item_in_field_list_processor(byte *arg); bool register_field_in_read_map(byte *arg); - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} void cleanup(); bool result_as_longlong() { @@ -1397,7 +1420,7 @@ public: bool is_null() { return 1; } void print(String *str) { str->append(STRING_WITH_LEN("NULL")); } Item *safe_charset_converter(CHARSET_INFO *tocs); - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; class Item_null_result :public Item_null @@ -1410,8 +1433,7 @@ public: { save_in_field(result_field, no_conversions); } - bool check_partition_func_processor(byte *int_arg) - { *(int *)int_arg= 0; return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return TRUE;} }; /* Item represents one placeholder ('?') of prepared statement */ @@ -1702,8 +1724,7 @@ public: {} void print(String *str) { str->append(func_name); } Item *safe_charset_converter(CHARSET_INFO *tocs); - bool check_partition_func_processor(byte *int_arg) - { *(int *)int_arg= 0; return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return TRUE;} }; @@ -1781,7 +1802,7 @@ public: void print(String *str); // to prevent drop fixed flag (no need parent cleanup call) void cleanup() {} - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -1796,8 +1817,7 @@ public: {} Item *safe_charset_converter(CHARSET_INFO *tocs); void print(String *str) { str->append(func_name); } - bool check_partition_func_processor(byte *int_arg) - { *(int *)int_arg= 0; return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return TRUE;} }; @@ -1810,8 +1830,7 @@ public: &my_charset_bin) { max_length=19;} enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; } - bool check_partition_func_processor(byte *int_arg) - { *(int *)int_arg= 0; return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return TRUE;} }; class Item_empty_string :public Item_string @@ -1834,8 +1853,7 @@ public: unsigned_flag=1; } enum_field_types field_type() const { return int_field_type; } - bool check_partition_func_processor(byte *int_arg) - { *(int *)int_arg= 0; return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return TRUE;} }; @@ -1859,7 +1877,7 @@ public: void cleanup() {} bool eq(const Item *item, bool binary_cmp) const; virtual Item *safe_charset_converter(CHARSET_INFO *tocs); - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -2086,8 +2104,7 @@ public: } Item *new_item(); virtual Item *real_item() { return ref; } - bool check_partition_func_processor(byte *int_arg) - { *(int *)int_arg= 0; return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return TRUE;} }; #ifdef MYSQL_SERVER diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index a3b8d9757d8..18badc71c1d 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -240,7 +240,7 @@ public: } Item *neg_transformer(THD *thd); virtual Item *negated_item(); - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} bool subst_argument_checker(byte **arg) { return TRUE; } }; @@ -252,7 +252,7 @@ public: enum Functype functype() const { return NOT_FUNC; } const char *func_name() const { return "not"; } Item *neg_transformer(THD *thd); - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; class Item_maxmin_subselect; @@ -469,7 +469,7 @@ public: bool is_bool_func() { return 1; } CHARSET_INFO *compare_collation() { return cmp_collation.collation; } uint decimal_precision() const { return 1; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -481,7 +481,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); } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -544,7 +544,7 @@ public: const char *func_name() const { return "ifnull"; } Field *tmp_table_field(TABLE *table); uint decimal_precision() const; - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -585,7 +585,7 @@ public: void print(String *str) { Item_func::print(str); } table_map not_null_tables() const { return 0; } bool is_null(); - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -628,7 +628,7 @@ public: void print(String *str); Item *find_item(String *str); CHARSET_INFO *compare_collation() { return cmp_collation.collation; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -979,7 +979,7 @@ public: bool nulls_in_row(); bool is_bool_func() { return 1; } CHARSET_INFO *compare_collation() { return cmp_collation.collation; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; /* Functions used by where clause */ @@ -1021,7 +1021,7 @@ public: optimize_type select_optimize() const { return OPTIMIZE_NULL; } Item *neg_transformer(THD *thd); CHARSET_INFO *compare_collation() { return args[0]->collation.collation; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; /* Functions used by HAVING for rewriting IN subquery */ @@ -1043,8 +1043,7 @@ public: */ table_map used_tables() const { return used_tables_cache | RAND_TABLE_BIT; } - bool check_partition_func_processor(byte *int_arg) - { *(int *)int_arg= 0; return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return TRUE;} }; @@ -1067,7 +1066,7 @@ public: void print(String *str); CHARSET_INFO *compare_collation() { return args[0]->collation.collation; } void top_level_item() { abort_on_null=1; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -1106,7 +1105,7 @@ public: const char *func_name() const { return "like"; } bool fix_fields(THD *thd, Item **ref); void cleanup(); - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; #ifdef USE_REGEX @@ -1129,7 +1128,7 @@ public: const char *func_name() const { return "regexp"; } void print(String *str) { print_op(str); } CHARSET_INFO *compare_collation() { return cmp_collation.collation; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; #else @@ -1186,7 +1185,7 @@ public: Item *transform(Item_transformer transformer, byte *arg); void traverse_cond(Cond_traverser, void *arg, traverse_order order); void neg_arguments(THD *thd); - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} bool subst_argument_checker(byte **arg) { return TRUE; } Item *compile(Item_analyzer analyzer, byte **arg_p, Item_transformer transformer, byte *arg_t); diff --git a/sql/item_func.h b/sql/item_func.h index 8c96b74ef26..f820a89b5b6 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -254,7 +254,7 @@ public: void fix_num_length_and_dec(); void find_num_type(); String *str_op(String *str) { DBUG_ASSERT(0); return 0; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -267,7 +267,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; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -318,7 +318,7 @@ public: { max_length=args[0]->max_length; unsigned_flag=0; } void print(String *str); uint decimal_precision() const { return args[0]->decimal_precision(); } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -352,7 +352,7 @@ public: void fix_length_and_dec() {}; const char *func_name() const { return "decimal_typecast"; } void print(String *); - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -421,7 +421,7 @@ public: const char *func_name() const { return "DIV"; } void fix_length_and_dec(); void print(String *str) { print_op(str); } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -494,7 +494,7 @@ public: Item_func_exp(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "exp"; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -504,7 +504,7 @@ public: Item_func_ln(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "ln"; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -515,7 +515,7 @@ public: Item_func_log(Item *a,Item *b) :Item_dec_func(a,b) {} double val_real(); const char *func_name() const { return "log"; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -525,7 +525,7 @@ public: Item_func_log2(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "log2"; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -535,7 +535,7 @@ public: Item_func_log10(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "log10"; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -545,7 +545,7 @@ public: Item_func_sqrt(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "sqrt"; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -555,7 +555,7 @@ public: Item_func_pow(Item *a,Item *b) :Item_dec_func(a,b) {} double val_real(); const char *func_name() const { return "pow"; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -565,7 +565,7 @@ public: Item_func_acos(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "acos"; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; class Item_func_asin :public Item_dec_func @@ -574,7 +574,7 @@ public: Item_func_asin(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "asin"; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; class Item_func_atan :public Item_dec_func @@ -584,7 +584,7 @@ public: Item_func_atan(Item *a,Item *b) :Item_dec_func(a,b) {} double val_real(); const char *func_name() const { return "atan"; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; class Item_func_cos :public Item_dec_func @@ -593,7 +593,7 @@ public: Item_func_cos(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "cos"; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; class Item_func_sin :public Item_dec_func @@ -602,7 +602,7 @@ public: Item_func_sin(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "sin"; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; class Item_func_tan :public Item_dec_func @@ -611,7 +611,7 @@ public: Item_func_tan(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "tan"; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; class Item_func_integer :public Item_int_func @@ -688,7 +688,7 @@ public: Item_func_sign(Item *a) :Item_int_func(a) {} const char *func_name() const { return "sign"; } longlong val_int(); - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -703,7 +703,7 @@ public: const char *func_name() const { return name; } void fix_length_and_dec() { decimals= NOT_FIXED_DEC; max_length= float_length(decimals); } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -721,7 +721,7 @@ public: my_decimal *val_decimal(my_decimal *); void fix_length_and_dec(); enum Item_result result_type () const { return cmp_type; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; class Item_func_min :public Item_func_min_max @@ -747,7 +747,7 @@ public: longlong val_int(); const char *func_name() const { return "length"; } void fix_length_and_dec() { max_length=10; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; class Item_func_bit_length :public Item_func_length @@ -767,7 +767,7 @@ public: longlong val_int(); const char *func_name() const { return "char_length"; } void fix_length_and_dec() { max_length=10; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; class Item_func_coercibility :public Item_int_func @@ -791,7 +791,7 @@ public: longlong val_int(); void fix_length_and_dec(); void print(String *str); - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -816,7 +816,7 @@ public: longlong val_int(); const char *func_name() const { return "ascii"; } void fix_length_and_dec() { max_length=3; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; class Item_func_ord :public Item_int_func @@ -826,7 +826,7 @@ public: Item_func_ord(Item *a) :Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "ord"; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; class Item_func_find_in_set :public Item_int_func @@ -840,7 +840,7 @@ public: longlong val_int(); const char *func_name() const { return "find_in_set"; } void fix_length_and_dec(); - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; /* Base class for all bit functions: '~', '|', '^', '&', '>>', '<<' */ @@ -852,7 +852,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); } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; class Item_func_bit_or :public Item_func_bit @@ -878,7 +878,7 @@ public: longlong val_int(); const char *func_name() const { return "bit_count"; } void fix_length_and_dec() { max_length=2; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; class Item_func_shift_left :public Item_func_bit @@ -1318,7 +1318,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;} - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 77672d51933..2adccd212b3 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -50,7 +50,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "md5"; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -94,7 +94,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "concat"; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; class Item_func_concat_ws :public Item_str_func @@ -116,7 +116,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "reverse"; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -154,7 +154,7 @@ protected: public: Item_str_conv(Item *item) :Item_str_func(item) {} String *val_str(String *); - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -457,7 +457,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "soundex"; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -558,7 +558,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "rpad"; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -571,7 +571,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "lpad"; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -586,7 +586,7 @@ public: collation.set(default_charset()); max_length= 64; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -603,7 +603,7 @@ public: decimals=0; max_length=args[0]->max_length*2*collation.collation->mbmaxlen; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; class Item_func_unhex :public Item_str_func @@ -619,7 +619,7 @@ public: decimals=0; max_length=(1+args[0]->max_length)/2; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -643,7 +643,7 @@ public: } void print(String *str); const char *func_name() const { return "cast_as_binary"; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -683,7 +683,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; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; class Item_func_quote :public Item_str_func @@ -698,7 +698,7 @@ public: collation.set(args[0]->collation); max_length= args[0]->max_length * 2 + 2; } - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; class Item_func_conv_charset :public Item_str_func @@ -799,7 +799,7 @@ public: const char *func_name() const { return "crc32"; } void fix_length_and_dec() { max_length=10; } longlong val_int(); - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; class Item_func_uncompressed_length : public Item_int_func diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 6623f7ad418..2a6ddd1bc65 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -39,7 +39,7 @@ public: { max_length=6*MY_CHARSET_BIN_MB_MAXLEN; } - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -54,7 +54,7 @@ public: decimals=0; max_length=6*MY_CHARSET_BIN_MB_MAXLEN; } - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -71,7 +71,7 @@ public: maybe_null=1; } enum_monotonicity_info get_monotonicity_info() const; - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -87,7 +87,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -112,7 +112,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -145,7 +145,7 @@ public: max_length=3*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -161,7 +161,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -177,7 +177,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -193,7 +193,7 @@ public: max_length=1*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -209,7 +209,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -225,7 +225,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; class Item_func_yearweek :public Item_int_func @@ -240,7 +240,7 @@ public: max_length=6*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -257,7 +257,7 @@ public: max_length=4*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -287,7 +287,7 @@ public: max_length=1*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; class Item_func_dayname :public Item_func_weekday @@ -320,7 +320,7 @@ public: decimals=0; max_length=10*MY_CHARSET_BIN_MB_MAXLEN; } - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -335,7 +335,7 @@ public: decimals=0; max_length=10*MY_CHARSET_BIN_MB_MAXLEN; } - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -545,7 +545,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); - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -563,7 +563,7 @@ public: void fix_length_and_dec(); uint format_length(const String *format); bool eq(const Item *item, bool binary_cmp) const; - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -582,7 +582,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); - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -651,7 +651,7 @@ public: return tmp_table_field_from_field_type(table, 0); } bool result_as_longlong() { return TRUE; } - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -674,7 +674,7 @@ public: bool get_date(TIME *res, uint fuzzy_date); bool eq(const Item *item, bool binary_cmp) const; void print(String *str); - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -692,7 +692,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); - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -729,7 +729,7 @@ public: max_length=args[0]->max_length; maybe_null= 1; } - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -749,7 +749,7 @@ public: String *val_str(String *a); void fix_length_and_dec(); void print(String *str); - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -829,7 +829,7 @@ public: } bool result_as_longlong() { return TRUE; } longlong val_int(); - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -852,7 +852,7 @@ public: } void print(String *str); const char *func_name() const { return "add_time"; } - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; class Item_func_timediff :public Item_str_func @@ -892,7 +892,7 @@ public: { return tmp_table_field_from_field_type(table, 0); } - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; class Item_func_microsecond :public Item_int_func @@ -906,7 +906,7 @@ public: decimals=0; maybe_null=1; } - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -924,7 +924,7 @@ public: maybe_null=1; } void print(String *str); - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -971,7 +971,7 @@ public: { return tmp_table_field_from_field_type(table, 1); } - bool check_partition_func_processor(byte *int_arg) { return FALSE;} + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; diff --git a/sql/item_xmlfunc.h b/sql/item_xmlfunc.h index 513a85aa665..6fa33081373 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 *); - bool check_partition_func_processor(byte *int_arg) { return FALSE; } + bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; From 6df933a8cb785fe4ad444bc79e4c9bfdf4cc73cc Mon Sep 17 00:00:00 2001 From: "mikael/pappa@dator5.(none)" <> Date: Tue, 26 Sep 2006 02:30:40 -0400 Subject: [PATCH 17/21] BUG#18198 Fixed interface to check_partition_func_processor --- sql/partition_info.cc | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/sql/partition_info.cc b/sql/partition_info.cc index ecf423f08b1..c8cf38e5629 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -722,25 +722,17 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type, if (check_partition_function) { - int part_expression_ok= 1; - int pf_collation_allowed= 1; - int spf_collation_allowed= 1; + int err= 0; if (part_type != HASH_PARTITION || !list_of_part_fields) { - part_expr->walk(&Item::check_partition_func_processor, 0, - (byte*)(&part_expression_ok)); - pf_collation_allowed= part_expression_ok; - part_expression_ok= 1; - if (is_sub_partitioned() && !list_of_subpart_fields) - { - subpart_expr->walk(&Item::check_partition_func_processor, 0, - (byte*)(&part_expression_ok)); - } - spf_collation_allowed= part_expression_ok; + err= part_expr->walk(&Item::check_partition_func_processor, 0, + NULL); + if (!err && is_sub_partitioned() && !list_of_subpart_fields) + err= subpart_expr->walk(&Item::check_partition_func_processor, 0, + NULL); } - if (!pf_collation_allowed || - !spf_collation_allowed) + if (err) { my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0)); goto end; From 6be97e4e4359dc8f0c00b56fc4655fed9a757573 Mon Sep 17 00:00:00 2001 From: "mikael/pappa@dator5.(none)" <> Date: Tue, 26 Sep 2006 16:30:39 -0400 Subject: [PATCH 18/21] Final step of Take 7 on review fixes of this fairly complex bug --- mysql-test/r/partition.result | 5 - sql/partition_info.cc | 168 ++++++++++++++++++++++++++++- sql/partition_info.h | 18 ++-- sql/sql_partition.cc | 195 ++++++++++------------------------ sql/sql_partition.h | 3 + sql/sql_yacc.yy | 5 +- 6 files changed, 241 insertions(+), 153 deletions(-) diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index d8d433ef216..97d6275a835 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -1,9 +1,4 @@ drop table if exists t1; -create table t1 (s1 char(2) character set utf8) -partition by list (case when s1 > 'cz' then 1 else 2 end) -(partition p1 values in (1), -partition p2 values in (2)); -drop table t1; create table t1 (a int) partition by key(a) partitions 0.2+e1; diff --git a/sql/partition_info.cc b/sql/partition_info.cc index c8cf38e5629..724464125ea 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -859,5 +859,171 @@ void partition_info::print_no_partition_found(TABLE *table) my_error(ER_NO_PARTITION_FOR_GIVEN_VALUE, MYF(0), buf_ptr); dbug_tmp_restore_column_map(table->read_set, old_map); } +/* + Set up buffers and arrays for fields requiring preparation + SYNOPSIS + set_up_charset_field_preps() + part_info Partition info object + RETURN VALUES + TRUE Memory Allocation error + FALSE Success + DESCRIPTION + Set up arrays and buffers for fields that require special care for + calculation of partition id. This is used for string fields with + variable length or string fields with fixed length that isn't using + the binary collation. +*/ -#endif /* WITH_PARTITION_STORAGE_ENGINE */ +bool partition_info::set_up_charset_field_preps() +{ + Field *field, **ptr; + char *field_buf; + char **char_ptrs; + unsigned i; + bool found; + size_t size; + uint tot_fields= 0; + uint tot_part_fields= 0; + uint tot_subpart_fields= 0; + DBUG_ENTER("set_up_charset_field_preps"); + + if (!(part_type == HASH_PARTITION && + list_of_part_fields) && + check_part_func_fields(part_field_array, FALSE)) + { + ptr= part_field_array; + /* Set up arrays and buffers for those fields */ + i= 0; + while ((field= *(ptr++))) + { + if (field_is_partition_charset(field)) + { + tot_part_fields++; + tot_fields++; + } + } + size= tot_part_fields * sizeof(char*); + if (!(char_ptrs= (char**)sql_calloc(size))) + goto error; + part_field_buffers= char_ptrs; + if (!(char_ptrs= (char**)sql_calloc(size))) + goto error; + restore_part_field_ptrs= char_ptrs; + size= (tot_part_fields + 1) * sizeof(Field*); + if (!(char_ptrs= (char**)sql_alloc(size))) + goto error; + part_charset_field_array= (Field**)char_ptrs; + ptr= part_field_array; + i= 0; + while ((field= *(ptr++))) + { + if (field_is_partition_charset(field)) + { + CHARSET_INFO *cs= ((Field_str*)field)->charset(); + size= field->pack_length(); + if (!(field_buf= sql_calloc(size))) + goto error; + part_charset_field_array[i]= field; + part_field_buffers[i++]= field_buf; + } + } + part_charset_field_array[i]= NULL; + } + if (is_sub_partitioned() && list_of_subpart_fields && + check_part_func_fields(subpart_field_array, FALSE)) + { + /* Set up arrays and buffers for those fields */ + ptr= subpart_field_array; + while ((field= *(ptr++))) + { + if (field_is_partition_charset(field)) + tot_subpart_fields++; + } + size= tot_subpart_fields * sizeof(char*); + if (!(char_ptrs= (char**)sql_calloc(size))) + goto error; + subpart_field_buffers= char_ptrs; + if (!(char_ptrs= (char**)sql_calloc(size))) + goto error; + restore_subpart_field_ptrs= char_ptrs; + size= (tot_subpart_fields + 1) * sizeof(Field*); + if (!(char_ptrs= (char**)sql_alloc(size))) + goto error; + subpart_charset_field_array= (Field**)char_ptrs; + i= 0; + while ((field= *(ptr++))) + { + unsigned j= 0; + Field *part_field; + CHARSET_INFO *cs; + + if (!field_is_partition_charset(field)) + continue; + cs= ((Field_str*)field)->charset(); + size= field->pack_length(); + found= FALSE; + for (j= 0; j < tot_part_fields; j++) + { + if (field == part_charset_field_array[i]) + found= TRUE; + } + if (!found) + { + tot_fields++; + if (!(field_buf= sql_calloc(size))) + goto error; + } + subpart_field_buffers[i++]= field_buf; + } + if (!(char_ptrs= (char**)sql_calloc(size))) + goto error; + restore_subpart_field_ptrs= char_ptrs; + } + if (tot_fields) + { + Field *part_field, *subpart_field; + uint j,k,l; + + size= tot_fields*sizeof(char**); + if (!(char_ptrs= (char**)sql_calloc(size))) + goto error; + full_part_field_buffers= char_ptrs; + if (!(char_ptrs= (char**)sql_calloc(size))) + goto error; + restore_full_part_field_ptrs= char_ptrs; + size= (tot_fields + 1) * sizeof(char**); + if (!(char_ptrs= (char**)sql_calloc(size))) + goto error; + full_part_charset_field_array= (Field**)char_ptrs; + for (i= 0; i < tot_part_fields; i++) + { + full_part_charset_field_array[i]= part_charset_field_array[i]; + full_part_field_buffers[i]= part_field_buffers[i]; + } + k= tot_part_fields; + l= 0; + for (i= 0; i < tot_subpart_fields; i++) + { + field= subpart_charset_field_array[i]; + found= FALSE; + for (j= 0; j < tot_part_fields; j++) + { + if (field == part_charset_field_array[i]) + found= TRUE; + } + if (!found) + { + full_part_charset_field_array[l]= subpart_charset_field_array[k]; + full_part_field_buffers[l]= subpart_field_buffers[k]; + k++; l++; + } + } + full_part_charset_field_array[tot_fields]= NULL; + } + DBUG_RETURN(FALSE); +error: + mem_alloc_error(size); + DBUG_RETURN(TRUE); +} +#endif + /* WITH_PARTITION_STORAGE_ENGINE */ diff --git a/sql/partition_info.h b/sql/partition_info.h index 91beaf569e0..b45789c4bae 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -73,14 +73,15 @@ public: /* NULL-terminated array of fields used in partitioned expression */ Field **part_field_array; - /* NULL-terminated array of fields used in subpartitioned expression */ Field **subpart_field_array; - + Field **part_charset_field_array; + Field **subpart_charset_field_array; /* Array of all fields used in partition and subpartition expression, without duplicates, NULL-terminated. */ Field **full_part_field_array; + Field **full_part_charset_field_array; /* When we have a field that requires transformation before calling the @@ -89,8 +90,10 @@ public: */ char **part_field_buffers; char **subpart_field_buffers; + char **full_part_field_buffers; char **restore_part_field_ptrs; char **restore_subpart_field_ptrs; + char **restore_full_part_field_ptrs; Item *part_expr; Item *subpart_expr; @@ -208,17 +211,20 @@ public: bool is_auto_partitioned; bool from_openfrm; bool has_null_value; - bool includes_charset_field_part; - bool includes_charset_field_subpart; partition_info() : get_partition_id(NULL), get_part_partition_id(NULL), get_subpartition_id(NULL), part_field_array(NULL), subpart_field_array(NULL), + part_charset_field_array(NULL), + subpart_charset_field_array(NULL), full_part_field_array(NULL), + full_part_charset_field_array(NULL), part_field_buffers(NULL), subpart_field_buffers(NULL), + full_part_field_buffers(NULL), restore_part_field_ptrs(NULL), restore_subpart_field_ptrs(NULL), + restore_full_part_field_ptrs(NULL), part_expr(NULL), subpart_expr(NULL), item_free_list(NULL), first_log_entry(NULL), exec_log_entry(NULL), frm_log_entry(NULL), list_array(NULL), @@ -241,8 +247,7 @@ public: list_of_part_fields(FALSE), list_of_subpart_fields(FALSE), linear_hash_ind(FALSE), fixed(FALSE), is_auto_partitioned(FALSE), from_openfrm(FALSE), - has_null_value(FALSE), includes_charset_field_part(FALSE), - includes_charset_field_subpart(FALSE) + has_null_value(FALSE) { all_fields_in_PF.clear_all(); all_fields_in_PPF.clear_all(); @@ -278,6 +283,7 @@ public: handler *file, HA_CREATE_INFO *info, bool check_partition_function); void print_no_partition_found(TABLE *table); + bool set_up_charset_field_preps(); private: static int list_part_cmp(const void* a, const void* b); static int list_part_cmp_unsigned(const void* a, const void* b); diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index eb431134d9d..796f018e04b 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1346,20 +1346,19 @@ static void set_up_partition_func_pointers(partition_info *part_info) } } } - if (part_info->includes_charset_field_part || - part_info->includes_charset_field_subpart) + if (part_info->full_part_charset_field_array) { DBUG_ASSERT(part_info->get_partition_id); part_info->get_partition_id_charset= part_info->get_partition_id; - if (part_info->includes_charset_field_part && - part_info->includes_charset_field_subpart) + if (part_info->part_charset_field_array && + part_info->subpart_charset_field_array) part_info->get_partition_id= get_part_id_charset_func_all; - else if (part_info->includes_charset_field_part) + else if (part_info->part_charset_field_array) part_info->get_partition_id= get_part_id_charset_func_part; else part_info->get_partition_id= get_part_id_charset_func_subpart; } - if (part_info->includes_charset_field_part && + if (part_info->part_charset_field_array && part_info->is_sub_partitioned()) { DBUG_ASSERT(part_info->get_part_partition_id); @@ -1367,7 +1366,7 @@ static void set_up_partition_func_pointers(partition_info *part_info) part_info->get_part_partition_id; part_info->get_part_partition_id= get_part_part_id_charset_func; } - if (part_info->includes_charset_field_subpart) + if (part_info->subpart_charset_field_array) { DBUG_ASSERT(part_info->get_subpartition_id); part_info->get_subpartition_id_charset= @@ -1435,6 +1434,32 @@ static uint32 get_part_id_from_linear_hash(longlong hash_value, uint mask, } +/* + Check if a particular field is in need of character set + handling for partition functions. + SYNOPSIS + field_is_partition_charset() + field The field to check + RETURN VALUES + FALSE Not in need of character set handling + TRUE In need of character set handling +*/ + +bool field_is_partition_charset(Field *field) +{ + if (!field->type() == MYSQL_TYPE_STRING && + !field->type() == MYSQL_TYPE_VARCHAR) + return FALSE; + { + CHARSET_INFO *cs= ((Field_str*)field)->charset(); + if (!field->type() == MYSQL_TYPE_STRING || + !(cs->state & MY_CS_BINSORT)) + return TRUE; + return FALSE; + } +} + + /* Check that partition function do not contain any forbidden character sets and collations. @@ -1453,7 +1478,7 @@ static uint32 get_part_id_from_linear_hash(longlong hash_value, uint mask, calling the functions to calculate partition id. */ -static bool check_part_func_fields(Field **ptr, bool ok_with_charsets) +bool check_part_func_fields(Field **ptr, bool ok_with_charsets) { Field *field; DBUG_ENTER("check_part_func_field"); @@ -1465,13 +1490,9 @@ static bool check_part_func_fields(Field **ptr, bool ok_with_charsets) Binary collation with CHAR is automatically supported. Other types need some kind of standardisation function handling */ - if (field->type() == MYSQL_TYPE_STRING || - field->type() == MYSQL_TYPE_VARCHAR) + if (field_is_partition_charset(field)) { CHARSET_INFO *cs= ((Field_str*)field)->charset(); - if (field->type() == MYSQL_TYPE_STRING && - cs->state & MY_CS_BINSORT) - continue; if (!ok_with_charsets || cs->mbmaxlen > 1 || cs->strxfrm_multiply > 1) @@ -1483,106 +1504,6 @@ static bool check_part_func_fields(Field **ptr, bool ok_with_charsets) DBUG_RETURN(FALSE); } -/* - Set up buffers and arrays for fields requiring preparation - SYNOPSIS - set_up_charset_field_preps() - part_info Partition info object - RETURN VALUES - TRUE Memory Allocation error - FALSE Success - DESCRIPTION - Set up arrays and buffers for fields that require special care for - calculation of partition id. This is used for string fields with - variable length or string fields with fixed length that isn't using - the binary collation. -*/ - -static bool set_up_charset_field_preps(partition_info *part_info) -{ - Field *field, **ptr; - char *field_buf; - char **char_ptrs; - unsigned i; - size_t size; - - DBUG_ENTER("set_up_charset_field_preps"); - if (check_part_func_fields(part_info->part_field_array, FALSE)) - { - ptr= part_info->part_field_array; - part_info->includes_charset_field_part= TRUE; - /* - Set up arrays and buffers for those fields - */ - i= 0; - while ((field= *(ptr++))) - i++; - size= i * sizeof(char*); - - if (!(char_ptrs= (char**)sql_calloc(size))) - goto error; - part_info->part_field_buffers= char_ptrs; - - if (!(char_ptrs= (char**)sql_calloc(size))) - goto error; - part_info->restore_part_field_ptrs= char_ptrs; - - ptr= part_info->part_field_array; - i= 0; - while ((field= *(ptr++))) - { - CHARSET_INFO *cs= ((Field_str*)field)->charset(); - size= field->pack_length(); - if (!(field_buf= sql_calloc(size))) - goto error; - part_info->part_field_buffers[i++]= field_buf; - } - } - if (part_info->is_sub_partitioned() && - check_part_func_fields(part_info->subpart_field_array, FALSE)) - { - /* - Set up arrays and buffers for those fields - */ - part_info->includes_charset_field_subpart= TRUE; - - ptr= part_info->subpart_field_array; - i= 0; - while ((field= *(ptr++))) - { - unsigned j= 0; - Field *part_field; - Field **part_ptr= part_info->part_field_array; - bool field_already_have_buffer= FALSE; - CHARSET_INFO *cs= ((Field_str*)field)->charset(); - size= field->pack_length(); - - while ((part_field= *(part_ptr++))) - { - field_buf= part_info->part_field_buffers[j++]; - if (field == part_field) - { - field_already_have_buffer= TRUE; - break; - } - } - if (!field_already_have_buffer) - { - if (!(field_buf= sql_calloc(size))) - goto error; - } - part_info->subpart_field_buffers[i++]= field_buf; - } - size= i * sizeof(char*); - if (!(char_ptrs= (char**)sql_calloc(i * sizeof(char*)))) - goto error; - part_info->restore_subpart_field_ptrs= char_ptrs; - } - DBUG_RETURN(FALSE); -error: - mem_alloc_error(size); - DBUG_RETURN(TRUE); -} /* fix partition functions @@ -1747,7 +1668,7 @@ bool fix_partition_func(THD *thd, TABLE *table, goto end; if (unlikely(set_up_partition_bitmap(thd, part_info))) goto end; - if (unlikely(set_up_charset_field_preps(part_info))) + if (unlikely(part_info->set_up_charset_field_preps())) { my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0)); goto end; @@ -2491,10 +2412,7 @@ static void copy_to_part_field_buffers(Field **ptr, { *restore_ptr= field->ptr; restore_ptr++; - if ((field->type() == MYSQL_TYPE_VARCHAR || - (field->type() == MYSQL_TYPE_STRING && - (!(((Field_str*)field)->charset()->state & MY_CS_BINSORT))) && - ((!field->maybe_null()) || (!field->is_null())))) + if (!field->maybe_null() || !field->is_null()) { CHARSET_INFO *cs= ((Field_str*)field)->charset(); uint len= field->pack_length(); @@ -2628,74 +2546,75 @@ static int get_part_id_charset_func_subpart(partition_info *part_info, longlong *func_value) { int res; - copy_to_part_field_buffers(part_info->subpart_field_array, + copy_to_part_field_buffers(part_info->subpart_charset_field_array, part_info->subpart_field_buffers, part_info->restore_subpart_field_ptrs); res= part_info->get_partition_id_charset(part_info, part_id, func_value); - restore_part_field_pointers(part_info->subpart_field_array, + restore_part_field_pointers(part_info->subpart_charset_field_array, part_info->restore_subpart_field_ptrs); return res; } + + static int get_part_id_charset_func_part(partition_info *part_info, uint32 *part_id, longlong *func_value) { int res; - copy_to_part_field_buffers(part_info->part_field_array, + copy_to_part_field_buffers(part_info->part_charset_field_array, part_info->part_field_buffers, part_info->restore_part_field_ptrs); res= part_info->get_partition_id_charset(part_info, part_id, func_value); - restore_part_field_pointers(part_info->part_field_array, + restore_part_field_pointers(part_info->part_charset_field_array, part_info->restore_part_field_ptrs); return res; } + static int get_part_id_charset_func_all(partition_info *part_info, uint32 *part_id, longlong *func_value) { int res; - copy_to_part_field_buffers(part_info->part_field_array, - part_info->part_field_buffers, - part_info->restore_part_field_ptrs); - copy_to_part_field_buffers(part_info->subpart_field_array, - part_info->subpart_field_buffers, - part_info->restore_subpart_field_ptrs); + copy_to_part_field_buffers(part_info->full_part_field_array, + part_info->full_part_field_buffers, + part_info->restore_full_part_field_ptrs); res= part_info->get_partition_id_charset(part_info, part_id, func_value); - restore_part_field_pointers(part_info->part_field_array, - part_info->restore_part_field_ptrs); - restore_part_field_pointers(part_info->subpart_field_array, - part_info->restore_subpart_field_ptrs); + restore_part_field_pointers(part_info->full_part_field_array, + part_info->restore_full_part_field_ptrs); return res; } + static int get_part_part_id_charset_func(partition_info *part_info, uint32 *part_id, longlong *func_value) { int res; - copy_to_part_field_buffers(part_info->part_field_array, + copy_to_part_field_buffers(part_info->part_charset_field_array, part_info->part_field_buffers, part_info->restore_part_field_ptrs); res= part_info->get_part_partition_id_charset(part_info, part_id, func_value); - restore_part_field_pointers(part_info->part_field_array, + restore_part_field_pointers(part_info->part_charset_field_array, part_info->restore_part_field_ptrs); return res; } + static uint32 get_subpart_id_charset_func(partition_info *part_info) { int res; - copy_to_part_field_buffers(part_info->subpart_field_array, + copy_to_part_field_buffers(part_info->subpart_charset_field_array, part_info->subpart_field_buffers, part_info->restore_subpart_field_ptrs); res= part_info->get_subpartition_id_charset(part_info); - restore_part_field_pointers(part_info->subpart_field_array, + restore_part_field_pointers(part_info->subpart_charset_field_array, part_info->restore_subpart_field_ptrs); return res; } + int get_partition_id_list(partition_info *part_info, uint32 *part_id, longlong *func_value) @@ -6782,7 +6701,7 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info, if (part_info->part_type == RANGE_PARTITION) { - if (part_info->includes_charset_field_part) + if (part_info->part_charset_field_array) get_endpoint= get_partition_id_range_for_endpoint_charset; else get_endpoint= get_partition_id_range_for_endpoint; @@ -6792,7 +6711,7 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info, else if (part_info->part_type == LIST_PARTITION) { - if (part_info->includes_charset_field_part) + if (part_info->part_charset_field_array) get_endpoint= get_list_array_idx_for_endpoint_charset; else get_endpoint= get_list_array_idx_for_endpoint; diff --git a/sql/sql_partition.h b/sql/sql_partition.h index e34d71dfdc5..c5b930162a9 100644 --- a/sql/sql_partition.h +++ b/sql/sql_partition.h @@ -93,6 +93,9 @@ uint32 get_partition_id_range_for_endpoint(partition_info *part_info, bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table, bool is_sub_part, bool is_field_to_be_setup); +bool check_part_func_fields(Field **ptr, bool ok_with_charsets); +bool field_is_partition_charset(Field *field); + /* A "Get next" function for partition iterator. diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index aedbb2fc894..fd53983c33f 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3618,9 +3618,8 @@ part_bit_expr: mem_alloc_error(sizeof(part_elem_value)); YYABORT; } - part_expr->walk(&Item::check_partition_func_processor, 0, - (byte*)(&part_expression_ok)); - if (!part_expression_ok) + if (part_expr->walk(&Item::check_partition_func_processor, 0, + NULL)) { my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0)); YYABORT; From 81248942b717bb4e3a38003d1e68c5c7ed17eb9c Mon Sep 17 00:00:00 2001 From: "mikael/pappa@dator5.(none)" <> Date: Sat, 30 Sep 2006 17:38:15 -0400 Subject: [PATCH 19/21] BUG#18198: Partition function handling Review fixes --- mysql-test/r/partition_range.result | 34 +++++++++++++++++++++++ mysql-test/t/partition_hash.test | 12 ++++++++ mysql-test/t/partition_range.test | 43 +++++++++++++++++++++++++++++ sql/item.h | 14 ++++++++-- sql/partition_info.cc | 9 +++--- sql/sql_partition.cc | 13 +++++++-- 6 files changed, 116 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/partition_range.result b/mysql-test/r/partition_range.result index 2fa40b44815..c8380446f44 100644 --- a/mysql-test/r/partition_range.result +++ b/mysql-test/r/partition_range.result @@ -1,4 +1,38 @@ drop table if exists t1; +create table t1 (a varchar(10) charset latin1 collate latin1_bin, b int) +partition by range (length(a) * b) +(partition p0 values less than (2), partition p1 values less than (10)); +insert into t1 values ('a ', 2),('a',3); +drop table t1; +create table t1 (a varchar(10) charset latin1 collate latin1_bin, b int) +partition by range (b* length(a) * b) +(partition p0 values less than (2), partition p1 values less than (10)); +insert into t1 values ('a ', 2),('a',3); +drop table t1; +create table t1 (a varchar(10) charset latin1 collate latin1_bin, +b varchar(10) charset latin1 collate latin1_bin) +partition by range (length(b) * length(a)) +(partition p0 values less than (2), partition p1 values less than (10)); +insert into t1 values ('a ', 'b '),('a','b'); +drop table t1; +create table t1 (a varchar(10) charset latin1 collate latin1_bin, +b varchar(10) charset latin1 collate latin1_bin) +partition by range (length(a) * length(b)) +(partition p0 values less than (2), partition p1 values less than (10)); +insert into t1 values ('a ', 'b '),('a','b'); +drop table t1; +create table t1 (a varchar(10) charset latin1 collate latin1_bin, +b varchar(10) charset latin1 collate latin1_bin, c int) +partition by range (length(a) * c) +(partition p0 values less than (2), partition p1 values less than (10)); +insert into t1 values ('a ', 'b ', 2),('a','b', 3); +drop table t1; +create table t1 (a varchar(10) charset latin1 collate latin1_bin, +b varchar(10) charset latin1 collate latin1_bin, c int) +partition by range (c * length(a)) +(partition p0 values less than (2), partition p1 values less than (10)); +insert into t1 values ('a ', 'b ', 2),('a','b', 3); +drop table t1; create table t1 (a int unsigned) partition by range (a) (partition pnull values less than (0), diff --git a/mysql-test/t/partition_hash.test b/mysql-test/t/partition_hash.test index 3304f30fb1a..d3f1a5f4892 100644 --- a/mysql-test/t/partition_hash.test +++ b/mysql-test/t/partition_hash.test @@ -9,6 +9,18 @@ drop table if exists t1; --enable_warnings +# +# BUG 18198: Partition functions handling +# +create table t1 (a varchar(10) charset latin1 collate latin1_bin) +partition by hash(length(a)) +partitions 10; +insert into t1 values (''),(' '),('a'),('a '),('a '); +explain partitions select * from t1 where a='a '; +explain partitions select * from t1 where a='a'; +explain partitions select * from t1 where a='a ' OR a='a'; +drop table t1; + # # More partition pruning tests, especially on interval walking # diff --git a/mysql-test/t/partition_range.test b/mysql-test/t/partition_range.test index 8cf2313e39c..ead971c189e 100644 --- a/mysql-test/t/partition_range.test +++ b/mysql-test/t/partition_range.test @@ -9,6 +9,49 @@ drop table if exists t1; --enable_warnings +# +# BUG 18198: Various tests for partition functions +# +create table t1 (a varchar(10) charset latin1 collate latin1_bin, b int) +partition by range (length(a) * b) +(partition p0 values less than (2), partition p1 values less than (10)); +insert into t1 values ('a ', 2),('a',3); +drop table t1; + +create table t1 (a varchar(10) charset latin1 collate latin1_bin, b int) +partition by range (b* length(a) * b) +(partition p0 values less than (2), partition p1 values less than (10)); +insert into t1 values ('a ', 2),('a',3); +drop table t1; + +create table t1 (a varchar(10) charset latin1 collate latin1_bin, + b varchar(10) charset latin1 collate latin1_bin) +partition by range (length(b) * length(a)) +(partition p0 values less than (2), partition p1 values less than (10)); +insert into t1 values ('a ', 'b '),('a','b'); +drop table t1; + +create table t1 (a varchar(10) charset latin1 collate latin1_bin, + b varchar(10) charset latin1 collate latin1_bin) +partition by range (length(a) * length(b)) +(partition p0 values less than (2), partition p1 values less than (10)); +insert into t1 values ('a ', 'b '),('a','b'); +drop table t1; + +create table t1 (a varchar(10) charset latin1 collate latin1_bin, + b varchar(10) charset latin1 collate latin1_bin, c int) +partition by range (length(a) * c) +(partition p0 values less than (2), partition p1 values less than (10)); +insert into t1 values ('a ', 'b ', 2),('a','b', 3); +drop table t1; + +create table t1 (a varchar(10) charset latin1 collate latin1_bin, + b varchar(10) charset latin1 collate latin1_bin, c int) +partition by range (c * length(a)) +(partition p0 values less than (2), partition p1 values less than (10)); +insert into t1 values ('a ', 'b ', 2),('a','b', 3); +drop table t1; + # # More checks for partition pruning # diff --git a/sql/item.h b/sql/item.h index 1f5324f33be..8799fa07eb7 100644 --- a/sql/item.h +++ b/sql/item.h @@ -831,12 +831,20 @@ public: Check if a partition function is allowed SYNOPSIS check_partition_func_processor() - int_arg Return argument + int_arg Ignored RETURN VALUE - 0 + TRUE Partition function not accepted + FALSE Partition function accepted + 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 + uses an allowed function. An allowed function will always ensure that + X=Y guarantees that also part_function(X)=part_function(Y) where X is + a set of partition fields and so is Y. The problems comes mainly from + character sets where two equal strings can be quite unequal. E.g. the + german character for double s is equal to 2 s. + + 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 diff --git a/sql/partition_info.cc b/sql/partition_info.cc index 724464125ea..1f84d3f1e83 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -838,11 +838,12 @@ end: /* Print error for no partition found + SYNOPSIS print_no_partition_found() table Table object + RETURN VALUES - NONE */ void partition_info::print_no_partition_found(TABLE *table) @@ -863,10 +864,11 @@ void partition_info::print_no_partition_found(TABLE *table) Set up buffers and arrays for fields requiring preparation SYNOPSIS set_up_charset_field_preps() - part_info Partition info object + RETURN VALUES TRUE Memory Allocation error FALSE Success + DESCRIPTION Set up arrays and buffers for fields that require special care for calculation of partition id. This is used for string fields with @@ -1025,5 +1027,4 @@ error: mem_alloc_error(size); DBUG_RETURN(TRUE); } -#endif - /* WITH_PARTITION_STORAGE_ENGINE */ +#endif /* WITH_PARTITION_STORAGE_ENGINE */ diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 796f018e04b..cedd3f6b265 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1437,9 +1437,11 @@ static uint32 get_part_id_from_linear_hash(longlong hash_value, uint mask, /* Check if a particular field is in need of character set handling for partition functions. + SYNOPSIS field_is_partition_charset() field The field to check + RETURN VALUES FALSE Not in need of character set handling TRUE In need of character set handling @@ -1461,8 +1463,9 @@ bool field_is_partition_charset(Field *field) /* - Check that partition function do not contain any forbidden + Check that partition function doesn't contain any forbidden character sets and collations. + SYNOPSIS check_part_func_fields() ptr Array of Field pointers @@ -1471,6 +1474,7 @@ bool field_is_partition_charset(Field *field) RETURN VALUES FALSE Success TRUE Error + DESCRIPTION We will check in this routine that the fields of the partition functions do not contain unallowed parts. It can also be used to check if there @@ -2390,9 +2394,13 @@ static uint32 get_part_id_linear_key(partition_info *part_info, /* Copy to field buffers and set up field pointers + SYNOPSIS copy_to_part_field_buffers() ptr Array of fields to copy + field_bufs Array of field buffers to copy to + restore_ptr Array of pointers to restore to + RETURN VALUES NONE DESCRIPTION @@ -2451,8 +2459,9 @@ static void copy_to_part_field_buffers(Field **ptr, SYNOPSIS restore_part_field_pointers() ptr Array of fields to restore + restore_ptr Array of field pointers to restore to + RETURN VALUES - NONE */ static void restore_part_field_pointers(Field **ptr, char **restore_ptr) From 74c7f60d45e8285b17e2ecac71b33b35114be975 Mon Sep 17 00:00:00 2001 From: "mikael/pappa@dator5.(none)" <> Date: Mon, 2 Oct 2006 05:54:30 -0400 Subject: [PATCH 20/21] Bug fix --- sql/sql_partition.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index cedd3f6b265..0944db9ccb8 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1449,12 +1449,12 @@ static uint32 get_part_id_from_linear_hash(longlong hash_value, uint mask, bool field_is_partition_charset(Field *field) { - if (!field->type() == MYSQL_TYPE_STRING && - !field->type() == MYSQL_TYPE_VARCHAR) + if (!(field->type() == MYSQL_TYPE_STRING) && + !(field->type() == MYSQL_TYPE_VARCHAR)) return FALSE; { CHARSET_INFO *cs= ((Field_str*)field)->charset(); - if (!field->type() == MYSQL_TYPE_STRING || + if (!(field->type() == MYSQL_TYPE_STRING) || !(cs->state & MY_CS_BINSORT)) return TRUE; return FALSE; @@ -1485,7 +1485,7 @@ bool field_is_partition_charset(Field *field) bool check_part_func_fields(Field **ptr, bool ok_with_charsets) { Field *field; - DBUG_ENTER("check_part_func_field"); + DBUG_ENTER("check_part_func_fields"); while ((field= *(ptr++))) { From 1cdf82e012148370a721d9c4ac5c3cc9bcba00ba Mon Sep 17 00:00:00 2001 From: "mikael/pappa@dator5.(none)" <> Date: Mon, 2 Oct 2006 15:52:29 -0400 Subject: [PATCH 21/21] BUG#18198: Partition function handling Fixes of after review fixes --- mysql-test/r/partition_hash.result | 14 ++++++++++++++ mysql-test/r/partition_range.result | 12 ++++++------ mysql-test/t/partition_range.test | 12 ++++++------ sql/ha_ndbcluster.cc | 7 +++++++ sql/ha_partition.cc | 4 ++++ sql/partition_info.cc | 2 +- sql/partition_info.h | 5 +++-- sql/sql_partition.cc | 4 ++-- 8 files changed, 43 insertions(+), 17 deletions(-) diff --git a/mysql-test/r/partition_hash.result b/mysql-test/r/partition_hash.result index 9a82a36d902..7ef3ee5c6c8 100644 --- a/mysql-test/r/partition_hash.result +++ b/mysql-test/r/partition_hash.result @@ -1,4 +1,18 @@ drop table if exists t1; +create table t1 (a varchar(10) charset latin1 collate latin1_bin) +partition by hash(length(a)) +partitions 10; +insert into t1 values (''),(' '),('a'),('a '),('a '); +explain partitions select * from t1 where a='a '; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 5 Using where +explain partitions select * from t1 where a='a'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 5 Using where +explain partitions select * from t1 where a='a ' OR a='a'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 5 Using where +drop table t1; create table t1 (a int unsigned) partition by hash(a div 2) partitions 4; diff --git a/mysql-test/r/partition_range.result b/mysql-test/r/partition_range.result index c8380446f44..d39b39f413a 100644 --- a/mysql-test/r/partition_range.result +++ b/mysql-test/r/partition_range.result @@ -1,36 +1,36 @@ drop table if exists t1; create table t1 (a varchar(10) charset latin1 collate latin1_bin, b int) partition by range (length(a) * b) -(partition p0 values less than (2), partition p1 values less than (10)); +(partition p0 values less than (2), partition p1 values less than (400)); insert into t1 values ('a ', 2),('a',3); drop table t1; create table t1 (a varchar(10) charset latin1 collate latin1_bin, b int) partition by range (b* length(a) * b) -(partition p0 values less than (2), partition p1 values less than (10)); +(partition p0 values less than (2), partition p1 values less than (400)); insert into t1 values ('a ', 2),('a',3); drop table t1; create table t1 (a varchar(10) charset latin1 collate latin1_bin, b varchar(10) charset latin1 collate latin1_bin) partition by range (length(b) * length(a)) -(partition p0 values less than (2), partition p1 values less than (10)); +(partition p0 values less than (2), partition p1 values less than (400)); insert into t1 values ('a ', 'b '),('a','b'); drop table t1; create table t1 (a varchar(10) charset latin1 collate latin1_bin, b varchar(10) charset latin1 collate latin1_bin) partition by range (length(a) * length(b)) -(partition p0 values less than (2), partition p1 values less than (10)); +(partition p0 values less than (2), partition p1 values less than (400)); insert into t1 values ('a ', 'b '),('a','b'); drop table t1; create table t1 (a varchar(10) charset latin1 collate latin1_bin, b varchar(10) charset latin1 collate latin1_bin, c int) partition by range (length(a) * c) -(partition p0 values less than (2), partition p1 values less than (10)); +(partition p0 values less than (2), partition p1 values less than (400)); insert into t1 values ('a ', 'b ', 2),('a','b', 3); drop table t1; create table t1 (a varchar(10) charset latin1 collate latin1_bin, b varchar(10) charset latin1 collate latin1_bin, c int) partition by range (c * length(a)) -(partition p0 values less than (2), partition p1 values less than (10)); +(partition p0 values less than (2), partition p1 values less than (400)); insert into t1 values ('a ', 'b ', 2),('a','b', 3); drop table t1; create table t1 (a int unsigned) diff --git a/mysql-test/t/partition_range.test b/mysql-test/t/partition_range.test index ead971c189e..84f67febe8b 100644 --- a/mysql-test/t/partition_range.test +++ b/mysql-test/t/partition_range.test @@ -14,41 +14,41 @@ drop table if exists t1; # create table t1 (a varchar(10) charset latin1 collate latin1_bin, b int) partition by range (length(a) * b) -(partition p0 values less than (2), partition p1 values less than (10)); +(partition p0 values less than (2), partition p1 values less than (400)); insert into t1 values ('a ', 2),('a',3); drop table t1; create table t1 (a varchar(10) charset latin1 collate latin1_bin, b int) partition by range (b* length(a) * b) -(partition p0 values less than (2), partition p1 values less than (10)); +(partition p0 values less than (2), partition p1 values less than (400)); insert into t1 values ('a ', 2),('a',3); drop table t1; create table t1 (a varchar(10) charset latin1 collate latin1_bin, b varchar(10) charset latin1 collate latin1_bin) partition by range (length(b) * length(a)) -(partition p0 values less than (2), partition p1 values less than (10)); +(partition p0 values less than (2), partition p1 values less than (400)); insert into t1 values ('a ', 'b '),('a','b'); drop table t1; create table t1 (a varchar(10) charset latin1 collate latin1_bin, b varchar(10) charset latin1 collate latin1_bin) partition by range (length(a) * length(b)) -(partition p0 values less than (2), partition p1 values less than (10)); +(partition p0 values less than (2), partition p1 values less than (400)); insert into t1 values ('a ', 'b '),('a','b'); drop table t1; create table t1 (a varchar(10) charset latin1 collate latin1_bin, b varchar(10) charset latin1 collate latin1_bin, c int) partition by range (length(a) * c) -(partition p0 values less than (2), partition p1 values less than (10)); +(partition p0 values less than (2), partition p1 values less than (400)); insert into t1 values ('a ', 'b ', 2),('a','b', 3); drop table t1; create table t1 (a varchar(10) charset latin1 collate latin1_bin, b varchar(10) charset latin1 collate latin1_bin, c int) partition by range (c * length(a)) -(partition p0 values less than (2), partition p1 values less than (10)); +(partition p0 values less than (2), partition p1 values less than (400)); insert into t1 values ('a ', 'b ', 2),('a','b', 3); drop table t1; diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 0739b704462..ccfe8e717fb 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -1899,7 +1899,10 @@ int ha_ndbcluster::peek_indexed_rows(const byte *record) error= m_part_info->get_partition_id(m_part_info, &part_id, &func_value); dbug_tmp_restore_column_map(table->read_set, old_map); if (error) + { + m_part_info->err_value= func_value; DBUG_RETURN(error); + } op->setPartitionId(part_id); } } @@ -2534,7 +2537,10 @@ int ha_ndbcluster::write_row(byte *record) error= m_part_info->get_partition_id(m_part_info, &part_id, &func_value); dbug_tmp_restore_column_map(table->read_set, old_map); if (error) + { + m_part_info->err_value= func_value; DBUG_RETURN(error); + } op->setPartitionId(part_id); } @@ -2726,6 +2732,7 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data) m_part_info, &old_part_id, &new_part_id, &func_value))) { + m_part_info->err_value= func_value; DBUG_RETURN(error); } diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 3cb855b1035..1e75dd08f38 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -2670,7 +2670,10 @@ int ha_partition::write_row(byte * buf) #endif dbug_tmp_restore_column_map(table->read_set, old_map); if (unlikely(error)) + { + m_part_info->err_value= func_value; DBUG_RETURN(error); + } m_last_part= part_id; DBUG_PRINT("info", ("Insert in partition %d", part_id)); DBUG_RETURN(m_file[part_id]->write_row(buf)); @@ -2719,6 +2722,7 @@ int ha_partition::update_row(const byte *old_data, byte *new_data) m_part_info, &old_part_id, &new_part_id, &func_value))) { + m_part_info->err_value= func_value; DBUG_RETURN(error); } diff --git a/sql/partition_info.cc b/sql/partition_info.cc index 1f84d3f1e83..2a06a649eca 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -855,7 +855,7 @@ void partition_info::print_no_partition_found(TABLE *table) if (part_expr->null_value) buf_ptr= (char*)"NULL"; else - longlong2str(part_expr->val_int(), buf, + longlong2str(err_value, buf, part_expr->unsigned_flag ? 10 : -10); my_error(ER_NO_PARTITION_FOR_GIVEN_VALUE, MYF(0), buf_ptr); dbug_tmp_restore_column_map(table->read_set, old_map); diff --git a/sql/partition_info.h b/sql/partition_info.h index b45789c4bae..09d827d44c4 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -150,7 +150,8 @@ public: /******************************************** * INTERVAL ANALYSIS ENDS ********************************************/ - + + longlong err_value; char* part_info_string; char *part_func_string; @@ -227,7 +228,7 @@ public: restore_full_part_field_ptrs(NULL), part_expr(NULL), subpart_expr(NULL), item_free_list(NULL), first_log_entry(NULL), exec_log_entry(NULL), frm_log_entry(NULL), - list_array(NULL), + list_array(NULL), err_value(0), part_info_string(NULL), part_func_string(NULL), subpart_func_string(NULL), part_state(NULL), diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 0944db9ccb8..a20e5dd512b 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -2771,8 +2771,8 @@ notfound: int get_partition_id_range(partition_info *part_info, - uint32 *part_id, - longlong *func_value) + uint32 *part_id, + longlong *func_value) { longlong *range_array= part_info->range_int_array; uint max_partition= part_info->no_parts - 1;