Commit 6f27ad15 authored by Mikael Ronstrom's avatar Mikael Ronstrom

A lot of fixes to make character set work ok, first step to fixing BUG#48163

parent f3f4e41c
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 partition_description
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 table_name = "t1";
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 table_name = "t1";
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 table_name = "t1";
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));
......
......@@ -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));
......
......@@ -1222,6 +1222,8 @@ int prepare_create_field(Create_field *sql_field,
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, TABLE *table, Alter_info *alter_info,
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() */
......
......@@ -1876,6 +1876,34 @@ int partition_info::fix_func_partition(THD *thd,
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_functions(THD *thd,
{
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));
......
......@@ -281,6 +281,7 @@ class partition_info : public Sql_alloc
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,
......
......@@ -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"
......@@ -150,6 +150,38 @@ static int cmp_rec_and_tuple_prune(part_column_list_val *val,
bool tail_is_min);
#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
......@@ -512,7 +544,9 @@ static bool set_up_field_array(TABLE *table,
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 fptr, partition_element *p_elem)
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 fptr, partition_info *part_info,
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 fptr, partition_info *part_info,
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 fptr, partition_info *part_info,
}
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 fptr, partition_info *part_info,
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 fptr, partition_info *part_info,
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 @@ static int add_partition_values(File fptr, partition_info *part_info,
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 @@ static int add_partition_values(File fptr, partition_info *part_info,
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(partition_info *part_info,
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)
{
......
......@@ -67,9 +67,6 @@ bool check_partition_info(partition_info *part_info,handlerton **eng_type,
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* func_expr, TABLE *table,
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.
......
......@@ -1465,7 +1465,8 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
((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(partition_info *part_info,
{
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)
......
......@@ -1583,7 +1583,9 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
{
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_PARAM_TYPE *lpt, uint flags)
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 *sql_field,
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_CREATE_INFO *create_info,
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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment