BUG#48165, needed to introduce length restrictions on partitioning fields to ensure that no stack overruns occur
This commit is contained in:
parent
59cc518990
commit
b572e51c30
@ -1,4 +1,19 @@
|
|||||||
drop table if exists t1;
|
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;
|
set @@sql_mode=allow_invalid_dates;
|
||||||
create table t1 (a char, b char, c date)
|
create table t1 (a char, b char, c date)
|
||||||
partition by range column_list (a,b,c)
|
partition by range column_list (a,b,c)
|
||||||
|
@ -273,7 +273,7 @@ select * from t1 where a = 'y';
|
|||||||
a
|
a
|
||||||
y
|
y
|
||||||
drop table t1;
|
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 ('bbbb');
|
||||||
insert into t1 values ('aaaa');
|
insert into t1 values ('aaaa');
|
||||||
select * from t1 where a = 'aaaa';
|
select * from t1 where a = 'aaaa';
|
||||||
@ -286,7 +286,7 @@ select * from t1 where a = 'bbbb';
|
|||||||
a
|
a
|
||||||
bbbb
|
bbbb
|
||||||
drop table t1;
|
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 ('bbbb');
|
||||||
insert into t1 values ('aaaa');
|
insert into t1 values ('aaaa');
|
||||||
select * from t1 where a = 'aaaa';
|
select * from t1 where a = 'aaaa';
|
||||||
@ -299,7 +299,7 @@ select * from t1 where a = 'bbbb';
|
|||||||
a
|
a
|
||||||
bbbb
|
bbbb
|
||||||
drop table t1;
|
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 ('bbbb');
|
||||||
insert into t1 values ('aaaa');
|
insert into t1 values ('aaaa');
|
||||||
select * from t1 where a = 'aaaa';
|
select * from t1 where a = 'aaaa';
|
||||||
@ -312,6 +312,8 @@ select * from t1 where a = 'bbbb';
|
|||||||
a
|
a
|
||||||
bbbb
|
bbbb
|
||||||
drop table t1;
|
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);
|
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
|
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);
|
create table t1 (a varchar(65534) not null) partition by key (a);
|
||||||
|
@ -8,6 +8,23 @@
|
|||||||
drop table if exists t1;
|
drop table if exists t1;
|
||||||
--enable_warnings
|
--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
|
# BUG#48165, sql_mode gives error
|
||||||
#
|
#
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
# as partition by key
|
# as partition by key
|
||||||
# Created to verify the fix for Bug#31705
|
# Created to verify the fix for Bug#31705
|
||||||
# Partitions: crash if varchar length > 65530
|
# Partitions: crash if varchar length > 65530
|
||||||
|
# BUG#48164 limited size to 3072 bytes
|
||||||
#
|
#
|
||||||
-- source include/have_partition.inc
|
-- 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');
|
insert into t1 values ('y');
|
||||||
select * from t1 where a = 'y';
|
select * from t1 where a = 'y';
|
||||||
drop table t1;
|
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 ('bbbb');
|
||||||
insert into t1 values ('aaaa');
|
insert into t1 values ('aaaa');
|
||||||
select * from t1 where a = 'aaaa';
|
select * from t1 where a = 'aaaa';
|
||||||
select * from t1 where a like 'aaa%';
|
select * from t1 where a like 'aaa%';
|
||||||
select * from t1 where a = 'bbbb';
|
select * from t1 where a = 'bbbb';
|
||||||
drop table t1;
|
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 ('bbbb');
|
||||||
insert into t1 values ('aaaa');
|
insert into t1 values ('aaaa');
|
||||||
select * from t1 where a = 'aaaa';
|
select * from t1 where a = 'aaaa';
|
||||||
select * from t1 where a like 'aaa%';
|
select * from t1 where a like 'aaa%';
|
||||||
select * from t1 where a = 'bbbb';
|
select * from t1 where a = 'bbbb';
|
||||||
drop table t1;
|
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 ('bbbb');
|
||||||
insert into t1 values ('aaaa');
|
insert into t1 values ('aaaa');
|
||||||
select * from t1 where a = 'aaaa';
|
select * from t1 where a = 'aaaa';
|
||||||
select * from t1 where a like 'aaa%';
|
select * from t1 where a like 'aaa%';
|
||||||
select * from t1 where a = 'bbbb';
|
select * from t1 where a = 'bbbb';
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
-- error ER_PARTITION_FIELDS_TOO_LONG
|
||||||
|
create table t1 (a varchar(3070)) partition by key (a);
|
||||||
-- error ER_TOO_BIG_ROWSIZE
|
-- error ER_TOO_BIG_ROWSIZE
|
||||||
create table t1 (a varchar(65533)) partition by key (a);
|
create table t1 (a varchar(65533)) partition by key (a);
|
||||||
-- error ER_TOO_BIG_ROWSIZE
|
-- 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->key= 0;
|
||||||
key_part->part= part;
|
key_part->part= part;
|
||||||
key_part->store_length= key_part->length= (uint16) (*field)->key_length();
|
key_part->length= (uint16)get_partition_field_store_length(*field);
|
||||||
if ((*field)->real_maybe_null())
|
key_part->store_length= key_part->length;
|
||||||
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;
|
|
||||||
|
|
||||||
DBUG_PRINT("info", ("part %u length %u store_length %u", part,
|
DBUG_PRINT("info", ("part %u length %u store_length %u", part,
|
||||||
key_part->length, key_part->store_length));
|
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
|
Set up buffers and arrays for fields requiring preparation
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
|
@ -19,8 +19,6 @@
|
|||||||
|
|
||||||
#include "partition_element.h"
|
#include "partition_element.h"
|
||||||
|
|
||||||
#define MAX_STR_SIZE_PF 2048
|
|
||||||
|
|
||||||
class partition_info;
|
class partition_info;
|
||||||
|
|
||||||
/* Some function typedefs */
|
/* Some function typedefs */
|
||||||
@ -298,6 +296,7 @@ public:
|
|||||||
char *end_token, bool is_subpart);
|
char *end_token, bool is_subpart);
|
||||||
static int compare_column_values(const void *a, const void *b);
|
static int compare_column_values(const void *a, const void *b);
|
||||||
bool set_up_charset_field_preps();
|
bool set_up_charset_field_preps();
|
||||||
|
bool check_partition_field_length();
|
||||||
bool init_column_part();
|
bool init_column_part();
|
||||||
bool add_column_list_value(THD *thd, Item *item);
|
bool add_column_list_value(THD *thd, Item *item);
|
||||||
private:
|
private:
|
||||||
|
@ -6222,3 +6222,5 @@ ER_ROW_SINGLE_PARTITION_FIELD_ERROR
|
|||||||
eng "Row expressions in VALUES IN only allowed for multi-field column partitioning"
|
eng "Row expressions in VALUES IN only allowed for multi-field column partitioning"
|
||||||
ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD
|
ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD
|
||||||
eng "Field '%-.192s' is of a not allowed type for this type of partitioning"
|
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));
|
my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
|
||||||
goto end;
|
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);
|
check_range_capable_PF(table);
|
||||||
set_up_partition_key_maps(table, part_info);
|
set_up_partition_key_maps(table, part_info);
|
||||||
set_up_partition_func_pointers(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_VARCHAR:
|
||||||
case MYSQL_TYPE_STRING:
|
case MYSQL_TYPE_STRING:
|
||||||
case MYSQL_TYPE_VAR_STRING:
|
case MYSQL_TYPE_VAR_STRING:
|
||||||
if (sql_field->length > MAX_STR_SIZE_PF)
|
|
||||||
goto error;
|
|
||||||
*need_cs_check= TRUE;
|
*need_cs_check= TRUE;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
break;
|
break;
|
||||||
@ -2095,7 +2098,7 @@ static int add_column_list_values(File fptr, partition_info *part_info,
|
|||||||
err+= add_string(fptr, "NULL");
|
err+= add_string(fptr, "NULL");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char buffer[3 * MAX_STR_SIZE_PF + 10];
|
char buffer[MAX_KEY_LENGTH];
|
||||||
String str(buffer, sizeof(buffer), &my_charset_bin);
|
String str(buffer, sizeof(buffer), &my_charset_bin);
|
||||||
Item *item_expr= col_val->item_expression;
|
Item *item_expr= col_val->item_expression;
|
||||||
if (item_expr->null_value)
|
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,
|
strxmov(out, in1, "#P#", transl_part_name,
|
||||||
"#SP#", transl_subpart_name, "#REN#", NullS);
|
"#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
|
#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,
|
void get_partition_set(const TABLE *table, uchar *buf, const uint index,
|
||||||
const key_range *key_spec,
|
const key_range *key_spec,
|
||||||
part_id_range *part_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,
|
void get_full_part_id_from_key(const TABLE *table, uchar *buf,
|
||||||
KEY *key_info,
|
KEY *key_info,
|
||||||
const key_range *key_spec,
|
const key_range *key_spec,
|
||||||
|
@ -4846,7 +4846,7 @@ get_partition_column_description(partition_info *part_info,
|
|||||||
tmp_str.append("NULL");
|
tmp_str.append("NULL");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char buffer[3 * MAX_STR_SIZE_PF + 10];
|
char buffer[MAX_KEY_LENGTH];
|
||||||
String str(buffer, sizeof(buffer), &my_charset_bin);
|
String str(buffer, sizeof(buffer), &my_charset_bin);
|
||||||
Item *item= col_val->item_expression;
|
Item *item= col_val->item_expression;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user