3969 Marko Mäkelä 2012-06-12
WL#6255 rb:1105 Problem 20,21 fix.
Check the maximum column prefix length when changing ROW_FORMAT or
KEY_BLOCK_SIZE.
innobase_check_column_length(): Replace table with max_col_len.
ha_innobase::prepare_inplace_alter_table(): Compute max_col_len
by invoking innobase_table_flags() when needed. Enforce the max_col_len
also in existing indexes of the table.
innobase_table_flags(): Remove the parameter name. Do not complain
about badly formed FTS_DOC_ID_INDEX, unless the table is also to have
FULLTEXT indexes. When complaining, use the dedicated error code
ER_INNODB_FT_WRONG_DOCID_INDEX instead of the generic and misleading
ER_WRONG_NAME_FOR_INDEX.
prepare_inplace_alter_table_dict(): Add the parameters flags, flags2,
so that innobase_table_flags() does not need to be invoked again. Its
outcome can change if innodb_file_format is changed between calls.
modified:
mysql-test/suite/innodb/r/innodb_prefix_index_liftedlimit.result
mysql-test/suite/innodb/t/innodb_prefix_index_liftedlimit.test
mysql-test/suite/innodb_fts/r/innodb-fts-ddl.result
mysql-test/suite/innodb_fts/t/innodb-fts-ddl.test
storage/innobase/handler/ha_innodb.cc
storage/innobase/handler/ha_innodb.h
storage/innobase/handler/handler0alter.cc
3968 Marko Mäkelä 2012-06-12
row_log_table_apply_convert_mrec(): The clustered index tree of the
source table should already be X-latched in row_log_table_apply().
modified:
storage/innobase/row/row0log.cc
=== modified file 'mysql-test/suite/innodb/r/innodb_prefix_index_liftedlimit.result'
--- a/mysql-test/suite/innodb/r/innodb_prefix_index_liftedlimit.result revid:marko.makela@stripped
+++ b/mysql-test/suite/innodb/r/innodb_prefix_index_liftedlimit.result revid:marko.makela@stripped5n0asg6d
@@ -31,6 +31,11 @@ SELECT col_1_varchar = REPEAT("c", 4000)
col_1_varchar = REPEAT("c", 4000)
0
1
+ALTER TABLE worklog5743 ROW_FORMAT=REDUNDANT;
+ERROR HY000: Index column size too large. The maximum column size is 767 bytes.
+ALTER TABLE worklog5743 ROW_FORMAT=COMPACT;
+ERROR HY000: Index column size too large. The maximum column size is 767 bytes.
+ALTER TABLE worklog5743 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=16;
DROP TABLE worklog5743;
CREATE TABLE worklog5743 (
col_1_text TEXT (4000) , col_2_text TEXT (4000) ,
@@ -1364,8 +1369,22 @@ CREATE TABLE worklog5743 (
col_1_varchar VARCHAR (4000) , col_2_varchar VARCHAR (4000) ,
PRIMARY KEY (col_1_varchar(767))
) engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT('a',4000),REPEAT('b',4000));
CREATE INDEX prefix_idx ON worklog5743(col_1_varchar (1000));
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 1
Warnings:
Warning 1071 Specified key was too long; max key length is 767 bytes
+ALTER TABLE worklog5743 ROW_FORMAT=REDUNDANT;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+SHOW CREATE TABLE worklog5743;
+Table Create Table
+worklog5743 CREATE TABLE `worklog5743` (
+ `col_1_varchar` varchar(4000) NOT NULL DEFAULT '',
+ `col_2_varchar` varchar(4000) DEFAULT NULL,
+ PRIMARY KEY (`col_1_varchar`(767)),
+ KEY `prefix_idx` (`col_1_varchar`(767))
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=REDUNDANT
DROP TABLE worklog5743;
"Disconnect the connection 1"
=== modified file 'mysql-test/suite/innodb/t/innodb_prefix_index_liftedlimit.test'
--- a/mysql-test/suite/innodb/t/innodb_prefix_index_liftedlimit.test revid:marko.makela@oracle.com-20120612190148-6zwi4r5jaehbw50n
+++ b/mysql-test/suite/innodb/t/innodb_prefix_index_liftedlimit.test revid:marko.makela@strippedg6d
@@ -52,6 +52,11 @@ WHERE col_1_varchar = REPEAT("c", 4000)
INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
DELETE FROM worklog5743 WHERE col_1_varchar = REPEAT("b", 4000);
SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743;
+--error ER_INDEX_COLUMN_TOO_LONG
+ALTER TABLE worklog5743 ROW_FORMAT=REDUNDANT;
+--error ER_INDEX_COLUMN_TOO_LONG
+ALTER TABLE worklog5743 ROW_FORMAT=COMPACT;
+ALTER TABLE worklog5743 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=16;
DROP TABLE worklog5743;
@@ -1024,7 +1029,7 @@ AND col_2_varchar = REPEAT("o", 4000);
ALTER TABLE worklog5743 ADD PRIMARY KEY (col_1_varchar(3072));
INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
---error 1062
+--error ER_DUP_ENTRY
INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
DELETE FROM worklog5743 WHERE col_1_varchar = REPEAT("b", 4000);
SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743;
@@ -1058,7 +1063,7 @@ ALTER TABLE worklog5743 ADD PRIMARY KEY
CREATE INDEX prefix_idx ON worklog5743(col_1_varchar (3072));
INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
---error 1062
+--error ER_DUP_ENTRY
INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
DELETE FROM worklog5743 WHERE col_1_varchar = REPEAT("b", 4000);
SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743;
@@ -1341,7 +1346,7 @@ VALUES(concat(REPEAT("a", 2000),REPEAT("
REPEAT("o", 4000));
INSERT INTO worklog5743
VALUES(concat(REPEAT("a", 2000),REPEAT("b", 2000)), REPEAT("o", 4000));
---error 1062
+--error ER_DUP_ENTRY
ALTER TABLE worklog5743 ADD PRIMARY KEY `pk_idx` (col_1_varchar(3000));
DROP TABLE worklog5743;
@@ -1363,8 +1368,13 @@ CREATE TABLE worklog5743 (
col_1_varchar VARCHAR (4000) , col_2_varchar VARCHAR (4000) ,
PRIMARY KEY (col_1_varchar(767))
) engine = innodb;
-# Prefix index > 767 is truncated with REDUNDANT and COMPACT
+INSERT INTO worklog5743 VALUES(REPEAT('a',4000),REPEAT('b',4000));
+# Prefix index > 767 is truncated with REDUNDANT and COMPACT
+--enable_info
CREATE INDEX prefix_idx ON worklog5743(col_1_varchar (1000));
+ALTER TABLE worklog5743 ROW_FORMAT=REDUNDANT;
+--disable_info
+SHOW CREATE TABLE worklog5743;
DROP TABLE worklog5743;
#------------------------------------------------------------------------------
=== modified file 'mysql-test/suite/innodb_fts/r/innodb-fts-ddl.result'
--- a/mysql-test/suite/innodb_fts/r/innodb-fts-ddl.result revid:marko.makela@strippedzwi4r5jaehbw50n
+++ b/mysql-test/suite/innodb_fts/r/innodb-fts-ddl.result revid:marko.makela@stripped3614-7jczc2of5n0asg6d
@@ -144,7 +144,7 @@ PRIMARY KEY (FTS_DOC_ID),
KEY FTS_DOC_ID_INDEX (FTS_DOC_ID),
FULLTEXT KEY idx (title,text)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
-ERROR 42000: Incorrect index name 'FTS_DOC_ID_INDEX'
+ERROR HY000: Index 'FTS_DOC_ID_INDEX' is of wrong type for an InnoDB FULLTEXT index
CREATE TABLE articles (
FTS_DOC_ID BIGINT UNSIGNED NOT NULL ,
title VARCHAR(200),
=== modified file 'mysql-test/suite/innodb_fts/t/innodb-fts-ddl.test'
--- a/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.test revid:marko.makela@oracle.com-20120612190148-6zwi4r5jaehbw50n
+++ b/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.test revid:marko.makela@oracle.com-20120612203614-7jczc2of5n0asg6d
@@ -163,7 +163,7 @@ CREATE TABLE fts_test (
# This should fail:
# Create a FTS_DOC_ID_INDEX of the wrong type (should be unique)
---error 1280
+--error ER_INNODB_FT_WRONG_DOCID_INDEX
CREATE TABLE fts_test (
FTS_DOC_ID bigint(20) unsigned NOT NULL AUTO_INCREMENT,
title varchar(255) NOT NULL DEFAULT '',
=== modified file 'storage/innobase/handler/ha_innodb.cc'
--- a/storage/innobase/handler/ha_innodb.cc revid:marko.makela@strippedehbw50n
+++ b/storage/innobase/handler/ha_innodb.cc revid:marko.makela@stripped
@@ -8888,7 +8888,6 @@ UNIV_INTERN
bool
innobase_table_flags(
/*=================*/
- const char* name, /*!< in: table name */
const TABLE* form, /*!< in: table */
const HA_CREATE_INFO* create_info, /*!< in: information
on table columns and indexes */
@@ -8900,6 +8899,7 @@ innobase_table_flags(
{
DBUG_ENTER("innobase_table_flags");
+ const char* fts_index_bad = NULL;
bool zip_allowed = true;
ulint zip_ssize = 0;
enum row_type row_format;
@@ -8925,6 +8925,10 @@ innobase_table_flags(
my_error(ER_INNODB_NO_FT_TEMP_TABLE, MYF(0));
DBUG_RETURN(false);
}
+
+ if (fts_index_bad) {
+ goto index_bad;
+ }
}
if (innobase_strcasecmp(key->name, FTS_DOC_ID_INDEX_NAME)) {
@@ -8936,21 +8940,13 @@ innobase_table_flags(
|| strcmp(key->name, FTS_DOC_ID_INDEX_NAME)
|| strcmp(key->key_part[0].field->field_name,
FTS_DOC_ID_COL_NAME)) {
- push_warning_printf(thd,
- Sql_condition::WARN_LEVEL_WARN,
- ER_WRONG_NAME_FOR_INDEX,
- " InnoDB: Index name %s is reserved"
- " for the unique index on"
- " FTS_DOC_ID column for FTS"
- " document ID indexing"
- " on table %s. Please check"
- " the index definition to"
- " make sure it is of correct"
- " type\n",
- FTS_DOC_ID_INDEX_NAME,
- name);
- my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
- FTS_DOC_ID_INDEX_NAME);
+ fts_index_bad = key->name;
+ }
+
+ if (fts_index_bad && (*flags2 & DICT_TF2_FTS)) {
+index_bad:
+ my_error(ER_INNODB_FT_WRONG_DOCID_INDEX, MYF(0),
+ fts_index_bad);
DBUG_RETURN(false);
}
}
@@ -9185,7 +9181,7 @@ ha_innobase::create(
DBUG_RETURN(HA_WRONG_CREATE_OPTION);
}
- if (!innobase_table_flags(name, form, create_info,
+ if (!innobase_table_flags(form, create_info,
thd, use_tablespace,
&flags, &flags2)) {
DBUG_RETURN(-1);
=== modified file 'storage/innobase/handler/ha_innodb.h'
--- a/storage/innobase/handler/ha_innodb.h revid:marko.makela@stripped8-6zwi4r5jaehbw50n
+++ b/storage/innobase/handler/ha_innodb.h revid:marko.makela@strippedf5n0asg6d
@@ -467,7 +467,6 @@ UNIV_INTERN
bool
innobase_table_flags(
/*=================*/
- const char* name, /*!< in: table name */
const TABLE* form, /*!< in: table */
const HA_CREATE_INFO* create_info, /*!< in: information
on table columns and indexes */
=== modified file 'storage/innobase/handler/handler0alter.cc'
--- a/storage/innobase/handler/handler0alter.cc revid:marko.makela@stripped
+++ b/storage/innobase/handler/handler0alter.cc revid:marko.makela@stripped
@@ -1777,15 +1777,13 @@ created_clustered:
/*******************************************************************//**
Check each index column size, make sure they do not exceed the max limit
@return true if index column size exceeds limit */
-static
+static __attribute__((nonnull, warn_unused_result))
bool
innobase_check_column_length(
/*=========================*/
- const dict_table_t*table, /*!< in: table definition */
+ ulint max_col_len, /*!< in: maximum column length */
const KEY* key_info) /*!< in: Indexes to be created */
{
- ulint max_col_len = DICT_MAX_FIELD_LEN_BY_FORMAT(table);
-
for (ulint key_part = 0; key_part < key_info->key_parts; key_part++) {
if (key_info->key_part[key_part].length > max_col_len) {
return(true);
@@ -2297,6 +2295,8 @@ while preparing ALTER TABLE.
@param user_table InnoDB table that is being altered
@param user_trx User transaction, for locking the table
@param table_name Table name in MySQL
+@param flags Table and tablespace flags
+@param flags2 Additional table flags
@param heap Memory heap, or NULL
@param drop_index Indexes to be dropped, or NULL
@param n_drop_index Number of indexes to drop
@@ -2322,6 +2322,8 @@ prepare_inplace_alter_table_dict(
dict_table_t* user_table,
trx_t* user_trx,
const char* table_name,
+ ulint flags,
+ ulint flags2,
mem_heap_t* heap,
dict_index_t** drop_index,
ulint n_drop_index,
@@ -2465,19 +2467,8 @@ prepare_inplace_alter_table_dict(
if (new_clustered) {
char* new_table_name = innobase_create_temporary_tablename(
heap, indexed_table->name, indexed_table->id);
- ulint flags;
- ulint flags2;
ulint n_cols;
- if (!innobase_table_flags(table_name, altered_table,
- ha_alter_info->create_info,
- trx->mysql_thd,
- srv_file_per_table
- || user_table->space != 0,
- &flags, &flags2)) {
- goto new_clustered_failed;
- }
-
if (innobase_check_foreigns(
ha_alter_info, altered_table, old_table,
user_table, drop_foreign, n_drop_foreign)) {
@@ -2949,6 +2940,9 @@ ha_innobase::prepare_inplace_alter_table
dict_table_t* indexed_table; /*!< Table where indexes are created */
mem_heap_t* heap;
int error;
+ ulint flags;
+ ulint flags2;
+ ulint max_col_len;
ulint num_fts_index;
ulint add_autoinc_col_no = ULINT_UNDEFINED;
ulint fts_doc_col_no = ULINT_UNDEFINED;
@@ -3075,6 +3069,17 @@ check_if_ok_to_rename:
}
}
+ if (!innobase_table_flags(altered_table,
+ ha_alter_info->create_info,
+ user_thd,
+ srv_file_per_table
+ || indexed_table->space != 0,
+ &flags, &flags2)) {
+ goto err_exit_no_heap;
+ }
+
+ max_col_len = DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags);
+
/* Check each index's column length to make sure they do not
exceed limit */
for (ulint i = 0; i < ha_alter_info->index_add_count; i++) {
@@ -3093,14 +3098,35 @@ check_if_ok_to_rename:
continue;
}
- if (innobase_check_column_length(indexed_table, key)) {
+ if (innobase_check_column_length(max_col_len, key)) {
my_error(ER_INDEX_COLUMN_TOO_LONG, MYF(0),
- DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(
- indexed_table->flags));
+ max_col_len);
goto err_exit_no_heap;
}
}
+ /* Check existing index definitions for too-long column
+ prefixes as well, in case max_col_len shrunk. */
+ for (const dict_index_t* index
+ = dict_table_get_first_index(indexed_table);
+ index;
+ index = dict_table_get_next_index(index)) {
+ if (index->type & DICT_FTS) {
+ DBUG_ASSERT(index->type == DICT_FTS);
+ continue;
+ }
+
+ for (ulint i = 0; i < dict_index_get_n_fields(index); i++) {
+ const dict_field_t* field
+ = dict_index_get_nth_field(index, i);
+ if (field->prefix_len > max_col_len) {
+ my_error(ER_INDEX_COLUMN_TOO_LONG, MYF(0),
+ max_col_len);
+ goto err_exit_no_heap;
+ }
+ }
+ }
+
n_drop_index = 0;
n_drop_fk = 0;
@@ -3487,6 +3513,7 @@ found_col:
ha_alter_info, altered_table, table,
prebuilt->table, prebuilt->trx,
table_share->table_name.str,
+ flags, flags2,
heap, drop_index, n_drop_index,
drop_fk, n_drop_fk, add_fk, n_add_fk,
num_fts_index,
No bundle (reason: useless for push emails).| Thread |
|---|
| • bzr push into mysql-trunk-wl6255 branch (marko.makela:3968 to 3969) WL#6255 | marko.makela | 13 Jun |