diff options
-rw-r--r-- | mysql-test/r/partition_error.result | 96 | ||||
-rw-r--r-- | mysql-test/t/partition_error.test | 46 | ||||
-rw-r--r-- | sql/sql_table.cc | 104 | ||||
-rw-r--r-- | sql/sql_table.h | 4 | ||||
-rw-r--r-- | sql/table.h | 3 | ||||
-rw-r--r-- | sql/unireg.cc | 78 |
6 files changed, 241 insertions, 90 deletions
diff --git a/mysql-test/r/partition_error.result b/mysql-test/r/partition_error.result index fb327e937f4..41ede085623 100644 --- a/mysql-test/r/partition_error.result +++ b/mysql-test/r/partition_error.result @@ -1764,3 +1764,99 @@ PARTITION pmax VALUES LESS THAN MAXVALUE); ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed DROP TABLE t1; 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; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +/*!50100 PARTITION BY LIST (a) +SUBPARTITION BY HASH (a) +(PARTITION p1 VALUES IN (1) + (SUBPARTITION p1spFirst COMMENT = 'SubPartition comment in p1spFirst' ENGINE = MyISAM, + SUBPARTITION p1spSecond COMMENT = 'SubPartition comment in p1spSecond' ENGINE = MyISAM), + PARTITION p2 VALUES IN (2) + (SUBPARTITION p2spFirst COMMENT = 'SubPartition comment in p2spFirst' ENGINE = MyISAM, + SUBPARTITION p2spSecond COMMENT = 'SubPartition comment in p2spSecond' ENGINE = MyISAM)) */ +SELECT PARTITION_NAME, SUBPARTITION_NAME, PARTITION_COMMENT FROM INFORMATION_SCHEMA.PARTITIONS +WHERE TABLE_NAME = 't1' AND TABLE_SCHEMA = 'test'; +PARTITION_NAME SUBPARTITION_NAME PARTITION_COMMENT +p1 p1spFirst SubPartition comment in p1spFirst +p1 p1spSecond SubPartition comment in p1spSecond +p2 p2spFirst SubPartition comment in p2spFirst +p2 p2spSecond SubPartition comment in p2spSecond +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; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +/*!50100 PARTITION BY LIST (a) +SUBPARTITION BY HASH (a) +(PARTITION p1 VALUES IN (1) + (SUBPARTITION p1spFirst COMMENT = 'SubPartition comment in p1spFirst' ENGINE = MyISAM, + SUBPARTITION p1spSecond ENGINE = MyISAM), + PARTITION p2 VALUES IN (2) + (SUBPARTITION p2spFirst COMMENT = 'Comment in p2' ENGINE = MyISAM, + SUBPARTITION p2spSecond COMMENT = 'SubPartition comment in p2spSecond' ENGINE = MyISAM)) */ +SELECT PARTITION_NAME, SUBPARTITION_NAME, PARTITION_COMMENT FROM INFORMATION_SCHEMA.PARTITIONS +WHERE TABLE_NAME = 't1' AND TABLE_SCHEMA = 'test'; +PARTITION_NAME SUBPARTITION_NAME PARTITION_COMMENT +p1 p1spFirst SubPartition comment in p1spFirst +p1 p1spSecond +p2 p2spFirst Comment in p2 +p2 p2spSecond SubPartition comment in p2spSecond +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` )); +Warnings: +Warning 1793 Comment for table partition 'pUpTo10' is too long (max = 1024) +Warning 1793 Comment for table partition 'pMax' is too long (max = 1024) +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + KEY `inx_a` (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +/*!50100 PARTITION BY RANGE (a) +SUBPARTITION BY HASH (a) +(PARTITION pUpTo10 VALUES LESS THAN (10) + (SUBPARTITION `p-10sp0` COMMENT = 'This is a long comment (2050 ascii characters) 50 pUpTo10 partition ......80-!.................. 100 ................................................................................................ 200....................................................................................................................................................................................................................................................................................................... 500 ............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................... 1000 ..............1024-|' ENGINE = MyISAM, + SUBPARTITION `p-10sp1` COMMENT = 'This is a long comment (2050 ascii characters) 50 pUpTo10 partition ......80-!.................. 100 ................................................................................................ 200....................................................................................................................................................................................................................................................................................................... 500 ............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................... 1000 ..............1024-|' ENGINE = MyISAM), + PARTITION pMax VALUES LESS THAN MAXVALUE + (SUBPARTITION pMaxsp0 COMMENT = 'This is a long comment (2050 ascii characters) 50 pMax partition comment .80-!.................. 100 ................................................................................................ 200....................................................................................................................................................................................................................................................................................................... 500 ............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................... 1000 ..............1024-|' ENGINE = MyISAM, + SUBPARTITION pMaxsp1 COMMENT = 'This is a long comment (2050 ascii characters) 50 pMax partition comment .80-!.................. 100 ................................................................................................ 200....................................................................................................................................................................................................................................................................................................... 500 ............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................... 1000 ..............1024-|' ENGINE = MyISAM)) */ +SELECT PARTITION_NAME, SUBPARTITION_NAME, PARTITION_COMMENT FROM INFORMATION_SCHEMA.PARTITIONS +WHERE TABLE_NAME = 't1' AND TABLE_SCHEMA = 'test'; +PARTITION_NAME SUBPARTITION_NAME PARTITION_COMMENT +pUpTo10 p-10sp0 This is a long comment (2050 ascii characters) 50 pUpTo10 partition ......80-! +pUpTo10 p-10sp1 This is a long comment (2050 ascii characters) 50 pUpTo10 partition ......80-! +pMax pMaxsp0 This is a long comment (2050 ascii characters) 50 pMax partition comment .80-! +pMax pMaxsp1 This is a long comment (2050 ascii characters) 50 pMax partition comment .80-! +DROP TABLE t1; diff --git a/mysql-test/t/partition_error.test b/mysql-test/t/partition_error.test index 9351dd2378a..c5b37615a92 100644 --- a/mysql-test/t/partition_error.test +++ b/mysql-test/t/partition_error.test @@ -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; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 878e40cbb02..d30eb3169e3 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -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)); diff --git a/sql/sql_table.h b/sql/sql_table.h index c148ae63b4e..cd1c4293c39 100644 --- a/sql/sql_table.h +++ b/sql/sql_table.h @@ -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); diff --git a/sql/table.h b/sql/table.h index 38a33886869..60a8578fc0b 100644 --- a/sql/table.h +++ b/sql/table.h @@ -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); diff --git a/sql/unireg.cc b/sql/unireg.cc index 4e4af221ddb..aeeba6f4f85 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -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); - 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 (validate_comment_length(thd, &create_info->comment, TABLE_COMMENT_MAXLEN, + ER_TOO_LONG_TABLE_COMMENT, table)) + DBUG_RETURN(frm); /* 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,32 +489,18 @@ 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; + if (validate_comment_length(thd, &field->comment, COLUMN_COMMENT_MAXLEN, + ER_TOO_LONG_FIELD_COMMENT, field->field_name)) + DBUG_RETURN(1); - my_error(ER_TOO_LONG_FIELD_COMMENT, myf_warning, field->field_name, - COLUMN_COMMENT_MAXLEN); - - if (!myf_warning) - 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, - field->vcol_info->expr_str.str, - field->vcol_info->expr_str.str + - field->vcol_info->expr_str.length, - col_expr_maxlen); + 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, + col_expr_maxlen); if (tmp_len < field->vcol_info->expr_str.length) { |