#At file:///home/mikael/mysql_clones/mysql-trunk-wl3352-values/
2897 Mikael Ronstrom 2009-10-22
A lot of fixes to make character set work ok, first step to fixing BUG#48163
modified:
mysql-test/r/partition_column.result
mysql-test/t/partition_column.test
sql/mysql_priv.h
sql/partition_info.cc
sql/partition_info.h
sql/share/errmsg.txt
sql/sql_partition.cc
sql/sql_partition.h
sql/sql_show.cc
sql/sql_table.cc
=== modified file 'mysql-test/r/partition_column.result'
--- a/mysql-test/r/partition_column.result 2009-10-21 18:53:44 +0000
+++ b/mysql-test/r/partition_column.result 2009-10-22 14:15:06 +0000
@@ -1,4 +1,32 @@
drop table if exists t1;
+create table t1 (a int, b char(10), c varchar(25), d datetime)
+partition by range column_list(a,b,c,d)
+subpartition by hash (to_seconds(d))
+subpartitions 4
+( partition p0 values less than (1, 0, MAXVALUE, 0),
+partition p1 values less than (1, 'a', MAXVALUE, TO_DAYS('1999-01-01')),
+partition p2 values less than (1, 'a', MAXVALUE, MAXVALUE),
+partition p3 values less than (1, MAXVALUE, MAXVALUE, MAXVALUE));
+select partition_method, partition_expression, partition_description
+from information_schema.partitions where table_name = "t1";
+partition_method partition_expression partition_description
+RANGE COLUMN_LIST a,b,c,d 1,'0',MAXVALUE,0
+RANGE COLUMN_LIST a,b,c,d 1,'0',MAXVALUE,0
+RANGE COLUMN_LIST a,b,c,d 1,'0',MAXVALUE,0
+RANGE COLUMN_LIST a,b,c,d 1,'0',MAXVALUE,0
+RANGE COLUMN_LIST a,b,c,d 1,'a',MAXVALUE,730120
+RANGE COLUMN_LIST a,b,c,d 1,'a',MAXVALUE,730120
+RANGE COLUMN_LIST a,b,c,d 1,'a',MAXVALUE,730120
+RANGE COLUMN_LIST a,b,c,d 1,'a',MAXVALUE,730120
+RANGE COLUMN_LIST a,b,c,d 1,'a',MAXVALUE,MAXVALUE
+RANGE COLUMN_LIST a,b,c,d 1,'a',MAXVALUE,MAXVALUE
+RANGE COLUMN_LIST a,b,c,d 1,'a',MAXVALUE,MAXVALUE
+RANGE COLUMN_LIST a,b,c,d 1,'a',MAXVALUE,MAXVALUE
+RANGE COLUMN_LIST a,b,c,d 1,MAXVALUE,MAXVALUE,MAXVALUE
+RANGE COLUMN_LIST a,b,c,d 1,MAXVALUE,MAXVALUE,MAXVALUE
+RANGE COLUMN_LIST a,b,c,d 1,MAXVALUE,MAXVALUE,MAXVALUE
+RANGE COLUMN_LIST a,b,c,d 1,MAXVALUE,MAXVALUE,MAXVALUE
+drop table t1;
create table t1 (a int, b int)
partition by range column_list (a,b)
(partition p0 values less than (NULL, maxvalue));
@@ -8,12 +36,19 @@ partition by list column_list(a,b)
( partition p0 values in ((maxvalue, 0)));
Got one of the listed errors
create table t1 (a int, b int)
+partition by list column_list (a,b)
+( partition p0 values in ((0,0)));
+alter table t1 add partition
+(partition p1 values in (maxvalue, maxvalue));
+Got one of the listed errors
+drop table t1;
+create table t1 (a int, b int)
partition by key (a,a);
-ERROR HY000: Duplicate partition field name a
+ERROR HY000: Duplicate partition field name 'a'
create table t1 (a int, b int)
partition by list column_list(a,a)
( partition p values in ((1,1)));
-ERROR HY000: Duplicate partition field name a
+ERROR HY000: Duplicate partition field name 'a'
create table t1 (a int signed)
partition by list (a)
( partition p0 values in (1, 3, 5, 7, 9, NULL),
@@ -61,6 +96,16 @@ partition_method partition_expression pa
LIST COLUMN_LIST a,b (1,NULL),(2,NULL),(NULL,NULL)
LIST COLUMN_LIST a,b (1,1),(2,2)
LIST COLUMN_LIST a,b (3,NULL),(NULL,1)
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY LIST COLUMN_LIST(a,b)
+(PARTITION p0 VALUES IN ((1,NULL),(2,NULL),(NULL,NULL)) ENGINE = MyISAM,
+ PARTITION p1 VALUES IN ((1,1),(2,2)) ENGINE = MyISAM,
+ PARTITION p2 VALUES IN ((3,NULL),(NULL,1)) ENGINE = MyISAM) */
insert into t1 values (3, NULL);
insert into t1 values (NULL, 1);
insert into t1 values (NULL, NULL);
@@ -110,6 +155,14 @@ from information_schema.partitions where
partition_method partition_expression partition_description
LIST a 2,1
LIST a NULL,4,3
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY LIST (a)
+(PARTITION p0 VALUES IN (2,1) ENGINE = MyISAM,
+ PARTITION p1 VALUES IN (NULL,4,3) ENGINE = MyISAM) */
insert into t1 values (1);
insert into t1 values (2);
insert into t1 values (3);
@@ -132,6 +185,14 @@ from information_schema.partitions where
partition_method partition_expression partition_description
LIST COLUMN_LIST a 2,1
LIST COLUMN_LIST a 4,NULL,3
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY LIST COLUMN_LIST(a)
+(PARTITION p0 VALUES IN (2,1) ENGINE = MyISAM,
+ PARTITION p1 VALUES IN (4,NULL,3) ENGINE = MyISAM) */
insert into t1 values (1);
insert into t1 values (2);
insert into t1 values (3);
@@ -148,34 +209,6 @@ t1 CREATE TABLE `t1` (
(PARTITION p0 VALUES IN (2,1) ENGINE = MyISAM,
PARTITION p1 VALUES IN (4,NULL,3) ENGINE = MyISAM) */
drop table t1;
-create table t1 (a int, b char(10), c varchar(25), d datetime)
-partition by range column_list(a,b,c,d)
-subpartition by hash (to_seconds(d))
-subpartitions 4
-( partition p0 values less than (1, 0, MAXVALUE, 0),
-partition p1 values less than (1, 'a', MAXVALUE, TO_DAYS('1999-01-01')),
-partition p2 values less than (1, 'a', MAXVALUE, MAXVALUE),
-partition p3 values less than (1, MAXVALUE, MAXVALUE, MAXVALUE));
-select partition_method, partition_expression, partition_description
-from information_schema.partitions where table_name = "t1";
-partition_method partition_expression partition_description
-RANGE COLUMN_LIST a,b,c,d 1,0,MAXVALUE,0
-RANGE COLUMN_LIST a,b,c,d 1,0,MAXVALUE,0
-RANGE COLUMN_LIST a,b,c,d 1,0,MAXVALUE,0
-RANGE COLUMN_LIST a,b,c,d 1,0,MAXVALUE,0
-RANGE COLUMN_LIST a,b,c,d 1,'a',MAXVALUE,730120
-RANGE COLUMN_LIST a,b,c,d 1,'a',MAXVALUE,730120
-RANGE COLUMN_LIST a,b,c,d 1,'a',MAXVALUE,730120
-RANGE COLUMN_LIST a,b,c,d 1,'a',MAXVALUE,730120
-RANGE COLUMN_LIST a,b,c,d 1,'a',MAXVALUE,MAXVALUE
-RANGE COLUMN_LIST a,b,c,d 1,'a',MAXVALUE,MAXVALUE
-RANGE COLUMN_LIST a,b,c,d 1,'a',MAXVALUE,MAXVALUE
-RANGE COLUMN_LIST a,b,c,d 1,'a',MAXVALUE,MAXVALUE
-RANGE COLUMN_LIST a,b,c,d 1,MAXVALUE,MAXVALUE,MAXVALUE
-RANGE COLUMN_LIST a,b,c,d 1,MAXVALUE,MAXVALUE,MAXVALUE
-RANGE COLUMN_LIST a,b,c,d 1,MAXVALUE,MAXVALUE,MAXVALUE
-RANGE COLUMN_LIST a,b,c,d 1,MAXVALUE,MAXVALUE,MAXVALUE
-drop table t1;
create table t1 (a int, b char(10), c varchar(5), d int)
partition by range column_list(a,b,c)
subpartition by key (c,d)
@@ -199,6 +232,21 @@ RANGE COLUMN_LIST a,b,c 3,'abc','abc'
RANGE COLUMN_LIST a,b,c 4,'abc','abc'
RANGE COLUMN_LIST a,b,c 4,'abc','abc'
RANGE COLUMN_LIST a,b,c 4,'abc','abc'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` char(10) DEFAULT NULL,
+ `c` varchar(5) DEFAULT NULL,
+ `d` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY RANGE COLUMN_LIST(a,b,c)
+SUBPARTITION BY KEY (c,d)
+SUBPARTITIONS 3
+(PARTITION p0 VALUES LESS THAN (1,'abc','abc') ENGINE = MyISAM,
+ PARTITION p1 VALUES LESS THAN (2,'abc','abc') ENGINE = MyISAM,
+ PARTITION p2 VALUES LESS THAN (3,'abc','abc') ENGINE = MyISAM,
+ PARTITION p3 VALUES LESS THAN (4,'abc','abc') ENGINE = MyISAM) */
insert into t1 values (1,'a','b',1),(2,'a','b',2),(3,'a','b',3);
insert into t1 values (1,'b','c',1),(2,'b','c',2),(3,'b','c',3);
insert into t1 values (1,'c','d',1),(2,'c','d',2),(3,'c','d',3);
@@ -218,6 +266,16 @@ from information_schema.partitions where
partition_method partition_expression partition_description
RANGE COLUMN_LIST a,b,c 1,'A',1
RANGE COLUMN_LIST a,b,c 1,'B',1
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` varchar(2) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY RANGE COLUMN_LIST(a,b,c)
+(PARTITION p0 VALUES LESS THAN (1,'A',1) ENGINE = MyISAM,
+ PARTITION p1 VALUES LESS THAN (1,'B',1) ENGINE = MyISAM) */
insert into t1 values (1, 'A', 1);
explain partitions select * from t1 where a = 1 AND b <= 'A' and c = 1;
id select_type table partitions type possible_keys key key_len ref rows Extra
@@ -234,11 +292,21 @@ select * from t1 where a = 'a';
a b c
a NULL NULL
drop table t1;
-create table t1 (d timestamp)
+create table t1 (d time)
partition by range column_list(d)
( partition p0 values less than ('2000-01-01'),
partition p1 values less than ('2040-01-01'));
ERROR HY000: Partition column values of incorrect type
+create table t1 (d timestamp)
+partition by range column_list(d)
+( partition p0 values less than ('2000-01-01'),
+partition p1 values less than ('2040-01-01'));
+ERROR HY000: Field 'd' is of a not allowed type for this type of partitioning
+create table t1 (d bit(1))
+partition by range column_list(d)
+( partition p0 values less than (0),
+partition p1 values less than (1));
+ERROR HY000: Field 'd' is of a not allowed type for this type of partitioning
create table t1 (a int, b int)
partition by range column_list(a,b)
(partition p0 values less than (maxvalue, 10));
=== modified file 'mysql-test/t/partition_column.test'
--- a/mysql-test/t/partition_column.test 2009-10-21 18:53:44 +0000
+++ b/mysql-test/t/partition_column.test 2009-10-22 14:15:06 +0000
@@ -8,6 +8,29 @@
drop table if exists t1;
--enable_warnings
+create table t1 (a int, b char(10), c varchar(25), d datetime)
+partition by range column_list(a,b,c,d)
+subpartition by hash (to_seconds(d))
+subpartitions 4
+( partition p0 values less than (1, 0, MAXVALUE, 0),
+ partition p1 values less than (1, 'a', MAXVALUE, TO_DAYS('1999-01-01')),
+ partition p2 values less than (1, 'a', MAXVALUE, MAXVALUE),
+ partition p3 values less than (1, MAXVALUE, MAXVALUE, MAXVALUE));
+select partition_method, partition_expression, partition_description
+ from information_schema.partitions where table_name = "t1";
+#show create table t1;
+drop table t1;
+
+#
+# BUG#48163, Dagger in UCS2 not working as partition value
+#
+#create table t1 (a varchar(2) character set ucs2)
+#partition by list column_list (a)
+#(partition p0 values in (0x2020),
+# partition p1 values in (''));
+#insert into t1 values ('');
+#drop table t1;
+
--error ER_NULL_IN_VALUES_LESS_THAN
create table t1 (a int, b int)
partition by range column_list (a,b)
@@ -18,6 +41,13 @@ create table t1 (a int, b int)
partition by list column_list(a,b)
( partition p0 values in ((maxvalue, 0)));
+create table t1 (a int, b int)
+partition by list column_list (a,b)
+( partition p0 values in ((0,0)));
+--error ER_MAXVALUE_IN_VALUES_IN, ER_PARSE_ERROR
+alter table t1 add partition
+(partition p1 values in (maxvalue, maxvalue));
+drop table t1;
#
# BUG#47837, Crash when two same fields in column list processing
#
@@ -61,6 +91,7 @@ partition by list column_list(a,b)
partition p2 values in ((3, NULL), (NULL, 1)));
select partition_method, partition_expression, partition_description
from information_schema.partitions where table_name = "t1";
+show create table t1;
#
# BUG#47754 Crash when selecting using NOT BETWEEN for column list partitioning
#
@@ -90,6 +121,7 @@ partition by list (a)
partition p1 values in (4, NULL, 3));
select partition_method, partition_expression, partition_description
from information_schema.partitions where table_name = "t1";
+show create table t1;
insert into t1 values (1);
insert into t1 values (2);
insert into t1 values (3);
@@ -111,6 +143,7 @@ partition by list column_list(a)
partition p1 values in (4, NULL, 3));
select partition_method, partition_expression, partition_description
from information_schema.partitions where table_name = "t1";
+show create table t1;
insert into t1 values (1);
insert into t1 values (2);
insert into t1 values (3);
@@ -121,18 +154,6 @@ insert into t1 values (5);
show create table t1;
drop table t1;
-create table t1 (a int, b char(10), c varchar(25), d datetime)
-partition by range column_list(a,b,c,d)
-subpartition by hash (to_seconds(d))
-subpartitions 4
-( partition p0 values less than (1, 0, MAXVALUE, 0),
- partition p1 values less than (1, 'a', MAXVALUE, TO_DAYS('1999-01-01')),
- partition p2 values less than (1, 'a', MAXVALUE, MAXVALUE),
- partition p3 values less than (1, MAXVALUE, MAXVALUE, MAXVALUE));
-select partition_method, partition_expression, partition_description
- from information_schema.partitions where table_name = "t1";
-drop table t1;
-
create table t1 (a int, b char(10), c varchar(5), d int)
partition by range column_list(a,b,c)
subpartition by key (c,d)
@@ -143,6 +164,7 @@ subpartitions 3
partition p3 values less than (4,'abc','abc'));
select partition_method, partition_expression, partition_description
from information_schema.partitions where table_name = "t1";
+show create table t1;
insert into t1 values (1,'a','b',1),(2,'a','b',2),(3,'a','b',3);
insert into t1 values (1,'b','c',1),(2,'b','c',2),(3,'b','c',3);
@@ -158,6 +180,7 @@ partition by range column_list (a, b, c)
partition p1 values less than (1, 'B', 1));
select partition_method, partition_expression, partition_description
from information_schema.partitions where table_name = "t1";
+show create table t1;
insert into t1 values (1, 'A', 1);
explain partitions select * from t1 where a = 1 AND b <= 'A' and c = 1;
select * from t1 where a = 1 AND b <= 'A' and c = 1;
@@ -171,11 +194,23 @@ select * from t1 where a = 'a';
drop table t1;
--error ER_WRONG_TYPE_COLUMN_VALUE_ERROR
+create table t1 (d time)
+partition by range column_list(d)
+( partition p0 values less than ('2000-01-01'),
+ partition p1 values less than ('2040-01-01'));
+
+--error ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD
create table t1 (d timestamp)
partition by range column_list(d)
( partition p0 values less than ('2000-01-01'),
partition p1 values less than ('2040-01-01'));
+--error ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD
+create table t1 (d bit(1))
+partition by range column_list(d)
+( partition p0 values less than (0),
+ partition p1 values less than (1));
+
create table t1 (a int, b int)
partition by range column_list(a,b)
(partition p0 values less than (maxvalue, 10));
=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h 2009-09-16 06:52:43 +0000
+++ b/sql/mysql_priv.h 2009-10-22 14:15:06 +0000
@@ -1222,6 +1222,8 @@ int prepare_create_field(Create_field *s
uint *blob_columns,
int *timestamps, int *timestamps_with_niladic,
longlong table_flags);
+CHARSET_INFO* get_sql_field_charset(Create_field *sql_field,
+ HA_CREATE_INFO *create_info);
bool mysql_create_table(THD *thd,const char *db, const char *table_name,
HA_CREATE_INFO *create_info,
Alter_info *alter_info,
@@ -1611,6 +1613,11 @@ uint prep_alter_part_table(THD *thd, TAB
handlerton *old_db_type,
bool *partition_changed,
uint *fast_alter_partition);
+char *generate_partition_syntax(partition_info *part_info,
+ uint *buf_length, bool use_sql_alloc,
+ bool show_partition_options,
+ HA_CREATE_INFO *create_info,
+ Alter_info *alter_info);
#endif
/* bits for last argument to remove_table_from_cache() */
=== modified file 'sql/partition_info.cc'
--- a/sql/partition_info.cc 2009-10-21 18:53:44 +0000
+++ b/sql/partition_info.cc 2009-10-22 14:15:06 +0000
@@ -1876,6 +1876,34 @@ int partition_info::fix_func_partition(T
DBUG_RETURN(FALSE);
}
+/*
+ Get column item with a proper character set according to the field
+
+ SYNOPSIS
+ get_column_item()
+ item Item object to start with
+ field Field for which the item will be compared to
+
+ RETURN VALUES
+ NULL Error
+ item Returned item
+*/
+
+Item* partition_info::get_column_item(Item *item, Field *field)
+{
+ if (field->result_type() == STRING_RESULT &&
+ item->collation.collation != field->charset())
+ {
+ if (!(item= convert_charset_partition_constant(item,
+ field->charset())))
+ {
+ my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
+ return NULL;
+ }
+ }
+ return item;
+}
+
/*
Evaluate VALUES functions for column list values
@@ -1921,6 +1949,12 @@ bool partition_info::fix_column_value_fu
{
uchar *val_ptr;
uint len= field->pack_length();
+ if (!(column_item= get_column_item(column_item,
+ field)))
+ {
+ result= TRUE;
+ goto end;
+ }
if (column_item->save_in_field(field, TRUE))
{
my_error(ER_WRONG_TYPE_COLUMN_VALUE_ERROR, MYF(0));
=== modified file 'sql/partition_info.h'
--- a/sql/partition_info.h 2009-10-21 11:59:11 +0000
+++ b/sql/partition_info.h 2009-10-22 14:15:06 +0000
@@ -281,6 +281,7 @@ public:
bool check_partition_function);
void print_no_partition_found(TABLE *table);
void print_debug(const char *str, uint*);
+ Item* get_column_item(Item *item, Field *field);
int fix_func_partition(THD *thd,
part_elem_value *val,
partition_element *part_elem,
=== modified file 'sql/share/errmsg.txt'
--- a/sql/share/errmsg.txt 2009-10-21 18:53:44 +0000
+++ b/sql/share/errmsg.txt 2009-10-22 14:15:06 +0000
@@ -6207,7 +6207,7 @@ ER_TOO_MANY_CONCURRENT_TRXS
WARN_NON_ASCII_SEPARATOR_NOT_IMPLEMENTED
eng "Non-ASCII separator arguments are not fully supported"
ER_SAME_NAME_PARTITION_FIELD
- eng "Duplicate partition field name %-.192s"
+ eng "Duplicate partition field name '%-.192s'"
ER_PARTITION_COLUMN_LIST_ERROR
eng "Inconsistency in usage of column lists for partitioning"
ER_WRONG_TYPE_COLUMN_VALUE_ERROR
@@ -6220,3 +6220,5 @@ ER_TOO_MANY_VALUES_ERROR
eng "Cannot have more than one value for this type of %-.64s partitioning"
ER_ROW_SINGLE_PARTITION_FIELD_ERROR
eng "Row expressions in VALUES IN only allowed for multi-field column partitioning"
+ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD
+ eng "Field '%-.192s' is of a not allowed type for this type of partitioning"
=== modified file 'sql/sql_partition.cc'
--- a/sql/sql_partition.cc 2009-10-21 16:27:34 +0000
+++ b/sql/sql_partition.cc 2009-10-22 14:15:06 +0000
@@ -151,6 +151,38 @@ static int cmp_rec_and_tuple_prune(part_
#ifdef WITH_PARTITION_STORAGE_ENGINE
/*
+ Convert constants in VALUES definition to the character set the
+ corresponding field uses.
+
+ SYNOPSIS
+ convert_charset_partition_constant()
+ item Item to convert
+ cs Character set to convert to
+
+ RETURN VALUE
+ NULL Error
+ item New converted item
+*/
+
+Item* convert_charset_partition_constant(Item *item, CHARSET_INFO *cs)
+{
+ THD *thd= current_thd;
+ Name_resolution_context *context= &thd->lex->current_select->context;
+ TABLE_LIST *save_list= context->table_list;
+ const char *save_where= thd->where;
+
+ item= item->safe_charset_converter(cs);
+ context->table_list= NULL;
+ thd->where= "convert character set partition constant";
+ if (!item || item->fix_fields(thd, (Item**)NULL))
+ item= NULL;
+ thd->where= save_where;
+ context->table_list= save_list;
+ return item;
+}
+
+
+/*
A support function to check if a name is in a list of strings
SYNOPSIS
@@ -512,7 +544,9 @@ static bool set_up_field_array(TABLE *ta
do
{
field_name= it++;
- if (!strcmp(field_name, field->field_name))
+ if (!my_strcasecmp(system_charset_info,
+ field_name,
+ field->field_name))
break;
} while (++inx < num_fields);
if (inx == num_fields)
@@ -1984,11 +2018,67 @@ static int add_partition_options(File fp
return err + add_engine(fptr,p_elem->engine_type);
}
+static int check_part_field(Create_field *sql_field,
+ bool *need_cs_check)
+{
+ *need_cs_check= FALSE;
+ if (sql_field->sql_type == MYSQL_TYPE_TIMESTAMP)
+ goto error;
+ if (sql_field->sql_type < MYSQL_TYPE_VARCHAR ||
+ sql_field->sql_type == MYSQL_TYPE_NEWDECIMAL)
+ return FALSE;
+ if (sql_field->sql_type >= MYSQL_TYPE_TINY_BLOB &&
+ sql_field->sql_type <= MYSQL_TYPE_BLOB)
+ {
+ my_error(ER_BLOB_FIELD_IN_PART_FUNC_ERROR, MYF(0));
+ return TRUE;
+ }
+ switch (sql_field->sql_type)
+ {
+ case MYSQL_TYPE_VARCHAR:
+ case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_VAR_STRING:
+ if (sql_field->length > MAX_STR_SIZE_PF)
+ goto error;
+ *need_cs_check= TRUE;
+ return FALSE;
+ break;
+ default:
+ goto error;
+ }
+error:
+ my_error(ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD, MYF(0),
+ sql_field->field_name);
+ return TRUE;
+}
+
+static Create_field* get_sql_field(char *field_name,
+ Alter_info *alter_info)
+{
+ List_iterator<Create_field> it(alter_info->create_list);
+ Create_field *sql_field;
+ DBUG_ENTER("get_sql_field");
+
+ while ((sql_field= it++))
+ {
+ if (!(my_strcasecmp(system_charset_info,
+ sql_field->field_name,
+ field_name)))
+ {
+ DBUG_RETURN(sql_field);
+ }
+ }
+ DBUG_RETURN(NULL);
+}
+
static int add_column_list_values(File fptr, partition_info *part_info,
- part_elem_value *list_value)
+ part_elem_value *list_value,
+ HA_CREATE_INFO *create_info,
+ Alter_info *alter_info)
{
int err= 0;
uint i;
+ List_iterator<char> it(part_info->part_field_list);
uint num_elements= part_info->part_field_list.elements;
bool use_parenthesis= (part_info->part_type == LIST_PARTITION &&
part_info->num_columns > 1U);
@@ -1998,6 +2088,7 @@ static int add_column_list_values(File f
for (i= 0; i < num_elements; i++)
{
part_column_list_val *col_val= &list_value->col_val_array[i];
+ char *field_name= it++;
if (col_val->max_value)
err+= add_string(fptr, partition_keywords[PKW_MAXVALUE].str);
else if (col_val->null_value)
@@ -2011,7 +2102,45 @@ static int add_column_list_values(File f
err+= add_string(fptr, "NULL");
else
{
- String *res= item_expr->val_str(&str);
+ String *res;
+ CHARSET_INFO *field_cs;
+
+ /*
+ This function is called at a very early stage, even before
+ we have prepared the sql_field objects. Thus we have to
+ find the proper sql_field object and get the character set
+ from that object.
+ */
+ if (create_info)
+ {
+ Create_field *sql_field;
+ bool need_cs_check= FALSE;
+
+ if (!(sql_field= get_sql_field(field_name,
+ alter_info)))
+ {
+ my_error(ER_FIELD_NOT_FOUND_PART_ERROR, MYF(0));
+ return 1;
+ }
+ if (check_part_field(sql_field, &need_cs_check))
+ return 1;
+ if (need_cs_check)
+ field_cs= get_sql_field_charset(sql_field, create_info);
+ else
+ field_cs= NULL;
+ }
+ else
+ field_cs= part_info->part_field_array[i]->charset();
+ if (field_cs && field_cs != item_expr->collation.collation)
+ {
+ if (!(item_expr= convert_charset_partition_constant(item_expr,
+ field_cs)))
+ {
+ my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
+ return 1;
+ }
+ }
+ res= item_expr->val_str(&str);
if (!res)
{
my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
@@ -2033,7 +2162,9 @@ static int add_column_list_values(File f
}
static int add_partition_values(File fptr, partition_info *part_info,
- partition_element *p_elem)
+ partition_element *p_elem,
+ HA_CREATE_INFO *create_info,
+ Alter_info *alter_info)
{
int err= 0;
@@ -2045,7 +2176,8 @@ static int add_partition_values(File fpt
List_iterator<part_elem_value> list_val_it(p_elem->list_val_list);
part_elem_value *list_value= list_val_it++;
err+= add_begin_parenthesis(fptr);
- err+= add_column_list_values(fptr, part_info, list_value);
+ err+= add_column_list_values(fptr, part_info, list_value,
+ create_info, alter_info);
err+= add_end_parenthesis(fptr);
}
else
@@ -2087,7 +2219,8 @@ static int add_partition_values(File fpt
part_elem_value *list_value= list_val_it++;
if (part_info->column_list)
- err+= add_column_list_values(fptr, part_info, list_value);
+ err+= add_column_list_values(fptr, part_info, list_value,
+ create_info, alter_info);
else
{
if (!list_value->unsigned_flag)
@@ -2116,6 +2249,8 @@ end:
use_sql_alloc Allocate buffer from sql_alloc if true
otherwise use my_malloc
show_partition_options Should we display partition options
+ create_info Info generated by parser
+ alter_info Info generated by parser
RETURN VALUES
NULL error
@@ -2144,7 +2279,9 @@ end:
char *generate_partition_syntax(partition_info *part_info,
uint *buf_length,
bool use_sql_alloc,
- bool show_partition_options)
+ bool show_partition_options,
+ HA_CREATE_INFO *create_info,
+ Alter_info *alter_info)
{
uint i,j, tot_num_parts, num_subparts;
partition_element *part_elem;
@@ -2263,7 +2400,8 @@ char *generate_partition_syntax(partitio
first= FALSE;
err+= add_partition(fptr);
err+= add_name_string(fptr, part_elem->partition_name);
- err+= add_partition_values(fptr, part_info, part_elem);
+ err+= add_partition_values(fptr, part_info, part_elem,
+ create_info, alter_info);
if (!part_info->is_sub_partitioned() ||
part_info->use_default_subpartitions)
{
=== modified file 'sql/sql_partition.h'
--- a/sql/sql_partition.h 2009-10-16 15:08:34 +0000
+++ b/sql/sql_partition.h 2009-10-22 14:15:06 +0000
@@ -67,9 +67,6 @@ bool check_partition_info(partition_info
TABLE *table, handler *file, HA_CREATE_INFO *info);
void set_linear_hash_mask(partition_info *part_info, uint num_parts);
bool fix_partition_func(THD *thd, TABLE *table, bool create_table_ind);
-char *generate_partition_syntax(partition_info *part_info,
- uint *buf_length, bool use_sql_alloc,
- bool show_partition_options);
bool partition_key_modified(TABLE *table, const MY_BITMAP *fields);
void get_partition_set(const TABLE *table, uchar *buf, const uint index,
const key_range *key_spec,
@@ -96,6 +93,7 @@ bool fix_fields_part_func(THD *thd, Item
bool check_part_func_fields(Field **ptr, bool ok_with_charsets);
bool field_is_partition_charset(Field *field);
+Item* convert_charset_partition_constant(Item *item, CHARSET_INFO *cs);
/*
A "Get next" function for partition iterator.
=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc 2009-10-21 18:04:34 +0000
+++ b/sql/sql_show.cc 2009-10-22 14:15:06 +0000
@@ -1465,7 +1465,8 @@ int store_create_info(THD *thd, TABLE_LI
((part_syntax= generate_partition_syntax(table->part_info,
&part_syntax_len,
FALSE,
- show_table_options))))
+ show_table_options,
+ NULL, NULL))))
{
packet->append(STRING_WITH_LEN("\n/*!50100"));
packet->append(part_syntax, part_syntax_len);
@@ -4847,16 +4848,23 @@ get_partition_column_description(partiti
{
char buffer[MAX_STR_SIZE_PF];
String str(buffer, sizeof(buffer), &my_charset_bin);
- String *res= col_val->item_expression->val_str(&str);
+ Item *item= col_val->item_expression;
+
+ if (!(item= part_info->get_column_item(item,
+ part_info->part_field_array[i])))
+ {
+ DBUG_RETURN(1);
+ }
+ String *res= item->val_str(&str);
if (!res)
{
my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
DBUG_RETURN(1);
}
- if (col_val->item_expression->result_type() == STRING_RESULT)
+ if (item->result_type() == STRING_RESULT)
tmp_str.append("'");
tmp_str.append(*res);
- if (col_val->item_expression->result_type() == STRING_RESULT)
+ if (item->result_type() == STRING_RESULT)
tmp_str.append("'");
}
if (i != num_elements - 1)
=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc 2009-10-19 10:09:52 +0000
+++ b/sql/sql_table.cc 2009-10-22 14:15:06 +0000
@@ -1583,7 +1583,9 @@ bool mysql_write_frm(ALTER_PARTITION_PAR
{
if (!(part_syntax_buf= generate_partition_syntax(part_info,
&syntax_len,
- TRUE, TRUE)))
+ TRUE, TRUE,
+ lpt->create_info,
+ lpt->alter_info)))
{
DBUG_RETURN(TRUE);
}
@@ -1675,7 +1677,9 @@ bool mysql_write_frm(ALTER_PARTITION_PAR
char *tmp_part_syntax_str;
if (!(part_syntax_buf= generate_partition_syntax(part_info,
&syntax_len,
- TRUE, TRUE)))
+ TRUE, TRUE,
+ lpt->create_info,
+ lpt->alter_info)))
{
error= 1;
goto err;
@@ -2494,6 +2498,39 @@ int prepare_create_field(Create_field *s
DBUG_RETURN(0);
}
+
+/*
+ Get character set from field object generated by parser using
+ default values when not set.
+
+ SYNOPSIS
+ get_sql_field_charset()
+ sql_field The sql_field object
+ create_info Info generated by parser
+
+ RETURN VALUES
+ cs Character set
+*/
+
+CHARSET_INFO* get_sql_field_charset(Create_field *sql_field,
+ HA_CREATE_INFO *create_info)
+{
+ CHARSET_INFO *cs= sql_field->charset;
+
+ if (!cs)
+ cs= create_info->default_table_charset;
+ /*
+ table_charset is set only in ALTER TABLE t1 CONVERT TO CHARACTER SET csname
+ if we want change character set for all varchar/char columns.
+ But the table charset must not affect the BLOB fields, so don't
+ allow to change my_charset_bin to somethig else.
+ */
+ if (create_info->table_charset && cs != &my_charset_bin)
+ cs= create_info->table_charset;
+ return cs;
+}
+
+
/*
Preparation for table creation
@@ -2557,18 +2594,8 @@ mysql_prepare_create_table(THD *thd, HA_
executing a prepared statement for the second time.
*/
sql_field->length= sql_field->char_length;
- if (!sql_field->charset)
- sql_field->charset= create_info->default_table_charset;
- /*
- table_charset is set in ALTER TABLE if we want change character set
- for all varchar/char columns.
- But the table charset must not affect the BLOB fields, so don't
- allow to change my_charset_bin to somethig else.
- */
- if (create_info->table_charset && sql_field->charset != &my_charset_bin)
- sql_field->charset= create_info->table_charset;
-
- save_cs= sql_field->charset;
+ save_cs= sql_field->charset= get_sql_field_charset(sql_field,
+ create_info);
if ((sql_field->flags & BINCMP_FLAG) &&
!(sql_field->charset= get_charset_by_csname(sql_field->charset->csname,
MY_CS_BINSORT,MYF(0))))
@@ -3617,6 +3644,9 @@ bool mysql_create_table_no_lock(THD *thd
}
if (check_engine(thd, table_name, create_info))
DBUG_RETURN(TRUE);
+
+ set_table_default_charset(thd, create_info, (char*) db);
+
db_options= create_info->table_options;
if (create_info->row_type == ROW_TYPE_DYNAMIC)
db_options|=HA_OPTION_PACK_RECORD;
@@ -3720,7 +3750,9 @@ bool mysql_create_table_no_lock(THD *thd
*/
if (!(part_syntax_buf= generate_partition_syntax(part_info,
&syntax_len,
- TRUE, TRUE)))
+ TRUE, TRUE,
+ create_info,
+ alter_info)))
goto err;
part_info->part_info_string= part_syntax_buf;
part_info->part_info_len= syntax_len;
@@ -3787,8 +3819,6 @@ bool mysql_create_table_no_lock(THD *thd
}
#endif
- set_table_default_charset(thd, create_info, (char*) db);
-
if (mysql_prepare_create_table(thd, create_info, alter_info,
internal_tmp_table,
&db_options, file,
| Thread |
|---|
| • bzr commit into mysql-5.5.0-trunk branch (mikael:2897) Bug#48163 | Mikael Ronstrom | 22 Oct |