diff options
author | Eugene Kosov <claprix@yandex.ru> | 2018-06-09 16:06:39 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2018-06-20 19:23:48 +0300 |
commit | 9dc81f7d387050dd62f2307b15c63c3a3f5ea1b0 (patch) | |
tree | c921284d68bfeb56cfcda8b30cd5927c9f10ec2c | |
parent | ff09512e07045b0997265d37c45f075daebe9531 (diff) | |
download | mariadb-git-9dc81f7d387050dd62f2307b15c63c3a3f5ea1b0.tar.gz |
MDEV-16330 Allow instant change of WITH SYSTEM VERSIONING column attribute
Changing columns WITH/WITHOUT SYSTEM VERSIONING doens't require to read data at
all. Thus it should be an instant operation.
Patch also fixes a bug when ALTER_COLUMN_UNVERSIONED wasn't passed to InnoDB
to change its internal structures.
change_field_versioning_try(): apply WITH/WITHOUT SYSTEM VERSIONING
change in SYS_COLUMNS for one field.
change_fields_versioning_try(): apply WITH/WITHOUT SYSTEM VERSIONING
change in SYS_COLUMNS for every changed field in a table.
change_fields_versioning_cache(): update cache for versioning property
of columns.
-rw-r--r-- | mysql-test/suite/versioning/r/trx_id.result | 96 | ||||
-rw-r--r-- | mysql-test/suite/versioning/r/trx_id_versioning_attribute_persistence.result | 86 | ||||
-rw-r--r-- | mysql-test/suite/versioning/t/trx_id.test | 83 | ||||
-rw-r--r-- | mysql-test/suite/versioning/t/trx_id_versioning_attribute_persistence.test | 87 | ||||
-rw-r--r-- | sql/sql_table.cc | 18 | ||||
-rw-r--r-- | storage/innobase/handler/handler0alter.cc | 192 |
6 files changed, 551 insertions, 11 deletions
diff --git a/mysql-test/suite/versioning/r/trx_id.result b/mysql-test/suite/versioning/r/trx_id.result index 7b2ea04985d..2e0db5f2cde 100644 --- a/mysql-test/suite/versioning/r/trx_id.result +++ b/mysql-test/suite/versioning/r/trx_id.result @@ -379,3 +379,99 @@ DROP TABLE tts; DROP TABLE ttx; DROP FUNCTION fts; DROP FUNCTION ftx; +# +# MDEV-16330 Allow instant change of WITH SYSTEM VERSIONING column attribute +# +SET @@SYSTEM_VERSIONING_ALTER_HISTORY=KEEP; +CREATE TABLE t ( +a INT, +b INT, +row_start BIGINT UNSIGNED AS ROW START INVISIBLE, +row_end BIGINT UNSIGNED AS ROW END INVISIBLE, +PERIOD FOR SYSTEM_TIME(row_start, row_end) +) WITH SYSTEM VERSIONING ENGINE=INNODB; +INSERT INTO t VALUES (1,1); +# without table rebuild +SELECT c.prtype FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS c +INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t +ON c.table_id=t.table_id +WHERE t.name='test/t' AND c.name='a'; +prtype +50179 +ALTER TABLE t +CHANGE a a INT WITHOUT SYSTEM VERSIONING; +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 +SELECT c.prtype FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS c +INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t +ON c.table_id=t.table_id +WHERE t.name='test/t' AND c.name='a'; +prtype +1027 +UPDATE t SET a=11; +SELECT COUNT(*) FROM t FOR SYSTEM_TIME ALL; +COUNT(*) +1 +# with table rebuild +SELECT c.prtype FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS c +INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t +ON c.table_id=t.table_id +WHERE t.name='test/t' AND c.name='a'; +prtype +1027 +ALTER TABLE t +CHANGE a a INT WITH SYSTEM VERSIONING, +ADD PRIMARY KEY pk(a); +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 +SELECT c.prtype FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS c +INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t +ON c.table_id=t.table_id +WHERE t.name='test/t' AND c.name='a'; +prtype +50435 +UPDATE t SET a=1; +SELECT COUNT(*) FROM t FOR SYSTEM_TIME ALL; +COUNT(*) +2 +SHOW CREATE TABLE t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) NOT NULL, + `b` int(11) DEFAULT NULL, + `row_start` bigint(20) unsigned GENERATED ALWAYS AS ROW START INVISIBLE, + `row_end` bigint(20) unsigned GENERATED ALWAYS AS ROW END INVISIBLE, + PRIMARY KEY (`a`,`row_end`), + PERIOD FOR SYSTEM_TIME (`row_start`, `row_end`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +# handles VIRTUAL columns too +CREATE OR REPLACE TABLE t ( +a INT AS (b + 1), +b INT, +row_start BIGINT UNSIGNED AS ROW START INVISIBLE, +row_end BIGINT UNSIGNED AS ROW END INVISIBLE, +PERIOD FOR SYSTEM_TIME(row_start, row_end) +) WITH SYSTEM VERSIONING ENGINE=INNODB; +INSERT INTO t VALUES (DEFAULT, 1); +SELECT c.prtype FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS c +INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t +ON c.table_id=t.table_id +WHERE t.name='test/t' AND c.name='b'; +prtype +50179 +ALTER TABLE t +CHANGE b b INT WITHOUT SYSTEM VERSIONING; +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 +SELECT c.prtype FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS c +INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t +ON c.table_id=t.table_id +WHERE t.name='test/t' AND c.name='b'; +prtype +1027 +UPDATE t SET b=11; +SELECT COUNT(*) FROM t FOR SYSTEM_TIME ALL; +COUNT(*) +1 +DROP TABLE t; +SET @@SYSTEM_VERSIONING_ALTER_HISTORY=ERROR; diff --git a/mysql-test/suite/versioning/r/trx_id_versioning_attribute_persistence.result b/mysql-test/suite/versioning/r/trx_id_versioning_attribute_persistence.result new file mode 100644 index 00000000000..bf555fb2a7d --- /dev/null +++ b/mysql-test/suite/versioning/r/trx_id_versioning_attribute_persistence.result @@ -0,0 +1,86 @@ +CREATE OR REPLACE TABLE t1 ( +a INT, +b INT, +row_start BIGINT UNSIGNED AS ROW START INVISIBLE, +row_end BIGINT UNSIGNED AS ROW END INVISIBLE, +PERIOD FOR SYSTEM_TIME(row_start, row_end) +) WITH SYSTEM VERSIONING ENGINE=INNODB; +CREATE OR REPLACE TABLE t2 ( +a INT WITHOUT SYSTEM VERSIONING, +b INT, +row_start BIGINT UNSIGNED AS ROW START INVISIBLE, +row_end BIGINT UNSIGNED AS ROW END INVISIBLE, +PERIOD FOR SYSTEM_TIME(row_start, row_end) +) WITH SYSTEM VERSIONING ENGINE=INNODB; +INSERT INTO t1 VALUES (1,1); +INSERT INTO t2 VALUES (1,1); +SET @@SYSTEM_VERSIONING_ALTER_HISTORY=KEEP; +# without rebuild +ALTER TABLE t1 +CHANGE a a INT WITHOUT SYSTEM VERSIONING, +ALGORITHM=INSTANT; +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 +ALTER TABLE t2 +CHANGE a a INT WITH SYSTEM VERSIONING, +ADD PRIMARY KEY pk (a), +ALGORITHM=INSTANT; +ERROR 0A000: ALGORITHM=INSTANT is not supported for this operation. Try ALGORITHM=INPLACE +# with rebuild +ALTER TABLE t2 +CHANGE a a INT WITH SYSTEM VERSIONING, +ADD PRIMARY KEY pk (a); +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 +UPDATE t1 SET a=2; +SELECT COUNT(*) FROM t1 FOR SYSTEM_TIME ALL; +COUNT(*) +1 +UPDATE t2 SET a=2; +SELECT COUNT(*) FROM t2 FOR SYSTEM_TIME ALL; +COUNT(*) +2 +DROP TABLE t1, t2; +# rollback ALTER TABLE: nothing should change +CREATE TABLE t ( +a INT, +b INT, +row_start BIGINT UNSIGNED AS ROW START INVISIBLE, +row_end BIGINT UNSIGNED AS ROW END INVISIBLE, +PERIOD FOR SYSTEM_TIME(row_start, row_end) +) WITH SYSTEM VERSIONING ENGINE=INNODB; +INSERT INTO t VALUES (1, 1); +SELECT C.PRTYPE FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS C +JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t ON C.TABLE_ID=t.TABLE_ID +WHERE t.NAME='test/t' AND C.NAME='b'; +PRTYPE +50179 +SET @@SYSTEM_VERSIONING_ALTER_HISTORY=KEEP; +SET @SAVED_DEBUG_DBUG = @@SESSION.DEBUG_DBUG; +SET DEBUG_DBUG='+d,ib_commit_inplace_fail_1'; +ALTER TABLE t +CHANGE b b INT WITHOUT SYSTEM VERSIONING; +ERROR HY000: Internal error: Injected error! +SET DEBUG_DBUG = @SAVED_DEBUG_DBUG; +SELECT C.PRTYPE FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS C +JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t ON C.TABLE_ID=t.TABLE_ID +WHERE t.NAME='test/t' AND C.NAME='b'; +PRTYPE +50179 +SHOW CREATE TABLE t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + `row_start` bigint(20) unsigned GENERATED ALWAYS AS ROW START INVISIBLE, + `row_end` bigint(20) unsigned GENERATED ALWAYS AS ROW END INVISIBLE, + PERIOD FOR SYSTEM_TIME (`row_start`, `row_end`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +SELECT COUNT(*) FROM t FOR SYSTEM_TIME ALL; +COUNT(*) +1 +UPDATE t SET b=11; +SELECT COUNT(*) FROM t FOR SYSTEM_TIME ALL; +COUNT(*) +2 +DROP TABLE t; diff --git a/mysql-test/suite/versioning/t/trx_id.test b/mysql-test/suite/versioning/t/trx_id.test index aab28d1057c..35ba6595440 100644 --- a/mysql-test/suite/versioning/t/trx_id.test +++ b/mysql-test/suite/versioning/t/trx_id.test @@ -1,5 +1,4 @@ -- source include/have_innodb.inc --- source include/not_embedded.inc set default_storage_engine= innodb; @@ -411,3 +410,85 @@ DROP TABLE tts; DROP TABLE ttx; DROP FUNCTION fts; DROP FUNCTION ftx; + +--echo # +--echo # MDEV-16330 Allow instant change of WITH SYSTEM VERSIONING column attribute +--echo # + +SET @@SYSTEM_VERSIONING_ALTER_HISTORY=KEEP; +CREATE TABLE t ( + a INT, + b INT, + row_start BIGINT UNSIGNED AS ROW START INVISIBLE, + row_end BIGINT UNSIGNED AS ROW END INVISIBLE, + PERIOD FOR SYSTEM_TIME(row_start, row_end) +) WITH SYSTEM VERSIONING ENGINE=INNODB; + +INSERT INTO t VALUES (1,1); + +--echo # without table rebuild +SELECT c.prtype FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS c + INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t + ON c.table_id=t.table_id + WHERE t.name='test/t' AND c.name='a'; +--enable_info +ALTER TABLE t + CHANGE a a INT WITHOUT SYSTEM VERSIONING; +--disable_info +SELECT c.prtype FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS c + INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t + ON c.table_id=t.table_id + WHERE t.name='test/t' AND c.name='a'; + +UPDATE t SET a=11; +SELECT COUNT(*) FROM t FOR SYSTEM_TIME ALL; + +--echo # with table rebuild +SELECT c.prtype FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS c + INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t + ON c.table_id=t.table_id + WHERE t.name='test/t' AND c.name='a'; +--enable_info +ALTER TABLE t + CHANGE a a INT WITH SYSTEM VERSIONING, + ADD PRIMARY KEY pk(a); +--disable_info +SELECT c.prtype FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS c + INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t + ON c.table_id=t.table_id + WHERE t.name='test/t' AND c.name='a'; + +UPDATE t SET a=1; +SELECT COUNT(*) FROM t FOR SYSTEM_TIME ALL; + +SHOW CREATE TABLE t; + +-- echo # handles VIRTUAL columns too +CREATE OR REPLACE TABLE t ( + a INT AS (b + 1), + b INT, + row_start BIGINT UNSIGNED AS ROW START INVISIBLE, + row_end BIGINT UNSIGNED AS ROW END INVISIBLE, + PERIOD FOR SYSTEM_TIME(row_start, row_end) +) WITH SYSTEM VERSIONING ENGINE=INNODB; + +INSERT INTO t VALUES (DEFAULT, 1); + +SELECT c.prtype FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS c + INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t + ON c.table_id=t.table_id + WHERE t.name='test/t' AND c.name='b'; +--enable_info +ALTER TABLE t + CHANGE b b INT WITHOUT SYSTEM VERSIONING; +--disable_info +SELECT c.prtype FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS c + INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t + ON c.table_id=t.table_id + WHERE t.name='test/t' AND c.name='b'; + +UPDATE t SET b=11; +SELECT COUNT(*) FROM t FOR SYSTEM_TIME ALL; + +DROP TABLE t; +SET @@SYSTEM_VERSIONING_ALTER_HISTORY=ERROR; diff --git a/mysql-test/suite/versioning/t/trx_id_versioning_attribute_persistence.test b/mysql-test/suite/versioning/t/trx_id_versioning_attribute_persistence.test new file mode 100644 index 00000000000..4e92ee247e4 --- /dev/null +++ b/mysql-test/suite/versioning/t/trx_id_versioning_attribute_persistence.test @@ -0,0 +1,87 @@ +-- source include/have_innodb.inc +-- source include/have_debug.inc + +CREATE OR REPLACE TABLE t1 ( + a INT, + b INT, + row_start BIGINT UNSIGNED AS ROW START INVISIBLE, + row_end BIGINT UNSIGNED AS ROW END INVISIBLE, + PERIOD FOR SYSTEM_TIME(row_start, row_end) +) WITH SYSTEM VERSIONING ENGINE=INNODB; + +CREATE OR REPLACE TABLE t2 ( + a INT WITHOUT SYSTEM VERSIONING, + b INT, + row_start BIGINT UNSIGNED AS ROW START INVISIBLE, + row_end BIGINT UNSIGNED AS ROW END INVISIBLE, + PERIOD FOR SYSTEM_TIME(row_start, row_end) +) WITH SYSTEM VERSIONING ENGINE=INNODB; + +INSERT INTO t1 VALUES (1,1); +INSERT INTO t2 VALUES (1,1); + +SET @@SYSTEM_VERSIONING_ALTER_HISTORY=KEEP; + +--enable_info +--echo # without rebuild +ALTER TABLE t1 + CHANGE a a INT WITHOUT SYSTEM VERSIONING, + ALGORITHM=INSTANT; + +--error ER_ALTER_OPERATION_NOT_SUPPORTED +ALTER TABLE t2 + CHANGE a a INT WITH SYSTEM VERSIONING, + ADD PRIMARY KEY pk (a), + ALGORITHM=INSTANT; + +--echo # with rebuild +ALTER TABLE t2 + CHANGE a a INT WITH SYSTEM VERSIONING, + ADD PRIMARY KEY pk (a); +--disable_info + +--source include/restart_mysqld.inc + +UPDATE t1 SET a=2; +SELECT COUNT(*) FROM t1 FOR SYSTEM_TIME ALL; + +UPDATE t2 SET a=2; +SELECT COUNT(*) FROM t2 FOR SYSTEM_TIME ALL; + +DROP TABLE t1, t2; + +--echo # rollback ALTER TABLE: nothing should change +CREATE TABLE t ( + a INT, + b INT, + row_start BIGINT UNSIGNED AS ROW START INVISIBLE, + row_end BIGINT UNSIGNED AS ROW END INVISIBLE, + PERIOD FOR SYSTEM_TIME(row_start, row_end) +) WITH SYSTEM VERSIONING ENGINE=INNODB; + +INSERT INTO t VALUES (1, 1); + +SELECT C.PRTYPE FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS C + JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t ON C.TABLE_ID=t.TABLE_ID + WHERE t.NAME='test/t' AND C.NAME='b'; + +SET @@SYSTEM_VERSIONING_ALTER_HISTORY=KEEP; + +SET @SAVED_DEBUG_DBUG = @@SESSION.DEBUG_DBUG; +SET DEBUG_DBUG='+d,ib_commit_inplace_fail_1'; +--error ER_INTERNAL_ERROR +ALTER TABLE t + CHANGE b b INT WITHOUT SYSTEM VERSIONING; +SET DEBUG_DBUG = @SAVED_DEBUG_DBUG; + +SELECT C.PRTYPE FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS C + JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t ON C.TABLE_ID=t.TABLE_ID + WHERE t.NAME='test/t' AND C.NAME='b'; + +SHOW CREATE TABLE t; + +SELECT COUNT(*) FROM t FOR SYSTEM_TIME ALL; +UPDATE t SET b=11; +SELECT COUNT(*) FROM t FOR SYSTEM_TIME ALL; + +DROP TABLE t; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 2b0c4439146..ac65fbb90c2 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -6535,15 +6535,15 @@ static bool fill_alter_inplace_info(THD *thd, ALTER_DROP_INDEX are replaced with versions that have higher granuality. */ - ha_alter_info->handler_flags|= (alter_info->flags & - ~(ALTER_ADD_INDEX | - ALTER_DROP_INDEX | - ALTER_PARSER_ADD_COLUMN | - ALTER_PARSER_DROP_COLUMN | - ALTER_COLUMN_ORDER | - ALTER_RENAME_COLUMN | - ALTER_CHANGE_COLUMN | - ALTER_COLUMN_UNVERSIONED)); + alter_table_operations flags_to_remove= + ALTER_ADD_INDEX | ALTER_DROP_INDEX | ALTER_PARSER_ADD_COLUMN | + ALTER_PARSER_DROP_COLUMN | ALTER_COLUMN_ORDER | ALTER_RENAME_COLUMN | + ALTER_CHANGE_COLUMN; + + if (!table->file->native_versioned()) + flags_to_remove|= ALTER_COLUMN_UNVERSIONED; + + ha_alter_info->handler_flags|= (alter_info->flags & ~flags_to_remove); /* Comparing new and old default values of column is cumbersome. So instead of using such a comparison for detecting if default diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 08963ceff3e..435b2b2403f 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -87,7 +87,6 @@ static const alter_table_operations INNOBASE_ALTER_REBUILD /* | ALTER_STORED_COLUMN_TYPE */ - | ALTER_COLUMN_UNVERSIONED | ALTER_ADD_SYSTEM_VERSIONING | ALTER_DROP_SYSTEM_VERSIONING ; @@ -128,6 +127,7 @@ static const alter_table_operations INNOBASE_ALTER_INSTANT | ALTER_ADD_VIRTUAL_COLUMN | INNOBASE_FOREIGN_OPERATIONS | ALTER_COLUMN_EQUAL_PACK_LENGTH + | ALTER_COLUMN_UNVERSIONED | ALTER_DROP_VIRTUAL_COLUMN; struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx @@ -8433,6 +8433,188 @@ innobase_update_foreign_cache( DBUG_RETURN(err); } +/** Changes SYS_COLUMNS.PRTYPE for one column. +@param[in,out] trx transaction +@param[in] table_name table name +@param[in] tableid table ID as in SYS_TABLES +@param[in] pos column position +@param[in] prtype new precise type +@return boolean flag +@retval true on failure +@retval false on success */ +static +bool +change_field_versioning_try( + trx_t* trx, + const char* table_name, + const table_id_t tableid, + const ulint pos, + const ulint prtype) +{ + DBUG_ENTER("change_field_versioning_try"); + + pars_info_t* info = pars_info_create(); + + pars_info_add_int4_literal(info, "prtype", prtype); + pars_info_add_ull_literal(info,"tableid", tableid); + pars_info_add_int4_literal(info, "pos", pos); + + dberr_t error = que_eval_sql(info, + "PROCEDURE CHANGE_COLUMN_MTYPE () IS\n" + "BEGIN\n" + "UPDATE SYS_COLUMNS SET PRTYPE=:prtype\n" + "WHERE TABLE_ID=:tableid AND POS=:pos;\n" + "END;\n", + false, trx); + + if (error != DB_SUCCESS) { + my_error_innodb(error, table_name, 0); + trx->error_state = DB_SUCCESS; + trx->op_info = ""; + DBUG_RETURN(true); + } + + DBUG_RETURN(false); +} + +/** Changes fields WITH/WITHOUT SYSTEM VERSIONING property in SYS_COLUMNS. +@param[in] ha_alter_info alter info +@param[in] ctx alter inplace context +@param[in] trx transaction +@param[in] table old table +@return boolean flag +@retval true on failure +@retval false on success */ +static +bool +change_fields_versioning_try( + const Alter_inplace_info* ha_alter_info, + const ha_innobase_inplace_ctx* ctx, + trx_t* trx, + const TABLE* table) +{ + DBUG_ENTER("change_fields_versioning_try"); + + DBUG_ASSERT(ha_alter_info); + DBUG_ASSERT(ctx); + + if (!(ha_alter_info->handler_flags & ALTER_COLUMN_UNVERSIONED)){ + DBUG_RETURN(false); + } + + uint virtual_count = 0; + + List_iterator_fast<Create_field> it( + ha_alter_info->alter_info->create_list); + + for (uint i = 0; i < table->s->fields; i++) { + const Field* field = table->field[i]; + + if (innobase_is_v_fld(field)) { + virtual_count++; + continue; + } + + const Create_field* create_field = NULL; + while (const Create_field* cf = it++) { + if (cf->field == field) { + create_field = cf; + break; + } + } + it.rewind(); + DBUG_ASSERT(create_field); + + if (create_field->versioning + == Column_definition::VERSIONING_NOT_SET) { + continue; + } + + const dict_table_t* new_table = ctx->new_table; + ulint pos = i - virtual_count; + const dict_col_t* col = dict_table_get_nth_col(new_table, pos); + + DBUG_ASSERT(!col->vers_sys_start()); + DBUG_ASSERT(!col->vers_sys_end()); + + ulint new_prtype + = create_field->versioning + == Column_definition::WITHOUT_VERSIONING + ? col->prtype & ~DATA_VERSIONED + : col->prtype | DATA_VERSIONED; + + if (change_field_versioning_try(trx, table->s->table_name.str, + new_table->id, pos, + new_prtype)) { + DBUG_RETURN(true); + } + } + + DBUG_RETURN(false); +} + +/** Changes WITH/WITHOUT SYSTEM VERSIONING for fields +in the data dictionary cache. +@param ha_alter_info Data used during in-place alter +@param ctx In-place ALTER TABLE context +@param table MySQL table as it is before the ALTER operation */ +static +void +change_fields_versioning_cache( + Alter_inplace_info* ha_alter_info, + const ha_innobase_inplace_ctx* ctx, + const TABLE* table) +{ + DBUG_ENTER("change_fields_versioning"); + + DBUG_ASSERT(ha_alter_info); + DBUG_ASSERT(ctx); + DBUG_ASSERT(ha_alter_info->handler_flags & ALTER_COLUMN_UNVERSIONED); + + uint virtual_count = 0; + + List_iterator_fast<Create_field> it( + ha_alter_info->alter_info->create_list); + + for (uint i = 0; i < table->s->fields; i++) { + const Field* field = table->field[i]; + + if (innobase_is_v_fld(field)) { + virtual_count++; + continue; + } + + const Create_field* create_field = NULL; + while (const Create_field* cf = it++) { + if (cf->field == field) { + create_field = cf; + break; + } + } + it.rewind(); + DBUG_ASSERT(create_field); + + dict_col_t* col + = dict_table_get_nth_col(ctx->new_table, i - virtual_count); + + if (create_field->versioning + == Column_definition::WITHOUT_VERSIONING) { + + DBUG_ASSERT(!col->vers_sys_start()); + DBUG_ASSERT(!col->vers_sys_end()); + col->prtype &= ~DATA_VERSIONED; + } else if (create_field->versioning + == Column_definition::WITH_VERSIONING) { + + DBUG_ASSERT(!col->vers_sys_start()); + DBUG_ASSERT(!col->vers_sys_end()); + col->prtype |= DATA_VERSIONED; + } + } + + DBUG_VOID_RETURN; +} + /** Commit the changes made during prepare_inplace_alter_table() and inplace_alter_table() inside the data dictionary tables, when rebuilding the table. @@ -8742,6 +8924,10 @@ commit_try_norebuild( DBUG_RETURN(true); } + if (change_fields_versioning_try(ha_alter_info, ctx, trx, old_table)) { + DBUG_RETURN(true); + } + dberr_t error; /* We altered the table in place. Mark the indexes as committed. */ @@ -8947,6 +9133,10 @@ commit_cache_norebuild( ha_alter_info, table, ctx->new_table); } + if (ha_alter_info->handler_flags & ALTER_COLUMN_UNVERSIONED) { + change_fields_versioning_cache(ha_alter_info, ctx, table); + } + #ifdef MYSQL_RENAME_INDEX rename_indexes_in_cache(ctx, ha_alter_info); #endif |