Commit 88ec8a08 authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-5909 MySQL BUG#11748924 PARTITIONS: TOO-LONG COMMENT CAUSES NO WARNING

parent 11b498d6
This diff is collapsed.
......@@ -2016,3 +2016,49 @@ PARTITION pmax VALUES LESS THAN MAXVALUE);
DROP TABLE t1;
--echo End of 5.1 tests
CREATE TABLE t1 (a INT)
PARTITION BY LIST (a)
SUBPARTITION BY HASH (a) SUBPARTITIONS 2
(PARTITION p1 VALUES IN (1) COMMENT "Comment in p1"
(SUBPARTITION p1spFirst COMMENT "SubPartition comment in p1spFirst",
SUBPARTITION p1spSecond COMMENT "SubPartition comment in p1spSecond"),
PARTITION p2 VALUES IN (2) COMMENT "Comment in p2"
(SUBPARTITION p2spFirst COMMENT "SubPartition comment in p2spFirst",
SUBPARTITION p2spSecond COMMENT "SubPartition comment in p2spSecond"));
SHOW CREATE TABLE t1;
SELECT PARTITION_NAME, SUBPARTITION_NAME, PARTITION_COMMENT FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_NAME = 't1' AND TABLE_SCHEMA = 'test';
DROP TABLE t1;
CREATE TABLE t1 (a INT)
PARTITION BY LIST (a)
SUBPARTITION BY HASH (a) SUBPARTITIONS 2
(PARTITION p1 VALUES IN (1)
(SUBPARTITION p1spFirst COMMENT "SubPartition comment in p1spFirst",
SUBPARTITION p1spSecond),
PARTITION p2 VALUES IN (2) COMMENT "Comment in p2"
(SUBPARTITION p2spFirst,
SUBPARTITION p2spSecond COMMENT "SubPartition comment in p2spSecond"));
SHOW CREATE TABLE t1;
SELECT PARTITION_NAME, SUBPARTITION_NAME, PARTITION_COMMENT FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_NAME = 't1' AND TABLE_SCHEMA = 'test';
DROP TABLE t1;
CREATE TABLE t1
(a INT ,
KEY inx_a (a) )
PARTITION BY RANGE (a)
SUBPARTITION BY HASH (a) SUBPARTITIONS 2
(PARTITION pUpTo10 VALUES LESS THAN (10) COMMENT
"This is a long comment (2050 ascii characters) 50 pUpTo10 partition ......80-!.................. 100 ................................................................................................ 200....................................................................................................................................................................................................................................................................................................... 500 ............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................... 1000 ..............1024-|.......................................................................................................................................................................................................................................................................................................................................................................................................................................................................................... 1500 .............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................. 2000 ......................................2048-|++"
(SUBPARTITION `p-10sp0` ,SUBPARTITION `p-10sp1` ),
PARTITION pMax VALUES LESS THAN MAXVALUE COMMENT
"This is a long comment (2050 ascii characters) 50 pMax partition comment .80-!.................. 100 ................................................................................................ 200....................................................................................................................................................................................................................................................................................................... 500 ............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................... 1000 ..............1024-|.......................................................................................................................................................................................................................................................................................................................................................................................................................................................................................... 1500 .............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................. 2000 ......................................2048-|++"
(SUBPARTITION `pMaxsp0` ,SUBPARTITION `pMaxsp1` ));
SHOW CREATE TABLE t1;
SELECT PARTITION_NAME, SUBPARTITION_NAME, PARTITION_COMMENT FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_NAME = 't1' AND TABLE_SCHEMA = 'test';
DROP TABLE t1;
......@@ -4089,30 +4089,10 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
DBUG_RETURN(TRUE);
}
uint tmp_len= system_charset_info->cset->charpos(system_charset_info,
key->key_create_info.comment.str,
key->key_create_info.comment.str +
key->key_create_info.comment.length,
INDEX_COMMENT_MAXLEN);
if (tmp_len < key->key_create_info.comment.length)
{
if (thd->is_strict_mode())
{
my_error(ER_TOO_LONG_INDEX_COMMENT, MYF(0),
key_info->name, static_cast<ulong>(INDEX_COMMENT_MAXLEN));
DBUG_RETURN(-1);
}
char warn_buff[MYSQL_ERRMSG_SIZE];
my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_INDEX_COMMENT),
key_info->name, static_cast<ulong>(INDEX_COMMENT_MAXLEN));
/* do not push duplicate warnings */
if (!thd->get_stmt_da()->has_sql_condition(warn_buff, strlen(warn_buff)))
push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
ER_TOO_LONG_INDEX_COMMENT, warn_buff);
key->key_create_info.comment.length= tmp_len;
}
if (validate_comment_length(thd, &key->key_create_info.comment,
INDEX_COMMENT_MAXLEN, ER_TOO_LONG_INDEX_COMMENT,
key_info->name))
DBUG_RETURN(TRUE);
key_info->comment.length= key->key_create_info.comment.length;
if (key_info->comment.length > 0)
......@@ -4195,6 +4175,43 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
DBUG_RETURN(FALSE);
}
/**
check comment length of table, column, index and partition
If comment lenght is more than the standard length
truncate it and store the comment lenght upto the standard
comment length size
@param thd Thread handle
@param[in,out] comment Comment
@param max_len Maximum allowed comment length
@param err_code Error message
@param name Name of commented object
@return Operation status
@retval true Error found
@retval false On Success
*/
bool validate_comment_length(THD *thd, LEX_STRING *comment, size_t max_len,
uint err_code, const char *name)
{
DBUG_ENTER("validate_comment_length");
uint tmp_len= my_charpos(system_charset_info, comment->str,
comment->str + comment->length, max_len);
if (tmp_len < comment->length)
{
if (thd->is_strict_mode())
{
my_error(err_code, MYF(0), name, static_cast<ulong>(max_len));
DBUG_RETURN(true);
}
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, err_code,
ER(err_code), name, static_cast<ulong>(max_len));
comment->length= tmp_len;
}
DBUG_RETURN(false);
}
/*
Set table default charset, if not set
......@@ -4403,6 +4420,45 @@ handler *mysql_create_frm_image(THD *thd,
char *part_syntax_buf;
uint syntax_len;
handlerton *engine_type;
List_iterator<partition_element> part_it(part_info->partitions);
partition_element *part_elem;
while ((part_elem= part_it++))
{
if (part_elem->part_comment)
{
LEX_STRING comment= {
part_elem->part_comment, strlen(part_elem->part_comment)
};
if (validate_comment_length(thd, &comment,
TABLE_PARTITION_COMMENT_MAXLEN,
ER_TOO_LONG_TABLE_PARTITION_COMMENT,
part_elem->partition_name))
DBUG_RETURN(NULL);
part_elem->part_comment[comment.length]= '\0';
}
if (part_elem->subpartitions.elements)
{
List_iterator<partition_element> sub_it(part_elem->subpartitions);
partition_element *subpart_elem;
while ((subpart_elem= sub_it++))
{
if (subpart_elem->part_comment)
{
LEX_STRING comment= {
subpart_elem->part_comment, strlen(subpart_elem->part_comment)
};
if (validate_comment_length(thd, &comment,
TABLE_PARTITION_COMMENT_MAXLEN,
ER_TOO_LONG_TABLE_PARTITION_COMMENT,
subpart_elem->partition_name))
DBUG_RETURN(NULL);
subpart_elem->part_comment[comment.length]= '\0';
}
}
}
}
if (create_info->tmp_table())
{
my_error(ER_PARTITION_NO_TEMPORARY, MYF(0));
......
......@@ -267,10 +267,6 @@ bool sync_ddl_log();
void release_ddl_log();
void execute_ddl_log_recovery();
bool execute_ddl_log_entry(THD *thd, uint first_entry);
bool validate_comment_length(THD *thd, const char *comment_str,
size_t *comment_len, uint max_len,
uint err_code, const char *comment_name);
bool check_duplicate_warning(THD *thd, char *msg, ulong length);
template<typename T> class List;
void promote_first_timestamp_column(List<Create_field> *column_definitions);
......
......@@ -2539,6 +2539,9 @@ int rename_file_ext(const char * from,const char * to,const char * ext);
char *get_field(MEM_ROOT *mem, Field *field);
bool get_field(MEM_ROOT *mem, Field *field, class String *res);
bool validate_comment_length(THD *thd, LEX_STRING *comment, size_t max_len,
uint err_code, const char *name);
int closefrm(TABLE *table, bool free_share);
void free_blobs(TABLE *table);
void free_field_buffers_larger_than(TABLE *table, uint32 size);
......
......@@ -40,7 +40,7 @@
#define ALLOCA_THRESHOLD 2048
static uint pack_keys(uchar *,uint, KEY *, ulong);
static bool pack_header(uchar *, List<Create_field> &, uint, ulong, handler *);
static bool pack_header(THD *, uchar *, List<Create_field> &, uint, ulong, handler *);
static uint get_interval_id(uint *,List<Create_field> &, Create_field *);
static bool pack_fields(uchar *, List<Create_field> &, ulong);
static size_t packed_fields_length(List<Create_field> &);
......@@ -99,7 +99,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table,
uint keys, KEY *key_info, handler *db_file)
{
LEX_STRING str_db_type;
uint reclength, key_info_length, tmp_len, i;
uint reclength, key_info_length, i;
ulong key_buff_length;
ulong filepos, data_offset;
uint options_len;
......@@ -115,7 +115,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table,
create_info->null_bits++;
data_offset= (create_info->null_bits + 7) / 8;
error= pack_header(forminfo, create_fields, create_info->table_options,
error= pack_header(thd, forminfo, create_fields, create_info->table_options,
data_offset, db_file);
if (error)
......@@ -150,42 +150,9 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table,
keys, key_info);
DBUG_PRINT("info", ("Options length: %u", options_len));
/*
This gives us the byte-position of the character at
(character-position, not byte-position) TABLE_COMMENT_MAXLEN.
The trick here is that character-positions start at 0, so the last
character in a maximum-allowed length string would be at char-pos
MAXLEN-1; charpos MAXLEN will be the position of the terminator.
Consequently, bytepos(charpos(MAXLEN)) should be equal to
comment[length] (which should also be the terminator, or at least
the first byte after the payload in the strict sense). If this is
not so (bytepos(charpos(MAXLEN)) comes /before/ the end of the
string), the string is too long.
For additional credit, realise that UTF-8 has 1-3 bytes before 6.0,
and 1-4 bytes in 6.0 (6.0 also has UTF-32).
*/
tmp_len= system_charset_info->cset->charpos(system_charset_info,
create_info->comment.str,
create_info->comment.str +
create_info->comment.length,
TABLE_COMMENT_MAXLEN);
if (tmp_len < create_info->comment.length)
{
if (thd->is_strict_mode())
{
my_error(ER_TOO_LONG_TABLE_COMMENT, MYF(0),
table, TABLE_COMMENT_MAXLEN);
if (validate_comment_length(thd, &create_info->comment, TABLE_COMMENT_MAXLEN,
ER_TOO_LONG_TABLE_COMMENT, table))
DBUG_RETURN(frm);
}
char warn_buff[MYSQL_ERRMSG_SIZE];
my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_TABLE_COMMENT),
table, TABLE_COMMENT_MAXLEN);
push_warning(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_TOO_LONG_TABLE_COMMENT, warn_buff);
create_info->comment.length= tmp_len;
}
/*
If table comment is longer than TABLE_COMMENT_INLINE_MAXLEN bytes,
store the comment in an extra segment (up to TABLE_COMMENT_MAXLEN bytes).
......@@ -496,7 +463,8 @@ static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo,
/* Make formheader */
static bool pack_header(uchar *forminfo, List<Create_field> &create_fields,
static bool pack_header(THD *thd, uchar *forminfo,
List<Create_field> &create_fields,
uint table_options, ulong data_offset, handler *file)
{
uint length,int_count,int_length,no_empty, int_parts;
......@@ -521,28 +489,14 @@ static bool pack_header(uchar *forminfo, List<Create_field> &create_fields,
Create_field *field;
while ((field=it++))
{
uint tmp_len= system_charset_info->cset->charpos(system_charset_info,
field->comment.str,
field->comment.str +
field->comment.length,
COLUMN_COMMENT_MAXLEN);
if (tmp_len < field->comment.length)
{
myf myf_warning= current_thd->is_strict_mode() ? 0 : ME_JUST_WARNING;
my_error(ER_TOO_LONG_FIELD_COMMENT, myf_warning, field->field_name,
COLUMN_COMMENT_MAXLEN);
if (!myf_warning)
if (validate_comment_length(thd, &field->comment, COLUMN_COMMENT_MAXLEN,
ER_TOO_LONG_FIELD_COMMENT, field->field_name))
DBUG_RETURN(1);
field->comment.length= tmp_len;
}
if (field->vcol_info)
{
uint col_expr_maxlen= field->virtual_col_expr_maxlen();
tmp_len=
system_charset_info->cset->charpos(system_charset_info,
uint tmp_len= my_charpos(system_charset_info,
field->vcol_info->expr_str.str,
field->vcol_info->expr_str.str +
field->vcol_info->expr_str.length,
......
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