Commit 448ea971 authored by inaam's avatar inaam

branches/zip:

Introduced a new session level config param innodb_strict_mode.
If it is set we do extra checking at time of table creation
and fail if any invalid combination of KEY_BLOCK_SIZE
or ROW_FORMAT is specified.

Reviewed by: Sunny
parent 297e88eb
......@@ -201,6 +201,12 @@ static MYSQL_THDVAR_BOOL(table_locks, PLUGIN_VAR_OPCMDARG,
/* check_func */ NULL, /* update_func */ NULL,
/* default */ TRUE);
static MYSQL_THDVAR_BOOL(strict_mode,
PLUGIN_VAR_NOCMDARG,
"Use strict mode when evaluating create options.",
NULL, NULL, FALSE);
static handler *innobase_create_handler(handlerton *hton,
TABLE_SHARE *table,
MEM_ROOT *mem_root)
......@@ -5219,6 +5225,170 @@ create_clustered_index_when_no_primary(
return(error);
}
/*********************************************************************
Validates the create options. We may build on this function
in future. For now, it checks two specifiers:
KEY_BLOCK_SIZE and ROW_FORMAT
If innodb_strict_mode is not set then this function is a no-op */
static
ibool
create_options_are_valid(
/*=====================*/
/* out: TRUE if valid. */
THD* thd, /* in: connection thread. */
TABLE* form, /* in: information on table
columns and indexes */
HA_CREATE_INFO* create_info) /* in: create info. */
{
ibool kbs_specified = FALSE;
ibool ret = TRUE;
ut_ad(thd != NULL);
/* If innodb_strict_mode is not set don't do any validation. */
if (!(THDVAR(thd, strict_mode))) {
return(TRUE);
}
ut_ad(form != NULL);
ut_ad(create_info != NULL);
/* First check if KEY_BLOCK_SIZE was specified. */
if (create_info->key_block_size
|| (create_info->used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE)) {
kbs_specified = TRUE;
switch (create_info->key_block_size) {
case 1:
case 2:
case 4:
case 8:
case 16:
/* Valid value. */
break;
default:
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: invalid"
" KEY_BLOCK_SIZE = %lu."
" Valid values are"
" [1, 2, 4, 8, 16]",
create_info->key_block_size);
ret = FALSE;
}
}
/* If KEY_BLOCK_SIZE was specified, check for its
dependencies. */
if (kbs_specified && !srv_file_per_table) {
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: KEY_BLOCK_SIZE"
" requires innodb_file_per_table.");
ret = FALSE;
}
if (kbs_specified && srv_file_format < DICT_TF_FORMAT_ZIP) {
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: KEY_BLOCK_SIZE"
" requires innodb_file_format > 0.");
ret = FALSE;
}
/* Now check for ROW_FORMAT specifier. */
if (create_info->used_fields & HA_CREATE_USED_ROW_FORMAT) {
switch (form->s->row_type) {
const char* row_format_name;
case ROW_TYPE_COMPRESSED:
case ROW_TYPE_DYNAMIC:
row_format_name
= form->s->row_type == ROW_TYPE_COMPRESSED
? "COMPRESSED"
: "DYNAMIC";
/* These two ROW_FORMATs require
srv_file_per_table and srv_file_format */
if (!srv_file_per_table) {
push_warning_printf(
thd,
MYSQL_ERROR::WARN_LEVEL_ERROR,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: ROW_FORMAT=%s"
" requires innodb_file_per_table.",
row_format_name);
ret = FALSE;
}
if (srv_file_format < DICT_TF_FORMAT_ZIP) {
push_warning_printf(
thd,
MYSQL_ERROR::WARN_LEVEL_ERROR,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: ROW_FORMAT=%s"
" requires innodb_file_format > 0.",
row_format_name);
ret = FALSE;
}
/* Cannot specify KEY_BLOCK_SIZE with
ROW_FORMAT = DYNAMIC.
However, we do allow COMPRESSED to be
specified with KEY_BLOCK_SIZE. */
if (kbs_specified
&& form->s->row_type == ROW_TYPE_DYNAMIC) {
push_warning_printf(
thd,
MYSQL_ERROR::WARN_LEVEL_ERROR,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: cannot specify"
" ROW_FORMAT = DYNAMIC with"
" KEY_BLOCK_SIZE.");
ret = FALSE;
}
break;
case ROW_TYPE_REDUNDANT:
case ROW_TYPE_COMPACT:
case ROW_TYPE_DEFAULT:
/* Default is COMPACT. */
row_format_name
= form->s->row_type == ROW_TYPE_REDUNDANT
? "REDUNDANT"
: "COMPACT";
/* Cannot specify KEY_BLOCK_SIZE with these
format specifiers. */
if (kbs_specified) {
push_warning_printf(
thd,
MYSQL_ERROR::WARN_LEVEL_ERROR,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: cannot specify"
" ROW_FORMAT = %s with"
" KEY_BLOCK_SIZE.",
row_format_name);
ret = FALSE;
}
break;
default:
push_warning(thd,
MYSQL_ERROR::WARN_LEVEL_ERROR,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: invalid ROW_FORMAT specifier.");
ret = FALSE;
}
}
return(ret);
}
/*********************************************************************
Update create_info. Used in SHOW CREATE TABLE et al. */
UNIV_INTERN
......@@ -5316,6 +5486,12 @@ ha_innobase::create(
flags = 0;
/* Validate create options if innodb_strict_mode is set. */
if (!create_options_are_valid(thd, form, create_info)) {
error = ER_ILLEGAL_HA_CREATE_OPTION;
goto cleanup;
}
if (create_info->key_block_size
|| (create_info->used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE)) {
switch (create_info->key_block_size) {
......@@ -8708,6 +8884,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(adaptive_hash_index),
MYSQL_SYSVAR(replication_delay),
MYSQL_SYSVAR(status_file),
MYSQL_SYSVAR(strict_mode),
MYSQL_SYSVAR(support_xa),
MYSQL_SYSVAR(sync_spin_loops),
MYSQL_SYSVAR(table_locks),
......
This diff is collapsed.
......@@ -2,6 +2,7 @@
let $per_table=`select @@innodb_file_per_table`;
let $format=`select @@innodb_file_format`;
let $mode=`select @@innodb_strict_mode`;
set global innodb_file_per_table=off;
set global innodb_file_format=0;
......@@ -99,5 +100,151 @@ INSERT INTO t1 VALUES(
'FOXajs|.7@IR[dmv(2<FPZdnx+5?IS]gq{.8BLV`jt~1;EOYcmw*4>HR\fpz-7AKU_is}0:DNXblv)3=GQ[eoy,6@JT^hr|/9CMWaku(3>IT_ju)4?JU`kv*5@KValw+6ALWbmx,7BMXcny-8CNYdoz.9DOZep{/:EP[fq|0;FQ\gr}1<GR]hs~2=HS^it(4@LXdp|1=IUamy.:FR^jv+7CO[gs(4@LXdp|1=IUamy.:FR^jv+7CO[gs(4@LXdp|1=IUamy.:FR^jv+7CO[gs(5BO\iv,9FS`mz0=JWdq~4AN[hu+8ER_ly/<IVcp}3@MZgt*7DQ^kx.;HUbo|2?LYfs)6CP]jw-:GTan{1>KXer(6DR`n|3AO]ky0>LZhv-;IWes*8FTbp~5CQ_m{2@N\jx/=KYgu,:HVdr)7ESao}4BP^lz1?M[iw.<JXft+9GUcq(7FUds+:IXgv.=L[jy1@O^m|4CRap(7FUds+:IXgv.=L[jy1@O^m|4CRap(7FUds+:IXgv.=L[jy1@O^m|4CRap(8HXhx1AQaq*:JZjz3CScs,<L\l|5EUeu.>N^n~7GWgw0@P`p)9IYiy2BRbr+;K[k{4DTdt-=M]m}6FVfv/?O_o(9J[l}7HYj{5FWhy3DUfw1BSdu/@Qbs->O`q+<M^o):K\m~8IZk|6GXiz4EVgx2CTev0ARct.?Par,=N_p*;L]n(:L^p+=Oas.@Rdv1CUgy4FXj|7I[m(:L^p+=Oas.@Rdv1CUgy4FXj|7');
drop table t1;
#test strict mode.
--enable_errors
set global innodb_file_per_table = on;
set global innodb_file_format = 1;
#set strict_mode
set innodb_strict_mode = on;
#Test different values of KEY_BLOCK_SIZE
--error ER_CANT_CREATE_TABLE
create table t1 (id int primary key) engine = innodb key_block_size = 0;
show errors;
--error ER_CANT_CREATE_TABLE
create table t2 (id int primary key) engine = innodb key_block_size = 9;
show errors;
create table t3 (id int primary key) engine = innodb key_block_size = 1;
create table t4 (id int primary key) engine = innodb key_block_size = 2;
create table t5 (id int primary key) engine = innodb key_block_size = 4;
create table t6 (id int primary key) engine = innodb key_block_size = 8;
create table t7 (id int primary key) engine = innodb key_block_size = 16;
#check various ROW_FORMAT values.
create table t8 (id int primary key) engine = innodb row_format = compressed;
create table t9 (id int primary key) engine = innodb row_format = dynamic;
create table t10(id int primary key) engine = innodb row_format = compact;
create table t11(id int primary key) engine = innodb row_format = redundant;
SELECT table_schema, table_name, row_format
FROM information_schema.tables WHERE engine='innodb';
drop table t3, t4, t5, t6, t7, t8, t9, t10, t11;
#test different values of ROW_FORMAT with KEY_BLOCK_SIZE
create table t1 (id int primary key) engine = innodb
key_block_size = 8 row_format = compressed;
--error ER_CANT_CREATE_TABLE
create table t2 (id int primary key) engine = innodb
key_block_size = 8 row_format = redundant;
show errors;
--error ER_CANT_CREATE_TABLE
create table t3 (id int primary key) engine = innodb
key_block_size = 8 row_format = compact;
show errors;
--error ER_CANT_CREATE_TABLE
create table t4 (id int primary key) engine = innodb
key_block_size = 8 row_format = dynamic;
show errors;
--error ER_CANT_CREATE_TABLE
create table t5 (id int primary key) engine = innodb
key_block_size = 8 row_format = default;
show errors;
SELECT table_schema, table_name, row_format
FROM information_schema.tables WHERE engine='innodb';
drop table t1;
#test multiple errors
--error ER_CANT_CREATE_TABLE
create table t1 (id int primary key) engine = innodb
key_block_size = 9 row_format = redundant;
show errors;
--error ER_CANT_CREATE_TABLE
create table t2 (id int primary key) engine = innodb
key_block_size = 9 row_format = compact;
show errors;
--error ER_CANT_CREATE_TABLE
create table t2 (id int primary key) engine = innodb
key_block_size = 9 row_format = dynamic;
show errors;
SELECT table_schema, table_name, row_format
FROM information_schema.tables WHERE engine='innodb';
#test valid values with innodb_file_per_table unset
set global innodb_file_per_table = off;
--error ER_CANT_CREATE_TABLE
create table t1 (id int primary key) engine = innodb key_block_size = 1;
show errors;
--error ER_CANT_CREATE_TABLE
create table t2 (id int primary key) engine = innodb key_block_size = 2;
show errors;
--error ER_CANT_CREATE_TABLE
create table t3 (id int primary key) engine = innodb key_block_size = 4;
show errors;
--error ER_CANT_CREATE_TABLE
create table t4 (id int primary key) engine = innodb key_block_size = 8;
show errors;
--error ER_CANT_CREATE_TABLE
create table t5 (id int primary key) engine = innodb key_block_size = 16;
show errors;
--error ER_CANT_CREATE_TABLE
create table t6 (id int primary key) engine = innodb row_format = compressed;
show errors;
--error ER_CANT_CREATE_TABLE
create table t7 (id int primary key) engine = innodb row_format = dynamic;
show errors;
create table t8 (id int primary key) engine = innodb row_format = compact;
create table t9 (id int primary key) engine = innodb row_format = redundant;
SELECT table_schema, table_name, row_format
FROM information_schema.tables WHERE engine='innodb';
drop table t8, t9;
#test valid values with innodb_file_format unset
set global innodb_file_per_table = on;
set global innodb_file_format = 0;
--error ER_CANT_CREATE_TABLE
create table t1 (id int primary key) engine = innodb key_block_size = 1;
show errors;
--error ER_CANT_CREATE_TABLE
create table t2 (id int primary key) engine = innodb key_block_size = 2;
show errors;
--error ER_CANT_CREATE_TABLE
create table t3 (id int primary key) engine = innodb key_block_size = 4;
show errors;
--error ER_CANT_CREATE_TABLE
create table t4 (id int primary key) engine = innodb key_block_size = 8;
show errors;
--error ER_CANT_CREATE_TABLE
create table t5 (id int primary key) engine = innodb key_block_size = 16;
show errors;
--error ER_CANT_CREATE_TABLE
create table t6 (id int primary key) engine = innodb row_format = compressed;
show errors;
--error ER_CANT_CREATE_TABLE
create table t7 (id int primary key) engine = innodb row_format = dynamic;
show errors;
create table t8 (id int primary key) engine = innodb row_format = compact;
create table t9 (id int primary key) engine = innodb row_format = redundant;
SELECT table_schema, table_name, row_format
FROM information_schema.tables WHERE engine='innodb';
drop table t8, t9;
eval set global innodb_file_per_table=$per_table;
eval set global innodb_file_format=$format;
eval set innodb_strict_mode=$mode;
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