Commit eb9f422c authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-5667 online alter and changed field/index options

use the Alter_inplace_info::ALTER_COLUMN_OPTION flag if
field/column flags were altered.

change ha_example to use check_if_supported_inplace_alter() instead
of obsolete check_if_incompatible_data()
parent 1b608b0b
...@@ -127,7 +127,7 @@ drop table t1; ...@@ -127,7 +127,7 @@ drop table t1;
SET @OLD_SQL_MODE=@@SQL_MODE; SET @OLD_SQL_MODE=@@SQL_MODE;
SET SQL_MODE='IGNORE_BAD_TABLE_OPTIONS'; SET SQL_MODE='IGNORE_BAD_TABLE_OPTIONS';
#illegal value fixed #illegal value fixed
CREATE TABLE t1 (a int) ENGINE=example ULL=10000000000000000000 one_or_two='ttt' YESNO=SSS; CREATE TABLE t1 (a int, b int) ENGINE=example ULL=10000000000000000000 one_or_two='ttt' YESNO=SSS;
Warnings: Warnings:
Warning 1912 Incorrect value '10000000000000000000' for option 'ULL' Warning 1912 Incorrect value '10000000000000000000' for option 'ULL'
Warning 1912 Incorrect value 'ttt' for option 'one_or_two' Warning 1912 Incorrect value 'ttt' for option 'one_or_two'
...@@ -135,7 +135,8 @@ Warning 1912 Incorrect value 'SSS' for option 'YESNO' ...@@ -135,7 +135,8 @@ Warning 1912 Incorrect value 'SSS' for option 'YESNO'
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL `a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL
) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `ULL`=10000000000000000000 `one_or_two`='ttt' `YESNO`=SSS `VAROPT`='5' ) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `ULL`=10000000000000000000 `one_or_two`='ttt' `YESNO`=SSS `VAROPT`='5'
#alter table #alter table
alter table t1 ULL=10000000; alter table t1 ULL=10000000;
...@@ -144,7 +145,8 @@ Note 1105 EXAMPLE DEBUG: ULL 4294967290 -> 10000000 ...@@ -144,7 +145,8 @@ Note 1105 EXAMPLE DEBUG: ULL 4294967290 -> 10000000
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL `a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL
) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `one_or_two`='ttt' `YESNO`=SSS `VAROPT`='5' `ULL`=10000000 ) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `one_or_two`='ttt' `YESNO`=SSS `VAROPT`='5' `ULL`=10000000
alter table t1 change a a int complex='c,c,c'; alter table t1 change a a int complex='c,c,c';
Warnings: Warnings:
...@@ -152,15 +154,15 @@ Note 1105 EXAMPLE DEBUG: Field `a` COMPLEX '(null)' -> 'c,c,c' ...@@ -152,15 +154,15 @@ Note 1105 EXAMPLE DEBUG: Field `a` COMPLEX '(null)' -> 'c,c,c'
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL `complex`='c,c,c' `a` int(11) DEFAULT NULL `complex`='c,c,c',
`b` int(11) DEFAULT NULL
) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `one_or_two`='ttt' `YESNO`=SSS `VAROPT`='5' `ULL`=10000000 ) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `one_or_two`='ttt' `YESNO`=SSS `VAROPT`='5' `ULL`=10000000
alter table t1 one_or_two=two; alter table t1 one_or_two=two;
Warnings:
Note 1105 EXAMPLE DEBUG: Field `a` COMPLEX 'c,c,c' -> 'c,c,c'
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL `complex`='c,c,c' `a` int(11) DEFAULT NULL `complex`='c,c,c',
`b` int(11) DEFAULT NULL
) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `YESNO`=SSS `VAROPT`='5' `ULL`=10000000 `one_or_two`=two ) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `YESNO`=SSS `VAROPT`='5' `ULL`=10000000 `one_or_two`=two
drop table t1; drop table t1;
#illegal value error #illegal value error
...@@ -204,8 +206,6 @@ t1 CREATE TABLE `t1` ( ...@@ -204,8 +206,6 @@ t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL `a` int(11) DEFAULT NULL
) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `varopt`=15 ) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `varopt`=15
alter table t1 varopt=default; alter table t1 varopt=default;
Warnings:
Note 1105 EXAMPLE DEBUG: Field `a` COMPLEX '(null)' -> '(null)'
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
......
...@@ -121,7 +121,7 @@ SET @OLD_SQL_MODE=@@SQL_MODE; ...@@ -121,7 +121,7 @@ SET @OLD_SQL_MODE=@@SQL_MODE;
SET SQL_MODE='IGNORE_BAD_TABLE_OPTIONS'; SET SQL_MODE='IGNORE_BAD_TABLE_OPTIONS';
--echo #illegal value fixed --echo #illegal value fixed
CREATE TABLE t1 (a int) ENGINE=example ULL=10000000000000000000 one_or_two='ttt' YESNO=SSS; CREATE TABLE t1 (a int, b int) ENGINE=example ULL=10000000000000000000 one_or_two='ttt' YESNO=SSS;
show create table t1; show create table t1;
--echo #alter table --echo #alter table
......
...@@ -4123,6 +4123,7 @@ handler::check_if_supported_inplace_alter(TABLE *altered_table, ...@@ -4123,6 +4123,7 @@ handler::check_if_supported_inplace_alter(TABLE *altered_table,
Alter_inplace_info::ALTER_COLUMN_EQUAL_PACK_LENGTH | Alter_inplace_info::ALTER_COLUMN_EQUAL_PACK_LENGTH |
Alter_inplace_info::ALTER_COLUMN_NAME | Alter_inplace_info::ALTER_COLUMN_NAME |
Alter_inplace_info::ALTER_COLUMN_DEFAULT | Alter_inplace_info::ALTER_COLUMN_DEFAULT |
Alter_inplace_info::ALTER_COLUMN_OPTION |
Alter_inplace_info::CHANGE_CREATE_OPTION | Alter_inplace_info::CHANGE_CREATE_OPTION |
Alter_inplace_info::ALTER_RENAME; Alter_inplace_info::ALTER_RENAME;
......
...@@ -1740,8 +1740,11 @@ class Alter_inplace_info ...@@ -1740,8 +1740,11 @@ class Alter_inplace_info
// Table is renamed // Table is renamed
static const HA_ALTER_FLAGS ALTER_RENAME = 1L << 18; static const HA_ALTER_FLAGS ALTER_RENAME = 1L << 18;
// Change the storage type of column // column's engine options changed, something in field->option_struct
static const HA_ALTER_FLAGS ALTER_COLUMN_STORAGE_TYPE = 1L << 19; static const HA_ALTER_FLAGS ALTER_COLUMN_OPTION = 1L << 19;
// MySQL alias for the same thing:
static const HA_ALTER_FLAGS ALTER_COLUMN_STORAGE_TYPE = 1L << 19;
// Change the column format of column // Change the column format of column
static const HA_ALTER_FLAGS ALTER_COLUMN_COLUMN_FORMAT = 1L << 20; static const HA_ALTER_FLAGS ALTER_COLUMN_COLUMN_FORMAT = 1L << 20;
...@@ -1770,7 +1773,7 @@ class Alter_inplace_info ...@@ -1770,7 +1773,7 @@ class Alter_inplace_info
// Partition operation with ALL keyword // Partition operation with ALL keyword
static const HA_ALTER_FLAGS ALTER_ALL_PARTITION = 1L << 28; static const HA_ALTER_FLAGS ALTER_ALL_PARTITION = 1L << 28;
// Partition operation with ALL keyword // Virtual columns changed
static const HA_ALTER_FLAGS ALTER_COLUMN_VCOL = 1L << 29; static const HA_ALTER_FLAGS ALTER_COLUMN_VCOL = 1L << 29;
/** /**
......
...@@ -5894,9 +5894,6 @@ static bool fill_alter_inplace_info(THD *thd, ...@@ -5894,9 +5894,6 @@ static bool fill_alter_inplace_info(THD *thd,
if (new_field) if (new_field)
{ {
ha_alter_info->create_info->fields_option_struct[f_ptr - table->field]=
new_field->option_struct;
/* Field is not dropped. Evaluate changes bitmap for it. */ /* Field is not dropped. Evaluate changes bitmap for it. */
/* /*
...@@ -6008,6 +6005,15 @@ static bool fill_alter_inplace_info(THD *thd, ...@@ -6008,6 +6005,15 @@ static bool fill_alter_inplace_info(THD *thd,
if (new_field->column_format() != field->column_format()) if (new_field->column_format() != field->column_format())
ha_alter_info->handler_flags|= ha_alter_info->handler_flags|=
Alter_inplace_info::ALTER_COLUMN_COLUMN_FORMAT; Alter_inplace_info::ALTER_COLUMN_COLUMN_FORMAT;
if (engine_options_differ(field->option_struct, new_field->option_struct,
table->file->ht->field_options))
{
ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_COLUMN_OPTION;
ha_alter_info->create_info->fields_option_struct[f_ptr - table->field]=
new_field->option_struct;
}
} }
else else
{ {
......
...@@ -906,84 +906,84 @@ int ha_example::create(const char *name, TABLE *table_arg, ...@@ -906,84 +906,84 @@ int ha_example::create(const char *name, TABLE *table_arg,
/** /**
check_if_incompatible_data() called if ALTER TABLE can't detect otherwise check_if_supported_inplace_alter() is used to ask the engine whether
if new and old definition are compatible it can execute this ALTER TABLE statement in place or the server needs to
create a new table and copy th data over.
@details If there are no other explicit signs like changed number of
fields this function will be called by compare_tables() The engine may answer that the inplace alter is not supported or,
(sql/sql_tables.cc) to decide should we rewrite whole table or only .frm if supported, whether the server should protect the table from concurrent
file. accesses. Return values are
HA_ALTER_INPLACE_NOT_SUPPORTED
HA_ALTER_INPLACE_EXCLUSIVE_LOCK
HA_ALTER_INPLACE_SHARED_LOCK
etc
*/ */
bool ha_example::check_if_incompatible_data(HA_CREATE_INFO *info, enum_alter_inplace_result
uint table_changes) ha_example::check_if_supported_inplace_alter(TABLE* altered_table,
Alter_inplace_info* ha_alter_info)
{ {
ha_table_option_struct *param_old, *param_new; HA_CREATE_INFO *info= ha_alter_info->create_info;
DBUG_ENTER("ha_example::check_if_incompatible_data"); DBUG_ENTER("ha_example::check_if_supported_inplace_alter");
/*
This example shows how custom engine specific table and field
options can be accessed from this function to be compared.
*/
param_new= info->option_struct;
DBUG_PRINT("info", ("new strparam: '%-.64s' ullparam: %llu enumparam: %u "
"boolparam: %u",
(param_new->strparam ? param_new->strparam : "<NULL>"),
param_new->ullparam, param_new->enumparam,
param_new->boolparam));
param_old= table->s->option_struct;
DBUG_PRINT("info", ("old strparam: '%-.64s' ullparam: %llu enumparam: %u "
"boolparam: %u",
(param_old->strparam ? param_old->strparam : "<NULL>"),
param_old->ullparam, param_old->enumparam,
param_old->boolparam));
/*
check important parameters:
for this example engine, we'll assume that changing ullparam or
boolparam requires a table to be rebuilt, while changing strparam
or enumparam - does not.
For debugging purposes we'll announce this to the user
(don't do it in production!)
*/ if (ha_alter_info->handler_flags & Alter_inplace_info::CHANGE_CREATE_OPTION)
if (param_new->ullparam != param_old->ullparam)
{ {
push_warning_printf(ha_thd(), Sql_condition::WARN_LEVEL_NOTE, /*
ER_UNKNOWN_ERROR, "EXAMPLE DEBUG: ULL %llu -> %llu", This example shows how custom engine specific table and field
param_old->ullparam, param_new->ullparam); options can be accessed from this function to be compared.
DBUG_RETURN(COMPATIBLE_DATA_NO); */
} ha_table_option_struct *param_new= info->option_struct;
ha_table_option_struct *param_old= table->s->option_struct;
/*
check important parameters:
for this example engine, we'll assume that changing ullparam or
boolparam requires a table to be rebuilt, while changing strparam
or enumparam - does not.
For debugging purposes we'll announce this to the user
(don't do it in production!)
*/
if (param_new->ullparam != param_old->ullparam)
{
push_warning_printf(ha_thd(), Sql_condition::WARN_LEVEL_NOTE,
ER_UNKNOWN_ERROR, "EXAMPLE DEBUG: ULL %llu -> %llu",
param_old->ullparam, param_new->ullparam);
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
}
if (param_new->boolparam != param_old->boolparam) if (param_new->boolparam != param_old->boolparam)
{ {
push_warning_printf(ha_thd(), Sql_condition::WARN_LEVEL_NOTE, push_warning_printf(ha_thd(), Sql_condition::WARN_LEVEL_NOTE,
ER_UNKNOWN_ERROR, "EXAMPLE DEBUG: YESNO %u -> %u", ER_UNKNOWN_ERROR, "EXAMPLE DEBUG: YESNO %u -> %u",
param_old->boolparam, param_new->boolparam); param_old->boolparam, param_new->boolparam);
DBUG_RETURN(COMPATIBLE_DATA_NO); DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
}
} }
for (uint i= 0; i < table->s->fields; i++) if (ha_alter_info->handler_flags & Alter_inplace_info::ALTER_COLUMN_OPTION)
{ {
ha_field_option_struct *f_old, *f_new; for (uint i= 0; i < table->s->fields; i++)
f_old= table->s->field[i]->option_struct;
DBUG_ASSERT(f_old);
if (info->fields_option_struct[i])
{ {
f_new= info->fields_option_struct[i]; ha_field_option_struct *f_old= table->s->field[i]->option_struct;
push_warning_printf(ha_thd(), Sql_condition::WARN_LEVEL_NOTE, ha_field_option_struct *f_new= info->fields_option_struct[i];
ER_UNKNOWN_ERROR, "EXAMPLE DEBUG: Field %`s COMPLEX '%s' -> '%s'", DBUG_ASSERT(f_old);
table->s->field[i]->field_name, if (f_new)
f_old->complex_param_to_parse_it_in_engine, {
f_new->complex_param_to_parse_it_in_engine); push_warning_printf(ha_thd(), Sql_condition::WARN_LEVEL_NOTE,
ER_UNKNOWN_ERROR, "EXAMPLE DEBUG: Field %`s COMPLEX '%s' -> '%s'",
table->s->field[i]->field_name,
f_old->complex_param_to_parse_it_in_engine,
f_new->complex_param_to_parse_it_in_engine);
}
else
DBUG_PRINT("info", ("old field %i did not changed", i));
} }
else
DBUG_PRINT("info", ("old field %i did not changed", i));
} }
DBUG_RETURN(COMPATIBLE_DATA_YES); DBUG_RETURN(HA_ALTER_INPLACE_EXCLUSIVE_LOCK);
} }
......
...@@ -247,8 +247,9 @@ class ha_example: public handler ...@@ -247,8 +247,9 @@ class ha_example: public handler
int delete_table(const char *from); int delete_table(const char *from);
int create(const char *name, TABLE *form, int create(const char *name, TABLE *form,
HA_CREATE_INFO *create_info); ///< required HA_CREATE_INFO *create_info); ///< required
bool check_if_incompatible_data(HA_CREATE_INFO *info, enum_alter_inplace_result
uint table_changes); check_if_supported_inplace_alter(TABLE* altered_table,
Alter_inplace_info* ha_alter_info);
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type); ///< required enum thr_lock_type lock_type); ///< required
......
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