diff --git a/handler/ha_innodb.cc b/handler/ha_innodb.cc index c0c888b9ae6..bea87db4fdf 100644 --- a/handler/ha_innodb.cc +++ b/handler/ha_innodb.cc @@ -2327,14 +2327,34 @@ UNIV_INTERN enum row_type ha_innobase::get_row_type() const /*=============================*/ - /* out: ROW_TYPE_REDUNDANT or ROW_TYPE_COMPACT */ + /* out: one of + ROW_TYPE_REDUNDANT, + ROW_TYPE_COMPACT, + ROW_TYPE_COMPRESSED, + ROW_TYPE_DYNAMIC */ { if (prebuilt && prebuilt->table) { - if (dict_table_is_comp(prebuilt->table)) { - return(ROW_TYPE_COMPACT); - } else { + const ulint flags = prebuilt->table->flags; + + if (UNIV_UNLIKELY(!flags)) { return(ROW_TYPE_REDUNDANT); } + + ut_ad(flags & DICT_TF_COMPACT); + + switch (flags & DICT_TF_FORMAT_MASK) { + case DICT_TF_FORMAT_51 << DICT_TF_FORMAT_SHIFT: + return(ROW_TYPE_COMPACT); + case DICT_TF_FORMAT_ZIP << DICT_TF_FORMAT_SHIFT: + if (flags & DICT_TF_ZSSIZE_MASK) { + return(ROW_TYPE_COMPRESSED); + } else { + return(ROW_TYPE_DYNAMIC); + } +#if DICT_TF_FORMAT_ZIP != DICT_TF_FORMAT_MAX +# error "DICT_TF_FORMAT_ZIP != DICT_TF_FORMAT_MAX" +#endif + } } ut_ad(0); return(ROW_TYPE_NOT_USED); @@ -5231,6 +5251,8 @@ ha_innobase::create( THD* thd = ha_thd(); ib_longlong auto_inc_value; ulint flags; + /* Cache the value of innodb_file_format, in case it is + modified by another thread while the table is being created. */ const ulint file_format = srv_file_format; DBUG_ENTER("ha_innobase::create"); @@ -5287,68 +5309,152 @@ ha_innobase::create( flags = 0; - switch (create_info->key_block_size) { - case 0: - if (form->s->row_type != ROW_TYPE_REDUNDANT) { - flags |= DICT_TF_COMPACT; - } - - goto key_block_size_ok; - case 1: - flags |= 1 << DICT_TF_ZSSIZE_SHIFT | DICT_TF_COMPACT; - break; - case 2: - flags |= 2 << DICT_TF_ZSSIZE_SHIFT | DICT_TF_COMPACT; - break; - case 4: - flags |= 3 << DICT_TF_ZSSIZE_SHIFT | DICT_TF_COMPACT; - break; - case 8: - flags |= 4 << DICT_TF_ZSSIZE_SHIFT | DICT_TF_COMPACT; - break; - case 16: - flags |= 5 << DICT_TF_ZSSIZE_SHIFT | DICT_TF_COMPACT; - break; + if (create_info->key_block_size + || (create_info->used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE)) { + switch (create_info->key_block_size) { + case 1: + flags = 1 << DICT_TF_ZSSIZE_SHIFT + | DICT_TF_COMPACT + | DICT_TF_FORMAT_ZIP + << DICT_TF_FORMAT_SHIFT; + break; + case 2: + flags = 2 << DICT_TF_ZSSIZE_SHIFT + | DICT_TF_COMPACT + | DICT_TF_FORMAT_ZIP + << DICT_TF_FORMAT_SHIFT; + break; + case 4: + flags = 3 << DICT_TF_ZSSIZE_SHIFT + | DICT_TF_COMPACT + | DICT_TF_FORMAT_ZIP + << DICT_TF_FORMAT_SHIFT; + break; + case 8: + flags = 4 << DICT_TF_ZSSIZE_SHIFT + | DICT_TF_COMPACT + | DICT_TF_FORMAT_ZIP + << DICT_TF_FORMAT_SHIFT; + break; + case 16: + flags = 5 << DICT_TF_ZSSIZE_SHIFT + | DICT_TF_COMPACT + | DICT_TF_FORMAT_ZIP + << DICT_TF_FORMAT_SHIFT; + break; #if DICT_TF_ZSSIZE_MAX != 5 # error "DICT_TF_ZSSIZE_MAX != 5" #endif -key_block_size_wrong: - default: - if (create_info->used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE) { - my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0), - innobase_hton_name, "KEY_BLOCK_SIZE"); - error = -1; - goto cleanup; - } else { - sql_print_warning("InnoDB: ignoring" - " KEY_BLOCK_SIZE=%lu\n", - create_info->key_block_size); - flags &= ~DICT_TF_ZSSIZE_MASK; - goto key_block_size_ok; + } + + if (!srv_file_per_table) { + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_ILLEGAL_HA_CREATE_OPTION, + "InnoDB: KEY_BLOCK_SIZE" + " requires innodb_file_per_table."); + flags = 0; + } + + if (file_format < DICT_TF_FORMAT_ZIP) { + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_ILLEGAL_HA_CREATE_OPTION, + "InnoDB: KEY_BLOCK_SIZE" + " requires innodb_file_format>0."); + flags = 0; + } + + if (!flags) { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_ILLEGAL_HA_CREATE_OPTION, + "InnoDB: ignoring" + " KEY_BLOCK_SIZE=%lu.", + create_info->key_block_size); } } - if (!srv_file_per_table || file_format < DICT_TF_FORMAT_ZIP) { + if (create_info->used_fields & HA_CREATE_USED_ROW_FORMAT) { + if (flags) { + /* KEY_BLOCK_SIZE was specified. */ + if (form->s->row_type != ROW_TYPE_COMPRESSED) { + /* ROW_FORMAT other than COMPRESSED + ignores KEY_BLOCK_SIZE. It does not + make sense to reject conflicting + KEY_BLOCK_SIZE and ROW_FORMAT, because + such combinations can be obtained + with ALTER TABLE anyway. */ + push_warning_printf( + thd, + MYSQL_ERROR::WARN_LEVEL_WARN, + ER_ILLEGAL_HA_CREATE_OPTION, + "InnoDB: ignoring KEY_BLOCK_SIZE=%lu" + " unless ROW_FORMAT=COMPRESSED.", + create_info->key_block_size); + flags = 0; + } + } else { + /* No KEY_BLOCK_SIZE */ + if (form->s->row_type == ROW_TYPE_COMPRESSED) { + /* ROW_FORMAT=COMPRESSED without + KEY_BLOCK_SIZE implies + KEY_BLOCK_SIZE=8. */ + flags = 4 << DICT_TF_ZSSIZE_SHIFT + | DICT_TF_COMPACT + | DICT_TF_FORMAT_ZIP + << DICT_TF_FORMAT_SHIFT; + } + } - goto key_block_size_wrong; - } + switch (form->s->row_type) { + const char* row_format_name; + case ROW_TYPE_REDUNDANT: + break; + case ROW_TYPE_COMPRESSED: + case ROW_TYPE_DYNAMIC: + row_format_name + = form->s->row_type == ROW_TYPE_COMPRESSED + ? "COMPRESSED" + : "DYNAMIC"; -key_block_size_ok: + if (!srv_file_per_table) { + push_warning_printf( + thd, + MYSQL_ERROR::WARN_LEVEL_WARN, + ER_ILLEGAL_HA_CREATE_OPTION, + "InnoDB: ROW_FORMAT=%s" + " requires innodb_file_per_table.", + row_format_name); + } else if (file_format < DICT_TF_FORMAT_ZIP) { + push_warning_printf( + thd, + MYSQL_ERROR::WARN_LEVEL_WARN, + ER_ILLEGAL_HA_CREATE_OPTION, + "InnoDB: ROW_FORMAT=%s" + " requires innodb_file_format>0.", + row_format_name); + } else { + flags |= DICT_TF_COMPACT + | (DICT_TF_FORMAT_ZIP + << DICT_TF_FORMAT_SHIFT); + break; + } - if (UNIV_EXPECT(flags & DICT_TF_COMPACT, DICT_TF_COMPACT)) { - /* New formats are only available if ROW_FORMAT=COMPACT. */ - flags |= file_format << DICT_TF_FORMAT_SHIFT; - } - - if ((create_info->used_fields & HA_CREATE_USED_ROW_FORMAT) - && form->s->row_type != ((flags & DICT_TF_COMPACT) - ? ROW_TYPE_COMPACT - : ROW_TYPE_REDUNDANT)) { - - my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0), - innobase_hton_name, "ROW_FORMAT"); - error = -1; - goto cleanup; + /* fall through */ + case ROW_TYPE_NOT_USED: + case ROW_TYPE_FIXED: + default: + push_warning(thd, + MYSQL_ERROR::WARN_LEVEL_WARN, + ER_ILLEGAL_HA_CREATE_OPTION, + "InnoDB: assuming ROW_FORMAT=COMPACT."); + case ROW_TYPE_DEFAULT: + case ROW_TYPE_COMPACT: + flags = DICT_TF_COMPACT; + break; + } + } else if (!flags) { + /* No KEY_BLOCK_SIZE or ROW_FORMAT specified: + use ROW_FORMAT=COMPACT by default. */ + flags = DICT_TF_COMPACT; } error = create_table_def(trx, form, norm_name, @@ -8313,12 +8419,17 @@ ha_innobase::check_if_incompatible_data( } /* Check that row format didn't change */ - if ((info->used_fields & HA_CREATE_USED_AUTO) && - get_row_type() != info->row_type) { + if ((info->used_fields & HA_CREATE_USED_ROW_FORMAT) && + get_row_type() != info->row_type) { return(COMPATIBLE_DATA_NO); } + /* Specifying KEY_BLOCK_SIZE requests a rebuild of the table. */ + if (info->used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE) { + return(COMPATIBLE_DATA_NO); + } + return(COMPATIBLE_DATA_YES); } diff --git a/mysql-test/innodb-zip.result b/mysql-test/innodb-zip.result index e0694e972e2..bcb3ad0c692 100644 --- a/mysql-test/innodb-zip.result +++ b/mysql-test/innodb-zip.result @@ -1,53 +1,91 @@ set global innodb_file_per_table=off; set global innodb_file_format=0; create table t1(a int primary key) engine=innodb row_format=dynamic; -ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'ROW_FORMAT' -create table t1(a int primary key) engine=innodb row_format=redundant; -show create table t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `a` int(11) NOT NULL, - PRIMARY KEY (`a`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=REDUNDANT -drop table t1; -create table t1(a int primary key) engine=innodb row_format=compact; -show create table t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `a` int(11) NOT NULL, - PRIMARY KEY (`a`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT -drop table t1; -create table t1(a int primary key) engine=innodb key_block_size=9; -ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE' -create table t1(a int primary key) engine=innodb +Warnings: +Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_per_table. +Warning 1478 InnoDB: assuming ROW_FORMAT=COMPACT. +create table t2(a int primary key) engine=innodb row_format=redundant; +create table t3(a int primary key) engine=innodb row_format=compact; +create table t4(a int primary key) engine=innodb key_block_size=9; +Warnings: +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format>0. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=9. +create table t5(a int primary key) engine=innodb key_block_size=1 row_format=redundant; -ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE' +Warnings: +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format>0. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=1. set global innodb_file_per_table=on; -create table t1(a int primary key) engine=innodb +create table t6(a int primary key) engine=innodb key_block_size=1 row_format=redundant; -ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE' +Warnings: +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format>0. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=1. set global innodb_file_format=1; -create table t1(a int primary key) engine=innodb +create table t7(a int primary key) engine=innodb key_block_size=1 row_format=redundant; -ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'ROW_FORMAT' -create table t1(a int primary key) engine=innodb +Warnings: +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=1 unless ROW_FORMAT=COMPRESSED. +create table t8(a int primary key) engine=innodb +key_block_size=1 row_format=fixed; +Warnings: +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=1 unless ROW_FORMAT=COMPRESSED. +Warning 1478 InnoDB: assuming ROW_FORMAT=COMPACT. +create table t9(a int primary key) engine=innodb key_block_size=1 row_format=compact; -show create table t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `a` int(11) NOT NULL, - PRIMARY KEY (`a`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT KEY_BLOCK_SIZE=1 -drop table t1; -create table t1(a int primary key) engine=innodb +Warnings: +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=1 unless ROW_FORMAT=COMPRESSED. +create table t10(a int primary key) engine=innodb +key_block_size=1 row_format=dynamic; +Warnings: +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=1 unless ROW_FORMAT=COMPRESSED. +create table t11(a int primary key) engine=innodb +key_block_size=1 row_format=compressed; +create table t12(a int primary key) engine=innodb key_block_size=1; -show create table t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `a` int(11) NOT NULL, - PRIMARY KEY (`a`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=1 +create table t13(a int primary key) engine=innodb +row_format=compressed; +create table t14(a int primary key) engine=innodb key_block_size=9; +Warnings: +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=9. +SELECT table_schema, table_name, row_format +FROM information_schema.tables WHERE engine='innodb'; +table_schema table_name row_format +test t1 Compact +test t10 Dynamic +test t11 Compressed +test t12 Compressed +test t13 Compressed +test t14 Compact +test t2 Redundant +test t3 Compact +test t4 Compact +test t5 Redundant +test t6 Redundant +test t7 Redundant +test t8 Compact +test t9 Compact +drop table t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14; +alter table t1 key_block_size=0; +Warnings: +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=0. +alter table t1 row_format=dynamic; +SELECT table_schema, table_name, row_format +FROM information_schema.tables WHERE engine='innodb'; +table_schema table_name row_format +test t1 Dynamic +alter table t1 row_format=compact; +SELECT table_schema, table_name, row_format +FROM information_schema.tables WHERE engine='innodb'; +table_schema table_name row_format +test t1 Compact +alter table t1 row_format=redundant; +SELECT table_schema, table_name, row_format +FROM information_schema.tables WHERE engine='innodb'; +table_schema table_name row_format +test t1 Redundant drop table t1; create table t1(a int not null, b text, index(b(10))) engine=innodb key_block_size=1; @@ -64,7 +102,11 @@ rollback; select a,left(b,40) from t1 natural join t2; a left(b,40) 1 1abcdefghijklmnopqrstuvwxyzAAAAAAAAAAAAA -drop table t1; -drop table t2; +SELECT table_schema, table_name, row_format +FROM information_schema.tables WHERE engine='innodb'; +table_schema table_name row_format +test t1 Compressed +test t2 Compact +drop table t1,t2; set global innodb_file_per_table=0; set global innodb_file_format=0; diff --git a/mysql-test/innodb-zip.test b/mysql-test/innodb-zip.test index cf66847d30f..6425c572e6a 100644 --- a/mysql-test/innodb-zip.test +++ b/mysql-test/innodb-zip.test @@ -4,37 +4,48 @@ let $per_table=`select @@innodb_file_per_table`; let $format=`select @@innodb_file_format`; set global innodb_file_per_table=off; set global innodb_file_format=0; ---error 1478 -create table t1(a int primary key) engine=innodb row_format=dynamic; -create table t1(a int primary key) engine=innodb row_format=redundant; -show create table t1; -drop table t1; -create table t1(a int primary key) engine=innodb row_format=compact; -show create table t1; -drop table t1; ---error 1478 -create table t1(a int primary key) engine=innodb key_block_size=9; ---error 1478 -create table t1(a int primary key) engine=innodb +create table t1(a int primary key) engine=innodb row_format=dynamic; +create table t2(a int primary key) engine=innodb row_format=redundant; +create table t3(a int primary key) engine=innodb row_format=compact; +create table t4(a int primary key) engine=innodb key_block_size=9; +create table t5(a int primary key) engine=innodb key_block_size=1 row_format=redundant; + set global innodb_file_per_table=on; ---error 1478 -create table t1(a int primary key) engine=innodb +create table t6(a int primary key) engine=innodb key_block_size=1 row_format=redundant; set global innodb_file_format=1; ---error 1478 -create table t1(a int primary key) engine=innodb +create table t7(a int primary key) engine=innodb key_block_size=1 row_format=redundant; - -create table t1(a int primary key) engine=innodb +create table t8(a int primary key) engine=innodb +key_block_size=1 row_format=fixed; +create table t9(a int primary key) engine=innodb key_block_size=1 row_format=compact; -show create table t1; -drop table t1; - -create table t1(a int primary key) engine=innodb +create table t10(a int primary key) engine=innodb +key_block_size=1 row_format=dynamic; +create table t11(a int primary key) engine=innodb +key_block_size=1 row_format=compressed; +create table t12(a int primary key) engine=innodb key_block_size=1; -show create table t1; +create table t13(a int primary key) engine=innodb +row_format=compressed; +create table t14(a int primary key) engine=innodb key_block_size=9; + +SELECT table_schema, table_name, row_format +FROM information_schema.tables WHERE engine='innodb'; + +drop table t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14; +alter table t1 key_block_size=0; +alter table t1 row_format=dynamic; +SELECT table_schema, table_name, row_format +FROM information_schema.tables WHERE engine='innodb'; +alter table t1 row_format=compact; +SELECT table_schema, table_name, row_format +FROM information_schema.tables WHERE engine='innodb'; +alter table t1 row_format=redundant; +SELECT table_schema, table_name, row_format +FROM information_schema.tables WHERE engine='innodb'; drop table t1; create table t1(a int not null, b text, index(b(10))) engine=innodb @@ -66,7 +77,9 @@ connection default; disconnect a; disconnect b; -drop table t1; -drop table t2; +SELECT table_schema, table_name, row_format +FROM information_schema.tables WHERE engine='innodb'; +drop table t1,t2; + eval set global innodb_file_per_table=$per_table; eval set global innodb_file_format=$format; diff --git a/mysql-test/innodb.result b/mysql-test/innodb.result index ef7b2cfc37d..6e31b0142a4 100644 --- a/mysql-test/innodb.result +++ b/mysql-test/innodb.result @@ -2371,6 +2371,8 @@ t1 CREATE TABLE `t1` ( ) ENGINE=InnoDB DEFAULT CHARSET=latin1 drop table t1; create table t1 (v varchar(10), c char(10)) row_format=fixed; +Warnings: +Warning 1478 InnoDB: assuming ROW_FORMAT=COMPACT. show create table t1; Table Create Table t1 CREATE TABLE `t1` (