List:Commits« Previous MessageNext Message »
From:marko.makela Date:June 12 2012 8:38pm
Subject:bzr push into mysql-trunk-wl6255 branch (marko.makela:3968 to 3969) WL#6255
View as plain text  
 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#6255marko.makela13 Jun