From a17b8f707fb6e3bb7f665ea7617daf310f3a3d6b Mon Sep 17 00:00:00 2001 From: kevg Date: Wed, 7 Dec 2016 15:15:47 +0300 Subject: [PATCH] 0.5: basic support for ALTER TABLE for InnoDB and other storage engines [closes #57] --- mysql-test/suite/versioning/r/alter.result | 364 ++++++++++++++++++++ mysql-test/suite/versioning/r/create.result | 38 +- mysql-test/suite/versioning/t/alter.test | 170 +++++++++ mysql-test/suite/versioning/t/create.test | 35 ++ sql/field.h | 1 + sql/handler.cc | 300 ++++++++++++---- sql/handler.h | 31 +- sql/sql_table.cc | 44 +++ sql/sql_yacc.yy | 37 +- sql/table.cc | 37 +- storage/innobase/handler/handler0alter.cc | 18 + 11 files changed, 961 insertions(+), 114 deletions(-) create mode 100644 mysql-test/suite/versioning/r/alter.result create mode 100644 mysql-test/suite/versioning/t/alter.test diff --git a/mysql-test/suite/versioning/r/alter.result b/mysql-test/suite/versioning/r/alter.result new file mode 100644 index 00000000000..5011302f151 --- /dev/null +++ b/mysql-test/suite/versioning/r/alter.result @@ -0,0 +1,364 @@ +create table t( +a int +); +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +alter table t without system versioning; +ERROR HY000: Wrong parameters for versioned table `t`: table is not versioned +alter table t with system versioning without system versioning; +ERROR HY000: Wrong parameters for versioned table `t`: Versioning specified more than once for the same table +alter table t with system versioning; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +alter table t without system versioning; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +alter table t +add column trx_start bigint(20) unsigned generated always as row start, +add column trx_end bigint(20) unsigned generated always as row end, +add period for system_time(trx_start, trx_end), +with system versioning; +ERROR HY000: `trx_start` must be of type `TIMESTAMP(6)` for versioned table `t` +alter table t +add column trx_start timestamp generated always as row start, +add column trx_end timestamp generated always as row end, +add period for system_time(trx_start, trx_end), +with system versioning; +ERROR HY000: `trx_start` must be of type `TIMESTAMP(6)` for versioned table `t` +alter table t +add column trx_start timestamp(6) not null generated always as row start, +add column trx_end timestamp(6) not null generated always as row end, +add period for system_time(trx_start, trx_end), +with system versioning; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'generated always as row start, +add column trx_end timestamp(6) not null generate' at line 2 +alter table t +add column trx_start timestamp(6) generated always as row start, +add column trx_end timestamp(6) generated always as row end, +add period for system_time(trx_start, trx_end), +with system versioning; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `trx_start` timestamp(6) NOT NULL GENERATED ALWAYS AS ROW START, + `trx_end` timestamp(6) NOT NULL GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`trx_start`, `trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +alter table t without system versioning; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +alter table t with system versioning; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +alter table t add column b int; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +alter table t add column c int; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +alter table t add column d int first; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `d` int(11) DEFAULT NULL, + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +alter table t add column e int after d; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `d` int(11) DEFAULT NULL, + `e` int(11) DEFAULT NULL, + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +alter table t add column f int after sys_trx_start; +ERROR HY000: Wrong parameters for versioned table `t`: Can not put new field after system versioning field +alter table t add column f int after sys_trx_end; +ERROR HY000: Wrong parameters for versioned table `t`: Can not put new field after system versioning field +alter table t drop column a; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `d` int(11) DEFAULT NULL, + `e` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +alter table t drop column sys_trx_start; +ERROR HY000: Wrong parameters for versioned table `t`: Can not drop system versioning field +alter table t drop column sys_trx_end; +ERROR HY000: Wrong parameters for versioned table `t`: Can not drop system versioning field +create or replace table t( +a int +); +insert into t values(1); +alter table t with system versioning; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +insert into t values(2); +select * from t for system_time all; +a +1 +2 +select * from t; +a +1 +2 +update t set a=3 where a=1; +select * from t; +a +3 +2 +select * from t for system_time all; +a +3 +2 +1 +select sys_trx_start from t where a=3 into @tm; +alter table t add column b int; +select @tm=sys_trx_start from t where a=3; +@tm=sys_trx_start +1 +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +select * from t; +a b +3 NULL +2 NULL +select * from t for system_time all; +a b +3 NULL +2 NULL +1 NULL +alter table t without system versioning; +select * from t; +a b +3 NULL +2 NULL +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +alter table t modify a int with system versioning; +ERROR HY000: Wrong parameters for versioned table `t`: Can not change fields versioning mode in a non-versioned table +alter table t modify a int with system versioning with system versioning; +ERROR HY000: Wrong parameters for versioned table `t`: Versioning specified more than once for the same field +alter table t modify a int with system versioning without system versioning; +ERROR HY000: Wrong parameters for versioned table `t`: Versioning specified more than once for the same field +alter table t with system versioning; +alter table t modify a int without system versioning; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL WITHOUT SYSTEM VERSIONING, + `b` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +alter table t modify a int with system versioning; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + `sys_trx_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `sys_trx_end` timestamp(6) GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +set @@session.time_zone='+00:00'; +select ifnull(max(trx_id), 0) into @start_trx_id from information_schema.innodb_vtq; +create procedure if not exists verify_vtq() +begin +set @i= 0; +select +@i:= @i + 1 as No, +trx_id > 0 as A, +commit_id >= trx_id as B, +begin_ts > '1-1-1 0:0:0' as C, +commit_ts > begin_ts as D +from information_schema.innodb_vtq +where trx_id > @start_trx_id; +select ifnull(max(trx_id), 0) +into @start_trx_id +from information_schema.innodb_vtq; +end~~ +create or replace table t( +a int +) engine=innodb; +insert into t values(1); +select * from t; +a +1 +alter table t +add column trx_start timestamp(6) generated always as row start, +add column trx_end timestamp(6) generated always as row end, +add period for system_time(trx_start, trx_end), +with system versioning; +ERROR HY000: `trx_start` must be of type `BIGINT(20) UNSIGNED` for versioned table `t` +alter table t +add column trx_start bigint(20) unsigned generated always as row start, +add column trx_end bigint(20) unsigned generated always as row end, +add period for system_time(trx_start, trx_end), +with system versioning; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `trx_start` bigint(20) unsigned GENERATED ALWAYS AS ROW START, + `trx_end` bigint(20) unsigned GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`trx_start`, `trx_end`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +alter table t without system versioning; +alter table t with system versioning, algorithm=inplace; +ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY. +alter table t with system versioning, algorithm=copy; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` bigint(20) unsigned GENERATED ALWAYS AS ROW START, + `sys_trx_end` bigint(20) unsigned GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +update t set a=2; +select * from t for system_time all; +a +2 +1 +alter table t add column b int, algorithm=copy; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + `sys_trx_start` bigint(20) unsigned GENERATED ALWAYS AS ROW START, + `sys_trx_end` bigint(20) unsigned GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +select * from t; +a b +2 NULL +1 NULL +alter table t drop column b, algorithm=copy; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` bigint(20) unsigned GENERATED ALWAYS AS ROW START, + `sys_trx_end` bigint(20) unsigned GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +select * from t for system_time all; +a +2 +1 +alter table t add column b int, algorithm=inplace; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + `sys_trx_start` bigint(20) unsigned GENERATED ALWAYS AS ROW START, + `sys_trx_end` bigint(20) unsigned GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +select * from t; +a b +2 NULL +1 NULL +alter table t drop column b, algorithm=inplace; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + `sys_trx_start` bigint(20) unsigned GENERATED ALWAYS AS ROW START, + `sys_trx_end` bigint(20) unsigned GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +select * from t for system_time all; +a +2 +1 +alter table t without system versioning, algorithm=inplace; +ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY. +alter table t without system versioning, algorithm=copy; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +call verify_vtq; +No A B C D +1 1 1 1 1 +2 1 1 1 1 +3 1 1 1 1 +4 1 1 1 1 +5 1 1 1 1 +drop table t; +drop procedure verify_vtq; diff --git a/mysql-test/suite/versioning/r/create.result b/mysql-test/suite/versioning/r/create.result index 8f69b9c2fac..be9f9ae7ea9 100644 --- a/mysql-test/suite/versioning/r/create.result +++ b/mysql-test/suite/versioning/r/create.result @@ -88,35 +88,35 @@ Sys_start int generated always as row start, Sys_end timestamp(6) generated always as row end, period for system_time (Sys_start, Sys_end) ) with system versioning; -ERROR HY000: `Sys_start` must be of type `TIMESTAMP` for versioned table `t1` +ERROR HY000: `Sys_start` must be of type `TIMESTAMP(6)` for versioned table `t1` create or replace table t1 ( XNo int unsigned, Sys_start timestamp(6) generated always as row start, Sys_end int generated always as row end, period for system_time (Sys_start, Sys_end) ) with system versioning; -ERROR HY000: `Sys_end` must be of type `TIMESTAMP` for versioned table `t1` +ERROR HY000: `Sys_end` must be of type `TIMESTAMP(6)` for versioned table `t1` create or replace table t1 ( XNo int unsigned, Sys_start timestamp(6) generated always as row start, Sys_end bigint generated always as row end, period for system_time (Sys_start, Sys_end) ) with system versioning engine innodb; -ERROR HY000: `Sys_start` must be of type `BIGINT UNSIGNED` for versioned table `t1` +ERROR HY000: `Sys_start` must be of type `BIGINT(20) UNSIGNED` for versioned table `t1` create or replace table t1 ( XNo int unsigned, Sys_start bigint generated always as row start, Sys_end bigint generated always as row end, period for system_time (Sys_start, Sys_end) ) with system versioning engine innodb; -ERROR HY000: `Sys_start` must be of type `BIGINT UNSIGNED` for versioned table `t1` +ERROR HY000: `Sys_start` must be of type `BIGINT(20) UNSIGNED` for versioned table `t1` create or replace table t1 ( XNo int unsigned, Sys_start bigint unsigned generated always as row start, Sys_end bigint generated always as row end, period for system_time (Sys_start, Sys_end) ) with system versioning engine innodb; -ERROR HY000: `Sys_end` must be of type `BIGINT UNSIGNED` for versioned table `t1` +ERROR HY000: `Sys_end` must be of type `BIGINT(20) UNSIGNED` for versioned table `t1` create or replace table t1 ( A int with system versioning, B int @@ -195,4 +195,32 @@ create or replace table t1 ( A int without system versioning ) with system versioning; ERROR HY000: Wrong parameters for versioned table `t1`: versioned fields missing +create or replace table t1 ( +A int without system versioning with system versioning +); +ERROR HY000: Wrong parameters for versioned table `t1`: Versioning specified more than once for the same field +create or replace table t1 ( +A int with system versioning without system versioning +); +ERROR HY000: Wrong parameters for versioned table `t1`: Versioning specified more than once for the same field +create table t( +a int +) without system versioning; +ERROR HY000: Wrong parameters for versioned table `t`: 'WITHOUT SYSTEM VERSIONING' is not allowed +create or replace table t1 ( +A int +) without system versioning with system versioning; +ERROR HY000: Wrong parameters for versioned table `t1`: Versioning specified more than once for the same table +create or replace table t1 ( +A int +) with system versioning without system versioning; +ERROR HY000: Wrong parameters for versioned table `t1`: Versioning specified more than once for the same table +create or replace table t1 ( +A int +) with system versioning with system versioning; +ERROR HY000: Wrong parameters for versioned table `t1`: Versioning specified more than once for the same table +create or replace table t1 ( +A int +) without system versioning without system versioning; +ERROR HY000: Wrong parameters for versioned table `t1`: Versioning specified more than once for the same table drop table t1; diff --git a/mysql-test/suite/versioning/t/alter.test b/mysql-test/suite/versioning/t/alter.test new file mode 100644 index 00000000000..2fdd59979dc --- /dev/null +++ b/mysql-test/suite/versioning/t/alter.test @@ -0,0 +1,170 @@ +create table t( + a int +); +show create table t; +--error ER_VERS_WRONG_PARAMS +alter table t without system versioning; +--error ER_VERS_WRONG_PARAMS +alter table t with system versioning without system versioning; + +alter table t with system versioning; +show create table t; + +alter table t without system versioning; +show create table t; + +--error ER_VERS_FIELD_WRONG_TYPE +alter table t + add column trx_start bigint(20) unsigned generated always as row start, + add column trx_end bigint(20) unsigned generated always as row end, + add period for system_time(trx_start, trx_end), + with system versioning; + +--error ER_VERS_FIELD_WRONG_TYPE +alter table t + add column trx_start timestamp generated always as row start, + add column trx_end timestamp generated always as row end, + add period for system_time(trx_start, trx_end), + with system versioning; + +--error ER_PARSE_ERROR +alter table t + add column trx_start timestamp(6) not null generated always as row start, + add column trx_end timestamp(6) not null generated always as row end, + add period for system_time(trx_start, trx_end), + with system versioning; + +alter table t + add column trx_start timestamp(6) generated always as row start, + add column trx_end timestamp(6) generated always as row end, + add period for system_time(trx_start, trx_end), + with system versioning; +show create table t; + +alter table t without system versioning; +show create table t; + +alter table t with system versioning; +show create table t; + +alter table t add column b int; +show create table t; + +alter table t add column c int; +show create table t; + +alter table t add column d int first; +show create table t; + +alter table t add column e int after d; +show create table t; + +--error ER_VERS_WRONG_PARAMS +alter table t add column f int after sys_trx_start; +--error ER_VERS_WRONG_PARAMS +alter table t add column f int after sys_trx_end; + +alter table t drop column a; +show create table t; + +--error ER_VERS_WRONG_PARAMS +alter table t drop column sys_trx_start; +--error ER_VERS_WRONG_PARAMS +alter table t drop column sys_trx_end; + +create or replace table t( + a int +); +insert into t values(1); +alter table t with system versioning; +show create table t; +insert into t values(2); +select * from t for system_time all; +select * from t; + +update t set a=3 where a=1; +select * from t; +select * from t for system_time all; +select sys_trx_start from t where a=3 into @tm; +alter table t add column b int; +select @tm=sys_trx_start from t where a=3; +show create table t; +select * from t; +select * from t for system_time all; + +alter table t without system versioning; +select * from t; +show create table t; + +--error ER_VERS_WRONG_PARAMS +alter table t modify a int with system versioning; +--error ER_VERS_WRONG_PARAMS +alter table t modify a int with system versioning with system versioning; +--error ER_VERS_WRONG_PARAMS +alter table t modify a int with system versioning without system versioning; + +alter table t with system versioning; + +alter table t modify a int without system versioning; +show create table t; + +alter table t modify a int with system versioning; +show create table t; + +-- source suite/versioning/common.inc +create or replace table t( + a int +) engine=innodb; + +insert into t values(1); +select * from t; + +--error ER_VERS_FIELD_WRONG_TYPE +alter table t + add column trx_start timestamp(6) generated always as row start, + add column trx_end timestamp(6) generated always as row end, + add period for system_time(trx_start, trx_end), + with system versioning; + +alter table t + add column trx_start bigint(20) unsigned generated always as row start, + add column trx_end bigint(20) unsigned generated always as row end, + add period for system_time(trx_start, trx_end), + with system versioning; +show create table t; +alter table t without system versioning; + +--error ER_ALTER_OPERATION_NOT_SUPPORTED +alter table t with system versioning, algorithm=inplace; + +alter table t with system versioning, algorithm=copy; +show create table t; + +update t set a=2; +select * from t for system_time all; + +alter table t add column b int, algorithm=copy; +show create table t; +select * from t; + +alter table t drop column b, algorithm=copy; +show create table t; +select * from t for system_time all; + +alter table t add column b int, algorithm=inplace; +show create table t; +select * from t; + +alter table t drop column b, algorithm=inplace; +show create table t; +select * from t for system_time all; + +--error ER_ALTER_OPERATION_NOT_SUPPORTED +alter table t without system versioning, algorithm=inplace; + +alter table t without system versioning, algorithm=copy; +show create table t; + +call verify_vtq; +drop table t; +drop procedure verify_vtq; diff --git a/mysql-test/suite/versioning/t/create.test b/mysql-test/suite/versioning/t/create.test index 4310b57d90b..db07f5b2521 100644 --- a/mysql-test/suite/versioning/t/create.test +++ b/mysql-test/suite/versioning/t/create.test @@ -169,4 +169,39 @@ create or replace table t1 ( A int without system versioning ) with system versioning; +--error ER_VERS_WRONG_PARAMS +create or replace table t1 ( + A int without system versioning with system versioning +); + +--error ER_VERS_WRONG_PARAMS +create or replace table t1 ( + A int with system versioning without system versioning +); + +--error ER_VERS_WRONG_PARAMS +create table t( + a int +) without system versioning; + +--error ER_VERS_WRONG_PARAMS +create or replace table t1 ( + A int +) without system versioning with system versioning; + +--error ER_VERS_WRONG_PARAMS +create or replace table t1 ( + A int +) with system versioning without system versioning; + +--error ER_VERS_WRONG_PARAMS +create or replace table t1 ( + A int +) with system versioning with system versioning; + +--error ER_VERS_WRONG_PARAMS +create or replace table t1 ( + A int +) without system versioning without system versioning; + drop table t1; diff --git a/sql/field.h b/sql/field.h index a479ec569ff..ab480b84fda 100644 --- a/sql/field.h +++ b/sql/field.h @@ -4208,6 +4208,7 @@ public: uint from_length,to_length; Field *from_field,*to_field; String tmp; // For items + MYSQL_TIME now; // Used for sys_trx_start Copy_field() {} ~Copy_field() {} diff --git a/sql/handler.cc b/sql/handler.cc index 14b751c0628..f9391729e99 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -6553,6 +6553,18 @@ int del_global_index_stat(THD *thd, TABLE* table, KEY* key_info) DBUG_RETURN(res); } +bool Vers_parse_info::is_trx_start(const char *name) const +{ + DBUG_ASSERT(name); + return generated_as_row.start && + !strcmp(generated_as_row.start->c_ptr(), name); +} +bool Vers_parse_info::is_trx_end(const char *name) const +{ + DBUG_ASSERT(name); + return generated_as_row.end && !strcmp(generated_as_row.end->c_ptr(), name); +} + static bool create_string(MEM_ROOT *mem_root, String **s, const char *value) { *s= new (mem_root) String(value, system_charset_info); @@ -6581,7 +6593,7 @@ static bool create_sys_trx_field(THD *thd, const char *field_name, else { f->sql_type= MYSQL_TYPE_TIMESTAMP2; - f->length= 6; + f->length= MAX_DATETIME_PRECISION; } if (f->check(thd)) @@ -6594,37 +6606,17 @@ static bool create_sys_trx_field(THD *thd, const char *field_name, return false; } -bool Vers_parse_info::fix_implicit( - THD *thd, - Alter_info *alter_info, - bool integer_fields) +bool Vers_parse_info::fix_implicit(THD *thd, Alter_info *alter_info, + bool integer_fields) { - List_iterator it(alter_info->create_list); - while (Create_field *f= it++) - { - const char *name= f->field_name; - size_t len= strlen(name); - if (generated_as_row.start && - !strncmp(name, generated_as_row.start->c_ptr(), len)) - continue; - if (generated_as_row.end && - !strncmp(name, generated_as_row.end->c_ptr(), len)) - continue; - - if ((f->versioning == Column_definition::VERSIONING_NOT_SET && - !declared_system_versioning) || - f->versioning == Column_definition::WITHOUT_VERSIONING) - { - f->flags|= VERS_OPTIMIZED_UPDATE_FLAG; - } - } - // If user specified some of these he must specify the others too. Do nothing. if (generated_as_row.start || generated_as_row.end || period_for_system_time.start || period_for_system_time.end) return false; - return create_sys_trx_field(thd,"sys_trx_start", alter_info, + alter_info->flags|= Alter_info::ALTER_ADD_COLUMN; + + return create_sys_trx_field(thd, "sys_trx_start", alter_info, &generated_as_row.start, VERS_SYS_START_FLAG, integer_fields) || create_sys_trx_field(thd, "sys_trx_end", alter_info, @@ -6642,92 +6634,256 @@ bool Vers_parse_info::check_and_fix_implicit( bool integer_fields, const char* table_name) { - if (!( - has_versioned_fields || - has_unversioned_fields || - declared_system_versioning || - period_for_system_time.start || - period_for_system_time.end || - generated_as_row.start || - generated_as_row.end)) - { + if (!need_to_check()) return false; + + if (declared_without_system_versioning) + { + my_error(ER_VERS_WRONG_PARAMS, MYF(0), table_name, + "'WITHOUT SYSTEM VERSIONING' is not allowed"); + return true; } - if (!declared_system_versioning && !has_versioned_fields) + if (!declared_with_system_versioning && !has_versioned_fields) { - my_error(ER_VERS_WRONG_PARAMS, MYF(0), table_name, "'WITH SYSTEM VERSIONING' missing"); + my_error(ER_VERS_WRONG_PARAMS, MYF(0), table_name, + "'WITH SYSTEM VERSIONING' missing"); return true; } + List_iterator it(alter_info->create_list); + while (Create_field *f= it++) + { + if (is_trx_start(f->field_name) || is_trx_end(f->field_name)) + continue; + + if ((f->versioning == Column_definition::VERSIONING_NOT_SET && + !declared_with_system_versioning) || + f->versioning == Column_definition::WITHOUT_VERSIONING) + { + f->flags|= VERS_OPTIMIZED_UPDATE_FLAG; + } + } + if (fix_implicit(thd, alter_info, integer_fields)) return true; + int not_set= 0; + int with= 0; + it.rewind(); + while (const Create_field *f= it++) { - int not_set= 0; - int with= 0; - List_iterator it(alter_info->create_list); - while (const Create_field *f= it++) - { - const char *name= f->field_name; - size_t len= strlen(name); - if (generated_as_row.start && - !strncmp(name, generated_as_row.start->c_ptr(), len)) - continue; - if (generated_as_row.end && - !strncmp(name, generated_as_row.end->c_ptr(), len)) - continue; + if (is_trx_start(f->field_name) || is_trx_end(f->field_name)) + continue; - if (f->versioning == Column_definition::VERSIONING_NOT_SET) - not_set++; - else if (f->versioning == Column_definition::WITH_VERSIONING) - with++; - } - - bool table_with_system_versioning= - declared_system_versioning || generated_as_row.start || - generated_as_row.end || period_for_system_time.start || - period_for_system_time.end; - - if ((table_with_system_versioning && not_set == 0 && with == 0) || - (!table_with_system_versioning && with == 0)) - { - my_error(ER_VERS_WRONG_PARAMS, MYF(0), table_name, "versioned fields missing"); - return true; - } + if (f->versioning == Column_definition::VERSIONING_NOT_SET) + not_set++; + else if (f->versioning == Column_definition::WITH_VERSIONING) + with++; } + bool table_with_system_versioning= + generated_as_row.start || generated_as_row.end || + period_for_system_time.start || period_for_system_time.end; + + if (with == 0 && (not_set == 0 || !table_with_system_versioning)) + { + my_error(ER_VERS_WRONG_PARAMS, MYF(0), table_name, + "versioned fields missing"); + return true; + } + + return check_with_conditions(table_name) || + check_generated_type(table_name, alter_info, integer_fields); +} + +static bool add_field_to_drop_list(THD *thd, Alter_info *alter_info, + Field *field) +{ + DBUG_ASSERT(field); + DBUG_ASSERT(field->field_name); + Alter_drop *ad= new (thd->mem_root) + Alter_drop(Alter_drop::COLUMN, field->field_name, false); + return !ad || alter_info->drop_list.push_back(ad, thd->mem_root); +} + +bool Vers_parse_info::check_and_fix_alter(THD *thd, Alter_info *alter_info, + HA_CREATE_INFO *create_info, + TABLE_SHARE *share) +{ + bool integer_fields= + create_info->db_type->flags & HTON_SUPPORTS_SYS_VERSIONING; + const char *table_name= share->table_name.str; + + if (!need_to_check() && !share->versioned) + return false; + + if (declared_without_system_versioning) + { + if (!share->versioned) + { + my_error(ER_VERS_WRONG_PARAMS, MYF(0), table_name, + "table is not versioned"); + return true; + } + + if (add_field_to_drop_list(thd, alter_info, share->vers_start_field()) || + add_field_to_drop_list(thd, alter_info, share->vers_end_field())) + return true; + + alter_info->flags|= Alter_info::ALTER_DROP_COLUMN; + return false; + } + + if ((has_versioned_fields || has_unversioned_fields) && !share->versioned) + { + my_error(ER_VERS_WRONG_PARAMS, MYF(0), table_name, + "Can not change fields versioning mode in a non-versioned table"); + return true; + } + + if (share->versioned) + { + // copy info from existing table + create_info->options|= HA_VERSIONED_TABLE; + + DBUG_ASSERT(share->vers_start_field() && share->vers_end_field()); + const char *start= share->vers_start_field()->field_name; + const char *end= share->vers_end_field()->field_name; + DBUG_ASSERT(start && end); + + if (create_string(thd->mem_root, &generated_as_row.start, start) || + create_string(thd->mem_root, &generated_as_row.end, end) || + create_string(thd->mem_root, &period_for_system_time.start, start) || + create_string(thd->mem_root, &period_for_system_time.end, end)) + return true; + + if (alter_info->create_list.elements) + { + DBUG_ASSERT(share->fields > 2); + const char *after_this= share->field[share->fields - 3]->field_name; + List_iterator it(alter_info->create_list); + while (Create_field *f= it++) + { + if (f->versioning == Column_definition::WITHOUT_VERSIONING) + f->flags|= VERS_OPTIMIZED_UPDATE_FLAG; + + if (f->change) + continue; + + if (f->after) + { + if (is_trx_start(f->after) || is_trx_end(f->after)) + { + my_error(ER_VERS_WRONG_PARAMS, MYF(0), table_name, + "Can not put new field after system versioning field"); + return true; + } + + continue; + } + + // TODO: ALTER_COLUMN_ORDER? + f->after= after_this; + } + } + + if (alter_info->drop_list.elements) + { + List_iterator it(alter_info->drop_list); + while (Alter_drop* d= it++) + { + if (is_trx_start(d->name) || is_trx_end(d->name)) + { + my_error(ER_VERS_WRONG_PARAMS, MYF(0), table_name, + "Can not drop system versioning field"); + return true; + } + } + } + + return false; + } + + return fix_implicit(thd, alter_info, integer_fields) || + (declared_with_system_versioning && + (check_with_conditions(table_name) || + check_generated_type(table_name, alter_info, integer_fields))); +} + +bool Vers_parse_info::check_with_conditions(const char *table_name) const +{ if (!generated_as_row.start) { - my_error(ER_VERS_WRONG_PARAMS, MYF(0), table_name, "'GENERATED AS ROW START' column missing"); + my_error(ER_VERS_WRONG_PARAMS, MYF(0), table_name, + "'GENERATED AS ROW START' column missing"); return true; } if (!generated_as_row.end) { - my_error(ER_VERS_WRONG_PARAMS, MYF(0), table_name, "'GENERATED AS ROW END' column missing"); + my_error(ER_VERS_WRONG_PARAMS, MYF(0), table_name, + "'GENERATED AS ROW END' column missing"); return true; } if (!period_for_system_time.start || !period_for_system_time.end) { - my_error(ER_VERS_WRONG_PARAMS, MYF(0), table_name, "'PERIOD FOR SYSTEM_TIME' missing"); + my_error(ER_VERS_WRONG_PARAMS, MYF(0), table_name, + "'PERIOD FOR SYSTEM_TIME' missing"); return true; } if (my_strcasecmp(system_charset_info, generated_as_row.start->c_ptr(), period_for_system_time.start->c_ptr())) { - my_error(ER_VERS_WRONG_PARAMS, MYF(0), table_name, "'PERIOD FOR SYSTEM_TIME' and 'GENERATED AS ROW START' mismatch"); + my_error(ER_VERS_WRONG_PARAMS, MYF(0), table_name, + "'PERIOD FOR SYSTEM_TIME' and 'GENERATED AS ROW START' mismatch"); return true; } if (my_strcasecmp(system_charset_info, generated_as_row.end->c_ptr(), period_for_system_time.end->c_ptr())) { - my_error(ER_VERS_WRONG_PARAMS, MYF(0), table_name, "'PERIOD FOR SYSTEM_TIME' and 'GENERATED AS ROW END' mismatch"); + my_error(ER_VERS_WRONG_PARAMS, MYF(0), table_name, + "'PERIOD FOR SYSTEM_TIME' and 'GENERATED AS ROW END' mismatch"); return true; } return false; } + +bool Vers_parse_info::check_generated_type(const char *table_name, + Alter_info *alter_info, + bool integer_fields) const +{ + List_iterator it(alter_info->create_list); + while (Create_field *f= it++) + { + if (is_trx_start(f->field_name) || is_trx_end(f->field_name)) + { + if (integer_fields) + { + if (f->sql_type != MYSQL_TYPE_LONGLONG || !(f->flags & UNSIGNED_FLAG) || + f->length != (MY_INT64_NUM_DECIMAL_DIGITS - 1)) + { + my_error(ER_VERS_FIELD_WRONG_TYPE, MYF(0), f->field_name, + "BIGINT(20) UNSIGNED", table_name); + return true; + } + } + else + { + if (f->sql_type != MYSQL_TYPE_TIMESTAMP2 || + f->length != MAX_DATETIME_FULL_WIDTH) + { + my_error(ER_VERS_FIELD_WRONG_TYPE, MYF(0), f->field_name, + "TIMESTAMP(6)", table_name); + return true; + } + } + } + } + + return false; +} diff --git a/sql/handler.h b/sql/handler.h index 394d6276e4f..ced716ed11a 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1674,7 +1674,8 @@ struct Schema_specification_st struct Vers_parse_info { Vers_parse_info() : - declared_system_versioning(false), + declared_with_system_versioning(false), + declared_without_system_versioning(false), has_versioned_fields(false), has_unversioned_fields(false) {} @@ -1698,12 +1699,36 @@ struct Vers_parse_info } private: + bool is_trx_start(const char *name) const; + bool is_trx_end(const char *name) const; bool fix_implicit(THD *thd, Alter_info *alter_info, bool integer_fields); + bool need_to_check() const + { + return + has_versioned_fields || + has_unversioned_fields || + declared_with_system_versioning || + declared_without_system_versioning || + period_for_system_time.start || + period_for_system_time.end || + generated_as_row.start || + generated_as_row.end; + } + bool check_with_conditions(const char *table_name) const; + bool check_generated_type(const char *table_name, Alter_info *alter_info, + bool integer_fields) const; + public: - bool check_and_fix_implicit(THD *thd, Alter_info *alter_info, bool integer_fields, const char* table_name); + bool check_and_fix_implicit(THD *thd, Alter_info *alter_info, + bool integer_fields, const char *table_name); + bool check_and_fix_alter(THD *thd, Alter_info *alter_info, + HA_CREATE_INFO *create_info, TABLE_SHARE *share); /** User has added 'WITH SYSTEM VERSIONING' to table definition */ - bool declared_system_versioning : 1; + bool declared_with_system_versioning : 1; + + /** Use has added 'WITHOUT SYSTEM VERSIONING' to ALTER TABLE */ + bool declared_without_system_versioning : 1; /** At least one field was specified 'WITH SYSTEM VERSIONING'. Useful for diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 68504ffddba..9ad37134c86 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -55,6 +55,8 @@ #include "transaction.h" #include "sql_audit.h" #include "sql_sequence.h" +#include "tztime.h" + #ifdef __WIN__ #include @@ -8718,6 +8720,12 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, if (check_engine(thd, alter_ctx.new_db, alter_ctx.new_name, create_info)) DBUG_RETURN(true); + if (create_info->vers_info.check_and_fix_alter(thd, alter_info, create_info, + table->s)) + { + DBUG_RETURN(true); + } + if ((create_info->db_type != table->s->db_type() || alter_info->flags & Alter_info::ALTER_PARTITION) && !table->file->can_switch_engines()) @@ -9654,6 +9662,10 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, sql_mode_t save_sql_mode= thd->variables.sql_mode; ulonglong prev_insert_id, time_to_report_progress; Field **dfield_ptr= to->default_field; + bool make_versioned= !from->versioned() && to->versioned(); + bool make_unversioned= from->versioned() && !to->versioned(); + Field *to_sys_trx_start= NULL, *from_sys_trx_end= NULL, *to_sys_trx_end= NULL; + MYSQL_TIME now; DBUG_ENTER("copy_data_between_tables"); /* Two or 3 stages; Sorting, copying data and update indexes */ @@ -9753,6 +9765,19 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, thd_progress_next_stage(thd); } + if (make_versioned) + { + thd->variables.time_zone->gmt_sec_to_TIME(&now, thd->query_start()); + now.second_part= thd->query_start_sec_part(); + thd->time_zone_used= 1; + to_sys_trx_start= to->field[to->s->row_start_field]; + to_sys_trx_end= to->field[to->s->row_end_field]; + } + else if (make_unversioned) + { + from_sys_trx_end= from->field[from->s->row_end_field]; + } + THD_STAGE_INFO(thd, stage_copy_to_tmp_table); /* Tell handler that we have values for all columns in the to table */ to->use_all_columns(); @@ -9806,6 +9831,25 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, { copy_ptr->do_copy(copy_ptr); } + + if (make_versioned) + { + to_sys_trx_start->set_notnull(to_sys_trx_start->null_offset()); + // TODO: write directly to record bypassing the same checks on every call + to_sys_trx_start->store_time(&now); + + static const timeval max_tv= {0x7fffffff, 0}; + static const uint dec= 6; + to_sys_trx_end->set_notnull(to_sys_trx_end->null_offset()); + my_timestamp_to_binary(&max_tv, to_sys_trx_end->ptr, dec); + } + else if (make_unversioned) + { + // Drop history rows. + if (!from_sys_trx_end->is_max()) + continue; + } + prev_insert_id= to->file->next_insert_id; if (to->default_field) to->update_default_fields(0, ignore); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index a38c0861656..bc5d65264a0 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -5855,10 +5855,31 @@ create_table_option: } | WITH_SYSTEM_SYM VERSIONING { + const char *table_name= + Lex->create_last_non_select_table->table_name; Vers_parse_info &info= Lex->vers_get_info(); - info.declared_system_versioning= true; + if (info.declared_with_system_versioning || + info.declared_without_system_versioning) + my_yyabort_error( + (ER_VERS_WRONG_PARAMS, MYF(0), table_name, + "Versioning specified more than once for the same table")); + + info.declared_with_system_versioning= true; Lex->create_info.options|= HA_VERSIONED_TABLE; } + | WITHOUT SYSTEM VERSIONING + { + const char *table_name= + Lex->create_last_non_select_table->table_name; + Vers_parse_info &info= Lex->vers_get_info(); + if (info.declared_with_system_versioning || + info.declared_without_system_versioning) + my_yyabort_error( + (ER_VERS_WRONG_PARAMS, MYF(0), table_name, + "Versioning specified more than once for the same table")); + + info.declared_without_system_versioning= true; + } ; default_charset: @@ -6679,12 +6700,26 @@ serial_attribute: } | WITH_SYSTEM_SYM VERSIONING { + if (Lex->last_field->versioning != + Column_definition::VERSIONING_NOT_SET) + my_yyabort_error( + (ER_VERS_WRONG_PARAMS, MYF(0), + Lex->create_last_non_select_table->table_name, + "Versioning specified more than once for the same field")); + Lex->last_field->versioning = Column_definition::WITH_VERSIONING; Lex->create_info.vers_info.has_versioned_fields= true; Lex->create_info.options|= HA_VERSIONED_TABLE; } | WITHOUT SYSTEM VERSIONING { + if (Lex->last_field->versioning != + Column_definition::VERSIONING_NOT_SET) + my_yyabort_error( + (ER_VERS_WRONG_PARAMS, MYF(0), + Lex->create_last_non_select_table->table_name, + "Versioning specified more than once for the same field")); + Lex->last_field->versioning = Column_definition::WITHOUT_VERSIONING; Lex->create_info.vers_info.has_unversioned_fields= true; Lex->create_info.options|= HA_VERSIONED_TABLE; diff --git a/sql/table.cc b/sql/table.cc index 4b41a59a750..ad44f896621 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2551,44 +2551,15 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, else { DBUG_PRINT("info", ("Setting system versioning informations")); - uint16 row_start = uint2korr(system_period); - uint16 row_end = uint2korr(system_period + sizeof(uint16)); + uint16 row_start= uint2korr(system_period); + uint16 row_end= uint2korr(system_period + sizeof(uint16)); if (row_start >= share->fields || row_end >= share->fields) goto err; - DBUG_PRINT("info", ("Columns with system versioning: [%d, %d]", row_start, row_end)); + DBUG_PRINT("info", ("Columns with system versioning: [%d, %d]", row_start, + row_end)); share->enable_system_versioning(row_start, row_end); vers_start_field()->flags|= VERS_SYS_START_FLAG; vers_end_field()->flags|= VERS_SYS_END_FLAG; - - DBUG_ASSERT(db_type()); - if (db_type()->versioned()) - { - if (vers_start_field()->type() != MYSQL_TYPE_LONGLONG - || !(vers_start_field()->flags & UNSIGNED_FLAG)) - { - my_error(ER_VERS_FIELD_WRONG_TYPE, MYF(0), vers_start_field()->field_name, "BIGINT UNSIGNED", share->table_name); - goto err; - } - if (vers_end_field()->type() != MYSQL_TYPE_LONGLONG - || !(vers_end_field()->flags & UNSIGNED_FLAG)) - { - my_error(ER_VERS_FIELD_WRONG_TYPE, MYF(0), vers_end_field()->field_name, "BIGINT UNSIGNED", share->table_name); - goto err; - } - } - else - { - if (vers_start_field()->type() != MYSQL_TYPE_TIMESTAMP) - { - my_error(ER_VERS_FIELD_WRONG_TYPE, MYF(0), vers_start_field()->field_name, "TIMESTAMP", share->table_name); - goto err; - } - if (vers_end_field()->type() != MYSQL_TYPE_TIMESTAMP) - { - my_error(ER_VERS_FIELD_WRONG_TYPE, MYF(0), vers_end_field()->field_name, "TIMESTAMP", share->table_name); - goto err; - } - } // if (db_type()->versioned()) } // if (system_period == NULL) delete handler_file; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 27fa7e84aa3..0e36bf04fde 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -588,6 +588,15 @@ ha_innobase::check_if_supported_inplace_alter( DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); } + // It looks like it's actually possible to do this INPLACE, but we + // disallow this for now. + if (ha_alter_info->create_info->vers_info + .declared_with_system_versioning || + ha_alter_info->create_info->vers_info + .declared_without_system_versioning) { + DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); + } + update_thd(); trx_assert_no_search_latch(m_prebuilt->trx); @@ -4625,6 +4634,15 @@ prepare_inplace_alter_table_dict( field_type |= DATA_UNSIGNED; } + if (altered_table->versioned()) { + if (i == altered_table->s->row_start_field) { + field_type |= DATA_VERS_ROW_START; + } else if (i == + altered_table->s->row_end_field) { + field_type |= DATA_VERS_ROW_END; + } + } + if (dtype_is_string_type(col_type)) { charset_no = (ulint) field->charset()->number;