BUG#48165, needed to introduce length restrictions on partitioning fields to ensure that no stack overruns occur
This commit is contained in:
parent
cc43a2089c
commit
10fed1aca0
@ -1,4 +1,19 @@
|
||||
drop table if exists t1;
|
||||
create table t1 (a varchar(1500), b varchar(1570))
|
||||
partition by list column_list(a,b)
|
||||
( partition p0 values in (('a','b')));
|
||||
ERROR HY000: The total length of the partitioning fields is too large
|
||||
create table t1 (a varchar(1023) character set utf8 collate utf8_spanish2_ci)
|
||||
partition by range column_list(a)
|
||||
( partition p0 values less than ('CZ'),
|
||||
partition p1 values less than ('CH'),
|
||||
partition p2 values less than ('D'));
|
||||
insert into t1 values ('czz'),('chi'),('ci'),('cg');
|
||||
select * from t1 where a between 'cg' AND 'ci';
|
||||
a
|
||||
ci
|
||||
cg
|
||||
drop table t1;
|
||||
set @@sql_mode=allow_invalid_dates;
|
||||
create table t1 (a char, b char, c date)
|
||||
partition by range column_list (a,b,c)
|
||||
|
@ -273,7 +273,7 @@ select * from t1 where a = 'y';
|
||||
a
|
||||
y
|
||||
drop table t1;
|
||||
create table t1 (a varchar(65531)) partition by key (a);
|
||||
create table t1 (a varchar(3068)) partition by key (a);
|
||||
insert into t1 values ('bbbb');
|
||||
insert into t1 values ('aaaa');
|
||||
select * from t1 where a = 'aaaa';
|
||||
@ -286,7 +286,7 @@ select * from t1 where a = 'bbbb';
|
||||
a
|
||||
bbbb
|
||||
drop table t1;
|
||||
create table t1 (a varchar(65532)) partition by key (a);
|
||||
create table t1 (a varchar(3069)) partition by key (a);
|
||||
insert into t1 values ('bbbb');
|
||||
insert into t1 values ('aaaa');
|
||||
select * from t1 where a = 'aaaa';
|
||||
@ -299,7 +299,7 @@ select * from t1 where a = 'bbbb';
|
||||
a
|
||||
bbbb
|
||||
drop table t1;
|
||||
create table t1 (a varchar(65533) not null) partition by key (a);
|
||||
create table t1 (a varchar(3070) not null) partition by key (a);
|
||||
insert into t1 values ('bbbb');
|
||||
insert into t1 values ('aaaa');
|
||||
select * from t1 where a = 'aaaa';
|
||||
@ -312,6 +312,8 @@ select * from t1 where a = 'bbbb';
|
||||
a
|
||||
bbbb
|
||||
drop table t1;
|
||||
create table t1 (a varchar(3070)) partition by key (a);
|
||||
ERROR HY000: The total length of the partitioning fields is too large
|
||||
create table t1 (a varchar(65533)) partition by key (a);
|
||||
ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs
|
||||
create table t1 (a varchar(65534) not null) partition by key (a);
|
||||
|
@ -8,6 +8,23 @@
|
||||
drop table if exists t1;
|
||||
--enable_warnings
|
||||
|
||||
#
|
||||
# BUG#48164, too long partition fields causes crash
|
||||
#
|
||||
--error ER_PARTITION_FIELDS_TOO_LONG
|
||||
create table t1 (a varchar(1500), b varchar(1570))
|
||||
partition by list column_list(a,b)
|
||||
( partition p0 values in (('a','b')));
|
||||
|
||||
create table t1 (a varchar(1023) character set utf8 collate utf8_spanish2_ci)
|
||||
partition by range column_list(a)
|
||||
( partition p0 values less than ('CZ'),
|
||||
partition p1 values less than ('CH'),
|
||||
partition p2 values less than ('D'));
|
||||
insert into t1 values ('czz'),('chi'),('ci'),('cg');
|
||||
select * from t1 where a between 'cg' AND 'ci';
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# BUG#48165, sql_mode gives error
|
||||
#
|
||||
|
@ -4,6 +4,7 @@
|
||||
# as partition by key
|
||||
# Created to verify the fix for Bug#31705
|
||||
# Partitions: crash if varchar length > 65530
|
||||
# BUG#48164 limited size to 3072 bytes
|
||||
#
|
||||
-- source include/have_partition.inc
|
||||
|
||||
@ -192,27 +193,29 @@ create table t1 (a set('y','n')) partition by key (a);
|
||||
insert into t1 values ('y');
|
||||
select * from t1 where a = 'y';
|
||||
drop table t1;
|
||||
create table t1 (a varchar(65531)) partition by key (a);
|
||||
create table t1 (a varchar(3068)) partition by key (a);
|
||||
insert into t1 values ('bbbb');
|
||||
insert into t1 values ('aaaa');
|
||||
select * from t1 where a = 'aaaa';
|
||||
select * from t1 where a like 'aaa%';
|
||||
select * from t1 where a = 'bbbb';
|
||||
drop table t1;
|
||||
create table t1 (a varchar(65532)) partition by key (a);
|
||||
create table t1 (a varchar(3069)) partition by key (a);
|
||||
insert into t1 values ('bbbb');
|
||||
insert into t1 values ('aaaa');
|
||||
select * from t1 where a = 'aaaa';
|
||||
select * from t1 where a like 'aaa%';
|
||||
select * from t1 where a = 'bbbb';
|
||||
drop table t1;
|
||||
create table t1 (a varchar(65533) not null) partition by key (a);
|
||||
create table t1 (a varchar(3070) not null) partition by key (a);
|
||||
insert into t1 values ('bbbb');
|
||||
insert into t1 values ('aaaa');
|
||||
select * from t1 where a = 'aaaa';
|
||||
select * from t1 where a like 'aaa%';
|
||||
select * from t1 where a = 'bbbb';
|
||||
drop table t1;
|
||||
-- error ER_PARTITION_FIELDS_TOO_LONG
|
||||
create table t1 (a varchar(3070)) partition by key (a);
|
||||
-- error ER_TOO_BIG_ROWSIZE
|
||||
create table t1 (a varchar(65533)) partition by key (a);
|
||||
-- error ER_TOO_BIG_ROWSIZE
|
||||
|
@ -3600,12 +3600,8 @@ static bool create_partition_index_description(PART_PRUNE_PARAM *ppar)
|
||||
{
|
||||
key_part->key= 0;
|
||||
key_part->part= part;
|
||||
key_part->store_length= key_part->length= (uint16) (*field)->key_length();
|
||||
if ((*field)->real_maybe_null())
|
||||
key_part->store_length+= HA_KEY_NULL_LENGTH;
|
||||
if ((*field)->type() == MYSQL_TYPE_BLOB ||
|
||||
(*field)->real_type() == MYSQL_TYPE_VARCHAR)
|
||||
key_part->store_length+= HA_KEY_BLOB_LENGTH;
|
||||
key_part->length= (uint16)get_partition_field_store_length(*field);
|
||||
key_part->store_length= key_part->length;
|
||||
|
||||
DBUG_PRINT("info", ("part %u length %u store_length %u", part,
|
||||
key_part->length, key_part->store_length));
|
||||
|
@ -1343,6 +1343,36 @@ bool partition_info::set_part_expr(char *start_token, Item *item_ptr,
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Check that partition fields and subpartition fields are not too long
|
||||
|
||||
SYNOPSIS
|
||||
check_partition_field_length()
|
||||
|
||||
RETURN VALUES
|
||||
TRUE Total length was too big
|
||||
FALSE Length is ok
|
||||
*/
|
||||
|
||||
bool partition_info::check_partition_field_length()
|
||||
{
|
||||
uint store_length= 0;
|
||||
uint i;
|
||||
DBUG_ENTER("partition_info::check_partition_field_length");
|
||||
|
||||
for (i= 0; i < num_part_fields; i++)
|
||||
store_length+= get_partition_field_store_length(part_field_array[i]);
|
||||
if (store_length > MAX_KEY_LENGTH)
|
||||
DBUG_RETURN(TRUE);
|
||||
store_length= 0;
|
||||
for (i= 0; i < num_subpart_fields; i++)
|
||||
store_length+= get_partition_field_store_length(subpart_field_array[i]);
|
||||
if (store_length > MAX_KEY_LENGTH)
|
||||
DBUG_RETURN(TRUE);
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Set up buffers and arrays for fields requiring preparation
|
||||
SYNOPSIS
|
||||
|
@ -19,8 +19,6 @@
|
||||
|
||||
#include "partition_element.h"
|
||||
|
||||
#define MAX_STR_SIZE_PF 2048
|
||||
|
||||
class partition_info;
|
||||
|
||||
/* Some function typedefs */
|
||||
@ -298,6 +296,7 @@ public:
|
||||
char *end_token, bool is_subpart);
|
||||
static int compare_column_values(const void *a, const void *b);
|
||||
bool set_up_charset_field_preps();
|
||||
bool check_partition_field_length();
|
||||
bool init_column_part();
|
||||
bool add_column_list_value(THD *thd, Item *item);
|
||||
private:
|
||||
|
@ -6222,3 +6222,5 @@ 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"
|
||||
ER_PARTITION_FIELDS_TOO_LONG
|
||||
eng "The total length of the partitioning fields is too large"
|
||||
|
@ -1779,6 +1779,11 @@ bool fix_partition_func(THD *thd, TABLE *table,
|
||||
my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
|
||||
goto end;
|
||||
}
|
||||
if (unlikely(part_info->check_partition_field_length()))
|
||||
{
|
||||
my_error(ER_PARTITION_FIELDS_TOO_LONG, MYF(0));
|
||||
goto end;
|
||||
}
|
||||
check_range_capable_PF(table);
|
||||
set_up_partition_key_maps(table, part_info);
|
||||
set_up_partition_func_pointers(part_info);
|
||||
@ -2038,8 +2043,6 @@ static int check_part_field(Create_field *sql_field,
|
||||
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;
|
||||
@ -2095,7 +2098,7 @@ static int add_column_list_values(File fptr, partition_info *part_info,
|
||||
err+= add_string(fptr, "NULL");
|
||||
else
|
||||
{
|
||||
char buffer[3 * MAX_STR_SIZE_PF + 10];
|
||||
char buffer[MAX_KEY_LENGTH];
|
||||
String str(buffer, sizeof(buffer), &my_charset_bin);
|
||||
Item *item_expr= col_val->item_expression;
|
||||
if (item_expr->null_value)
|
||||
@ -7730,5 +7733,17 @@ void create_subpartition_name(char *out, const char *in1,
|
||||
strxmov(out, in1, "#P#", transl_part_name,
|
||||
"#SP#", transl_subpart_name, "#REN#", NullS);
|
||||
}
|
||||
|
||||
uint get_partition_field_store_length(Field *field)
|
||||
{
|
||||
uint store_length;
|
||||
|
||||
store_length= field->key_length();
|
||||
if (field->real_maybe_null())
|
||||
store_length+= HA_KEY_NULL_LENGTH;
|
||||
if (field->real_type() == MYSQL_TYPE_VARCHAR)
|
||||
store_length+= HA_KEY_BLOB_LENGTH;
|
||||
return store_length;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -71,6 +71,7 @@ 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,
|
||||
part_id_range *part_spec);
|
||||
uint get_partition_field_store_length(Field *field);
|
||||
void get_full_part_id_from_key(const TABLE *table, uchar *buf,
|
||||
KEY *key_info,
|
||||
const key_range *key_spec,
|
||||
|
@ -4846,7 +4846,7 @@ get_partition_column_description(partition_info *part_info,
|
||||
tmp_str.append("NULL");
|
||||
else
|
||||
{
|
||||
char buffer[3 * MAX_STR_SIZE_PF + 10];
|
||||
char buffer[MAX_KEY_LENGTH];
|
||||
String str(buffer, sizeof(buffer), &my_charset_bin);
|
||||
Item *item= col_val->item_expression;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user