List:Commits« Previous MessageNext Message »
From:Mikael Ronstrom Date:October 22 2009 2:15pm
Subject:bzr commit into mysql-5.5.0-trunk branch (mikael:2897) Bug#48163
View as plain text  
#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#48163Mikael Ronstrom22 Oct