summaryrefslogtreecommitdiff
path: root/mysql-test/suite/versioning
diff options
context:
space:
mode:
Diffstat (limited to 'mysql-test/suite/versioning')
-rw-r--r--mysql-test/suite/versioning/common.inc127
-rw-r--r--mysql-test/suite/versioning/common.opt1
-rw-r--r--mysql-test/suite/versioning/common_finish.inc11
-rw-r--r--mysql-test/suite/versioning/disabled.def15
-rw-r--r--mysql-test/suite/versioning/engines.combinations8
-rw-r--r--mysql-test/suite/versioning/engines.inc1
-rw-r--r--mysql-test/suite/versioning/key_type.combinations2
-rw-r--r--mysql-test/suite/versioning/key_type.inc23
-rw-r--r--mysql-test/suite/versioning/r/alter.result452
-rw-r--r--mysql-test/suite/versioning/r/auto_increment.result119
-rw-r--r--mysql-test/suite/versioning/r/commit_id.result98
-rw-r--r--mysql-test/suite/versioning/r/create.result470
-rw-r--r--mysql-test/suite/versioning/r/cte.result118
-rw-r--r--mysql-test/suite/versioning/r/ddl.result211
-rw-r--r--mysql-test/suite/versioning/r/debug.result54
-rw-r--r--mysql-test/suite/versioning/r/delete.result320
-rw-r--r--mysql-test/suite/versioning/r/derived.result295
-rw-r--r--mysql-test/suite/versioning/r/foreign.result232
-rw-r--r--mysql-test/suite/versioning/r/insert.result368
-rw-r--r--mysql-test/suite/versioning/r/online.result34
-rw-r--r--mysql-test/suite/versioning/r/optimized.result97
-rw-r--r--mysql-test/suite/versioning/r/partition.result420
-rw-r--r--mysql-test/suite/versioning/r/replace.result10
-rw-r--r--mysql-test/suite/versioning/r/rpl.result118
-rw-r--r--mysql-test/suite/versioning/r/select.result515
-rw-r--r--mysql-test/suite/versioning/r/select2,myisam.rdiff38
-rw-r--r--mysql-test/suite/versioning/r/select2.result338
-rw-r--r--mysql-test/suite/versioning/r/simple.result73
-rw-r--r--mysql-test/suite/versioning/r/sysvars.result129
-rw-r--r--mysql-test/suite/versioning/r/truncate.result71
-rw-r--r--mysql-test/suite/versioning/r/truncate_privilege.result33
-rw-r--r--mysql-test/suite/versioning/r/trx_id.result72
-rw-r--r--mysql-test/suite/versioning/r/update.result625
-rw-r--r--mysql-test/suite/versioning/r/view.result120
-rw-r--r--mysql-test/suite/versioning/r/vtmd.result365
-rw-r--r--mysql-test/suite/versioning/r/vtmd_show.result229
-rw-r--r--mysql-test/suite/versioning/t/alter.test395
-rw-r--r--mysql-test/suite/versioning/t/auto_increment.test68
-rw-r--r--mysql-test/suite/versioning/t/commit_id.test94
-rw-r--r--mysql-test/suite/versioning/t/create.test367
-rw-r--r--mysql-test/suite/versioning/t/cte.test101
-rw-r--r--mysql-test/suite/versioning/t/ddl.test105
-rw-r--r--mysql-test/suite/versioning/t/debug.test35
-rw-r--r--mysql-test/suite/versioning/t/delete.test129
-rw-r--r--mysql-test/suite/versioning/t/derived.test236
-rw-r--r--mysql-test/suite/versioning/t/engines.combinations8
-rw-r--r--mysql-test/suite/versioning/t/foreign.combinations5
-rw-r--r--mysql-test/suite/versioning/t/foreign.test282
-rw-r--r--mysql-test/suite/versioning/t/insert.test266
-rw-r--r--mysql-test/suite/versioning/t/online.test42
-rw-r--r--mysql-test/suite/versioning/t/optimized.test33
-rw-r--r--mysql-test/suite/versioning/t/partition.combinations5
-rw-r--r--mysql-test/suite/versioning/t/partition.opt1
-rw-r--r--mysql-test/suite/versioning/t/partition.test373
-rw-r--r--mysql-test/suite/versioning/t/replace.test13
-rw-r--r--mysql-test/suite/versioning/t/rpl.test108
-rw-r--r--mysql-test/suite/versioning/t/select.test306
-rw-r--r--mysql-test/suite/versioning/t/select2.test211
-rw-r--r--mysql-test/suite/versioning/t/simple.test73
-rw-r--r--mysql-test/suite/versioning/t/sysvars.test87
-rw-r--r--mysql-test/suite/versioning/t/truncate.opt1
-rw-r--r--mysql-test/suite/versioning/t/truncate.test72
-rw-r--r--mysql-test/suite/versioning/t/truncate_privilege.test41
-rw-r--r--mysql-test/suite/versioning/t/trx_id.test75
-rw-r--r--mysql-test/suite/versioning/t/update.test288
-rw-r--r--mysql-test/suite/versioning/t/view.test102
-rw-r--r--mysql-test/suite/versioning/t/vtmd.opt1
-rw-r--r--mysql-test/suite/versioning/t/vtmd.test204
-rw-r--r--mysql-test/suite/versioning/t/vtmd_show.opt1
-rw-r--r--mysql-test/suite/versioning/t/vtmd_show.test90
-rw-r--r--mysql-test/suite/versioning/wait_system_clock.inc10
71 files changed, 10440 insertions, 0 deletions
diff --git a/mysql-test/suite/versioning/common.inc b/mysql-test/suite/versioning/common.inc
new file mode 100644
index 00000000000..cbc515241b0
--- /dev/null
+++ b/mysql-test/suite/versioning/common.inc
@@ -0,0 +1,127 @@
+--disable_query_log
+source include/have_innodb.inc;
+
+set @@session.time_zone='+00:00';
+select ifnull(max(transaction_id), 0) into @start_trx_id from mysql.transaction_registry;
+set @test_start=now(6);
+
+delimiter ~~;
+create procedure if not exists verify_vtq()
+begin
+ set @i= 0;
+ select
+ @i:= @i + 1 as No,
+ transaction_id > 0 as A,
+ commit_id > transaction_id as B,
+ begin_timestamp > @test_start as C,
+ commit_timestamp >= begin_timestamp as D
+ from mysql.transaction_registry
+ where transaction_id > @start_trx_id;
+ select ifnull(max(transaction_id), 0)
+ into @start_trx_id
+ from mysql.transaction_registry;
+end~~
+
+create function if not exists default_engine()
+returns varchar(255)
+deterministic
+begin
+ declare e varchar(255);
+ select engine from information_schema.engines where support='DEFAULT' into e;
+ return e;
+end~~
+
+create function if not exists non_default_engine()
+returns varchar(255)
+deterministic
+begin
+ if default_engine() = 'InnoDB' then
+ return 'MyISAM';
+ end if;
+ return 'InnoDB';
+end~~
+
+create function if not exists sys_datatype(engine varchar(255))
+returns varchar(255)
+deterministic
+begin
+ if engine = 'InnoDB' then
+ return 'bigint(20) unsigned';
+ elseif engine = 'MyISAM' then
+ return 'timestamp(6)';
+ end if;
+ return NULL;
+end~~
+
+create function if not exists current_row(sys_trx_end varbinary(255))
+returns int
+deterministic
+begin
+ declare continue handler for sqlwarning begin end;
+ return sys_trx_end = timestamp'2038-01-19 03:14:07.999999'
+ or sys_trx_end = 18446744073709551615;
+end~~
+
+create function if not exists sys_commit_ts(sys_field varchar(255))
+returns varchar(255)
+deterministic
+begin
+ if default_engine() = 'InnoDB' then
+ return concat('vtq_commit_ts(', sys_field, ')');
+ elseif default_engine() = 'MyISAM' then
+ return sys_field;
+ end if;
+ return NULL;
+end~~
+
+create procedure if not exists verify_vtq_dummy(recs int)
+begin
+ declare i int default 1;
+ create temporary table tmp (No int, A bool, B bool, C bool, D bool);
+ while i <= recs do
+ insert into tmp values (i, 1, 1, 1, 1);
+ set i= i + 1;
+ end while;
+ select * from tmp;
+ drop table tmp;
+end~~
+
+create procedure concat_exec2(a varchar(255), b varchar(255))
+begin
+ prepare stmt from concat(a, b);
+ execute stmt;
+ deallocate prepare stmt;
+end~~
+
+create procedure concat_exec3(a varchar(255), b varchar(255), c varchar(255))
+begin
+ prepare stmt from concat(a, b, c);
+ execute stmt;
+ deallocate prepare stmt;
+end~~
+delimiter ;~~
+
+let $default_engine= `select default_engine()`;
+let $non_default_engine= `select non_default_engine()`;
+let $sys_datatype= timestamp(6);
+let $sys_datatype_expl= timestamp(6);
+let $sys_datatype_uc= TIMESTAMP(6);
+let $sys_datatype_expl_uc= TIMESTAMP(6);
+
+let $non_sys_datatype= `select sys_datatype(non_default_engine())`;
+let $non_sys_datatype_uc= `select upper(sys_datatype(non_default_engine()))`;
+let $sys_datatype_null= $sys_datatype NULL DEFAULT NULL;
+let $sys_datatype_default_null= $sys_datatype DEFAULT NULL;
+let $sys_datatype_not_null= $sys_datatype NOT NULL DEFAULT '0000-00-00 00:00:00.000000';
+let $non_sys_datatype_null= $non_sys_datatype NULL;
+
+if ($MTR_COMBINATION_MYISAM)
+{
+ --let $MTR_COMBINATION_TIMESTAMP= 1
+}
+if ($MTR_COMBINATION_TRX_ID)
+{
+ let $sys_datatype_expl= bigint(20) unsigned;
+ let $sys_datatype_expl_uc= BIGINT(20) UNSIGNED;
+}
+--enable_query_log
diff --git a/mysql-test/suite/versioning/common.opt b/mysql-test/suite/versioning/common.opt
new file mode 100644
index 00000000000..412290a7585
--- /dev/null
+++ b/mysql-test/suite/versioning/common.opt
@@ -0,0 +1 @@
+--plugin-load-add=test_versioning
diff --git a/mysql-test/suite/versioning/common_finish.inc b/mysql-test/suite/versioning/common_finish.inc
new file mode 100644
index 00000000000..1059bb1251d
--- /dev/null
+++ b/mysql-test/suite/versioning/common_finish.inc
@@ -0,0 +1,11 @@
+--disable_query_log
+drop procedure verify_vtq;
+drop procedure verify_vtq_dummy;
+drop function default_engine;
+drop function non_default_engine;
+drop function sys_commit_ts;
+drop function sys_datatype;
+drop function current_row;
+drop procedure concat_exec2;
+drop procedure concat_exec3;
+--enable_query_log
diff --git a/mysql-test/suite/versioning/disabled.def b/mysql-test/suite/versioning/disabled.def
new file mode 100644
index 00000000000..e0f1483d0ef
--- /dev/null
+++ b/mysql-test/suite/versioning/disabled.def
@@ -0,0 +1,15 @@
+##############################################################################
+#
+# List the test cases that are to be disabled temporarily.
+#
+# Separate the test case name and the comment with ':'.
+#
+# <testcasename> : BUG#<xxxx> <date disabled> <disabler> <comment>
+#
+# Do not use any TAB characters for whitespace.
+#
+##############################################################################
+ddl : DDL Survival WIP
+vtmd : DDL Survival WIP
+vtmd_show : DDL Survival WIP
+cte: MDEV-14820
diff --git a/mysql-test/suite/versioning/engines.combinations b/mysql-test/suite/versioning/engines.combinations
new file mode 100644
index 00000000000..561c5656929
--- /dev/null
+++ b/mysql-test/suite/versioning/engines.combinations
@@ -0,0 +1,8 @@
+[timestamp]
+default-storage-engine=innodb
+
+[trx_id]
+default-storage-engine=innodb
+
+[myisam]
+default-storage-engine=myisam
diff --git a/mysql-test/suite/versioning/engines.inc b/mysql-test/suite/versioning/engines.inc
new file mode 100644
index 00000000000..c841fece702
--- /dev/null
+++ b/mysql-test/suite/versioning/engines.inc
@@ -0,0 +1 @@
+--source include/have_innodb.inc
diff --git a/mysql-test/suite/versioning/key_type.combinations b/mysql-test/suite/versioning/key_type.combinations
new file mode 100644
index 00000000000..1929aee9a84
--- /dev/null
+++ b/mysql-test/suite/versioning/key_type.combinations
@@ -0,0 +1,2 @@
+[unique]
+[pk]
diff --git a/mysql-test/suite/versioning/key_type.inc b/mysql-test/suite/versioning/key_type.inc
new file mode 100644
index 00000000000..648430771cf
--- /dev/null
+++ b/mysql-test/suite/versioning/key_type.inc
@@ -0,0 +1,23 @@
+--disable_query_log
+if ($MTR_COMBINATION_UNIQUE)
+{
+ set @KEY_TYPE= 'unique';
+}
+if ($MTR_COMBINATION_PK)
+{
+ set @KEY_TYPE= 'primary key';
+}
+
+delimiter ~~;
+create procedure create_table(name varchar(255), cols varchar(255))
+begin
+ if (cols is null or cols = '') then
+ set cols= '';
+ else
+ set cols= concat(', ', cols);
+ end if;
+ set @str= concat('create or replace table ', name, '(id int ', @KEY_TYPE, cols, ') with system versioning');
+ prepare stmt from @str; execute stmt; drop prepare stmt;
+end~~
+delimiter ;~~
+--enable_query_log
diff --git a/mysql-test/suite/versioning/r/alter.result b/mysql-test/suite/versioning/r/alter.result
new file mode 100644
index 00000000000..04d7139b207
--- /dev/null
+++ b/mysql-test/suite/versioning/r/alter.result
@@ -0,0 +1,452 @@
+select @@system_versioning_alter_history;
+@@system_versioning_alter_history
+ERROR
+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 drop system versioning;
+ERROR HY000: Table `t` is not system-versioned
+alter table t add system versioning;
+show create table t;
+Table Create Table
+t CREATE TABLE `t` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+alter table t add column y int;
+ERROR HY000: Not allowed for system-versioned `test`.`t`. Change @@system_versioning_alter_history to proceed with ALTER.
+alter table t engine innodb;
+ERROR HY000: Not allowed for system-versioned `test`.`t`. Change to/from native system versioning engine is prohibited.
+alter table t drop system versioning;
+show create table t;
+Table Create Table
+t CREATE TABLE `t` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+set system_versioning_alter_history= keep;
+alter table t
+add column trx_start bigint(20) unsigned as row start invisible,
+add column trx_end bigint(20) unsigned as row end invisible,
+add period for system_time(trx_start, trx_end),
+add system versioning;
+ERROR HY000: `trx_start` must be of type TIMESTAMP(6) for system-versioned table `t`
+alter table t
+add column trx_start timestamp as row start invisible,
+add column trx_end timestamp as row end invisible,
+add period for system_time(trx_start, trx_end),
+add system versioning;
+ERROR HY000: `trx_start` must be of type TIMESTAMP(6) for system-versioned table `t`
+alter table t
+add column trx_start timestamp(6) not null as row start invisible,
+add column trx_end timestamp(6) not null as row end invisible,
+add period for system_time(trx_start, trx_end),
+add 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 'as row start invisible,
+add column trx_end timestamp(6) not null as row end invi' at line 2
+alter table t
+add column trx_start timestamp(6) as row start invisible,
+add column trx_end timestamp(6) as row end invisible,
+add period for system_time(trx_start, trx_end),
+add system versioning;
+show create table t;
+Table Create Table
+t CREATE TABLE `t` (
+ `a` int(11) DEFAULT NULL,
+ `trx_start` timestamp(6) GENERATED ALWAYS AS ROW START INVISIBLE,
+ `trx_end` timestamp(6) GENERATED ALWAYS AS ROW END INVISIBLE,
+ PERIOD FOR SYSTEM_TIME (`trx_start`, `trx_end`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+alter table t drop column trx_start, drop column trx_end;
+alter table t drop 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 system versioning;
+show create table t;
+Table Create Table
+t CREATE TABLE `t` (
+ `a` int(11) DEFAULT NULL
+) 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
+) 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
+) 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
+) 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
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+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
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+create or replace table t (
+a int,
+row_start timestamp(6) as row start invisible,
+row_end timestamp(6) as row end invisible,
+period for system_time(row_start, row_end))
+with system versioning;
+select * from t for system_time all;
+a
+alter table t drop column row_start;
+ERROR HY000: Wrong parameters for `t`: missing 'DROP COLUMN row_end'
+alter table t drop column row_end;
+ERROR HY000: Wrong parameters for `t`: missing 'DROP COLUMN row_start'
+alter table t drop column row_start, drop column row_end;
+select * from t for system_time all;
+a
+alter table t drop column row_start;
+ERROR 42000: Can't DROP COLUMN `row_start`; check that it exists
+alter table t drop column row_end;
+ERROR 42000: Can't DROP COLUMN `row_end`; check that it exists
+create or replace table t (
+a int,
+row_start timestamp(6) as row start invisible,
+row_end timestamp(6) as row end invisible,
+period for system_time(row_start, row_end))
+with system versioning;
+select * from t for system_time all;
+a
+alter table t drop column row_start, drop column row_end;
+select * from t for system_time all;
+a
+create or replace table t(
+a int
+);
+insert into t values(1);
+alter table t add system versioning;
+show create table t;
+Table Create Table
+t CREATE TABLE `t` (
+ `a` int(11) DEFAULT NULL
+) 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 row_start from t where a=3 into @tm;
+alter table t add column b int;
+select @tm=row_start from t where a=3;
+@tm=row_start
+1
+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 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 drop 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: Table `t` is not system-versioned
+alter table t modify a int without system versioning;
+ERROR HY000: Table `t` is not system-versioned
+alter table t add 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
+) 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
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+create or replace table t(
+a int
+) engine=innodb;
+alter table t
+add column trx_start timestamp(6) as row start invisible,
+add column trx_end timestamp(6) as row end invisible,
+add period for system_time(trx_start, trx_end),
+add system versioning;
+show create table t;
+Table Create Table
+t CREATE TABLE `t` (
+ `a` int(11) DEFAULT NULL,
+ `trx_start` timestamp(6) GENERATED ALWAYS AS ROW START INVISIBLE,
+ `trx_end` timestamp(6) GENERATED ALWAYS AS ROW END INVISIBLE,
+ PERIOD FOR SYSTEM_TIME (`trx_start`, `trx_end`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+# Issue #211: drop of system columns required before drop system versioning
+alter table t drop column trx_start, drop column trx_end;
+show create table t;
+Table Create Table
+t CREATE TABLE `t` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+alter table t drop system versioning;
+insert into t values(1);
+call verify_vtq;
+No A B C D
+alter table t
+add column trx_start bigint(20) unsigned as row start invisible,
+add column trx_end bigint(20) unsigned as row end invisible,
+add period for system_time(trx_start, trx_end),
+add system versioning;
+call verify_vtq;
+No A B C D
+1 1 1 1 1
+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 INVISIBLE,
+ `trx_end` bigint(20) unsigned GENERATED ALWAYS AS ROW END INVISIBLE,
+ PERIOD FOR SYSTEM_TIME (`trx_start`, `trx_end`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+alter table t drop column trx_start, drop column trx_end;
+call verify_vtq;
+No A B C D
+alter table t drop system versioning, algorithm=copy;
+call verify_vtq;
+No A B C D
+alter table t add system versioning, algorithm=copy;
+call verify_vtq;
+No A B C D
+show create table t;
+Table Create Table
+t CREATE TABLE `t` (
+ `a` int(11) DEFAULT NULL
+) 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
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+select * from t;
+a b
+2 NULL
+call verify_vtq;
+No A B C D
+alter table t drop column b, algorithm=copy;
+show create table t;
+Table Create Table
+t CREATE TABLE `t` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+select * from t for system_time all;
+a
+2
+1
+call verify_vtq;
+No A B C D
+alter table t drop 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
+create or replace table t (a int);
+insert t values (1),(2),(3),(4);
+alter table t add b int auto_increment null unique;
+select * from t;
+a b
+1 1
+2 2
+3 3
+4 4
+drop table t;
+create or replace table t (a int) with system versioning engine=innodb;
+insert into t values (1), (2), (3);
+delete from t where a<3;
+alter table t add b int not null unique;
+Got one of the listed errors
+alter table t add b int auto_increment unique;
+Got one of the listed errors
+alter table t add b int auto_increment null unique;
+select * from t;
+a b
+3 1
+select * from t for system_time all;
+a b
+1 NULL
+2 NULL
+3 1
+insert into t values (4, 0);
+select * from t for system_time all;
+a b
+1 NULL
+2 NULL
+3 1
+4 4
+create or replace table t (a int) with system versioning;
+insert into t values (1), (2), (3);
+delete from t where a<3;
+alter table t add b int not null unique;
+Got one of the listed errors
+alter table t add b int auto_increment unique;
+Got one of the listed errors
+alter table t add b int auto_increment null unique;
+select * from t;
+a b
+3 1
+select * from t for system_time all;
+a b
+1 NULL
+2 NULL
+3 1
+insert into t values (4, 0);
+select * from t for system_time all;
+a b
+1 NULL
+2 NULL
+3 1
+4 2
+create or replace table t (
+a int,
+row_start timestamp(6) as row start invisible,
+row_end timestamp(6) as row end invisible,
+period for system_time(row_start, row_end)
+) with system versioning;
+alter table t change column row_start asdf timestamp(6);
+ERROR HY000: Can not change system versioning field `row_start`
+insert into t values (1);
+alter table t modify column row_start bigint unsigned;
+ERROR HY000: Can not change system versioning field `row_start`
+set system_versioning_alter_history= SURVIVE;
+ERROR 42000: Variable 'system_versioning_alter_history' can't be set to the value of 'SURVIVE'
+set system_versioning_alter_history= 'DROP';
+ERROR 42000: Variable 'system_versioning_alter_history' can't be set to the value of 'DROP'
+create or replace table t (a int) with system versioning;
+alter table t add system versioning;
+ERROR HY000: Table `t` is already system-versioned
+alter table t add system versioning, drop system versioning;
+ERROR HY000: Table `t` is already system-versioned
+set @@system_versioning_alter_history=keep;
+create or replace table t(x int, y int) with system versioning engine=innodb;
+alter table t modify y int without system versioning;
+insert into t values(1, 1);
+update t set y=2;
+# MDEV-14681 Bogus ER_UNSUPPORTED_EXTENSION
+create or replace table t1 (pk int auto_increment unique) with system versioning;
+insert into t1 values (1);
+delete from t1;
+alter table t1 engine=myisam;
+# MDEV-14692 crash in MDL_context::upgrade_shared_lock()
+create or replace temporary table t (a int);
+alter table t change column if exists b c bigint unsigned generated always as row start;
+ERROR HY000: System versioning prohibited for TEMPORARY tables
+alter table t change column if exists b c bigint unsigned generated always as row end;
+ERROR HY000: System versioning prohibited for TEMPORARY tables
+alter table t add system versioning;
+ERROR HY000: System versioning prohibited for TEMPORARY tables
+drop table t;
+# MDEV-14744 trx_id-based and transaction-based mixup in assertion
+create or replace table t (c text) engine=innodb with system versioning;
+show create table t;
+Table Create Table
+t CREATE TABLE `t` (
+ `c` text DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+alter table t add fulltext key (c);
+Warnings:
+Warning 124 InnoDB rebuilding table to add column FTS_DOC_ID
+create or replace table t (a int) with system versioning;
+alter table t drop column a;
+ERROR HY000: Table `t` must have at least one versioned column
+alter table t drop column a, drop column a;
+ERROR 42000: Can't DROP COLUMN `a`; check that it exists
+create or replace table t1 (row_start int);
+alter table t1 with system versioning;
+ERROR 42S21: Duplicate column name 'row_start'
+create or replace table t1 (row_end int);
+alter table t1 with system versioning;
+ERROR 42S21: Duplicate column name 'row_end'
+create or replace table t1 (a int, row_start int) with system versioning;
+ERROR 42S21: Duplicate column name 'row_start'
+create or replace table t1 (a int) with system versioning;
+set statement system_versioning_alter_history=keep for
+alter table t1 add column row_start int;
+ERROR 42S21: Duplicate column name 'row_start'
+set statement system_versioning_alter_history=keep for
+alter table t1 add column row_start timestamp(6);
+ERROR 42S21: Duplicate column name 'row_start'
+# MDEV-14798 Add, drop system versioning semantic and syntax
+create or replace table t (a int) with system versioning;
+alter table t add period for system_time(sys_trx_start, sys_trx_end);
+ERROR HY000: Table `t` is already system-versioned
+drop database test;
+create database test;
diff --git a/mysql-test/suite/versioning/r/auto_increment.result b/mysql-test/suite/versioning/r/auto_increment.result
new file mode 100644
index 00000000000..1f43595848b
--- /dev/null
+++ b/mysql-test/suite/versioning/r/auto_increment.result
@@ -0,0 +1,119 @@
+create procedure test_01(
+sys_type varchar(255),
+engine varchar(255),
+fields varchar(255))
+begin
+set @str= concat('
+ create table t1(
+ id int unsigned auto_increment primary key,
+ x int unsigned,
+ y int unsigned,
+ sys_start ', sys_type, ' as row start invisible,
+ sys_end ', sys_type, ' as row end invisible,
+ period for system_time (sys_start, sys_end))
+ with system versioning
+ engine ', engine);
+prepare stmt from @str; execute stmt; drop prepare stmt;
+set @str= concat('
+ create table t2(
+ id int unsigned auto_increment primary key,
+ x int unsigned,
+ y int unsigned)
+ engine ', engine);
+prepare stmt from @str; execute stmt; drop prepare stmt;
+insert into t1(x, y) values(1, 11);
+insert into t2(x, y) values(1, 11);
+insert into t1(x, y) values(2, 12);
+insert into t2(x, y) values(2, 12);
+insert into t1(x, y) values(3, 13);
+insert into t2(x, y) values(3, 13);
+insert into t1(x, y) values(4, 14);
+insert into t2(x, y) values(4, 14);
+insert into t1(x, y) values(5, 15);
+insert into t2(x, y) values(5, 15);
+insert into t1(x, y) values(6, 16);
+insert into t2(x, y) values(6, 16);
+insert into t1(x, y) values(7, 17);
+insert into t2(x, y) values(7, 17);
+insert into t1(x, y) values(8, 18);
+insert into t2(x, y) values(8, 18);
+insert into t1(x, y) values(9, 19);
+insert into t2(x, y) values(9, 19);
+select t1.x = t2.x and t1.y = t2.y as A, t1.x, t1.y, t2.x, t2.y from t1 inner join t2 on t1.id = t2.id;
+delete from t1 where x = 2;
+delete from t2 where x = 2;
+select t1.x = t2.x and t1.y = t2.y as A, t1.x, t1.y, t2.x, t2.y from t1 inner join t2 on t1.id = t2.id;
+delete from t1 where x > 7;
+delete from t2 where x > 7;
+select t1.x = t2.x and t1.y = t2.y as A, t1.x, t1.y, t2.x, t2.y from t1 inner join t2 on t1.id = t2.id;
+drop table t1;
+drop table t2;
+end~~
+call test_01('timestamp(6)', 'myisam', 'sys_end');
+A x y x y
+1 1 11 1 11
+1 2 12 2 12
+1 3 13 3 13
+1 4 14 4 14
+1 5 15 5 15
+1 6 16 6 16
+1 7 17 7 17
+1 8 18 8 18
+1 9 19 9 19
+A x y x y
+1 1 11 1 11
+1 3 13 3 13
+1 4 14 4 14
+1 5 15 5 15
+1 6 16 6 16
+1 7 17 7 17
+1 8 18 8 18
+1 9 19 9 19
+A x y x y
+1 1 11 1 11
+1 3 13 3 13
+1 4 14 4 14
+1 5 15 5 15
+1 6 16 6 16
+1 7 17 7 17
+call test_01('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)');
+A x y x y
+1 1 11 1 11
+1 2 12 2 12
+1 3 13 3 13
+1 4 14 4 14
+1 5 15 5 15
+1 6 16 6 16
+1 7 17 7 17
+1 8 18 8 18
+1 9 19 9 19
+A x y x y
+1 1 11 1 11
+1 3 13 3 13
+1 4 14 4 14
+1 5 15 5 15
+1 6 16 6 16
+1 7 17 7 17
+1 8 18 8 18
+1 9 19 9 19
+A x y x y
+1 1 11 1 11
+1 3 13 3 13
+1 4 14 4 14
+1 5 15 5 15
+1 6 16 6 16
+1 7 17 7 17
+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
+6 1 1 1 1
+7 1 1 1 1
+8 1 1 1 1
+9 1 1 1 1
+10 1 1 1 1
+11 1 1 1 1
+drop procedure test_01;
diff --git a/mysql-test/suite/versioning/r/commit_id.result b/mysql-test/suite/versioning/r/commit_id.result
new file mode 100644
index 00000000000..e2bd0f21b64
--- /dev/null
+++ b/mysql-test/suite/versioning/r/commit_id.result
@@ -0,0 +1,98 @@
+create table t1(
+id int auto_increment primary key,
+sys_trx_start bigint unsigned as row start invisible,
+sys_trx_end bigint unsigned as row end invisible,
+period for system_time (sys_trx_start, sys_trx_end)
+)
+with system versioning
+engine innodb;
+insert into t1 values ();
+set @ts0= now(6);
+insert into t1 values ();
+select sys_trx_start from t1 where id = last_insert_id() into @tx0;
+select transaction_id = @tx0 from mysql.transaction_registry
+order by transaction_id desc limit 1;
+transaction_id = @tx0
+1
+set @ts1= now(6);
+insert into t1 values ();
+select sys_trx_start from t1 where id = last_insert_id() into @tx1;
+select transaction_id = @tx1 from mysql.transaction_registry
+order by transaction_id desc limit 1;
+transaction_id = @tx1
+1
+set @ts2= now(6);
+insert into t1 values ();
+select sys_trx_start from t1 where id = last_insert_id() into @tx2;
+select transaction_id = @tx2 from mysql.transaction_registry
+order by transaction_id desc limit 1;
+transaction_id = @tx2
+1
+set @ts3= now(6);
+select
+vtq_trx_id(@ts0) < @tx0 as A,
+vtq_trx_id(@ts0, true) = @tx0 as B,
+vtq_trx_id(@ts1) = @tx0 as C,
+vtq_trx_id(@ts1, true) = @tx1 as D,
+vtq_trx_id(@ts2) = @tx1 as E,
+vtq_trx_id(@ts2, true) = @tx2 as F,
+vtq_trx_id(@ts3) = @tx2 as G,
+vtq_trx_id(@ts3, true) is null as H;
+A B C D E F G H
+1 1 1 1 1 1 1 1
+select
+vtq_commit_id(@ts0) < @tx0 as A,
+vtq_commit_id(@ts0, true) = vtq_commit_id(null, @tx0) as B,
+vtq_commit_id(@ts1) = vtq_commit_id(null, @tx0) as C,
+vtq_commit_id(@ts1, true) = vtq_commit_id(null, @tx1) as D,
+vtq_commit_id(@ts2) = vtq_commit_id(null, @tx1) as E,
+vtq_commit_id(@ts2, true) = vtq_commit_id(null, @tx2) as F,
+vtq_commit_id(@ts3) = vtq_commit_id(null, @tx2) as G,
+vtq_commit_id(@ts3, true) is null as H;
+A B C D E F G H
+1 1 1 1 1 1 1 1
+select
+vtq_trx_sees(@tx1, @tx0) as A,
+not vtq_trx_sees(@tx0, @tx1) as B,
+vtq_trx_sees_eq(@tx1, @tx1) as C,
+not vtq_trx_sees(@tx1, @tx1) as D,
+vtq_trx_sees(@tx2, 0) as E,
+vtq_trx_sees(0, @tx2) is null as F,
+vtq_trx_sees(-1, @tx2) as H;
+A B C D E F H
+1 1 1 1 1 1 1
+set transaction isolation level read uncommitted;
+insert into t1 values ();
+select sys_trx_start from t1 where id = last_insert_id() into @tx3;
+select isolation_level = 'READ-UNCOMMITTED' from mysql.transaction_registry where transaction_id = @tx3;
+isolation_level = 'READ-UNCOMMITTED'
+1
+set transaction isolation level read committed;
+insert into t1 values ();
+select sys_trx_start from t1 where id = last_insert_id() into @tx4;
+select isolation_level = 'READ-COMMITTED' from mysql.transaction_registry where transaction_id = @tx4;
+isolation_level = 'READ-COMMITTED'
+1
+set transaction isolation level serializable;
+insert into t1 values ();
+select sys_trx_start from t1 where id = last_insert_id() into @tx5;
+select isolation_level = 'SERIALIZABLE' from mysql.transaction_registry where transaction_id = @tx5;
+isolation_level = 'SERIALIZABLE'
+1
+set transaction isolation level repeatable read;
+insert into t1 values ();
+select sys_trx_start from t1 where id = last_insert_id() into @tx6;
+select isolation_level = 'REPEATABLE-READ' from mysql.transaction_registry where transaction_id = @tx6;
+isolation_level = 'REPEATABLE-READ'
+1
+drop table t1;
+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
+6 1 1 1 1
+7 1 1 1 1
+8 1 1 1 1
diff --git a/mysql-test/suite/versioning/r/create.result b/mysql-test/suite/versioning/r/create.result
new file mode 100644
index 00000000000..7fe1db5964f
--- /dev/null
+++ b/mysql-test/suite/versioning/r/create.result
@@ -0,0 +1,470 @@
+drop table if exists t1;
+create table t1 (
+x1 int unsigned,
+Sys_start SYS_DATATYPE as row start invisible comment 'start',
+Sys_end SYS_DATATYPE as row end invisible comment 'end',
+period for system_time (Sys_start, Sys_end)
+) with system versioning;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `x1` int(10) unsigned DEFAULT NULL,
+ `Sys_start` SYS_DATATYPE GENERATED ALWAYS AS ROW START INVISIBLE COMMENT 'start',
+ `Sys_end` SYS_DATATYPE GENERATED ALWAYS AS ROW END INVISIBLE COMMENT 'end',
+ PERIOD FOR SYSTEM_TIME (`Sys_start`, `Sys_end`)
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+select table_catalog,table_schema,table_name,table_type,version,table_rows,avg_row_length,data_free,auto_increment,check_time,table_collation,checksum,create_options,table_comment from information_schema.tables where table_name='t1';
+table_catalog def
+table_schema test
+table_name t1
+table_type SYSTEM VERSIONED
+version 10
+table_rows 0
+avg_row_length 0
+data_free 0
+auto_increment NULL
+check_time NULL
+table_collation latin1_swedish_ci
+checksum NULL
+create_options
+table_comment
+select table_catalog,table_schema,table_name,column_name,ordinal_position,column_default,character_maximum_length,character_octet_length,character_set_name,collation_name,column_key,extra,column_comment,is_generated,generation_expression from information_schema.columns where table_name='t1';
+table_catalog def
+table_schema test
+table_name t1
+column_name x1
+ordinal_position 1
+column_default NULL
+character_maximum_length NULL
+character_octet_length NULL
+character_set_name NULL
+collation_name NULL
+column_key
+extra
+column_comment
+is_generated NEVER
+generation_expression NULL
+table_catalog def
+table_schema test
+table_name t1
+column_name Sys_start
+ordinal_position 2
+column_default NULL
+character_maximum_length NULL
+character_octet_length NULL
+character_set_name NULL
+collation_name NULL
+column_key
+extra INVISIBLE
+column_comment start
+is_generated ALWAYS
+generation_expression ROW START
+table_catalog def
+table_schema test
+table_name t1
+column_name Sys_end
+ordinal_position 3
+column_default NULL
+character_maximum_length NULL
+character_octet_length NULL
+character_set_name NULL
+collation_name NULL
+column_key
+extra INVISIBLE
+column_comment end
+is_generated ALWAYS
+generation_expression ROW END
+# Implicit fields test
+create or replace table t1 (
+x2 int unsigned
+) with system versioning;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `x2` int(10) unsigned DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+create or replace table t1 (
+x3 int unsigned,
+Sys_start SYS_DATATYPE as row start invisible,
+Sys_end SYS_DATATYPE as row end invisible,
+period for system_time (x, Sys_end)
+) with system versioning;
+ERROR HY000: PERIOD FOR SYSTEM_TIME must use columns `Sys_start` and `Sys_end`
+create or replace table t1 (
+x4 int unsigned,
+Sys_start SYS_DATATYPE as row start invisible,
+Sys_end2 SYS_DATATYPE as row end invisible,
+period for system_time (Sys_start, Sys_end)
+) with system versioning;
+ERROR HY000: PERIOD FOR SYSTEM_TIME must use columns `Sys_start` and `Sys_end2`
+create or replace table t1 (
+x5 int unsigned,
+Sys_start SYS_DATATYPE as row start invisible,
+Sys_end SYS_DATATYPE as row end invisible,
+period for system_time (Sys_start, x)
+) with system versioning;
+ERROR HY000: PERIOD FOR SYSTEM_TIME must use columns `Sys_start` and `Sys_end`
+create or replace table t1 (
+x6 int unsigned,
+period for system_time (Sys_start, Sys_end)
+) with system versioning;
+ERROR HY000: Wrong parameters for `t1`: missing 'AS ROW START'
+create or replace table t1 (
+x7 int unsigned,
+Sys_start SYS_DATATYPE as row start invisible,
+Sys_end SYS_DATATYPE as row end invisible,
+period for system_time (Sys_start, Sys_end)
+);
+ERROR HY000: Wrong parameters for `t1`: missing 'WITH SYSTEM VERSIONING'
+create or replace table t1 (
+x8 int unsigned,
+Sys_start SYS_DATATYPE as row start invisible,
+Sys_end SYS_DATATYPE as row end invisible,
+period for system_time (sys_insert, sys_remove)
+) with system versioning;
+ERROR HY000: PERIOD FOR SYSTEM_TIME must use columns `Sys_start` and `Sys_end`
+create or replace table t1 (
+x9 int unsigned,
+Sys_start SYS_DATATYPE as row start invisible,
+Sys_end SYS_DATATYPE as row end invisible,
+period for system_time (Sys_start, Sys_end)
+);
+ERROR HY000: Wrong parameters for `t1`: missing 'WITH SYSTEM VERSIONING'
+create or replace table t1 (
+x10 int unsigned,
+Sys_start SYS_DATATYPE as row start invisible,
+Sys_end SYS_DATATYPE as row end invisible,
+period for system_time (Sys_start, Sys_start)
+);
+ERROR HY000: Wrong parameters for `t1`: missing 'WITH SYSTEM VERSIONING'
+create or replace table t1 (
+x11 int unsigned,
+Sys_start bigint unsigned as row start invisible,
+Sys_end timestamp(6) as row end invisible,
+period for system_time (Sys_start, Sys_end)
+) with system versioning;
+Got one of the listed errors
+create or replace table t1 (
+x12 int unsigned,
+Sys_start timestamp(6) as row start invisible,
+Sys_end bigint unsigned as row end invisible,
+period for system_time (Sys_start, Sys_end)
+) with system versioning;
+Got one of the listed errors
+create or replace table t1 (
+x13 int unsigned,
+Sys_start bigint as row start invisible,
+Sys_end bigint unsigned as row end invisible,
+period for system_time (Sys_start, Sys_end)
+) with system versioning engine innodb;
+ERROR HY000: `Sys_start` must be of type TIMESTAMP(6) for system-versioned table `t1`
+create or replace table t1 (
+x14 int unsigned,
+Sys_start bigint unsigned as row start invisible,
+Sys_end bigint as row end invisible,
+period for system_time (Sys_start, Sys_end)
+) with system versioning engine innodb;
+ERROR HY000: `Sys_end` must be of type BIGINT(20) UNSIGNED for system-versioned table `t1`
+create or replace table t1 (
+x15 int with system versioning,
+B int
+);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `x15` int(11) DEFAULT NULL,
+ `B` int(11) DEFAULT NULL WITHOUT SYSTEM VERSIONING
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+create or replace table t1 (
+x16 int with system versioning,
+B int
+) with system versioning;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `x16` int(11) DEFAULT NULL,
+ `B` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+create or replace table t1 (
+x17 int,
+B int without system versioning
+);
+create or replace table t1 (
+x18 int,
+B int without system versioning
+) with system versioning;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `x18` int(11) DEFAULT NULL,
+ `B` int(11) DEFAULT NULL WITHOUT SYSTEM VERSIONING
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+create or replace table t1 (
+x19 int with system versioning,
+B int without system versioning
+);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `x19` int(11) DEFAULT NULL,
+ `B` int(11) DEFAULT NULL WITHOUT SYSTEM VERSIONING
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+create or replace table t1 (
+x20 int with system versioning,
+B int without system versioning
+) with system versioning;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `x20` int(11) DEFAULT NULL,
+ `B` int(11) DEFAULT NULL WITHOUT SYSTEM VERSIONING
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+create or replace table t1 (
+x21 int without system versioning
+);
+create or replace table t1 (
+x22 int without system versioning
+) with system versioning;
+ERROR HY000: Table `t1` must have at least one versioned column
+create or replace table t1 (a int) with system versioning;
+create table tt1 like t1;
+show create table tt1;
+Table Create Table
+tt1 CREATE TABLE `tt1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+drop table tt1;
+create temporary table tt1 like t1;
+Warnings:
+Warning 1105 System versioning is stripped from temporary `test.tt1`
+# Temporary is stripped from versioning
+show create table tt1;
+Table Create Table
+tt1 CREATE TEMPORARY TABLE `tt1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
+# CREATE TABLE ... SELECT
+create or replace table t1 (x23 int) with system versioning;
+create or replace table t0(
+y int,
+st SYS_DATATYPE as row start,
+en SYS_DATATYPE as row end,
+period for system_time (st, en)
+) with system versioning;
+## For non-versioned table:
+### 1. invisible fields are not included
+create or replace table t2 as select * from t1;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `x23` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
+### 2. all visible fields are included
+create or replace table t3 as select * from t0;
+select * from t0;
+y st en
+show create table t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `y` int(11) DEFAULT NULL,
+ `st` SYS_DATATYPE,
+ `en` SYS_DATATYPE
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
+## For versioned table
+insert into t1 values (1);
+select row_start from t1 into @row_start;
+insert into t0 (y) values (2);
+select st from t0 into @st;
+create or replace table t2 with system versioning as select * from t1;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `x23` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+#### invisible fields are not copied
+select * from t2;
+x23
+1
+select * from t2 where row_start <= @row_start;
+x23
+### 2. source table with visible system fields, target with invisible
+create or replace table t3 with system versioning as select * from t0;
+show create table t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `y` int(11) DEFAULT NULL,
+ `st` SYS_DATATYPE,
+ `en` SYS_DATATYPE
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+select * from t3 where y > 2;
+y st en
+select y from t3 where st = @st and row_start > @st;
+y
+2
+### 3. source and target table with visible system fields
+create or replace table t3 (
+st SYS_DATATYPE as row start invisible,
+en SYS_DATATYPE as row end invisible,
+period for system_time (st, en)
+) with system versioning as select * from t0;
+show create table t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `y` int(11) DEFAULT NULL,
+ `st` SYS_DATATYPE GENERATED ALWAYS AS ROW START INVISIBLE,
+ `en` SYS_DATATYPE GENERATED ALWAYS AS ROW END INVISIBLE,
+ PERIOD FOR SYSTEM_TIME (`st`, `en`)
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+select y from t3;
+y
+2
+select y from t3 where st = @st;
+y
+### 4. system fields not or wrongly selected
+create or replace table t3 with system versioning select x23 from t1;
+show create table t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `x23` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+select * from t3;
+x23
+1
+create or replace table t3 with system versioning select x23, row_start from t1;
+ERROR HY000: Wrong parameters for `t3`: missing 'AS ROW END'
+create or replace table t3 with system versioning select x23, row_end from t1;
+ERROR HY000: Wrong parameters for `t3`: missing 'AS ROW START'
+# Prepare checking for historical row
+delete from t1;
+select row_end from t1 for system_time all into @row_end;
+delete from t0;
+select en from t0 for system_time all into @en;
+## Combinations of versioned + non-versioned
+create or replace table t2 (y int);
+insert into t2 values (3);
+create or replace table t3 with system versioning select * from t1 for system_time all, t2;
+show create table t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `x23` int(11) DEFAULT NULL,
+ `y` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+select * from t3 for system_time all;
+x23 y
+1 3
+select * from t3 for system_time all where row_start = @row_start and row_end = @row_end;
+x23 y
+create or replace table t2 like t0;
+insert into t2 (y) values (1), (2);
+delete from t2 where y = 2;
+create or replace table t3 select * from t2 for system_time all;
+select st, en from t3 where y = 1 into @st, @en;
+select y from t2 for system_time all where st = @st and en = @en;
+y
+1
+select st, en from t3 where y = 2 into @st, @en;
+select y from t2 for system_time all where st = @st and en = @en;
+y
+2
+## Default engine detection
+create or replace table t1 (x25 int) with system versioning engine NON_DEFAULT_ENGINE;
+create or replace table t2
+as select x25, row_start, row_end from t1 for system_time all;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `x25` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
+create or replace table t2 with system versioning
+as select x25, row_start, row_end from t1;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `x25` int(11) DEFAULT NULL
+) ENGINE=NON_DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+create or replace table t1 (
+x26 int,
+st bigint unsigned as row start,
+en bigint unsigned as row end,
+period for system_time (st, en)
+) with system versioning engine innodb;
+create or replace table t2 with system versioning engine myisam
+as select * from t1;
+ERROR HY000: `st` must be of type TIMESTAMP(6) for system-versioned table `t2`
+create or replace table t1 (x27 int, id int) with system versioning engine NON_DEFAULT_ENGINE;
+create or replace table t2 (b int, id int);
+create or replace table t3 with system versioning
+as select t2.b, t1.x27, t1.row_start, t1.row_end from t2 inner join t1 on t2.id=t1.id;
+show create table t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `b` int(11) DEFAULT NULL,
+ `x27` int(11) DEFAULT NULL
+) ENGINE=NON_DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+## Errors
+create or replace temporary table t (x28 int) with system versioning;
+ERROR HY000: System versioning prohibited for TEMPORARY tables
+create or replace table t1 (
+x29 int unsigned,
+Sys_start0 timestamp(6) as row start invisible,
+Sys_start timestamp(6) as row start invisible,
+Sys_end timestamp(6) as row end invisible,
+period for system_time (Sys_start, Sys_end)
+) with system versioning;
+ERROR HY000: Duplicate ROW START column `Sys_start`
+create or replace table t1 (
+x29 int unsigned,
+Sys_end0 timestamp(6) as row end invisible,
+Sys_start timestamp(6) as row start invisible,
+Sys_end timestamp(6) as row end invisible,
+period for system_time (Sys_start, Sys_end)
+) with system versioning;
+ERROR HY000: Duplicate ROW END column `Sys_end`
+## System fields detection
+create or replace table t1 (x30 int) with system versioning;
+create or replace table t2 (
+y int,
+st SYS_DATATYPE as row start invisible,
+en SYS_DATATYPE as row end invisible,
+period for system_time (st, en)
+) with system versioning;
+create or replace table t3
+as select x30, y, row_start, row_end, st, en from t1, t2;
+show create table t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `x30` int(11) DEFAULT NULL,
+ `y` int(11) DEFAULT NULL,
+ `st` SYS_DATATYPE NOT NULL INVISIBLE DEFAULT '0000-00-00 00:00:00.000000',
+ `en` SYS_DATATYPE NOT NULL INVISIBLE DEFAULT '0000-00-00 00:00:00.000000'
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
+create or replace table t3 (
+y int,
+st SYS_DATATYPE as row start invisible,
+en SYS_DATATYPE as row end invisible,
+period for system_time (st, en)
+) with system versioning
+as select x30, y, row_start, row_end, st, en from t1, t2;
+show create table t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `x30` int(11) DEFAULT NULL,
+ `y` int(11) DEFAULT NULL,
+ `st` SYS_DATATYPE GENERATED ALWAYS AS ROW START INVISIBLE,
+ `en` SYS_DATATYPE GENERATED ALWAYS AS ROW END INVISIBLE,
+ PERIOD FOR SYSTEM_TIME (`st`, `en`)
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+# MDEV-14828 Server crashes in JOIN::prepare / setup_fields on 2nd execution of PS [#437]
+create or replace table t1 (x int) with system versioning;
+prepare bad from 'create or replace table t2 with system versioning as select * from t1';
+execute bad;
+execute bad;
+execute bad;
+execute bad;
+execute bad;
+execute bad;
+execute bad;
+execute bad;
+# bad is good.
+drop database test;
+create database test;
diff --git a/mysql-test/suite/versioning/r/cte.result b/mysql-test/suite/versioning/r/cte.result
new file mode 100644
index 00000000000..fda5e086be2
--- /dev/null
+++ b/mysql-test/suite/versioning/r/cte.result
@@ -0,0 +1,118 @@
+set default_storage_engine=innodb;
+create or replace table dept (
+dept_id int(10) primary key,
+name varchar(100)
+)
+with system versioning;
+create or replace table emp (
+emp_id int(10) primary key,
+dept_id int(10) not null,
+name varchar(100) not null,
+mgr int(10),
+salary int(10) not null,
+constraint `dept-emp-fk`
+ foreign key (dept_id) references dept (dept_id)
+on delete cascade
+on update restrict,
+constraint `mgr-fk`
+ foreign key (mgr) references emp (emp_id)
+on delete restrict
+on update restrict
+)
+with system versioning;
+insert into dept (dept_id, name) values (10, "accounting");
+insert into emp (emp_id, name, salary, dept_id, mgr) values
+(1, "bill", 1000, 10, null),
+(20, "john", 500, 10, 1),
+(30, "jane", 750, 10,1 );
+select max(sys_trx_start) into @ts_1 from emp;
+update emp set mgr=30 where name ="john";
+select sys_trx_start into @ts_2 from emp where name="john";
+/* All report to 'Bill' */
+with recursive
+ancestors
+as
+(
+select e.emp_id, e.name, e.mgr, e.salary
+from emp for system_time as of timestamp @ts_1 as e
+where name = 'bill'
+ union
+select e.emp_id, e.name, e.mgr, e.salary
+from emp for system_time as of timestamp @ts_1 as e,
+ancestors as a
+where e.mgr = a.emp_id
+)
+select * from ancestors;
+emp_id name mgr salary
+1 bill NULL 1000
+20 john 1 500
+30 jane 1 750
+/* Expected 3 rows */
+with recursive
+ancestors
+as
+(
+select e.emp_id, e.name, e.mgr, e.salary
+from emp for system_time as of timestamp @ts_2 as e
+where name = 'bill'
+ union
+select e.emp_id, e.name, e.mgr, e.salary
+from emp for system_time as of timestamp @ts_2 as e,
+ancestors as a
+where e.mgr = a.emp_id
+)
+select * from ancestors;
+emp_id name mgr salary
+1 bill NULL 1000
+30 jane 1 750
+20 john 30 500
+create or replace table emp ( emp_id int, name varchar(127), mgr int) with system versioning;
+create or replace table addr ( emp_id int, address varchar(100)) with system versioning;
+insert emp values (1, 'bill', 0), (2, 'bill', 1), (3, 'kate', 1);
+insert addr values (1, 'Moscow'), (2, 'New York'), (3, 'London');
+set @ts=now(6);
+delete from emp;
+delete from addr;
+with recursive
+ancestors
+as
+(
+select e.emp_id, e.name, e.mgr
+from emp for system_time as of timestamp @ts as e
+where name = 'bill'
+ union
+select ee.emp_id, ee.name, ee.mgr
+from emp for system_time as of timestamp @ts as ee, ancestors as a
+where ee.mgr = a.emp_id
+)
+select * from ancestors;
+emp_id name mgr
+1 bill 0
+2 bill 1
+3 kate 1
+insert emp values (4, 'john', 1);
+insert addr values (4, 'Paris');
+with ancestors as (select * from emp natural join addr) select * from ancestors;
+emp_id name mgr address
+4 john 1 Paris
+with ancestors as (select * from emp natural join addr) select * from ancestors for system_time all;
+emp_id name mgr address
+1 bill 0 Moscow
+2 bill 1 New York
+3 kate 1 London
+4 john 1 Paris
+with ancestors as (select * from (select * from emp natural join addr) for system_time all as t) select * from ancestors;
+emp_id name mgr address
+1 bill 0 Moscow
+2 bill 1 New York
+3 kate 1 London
+4 john 1 Paris
+select * from (select * from emp natural join addr) for system_time all as t;
+emp_id name mgr address
+1 bill 0 Moscow
+2 bill 1 New York
+3 kate 1 London
+4 john 1 Paris
+drop table emp;
+drop table dept;
+drop table addr;
diff --git a/mysql-test/suite/versioning/r/ddl.result b/mysql-test/suite/versioning/r/ddl.result
new file mode 100644
index 00000000000..a4323b89ee1
--- /dev/null
+++ b/mysql-test/suite/versioning/r/ddl.result
@@ -0,0 +1,211 @@
+set @@session.time_zone='+00:00';
+select ifnull(max(transaction_id), 0) into @start_trx_id from mysql.transaction_registry;
+set @test_start=now(6);
+create procedure if not exists verify_vtq()
+begin
+set @i= 0;
+select
+@i:= @i + 1 as No,
+transaction_id > 0 as A,
+commit_id > transaction_id as B,
+begin_timestamp > @test_start as C,
+commit_timestamp >= begin_timestamp as D
+from mysql.transaction_registry
+where transaction_id > @start_trx_id;
+select ifnull(max(transaction_id), 0)
+into @start_trx_id
+from mysql.transaction_registry;
+end~~
+create function if not exists default_engine()
+returns varchar(255)
+deterministic
+begin
+declare e varchar(255);
+select lower(engine) from information_schema.engines where support='DEFAULT' into e;
+return e;
+end~~
+create function if not exists sys_datatype()
+returns varchar(255)
+deterministic
+begin
+if default_engine() = 'innodb' then
+return 'bigint unsigned';
+elseif default_engine() = 'myisam' then
+return 'timestamp(6)';
+end if;
+return NULL;
+end~~
+create function if not exists sys_commit_ts(sys_field varchar(255))
+returns varchar(255)
+deterministic
+begin
+if default_engine() = 'innodb' then
+return concat('vtq_commit_ts(', sys_field, ')');
+elseif default_engine() = 'myisam' then
+return sys_field;
+end if;
+return NULL;
+end~~
+create procedure if not exists innodb_verify_vtq(recs int)
+begin
+declare i int default 1;
+if default_engine() = 'innodb' then
+call verify_vtq;
+elseif default_engine() = 'myisam' then
+create temporary table tmp (No int, A bool, B bool, C bool, D bool);
+while i <= recs do
+insert into tmp values (i, 1, 1, 1, 1);
+set i= i + 1;
+end while;
+select * from tmp;
+drop table tmp;
+end if;
+end~~
+create procedure concat_exec2(a varchar(255), b varchar(255))
+begin
+prepare stmt from concat(a, b);
+execute stmt;
+deallocate prepare stmt;
+end~~
+create procedure concat_exec3(a varchar(255), b varchar(255), c varchar(255))
+begin
+prepare stmt from concat(a, b, c);
+execute stmt;
+deallocate prepare stmt;
+end~~
+create function get_archive_table_name()
+returns varchar(255)
+begin
+return (select archive_name from t_vtmd for system_time all where archive_name is not NULL
+order by start desc limit 1);
+end~~
+create procedure drop_last_archive()
+begin
+call concat_exec2('drop table ', get_archive_table_name());
+end~~
+set versioning_alter_history= survive;
+create or replace table t (a int) with system versioning;
+insert into t values (1);
+update t set a=2 where a=1;
+select sys_trx_start from t where a=2 into @tm;
+alter table t add column b int;
+select * from t;
+a b
+2 NULL
+call concat_exec3('select * from ', get_archive_table_name(), ' for system_time all');
+a
+2
+1
+call concat_exec3('select @tm=sys_trx_start from ', get_archive_table_name(), ' for system_time all where a=2');
+@tm=sys_trx_start
+1
+select @tm<sys_trx_start from t where a=2;
+@tm<sys_trx_start
+1
+select sys_trx_start from t where a=2 into @tm;
+call concat_exec3('select @tm=sys_trx_end from ', get_archive_table_name(), ' for system_time all where a=2');
+@tm=sys_trx_end
+1
+call drop_last_archive();
+set versioning_alter_history= keep;
+drop table t_vtmd;
+drop table t;
+set versioning_alter_history= survive;
+create or replace table t (a int) with system versioning;
+insert into t values (1);
+update t set a=2 where a=1;
+select sys_trx_start from t where a=2 into @tm;
+alter table t add column b int;
+select * from t;
+a b
+2 NULL
+call concat_exec3('select * from ', get_archive_table_name(), ' for system_time all');
+a
+2
+1
+call concat_exec3('select @tm=sys_trx_start from ', get_archive_table_name(), ' for system_time all where a=2');
+@tm=sys_trx_start
+1
+select @tm<sys_trx_start from t where a=2;
+@tm<sys_trx_start
+1
+select sys_trx_start from t where a=2 into @tm;
+call concat_exec3('select @tm=sys_trx_end from ', get_archive_table_name(), ' for system_time all where a=2');
+@tm=sys_trx_end
+1
+call drop_last_archive();
+set versioning_alter_history= keep;
+drop table t_vtmd;
+drop table t;
+set versioning_alter_history= survive;
+create or replace table t (a int) with system versioning engine innodb;
+insert into t values (1);
+update t set a=2 where a=1;
+select sys_trx_start from t where a=2 into @tm;
+alter table t add column b int;
+select * from t;
+a b
+2 NULL
+call concat_exec3('select * from ', get_archive_table_name(), ' for system_time all');
+a
+2
+1
+call concat_exec3('select @tm=sys_trx_start from ', get_archive_table_name(), ' for system_time all where a=2');
+@tm=sys_trx_start
+1
+select @tm<sys_trx_start from t where a=2;
+@tm<sys_trx_start
+1
+select sys_trx_start from t where a=2 into @tm;
+call concat_exec3('select @tm=sys_trx_end from ', get_archive_table_name(), ' for system_time all where a=2');
+@tm=sys_trx_end
+1
+call drop_last_archive();
+set versioning_alter_history= keep;
+drop table t_vtmd;
+drop table t;
+set versioning_alter_history= survive;
+create or replace table t (a int) with system versioning engine innodb;
+insert into t values (1);
+update t set a=2 where a=1;
+alter table t add column b int, algorithm=inplace;
+set versioning_alter_history = keep;
+drop function get_archive_table_name;
+drop procedure drop_last_archive;
+select * from mysql.vtmd_template;
+start end name archive_name col_renames
+show create table mysql.vtmd_template;
+Table Create Table
+vtmd_template CREATE TABLE `vtmd_template` (
+ `start` bigint(20) unsigned GENERATED ALWAYS AS ROW START COMMENT 'TRX_ID of table lifetime start',
+ `end` bigint(20) unsigned GENERATED ALWAYS AS ROW END NOT NULL COMMENT 'TRX_ID of table lifetime end',
+ `name` varchar(64) COLLATE utf8_bin NOT NULL COMMENT 'Table name during current lifetime period',
+ `archive_name` varchar(64) COLLATE utf8_bin DEFAULT NULL COMMENT 'Name of archive table',
+ `col_renames` blob DEFAULT NULL COMMENT 'Column name mappings from previous lifetime',
+ PRIMARY KEY (`end`),
+ KEY `archive_name` (`archive_name`),
+ PERIOD FOR SYSTEM_TIME (`start`, `end`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin STATS_PERSISTENT=0 WITH SYSTEM VERSIONING
+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
+6 1 1 1 1
+7 1 1 1 1
+8 1 1 1 1
+9 1 1 1 1
+10 1 1 1 1
+11 1 1 1 1
+12 1 1 1 1
+drop table t;
+drop table t_vtmd;
+drop procedure verify_vtq;
+drop procedure innodb_verify_vtq;
+drop function default_engine;
+drop function sys_commit_ts;
+drop function sys_datatype;
+drop procedure concat_exec2;
+drop procedure concat_exec3;
diff --git a/mysql-test/suite/versioning/r/debug.result b/mysql-test/suite/versioning/r/debug.result
new file mode 100644
index 00000000000..406717f8b5d
--- /dev/null
+++ b/mysql-test/suite/versioning/r/debug.result
@@ -0,0 +1,54 @@
+create table t1 (a int);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+create temporary table tt1 (a int) with system versioning;
+ERROR HY000: System versioning prohibited for TEMPORARY tables
+set @old_dbug=@@global.debug_dbug;
+set global debug_dbug='+d,sysvers_force';
+create table t2 (a int);
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+create temporary table tt2 (a int) with system versioning;
+show create table tt2;
+Table Create Table
+tt2 CREATE TEMPORARY TABLE `tt2` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+connect con1, localhost, root;
+create table t3 (a int);
+show create table t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+create temporary table tt3 (a int) with system versioning;
+show create table tt3;
+Table Create Table
+tt3 CREATE TEMPORARY TABLE `tt3` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+disconnect con1;
+connection default;
+set debug_dbug='+d,sysvers_show';
+show create table t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+create table t4 (a int);
+show create table t4;
+Table Create Table
+t4 CREATE TABLE `t4` (
+ `a` int(11) DEFAULT NULL,
+ `row_start` timestamp(6) GENERATED ALWAYS AS ROW START,
+ `row_end` timestamp(6) GENERATED ALWAYS AS ROW END,
+ PERIOD FOR SYSTEM_TIME (`row_start`, `row_end`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+set global debug_dbug=@old_dbug;
+drop table t1, t2, t3, t4;
diff --git a/mysql-test/suite/versioning/r/delete.result b/mysql-test/suite/versioning/r/delete.result
new file mode 100644
index 00000000000..79f619fecdd
--- /dev/null
+++ b/mysql-test/suite/versioning/r/delete.result
@@ -0,0 +1,320 @@
+create or replace procedure test_01(
+sys_type varchar(255),
+engine varchar(255),
+fields varchar(255))
+begin
+set @str= concat('
+ create or replace table t1(
+ XNo int unsigned,
+ sys_start ', sys_type, ' as row start invisible,
+ sys_end ', sys_type, ' as row end invisible,
+ period for system_time (sys_start, sys_end))
+ with system versioning
+ engine ', engine);
+prepare stmt from @str; execute stmt; drop prepare stmt;
+insert into t1(XNo) values(0);
+insert into t1(XNo) values(1);
+insert into t1(XNo) values(2);
+insert into t1(XNo) values(3);
+insert into t1(XNo) values(4);
+insert into t1(XNo) values(5);
+insert into t1(XNo) values(6);
+insert into t1(XNo) values(7);
+insert into t1(XNo) values(8);
+insert into t1(XNo) values(9);
+set @str= concat('select XNo, ',
+fields, " < '2038-01-19 03:14:07'
+ from t1 for system_time
+ between timestamp '0000-0-0 0:0:0'
+ and timestamp '2038-01-19 04:14:07'");
+prepare stmt from @str; execute stmt;
+delete from t1 where XNo = 0;
+select "Deleted 0";
+execute stmt;
+delete from t1 where XNo = 1;
+select "Deleted 1";
+execute stmt;
+delete from t1 where XNo > 5;
+select "Deleted >5";
+create view vt1 as select XNo from t1;
+select XNo as XNo_vt1 from vt1;
+delete from vt1 where XNo = 3;
+select "Deleted from VIEW 3";
+select XNo as XNo_vt1 from vt1;
+execute stmt; drop prepare stmt;
+drop view vt1;
+drop table t1;
+end~~
+create or replace procedure test_02(
+sys_type varchar(255),
+engine varchar(255),
+fields varchar(255))
+begin
+set @str= concat('create or replace table t1 (
+ x int,
+ sys_start ', sys_type, ' as row start invisible,
+ sys_end ', sys_type, ' as row end invisible,
+ period for system_time (sys_start, sys_end))
+ with system versioning
+ engine ', engine);
+prepare stmt from @str; execute stmt; drop prepare stmt;
+insert into t1(x) values (1);
+select sys_start into @sys_start from t1;
+delete from t1;
+select * from t1;
+select x = 1 as A, sys_start = @sys_start as B, sys_end > sys_start as C
+from t1 for system_time between timestamp '0-0-0' and timestamp '2038-01-19 04:14:07';
+drop table t1;
+end~~
+create or replace procedure test_03(
+sys_type varchar(255),
+engine varchar(255),
+fields varchar(255))
+begin
+set @str0= concat('(
+ x int,
+ y int,
+ sys_start ', sys_type, ' as row start invisible,
+ sys_end ', sys_type, ' as row end invisible,
+ period for system_time (sys_start, sys_end))
+ with system versioning
+ engine ', engine);
+set @str= concat('create or replace table t1', @str0);
+prepare stmt from @str; execute stmt; drop prepare stmt;
+set @str= concat('create or replace table t2', @str0);
+prepare stmt from @str; execute stmt; drop prepare stmt;
+insert into t1(x, y) values (1, 1), (2, 2), (3, 3), (14, 4);
+insert into t2(x, y) values (11, 1), (12, 2), (13, 32), (14, 4);
+delete t1, t2 from t1 join t2 where t1.y = 3 and t2.y = 32;
+select x as t1_x from t1;
+select x as t2_x from t2;
+delete t1, t2 from t1 join t2 where t1.x = t2.x;
+select x as t1_x from t1;
+select x as t2_x from t2;
+select x as t1_x_all from t1 for system_time between timestamp '0-0-0' and timestamp '2038-01-19 04:14:07';
+select x as t2_x_all from t2 for system_time between timestamp '0-0-0' and timestamp '2038-01-19 04:14:07';
+drop table t1;
+drop table t2;
+end~~
+# Basic + delete from view
+call test_01('timestamp(6)', 'myisam', 'sys_end');
+XNo sys_end < '2038-01-19 03:14:07'
+0 0
+1 0
+2 0
+3 0
+4 0
+5 0
+6 0
+7 0
+8 0
+9 0
+Deleted 0
+Deleted 0
+XNo sys_end < '2038-01-19 03:14:07'
+0 1
+1 0
+2 0
+3 0
+4 0
+5 0
+6 0
+7 0
+8 0
+9 0
+Deleted 1
+Deleted 1
+XNo sys_end < '2038-01-19 03:14:07'
+0 1
+1 1
+2 0
+3 0
+4 0
+5 0
+6 0
+7 0
+8 0
+9 0
+Deleted >5
+Deleted >5
+XNo_vt1
+2
+3
+4
+5
+Deleted from VIEW 3
+Deleted from VIEW 3
+XNo_vt1
+2
+4
+5
+XNo sys_end < '2038-01-19 03:14:07'
+0 1
+1 1
+2 0
+3 1
+4 0
+5 0
+6 1
+7 1
+8 1
+9 1
+call test_01('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)');
+XNo vtq_commit_ts(sys_end) < '2038-01-19 03:14:07'
+0 0
+1 0
+2 0
+3 0
+4 0
+5 0
+6 0
+7 0
+8 0
+9 0
+Deleted 0
+Deleted 0
+XNo vtq_commit_ts(sys_end) < '2038-01-19 03:14:07'
+0 1
+1 0
+2 0
+3 0
+4 0
+5 0
+6 0
+7 0
+8 0
+9 0
+Deleted 1
+Deleted 1
+XNo vtq_commit_ts(sys_end) < '2038-01-19 03:14:07'
+0 1
+1 1
+2 0
+3 0
+4 0
+5 0
+6 0
+7 0
+8 0
+9 0
+Deleted >5
+Deleted >5
+XNo_vt1
+2
+3
+4
+5
+Deleted from VIEW 3
+Deleted from VIEW 3
+XNo_vt1
+2
+4
+5
+XNo vtq_commit_ts(sys_end) < '2038-01-19 03:14:07'
+0 1
+1 1
+2 0
+3 1
+4 0
+5 0
+6 1
+7 1
+8 1
+9 1
+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
+6 1 1 1 1
+7 1 1 1 1
+8 1 1 1 1
+9 1 1 1 1
+10 1 1 1 1
+11 1 1 1 1
+12 1 1 1 1
+13 1 1 1 1
+14 1 1 1 1
+# Check sys_start, sys_end
+call test_02('timestamp(6)', 'myisam', 'sys_end');
+x
+A B C
+1 1 1
+call test_02('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)');
+x
+A B C
+1 1 1
+call verify_vtq;
+No A B C D
+1 1 1 1 1
+2 1 1 1 1
+# Multi-delete
+call test_03('timestamp(6)', 'myisam', 'sys_end');
+t1_x
+1
+2
+14
+t2_x
+11
+12
+14
+t1_x
+1
+2
+t2_x
+11
+12
+t1_x_all
+1
+2
+3
+14
+t2_x_all
+11
+12
+13
+14
+call test_03('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)');
+t1_x
+1
+2
+14
+t2_x
+11
+12
+14
+t1_x
+1
+2
+t2_x
+11
+12
+t1_x_all
+1
+2
+3
+14
+t2_x_all
+11
+12
+13
+14
+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
+# Update + delete
+create or replace table t1 (x int) with system versioning;
+insert into t1 values (1);
+update t1 set x= 2;
+delete from t1;
+select x from t1 for system_time all;
+x
+2
+1
+drop database test;
+create database test;
diff --git a/mysql-test/suite/versioning/r/derived.result b/mysql-test/suite/versioning/r/derived.result
new file mode 100644
index 00000000000..cd6cec7e725
--- /dev/null
+++ b/mysql-test/suite/versioning/r/derived.result
@@ -0,0 +1,295 @@
+create table emp
+(
+emp_id int,
+name varchar(127),
+mgr int
+) with system versioning;
+insert into emp values (1, 'bill', 0),
+(2, 'bill', 1),
+(3, 'kate', 1);
+set @ts=now(6);
+delete from emp;
+insert into emp values (4, 'john', 1);
+with ancestors as (select * from emp) select * from ancestors;
+emp_id name mgr
+4 john 1
+set @tmp= "with ancestors as (select * from emp) select * from ancestors";
+prepare stmt from @tmp;
+execute stmt;
+emp_id name mgr
+4 john 1
+drop prepare stmt;
+with ancestors as (select * from emp for system_time all) select * from ancestors;
+emp_id name mgr
+1 bill 0
+2 bill 1
+3 kate 1
+4 john 1
+set @tmp= "with ancestors as (select * from emp for system_time all) select * from ancestors";
+prepare stmt from @tmp;
+execute stmt;
+emp_id name mgr
+1 bill 0
+2 bill 1
+3 kate 1
+4 john 1
+drop prepare stmt;
+with recursive ancestors as (select * from emp) select * from ancestors;
+emp_id name mgr
+4 john 1
+set @tmp= "with recursive ancestors as (select * from emp) select * from ancestors";
+prepare stmt from @tmp;
+execute stmt;
+emp_id name mgr
+4 john 1
+drop prepare stmt;
+select emp_id from (select emp_id from emp where row_end>'2031-1-1') as tmp;
+emp_id
+4
+set @tmp= "select emp_id from (select emp_id from emp where row_end>'2031-1-1') as tmp";
+prepare stmt from @tmp;
+execute stmt;
+emp_id
+4
+drop prepare stmt;
+with recursive
+ancestors
+as
+(
+select e.emp_id, e.name, e.mgr
+from emp as e
+where name = 'john'
+ union
+select ee.emp_id, ee.name, ee.mgr
+from emp as ee, ancestors as a
+where ee.mgr = a.emp_id
+)
+select * from ancestors;
+emp_id name mgr
+4 john 1
+set @tmp= "
+with recursive
+ancestors
+as
+(
+ select e.emp_id, e.name, e.mgr
+ from emp as e
+ where name = 'john'
+ union
+ select ee.emp_id, ee.name, ee.mgr
+ from emp as ee, ancestors as a
+ where ee.mgr = a.emp_id
+)
+select * from ancestors";
+prepare stmt from @tmp;
+execute stmt;
+emp_id name mgr
+4 john 1
+drop prepare stmt;
+with recursive
+ancestors
+as
+(
+select e.emp_id, e.name, e.mgr
+from emp for system_time as of timestamp @ts as e
+where name = 'bill'
+ union
+select ee.emp_id, ee.name, ee.mgr
+from emp for system_time as of timestamp @ts as ee,
+ancestors as a
+where ee.mgr = a.emp_id
+)
+select * from ancestors;
+emp_id name mgr
+1 bill 0
+2 bill 1
+3 kate 1
+set @tmp= "
+with recursive
+ancestors
+as
+(
+ select e.emp_id, e.name, e.mgr
+ from emp for system_time as of timestamp @ts as e
+ where name = 'bill'
+ union
+ select ee.emp_id, ee.name, ee.mgr
+ from emp for system_time as of timestamp @ts as ee,
+ ancestors as a
+ where ee.mgr = a.emp_id
+)
+select * from ancestors";
+prepare stmt from @tmp;
+execute stmt;
+emp_id name mgr
+1 bill 0
+2 bill 1
+3 kate 1
+drop prepare stmt;
+drop table emp;
+create or replace table t1 (x int) with system versioning;
+create or replace table t2 (y int) with system versioning;
+insert into t1 values (1);
+set @t0= now(6);
+delete from t1;
+insert into t1 values (2);
+insert into t2 values (10);
+select * from (select *, t1.row_end, t1.row_end as endo from t1) as s0;
+x row_end endo
+2 # #
+select * from (select *, t1.row_end, t2.row_start from t1, t2) as s0;
+x y row_end row_start
+2 10 # #
+# SYSTEM_TIME propagation from inner to outer
+select * from (select * from t1 for system_time as of timestamp @t0, t2) as s0;
+x y
+1 10
+with s1 as (select * from t1 for system_time as of timestamp @t0, t2) select * from s1;
+x y
+1 10
+# leading table selection
+select * from (select *, t1.row_end from t2, t1 for system_time as of timestamp @t0) as s2;
+y x row_end
+10 1 #
+with s3 as (select *, t1.row_end from t2, t1 for system_time as of timestamp @t0) select * from s3;
+y x row_end
+10 1 #
+### VIEW instead of t1
+set @q= concat("create view vt1 as select * from t1 for system_time as of timestamp '", @t0, "'");
+prepare q from @q;
+execute q;
+drop prepare q;
+create view vt2 as select * from t1;
+# SYSTEM_TIME propagation from view
+select * from vt1;
+x
+1
+# SYSTEM_TIME propagation from inner to outer
+select * from (select * from vt1, t2) as s0;
+x y
+1 10
+### SYSTEM_TIME clash
+select * from (select * from t1 for system_time all) for system_time all as dt0;
+ERROR HY000: Table `dt0` is not system-versioned
+select * from vt1 for system_time all;
+ERROR HY000: Table `vt1` is not system-versioned
+with dt1 as (select * from t1 for system_time all)
+select * from dt1 for system_time all;
+ERROR HY000: Table `dt1` is not system-versioned
+### UNION
+set @t1= now(6);
+delete from t2;
+insert into t2 values (3);
+# SYSTEM_TIME is not propagated
+select x from t1 union
+select y from t2;
+x
+2
+3
+select x from t1 for system_time as of @t0 union
+select y from t2;
+x
+1
+3
+select x from t1 union
+select y from t2 for system_time as of @t1;
+x
+2
+10
+select x from t1 for system_time as of @t0 union
+select y from t2 for system_time as of @t1;
+x
+1
+10
+# LEFT/RIGHT JOIN
+create or replace table t1 (x int, y int) with system versioning;
+create or replace table t2 (x int, y int) with system versioning;
+insert into t1 values (1, 1), (1, 2), (1, 3), (4, 4), (5, 5);
+insert into t2 values (1, 2), (2, 1), (3, 1);
+## Outer or inner SYSTEM_TIME produces same expression
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where; Using join buffer (flat, BNL join)
+Query A:
+Note 1003 select `test`.`t1`.`x` AS `x`,`test`.`t1`.`y` AS `y1`,`test`.`t2`.`x` AS `x2`,`test`.`t2`.`y` AS `y2` from `test`.`t1` FOR SYSTEM_TIME ALL join `test`.`t2` FOR SYSTEM_TIME ALL where `test`.`t1`.`x` = `test`.`t2`.`x` and `test`.`t1`.`row_end` > <cache>(cast(current_timestamp(6) as datetime(6))) and `test`.`t1`.`row_start` <= <cache>(cast(current_timestamp(6) as datetime(6))) and `test`.`t2`.`row_end` > <cache>(cast(current_timestamp(6) as datetime(6))) and `test`.`t2`.`row_start` <= <cache>(cast(current_timestamp(6) as datetime(6)))
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where; Using join buffer (flat, BNL join)
+Query B:
+Note 1003 select `test`.`t1`.`x` AS `x`,`test`.`t1`.`y` AS `y1`,`test`.`t2`.`x` AS `x2`,`test`.`t2`.`y` AS `y2` from `test`.`t1` FOR SYSTEM_TIME ALL join `test`.`t2` FOR SYSTEM_TIME ALL where `test`.`t1`.`x` = `test`.`t2`.`x` and `test`.`t1`.`row_end` > <cache>(cast(current_timestamp(6) as datetime(6))) and `test`.`t1`.`row_start` <= <cache>(cast(current_timestamp(6) as datetime(6))) and `test`.`t2`.`row_end` > <cache>(cast(current_timestamp(6) as datetime(6))) and `test`.`t2`.`row_start` <= <cache>(cast(current_timestamp(6) as datetime(6)))
+Fine result: queries A and B are equal.
+## LEFT JOIN: t1, t2 versioned
+select * from (
+select t1.x as LJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2
+from t1 left join t2 on t1.x = t2.x)
+as derived;
+LJ1_x1 y1 x2 y2
+1 1 1 2
+1 2 1 2
+1 3 1 2
+4 4 NULL NULL
+5 5 NULL NULL
+alter table t2 drop system versioning;
+## LEFT JOIN: t1 versioned
+select * from (
+select t1.x as LJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2
+from t1 left join t2 on t1.x = t2.x)
+as derived;
+LJ2_x1 y1 x2 y2
+1 1 1 2
+1 2 1 2
+1 3 1 2
+4 4 NULL NULL
+5 5 NULL NULL
+alter table t1 drop system versioning;
+alter table t2 add system versioning;
+## LEFT JOIN: t2 versioned
+select * from (
+select t1.x as LJ3_x1, t1.y as y1, t2.x as x2, t2.y as y2
+from t1 left join t2 on t1.x = t2.x)
+as derived;
+LJ3_x1 y1 x2 y2
+1 1 1 2
+1 2 1 2
+1 3 1 2
+4 4 NULL NULL
+5 5 NULL NULL
+alter table t1 add system versioning;
+## RIGHT JOIN: t1, t2 versioned
+select * from (
+select t1.x as RJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2
+from t1 right join t2 on t1.x = t2.x)
+as derived;
+RJ1_x1 y1 x2 y2
+1 1 1 2
+1 2 1 2
+1 3 1 2
+NULL NULL 2 1
+NULL NULL 3 1
+alter table t2 drop system versioning;
+## RIGHT JOIN: t1 versioned
+select * from (
+select t1.x as RJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2
+from t1 right join t2 on t1.x = t2.x)
+as derived;
+RJ2_x1 y1 x2 y2
+1 1 1 2
+1 2 1 2
+1 3 1 2
+NULL NULL 2 1
+NULL NULL 3 1
+alter table t1 drop system versioning;
+alter table t2 add system versioning;
+## RIGHT JOIN: t2 versioned
+select * from (
+select t1.x as RJ3_x1, t1.y as y1, t2.x as x2, t2.y as y2
+from t1 right join t2 on t1.x = t2.x)
+as derived;
+RJ3_x1 y1 x2 y2
+1 1 1 2
+1 2 1 2
+1 3 1 2
+NULL NULL 2 1
+NULL NULL 3 1
+drop table t1, t2;
+drop view vt1, vt2;
diff --git a/mysql-test/suite/versioning/r/foreign.result b/mysql-test/suite/versioning/r/foreign.result
new file mode 100644
index 00000000000..ca2459f784a
--- /dev/null
+++ b/mysql-test/suite/versioning/r/foreign.result
@@ -0,0 +1,232 @@
+#################
+# Test RESTRICT #
+#################
+create table parent(
+id int unique key
+) engine innodb;
+create table child(
+parent_id int,
+sys_start SYS_DATATYPE as row start invisible,
+sys_end SYS_DATATYPE as row end invisible,
+period for system_time(sys_start, sys_end),
+foreign key(parent_id) references parent(id)
+on delete restrict
+on update restrict
+) engine innodb with system versioning;
+insert into parent values(1);
+insert into child values(1);
+delete from parent where id = 1;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
+delete from child where parent_id = 1;
+delete from parent where id = 1;
+insert into parent values(1);
+insert into child values(1);
+update parent set id=id+1;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
+delete from child;
+update parent set id=id+1;
+select * from child for system_time from timestamp '1-1-1' to timestamp now(6);
+parent_id
+1
+1
+drop table child;
+drop table parent;
+##############################################
+# Test when clustered index is a foreign key #
+##############################################
+create table parent(
+id int(10) unsigned unique key
+) engine innodb;
+create table child(
+parent_id int(10) unsigned primary key,
+sys_start SYS_DATATYPE as row start invisible,
+sys_end SYS_DATATYPE as row end invisible,
+period for system_time(sys_start, sys_end),
+foreign key(parent_id) references parent(id)
+) engine innodb with system versioning;
+insert into parent values(1);
+insert into child values(1);
+delete from parent where id = 1;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
+drop table child;
+drop table parent;
+################
+# Test CASCADE #
+################
+create table parent(
+id int unique key
+) engine innodb;
+create table child(
+parent_id int,
+sys_start SYS_DATATYPE as row start invisible,
+sys_end SYS_DATATYPE as row end invisible,
+period for system_time(sys_start, sys_end),
+foreign key(parent_id) references parent(id)
+on delete cascade
+on update cascade
+) engine innodb with system versioning;
+insert into parent values(1);
+insert into child values(1);
+## FIXME: #415 update of foreign constraints is disabled
+call mtr.add_suppression("foreign key constraints in timestamp-based temporal table");
+delete from parent where id = 1;
+ERROR 42000: Table 'parent' uses an extension that doesn't exist in this MariaDB version
+delete from child where parent_id = 1;
+## FIXME END
+delete from parent where id = 1;
+select * from child;
+parent_id
+select * from child for system_time all;
+parent_id
+1
+insert into parent values(1);
+insert into child values(1);
+update parent set id = id + 1;
+select * from child;
+parent_id
+2
+select * from child for system_time all;
+parent_id
+1
+2
+drop table child;
+drop table parent;
+create or replace table parent (
+id int primary key,
+sys_start SYS_DATATYPE as row start invisible,
+sys_end SYS_DATATYPE as row end invisible,
+period for system_time(sys_start, sys_end)
+) with system versioning
+engine innodb;
+create or replace table child (
+x int,
+parent_id int not null,
+constraint `parent-fk`
+ foreign key (parent_id) references parent (id)
+on delete cascade
+on update restrict
+)
+engine innodb;
+insert into parent (id) values (2);
+insert into child (x, parent_id) values (2, 2);
+delete from parent;
+select * from child;
+x parent_id
+drop table child;
+drop table parent;
+create or replace table parent (
+id int primary key
+)
+engine innodb;
+create or replace table child (
+id int primary key,
+parent_id int not null,
+constraint `parent-fk`
+ foreign key (parent_id) references parent (id)
+on delete cascade
+on update restrict
+) with system versioning
+engine innodb;
+insert into parent (id) values (3);
+insert into child (id, parent_id) values (3, 3);
+## FIXME: #415 update of foreign constraints is disabled
+delete from child;
+## FIXME END
+delete from parent;
+select * from child;
+id parent_id
+select * from child for system_time all;
+id parent_id
+3 3
+drop table child;
+drop table parent;
+#################
+# Test SET NULL #
+#################
+create table parent(
+id int unique key
+) engine innodb;
+create table child(
+parent_id int,
+sys_start SYS_DATATYPE as row start invisible,
+sys_end SYS_DATATYPE as row end invisible,
+period for system_time(sys_start, sys_end),
+foreign key(parent_id) references parent(id)
+on delete set null
+on update set null
+) engine innodb with system versioning;
+insert into parent values(1);
+insert into child values(1);
+delete from child;
+insert into child values(1);
+## FIXME: #415 update of foreign constraints is disabled
+delete from child where parent_id = 1;
+## FIXME END
+delete from parent where id = 1;
+select * from child;
+parent_id
+select * from child for system_time from timestamp '1-1-1' to timestamp now(6);
+parent_id
+1
+1
+delete from child;
+insert into parent values(1);
+insert into child values(1);
+drop table child;
+drop table parent;
+###########################
+# Parent table is foreign #
+###########################
+create or replace table parent(
+id int unique key,
+sys_start SYS_DATATYPE as row start invisible,
+sys_end SYS_DATATYPE as row end invisible,
+period for system_time(sys_start, sys_end)
+) engine innodb with system versioning;
+create or replace table child(
+parent_id int,
+foreign key(parent_id) references parent(id)
+) engine innodb;
+insert into parent values(1);
+insert into child values(1);
+delete from parent;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
+update parent set id=2;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
+delete from child;
+delete from parent;
+insert into child values(1);
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
+insert into parent values(1);
+insert into child values(1);
+delete from parent;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
+update parent set id=2;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
+drop table child;
+drop table parent;
+###################
+# crash on DELETE #
+###################
+create or replace table a (
+cola int(10) primary key,
+v_cola int(10) as (cola mod 10) virtual,
+sys_start SYS_DATATYPE as row start invisible,
+sys_end SYS_DATATYPE as row end invisible,
+period for system_time(sys_start, sys_end)
+) engine=innodb with system versioning;
+create index v_cola on a (v_cola);
+create or replace table b(
+cola int(10),
+v_cola int(10),
+sys_start SYS_DATATYPE as row start invisible,
+sys_end SYS_DATATYPE as row end invisible,
+period for system_time(sys_start, sys_end)
+) engine=innodb with system versioning;
+alter table b add constraint `v_cola_fk`
+foreign key (v_cola) references a (v_cola);
+insert into a(cola) values (12);
+insert into b(cola, v_cola) values (10,2);
+delete from a;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`b`, CONSTRAINT `v_cola_fk` FOREIGN KEY (`v_cola`) REFERENCES `a` (`v_cola`))
+drop table b, a;
diff --git a/mysql-test/suite/versioning/r/insert.result b/mysql-test/suite/versioning/r/insert.result
new file mode 100644
index 00000000000..0c9718c106b
--- /dev/null
+++ b/mysql-test/suite/versioning/r/insert.result
@@ -0,0 +1,368 @@
+create procedure test_01(
+sys_type varchar(255),
+engine varchar(255),
+fields varchar(255))
+begin
+set @str= concat('
+ create table t1(
+ x int unsigned,
+ y int unsigned,
+ sys_start ', sys_type, ' as row start invisible,
+ sys_end ', sys_type, ' as row end invisible,
+ period for system_time (sys_start, sys_end))
+ with system versioning
+ engine ', engine);
+prepare stmt from @str; execute stmt; drop prepare stmt;
+insert into t1(x, y) values(3, 4);
+insert delayed into t1(x, y) values(2, 3);
+insert into t1 values(40, 33);
+set @str= concat('select x, y, ', fields, ' from t1');
+prepare stmt from @str; execute stmt; drop prepare stmt;
+drop table t1;
+end~~
+create procedure test_02(
+sys_type varchar(255),
+engine varchar(255),
+fields varchar(255))
+begin
+set @str= concat('
+ create table t1(
+ id int unsigned auto_increment primary key,
+ x int unsigned,
+ y int unsigned,
+ sys_start ', sys_type, ' as row start invisible,
+ sys_end ', sys_type, ' as row end invisible,
+ period for system_time (sys_start, sys_end))
+ with system versioning
+ engine ', engine);
+prepare stmt from @str; execute stmt; drop prepare stmt;
+insert into t1(x, y) values(33, 44);
+insert into t1(id, x, y) values(20, 33, 44);
+insert into t1 values(40, 33, 44);
+set @str= concat('select id, x, y, ', fields, ' from t1');
+prepare stmt from @str; execute stmt; drop prepare stmt;
+drop table t1;
+end~~
+create procedure test_03(
+sys_type varchar(255),
+engine varchar(255),
+fields varchar(255))
+begin
+set @str= concat('
+ create table t1(
+ x int unsigned,
+ y int unsigned,
+ sys_start ', sys_type, ' as row start invisible,
+ sys_end ', sys_type, ' as row end invisible,
+ period for system_time (sys_start, sys_end))
+ with system versioning
+ engine ', engine);
+prepare stmt from @str; execute stmt; drop prepare stmt;
+create view vt1_1 as select x, y from t1;
+insert into t1(x, y) values(8001, 9001);
+insert into vt1_1(x, y) values(1001, 2001);
+insert into vt1_1 values(1002, 2002);
+set @str= concat('select x, y, ', fields, ' from t1');
+prepare stmt from @str; execute stmt; drop prepare stmt;
+select x, y from vt1_1;
+end~~
+create procedure test_04(
+sys_type varchar(255),
+engine varchar(255),
+fields varchar(255))
+begin
+set @str= concat('
+ create table t1(
+ id bigint primary key,
+ a int,
+ b int)
+ with system versioning
+ engine ', engine);
+prepare stmt from @str; execute stmt; drop prepare stmt;
+insert into t1 values(1, 1, 1);
+select row_start, row_end from t1 into @sys_start, @sys_end;
+select id, a, b from t1;
+insert into t1 values(2, 2, 2);
+select id, a, b, row_start > @sys_start as C, row_end = @sys_end as D from t1 where id = 2;
+drop table t1;
+end~~
+create procedure test_05(
+sys_type varchar(255),
+engine varchar(255),
+fields varchar(255))
+begin
+set @str= concat('(
+ x int unsigned,
+ y int unsigned,
+ sys_start ', sys_type, ' as row start invisible,
+ sys_end ', sys_type, ' as row end invisible,
+ period for system_time (sys_start, sys_end))
+ with system versioning
+ engine ', engine);
+set @str2= concat('create table t1', @str);
+prepare stmt from @str2; execute stmt; drop prepare stmt;
+set @str2= concat('create table t2', @str);
+prepare stmt from @str2; execute stmt; drop prepare stmt;
+insert into t1(x, y) values
+(1, 1000),
+(2, 2000),
+(3, 3000),
+(4, 4000),
+(5, 5000),
+(6, 6000),
+(7, 7000),
+(8, 8000),
+(9, 9000);
+delete from t1 where x >= 1;
+insert into t1(x, y) values
+(1, 1001),
+(2, 2001),
+(3, 3001),
+(4, 4001),
+(5, 5001),
+(6, 6001);
+insert into t1(x, y, sys_start) values
+(7, 7001, DEFAULT);
+insert into t1(x, y, sys_end) values
+(8, 8001, DEFAULT);
+insert into t1(x, y, sys_start, sys_end) values
+(9, 9001, DEFAULT, DEFAULT);
+insert into t2 select x, y from t1 for system_time between timestamp '0000-0-0 0:0:0' and timestamp '9999-1-1 0:0:0';
+select x, y from t1;
+select x, y from t2;
+drop table t1;
+drop table t2;
+end~~
+call test_01('timestamp(6)', 'myisam', 'sys_end');
+x y sys_end
+3 4 2038-01-19 03:14:07.999999
+2 3 2038-01-19 03:14:07.999999
+40 33 2038-01-19 03:14:07.999999
+call test_01('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)');
+x y vtq_commit_ts(sys_end)
+3 4 2038-01-19 03:14:07.999999
+2 3 2038-01-19 03:14:07.999999
+40 33 2038-01-19 03:14:07.999999
+call test_02('timestamp(6)', 'myisam', 'sys_end');
+id x y sys_end
+1 33 44 2038-01-19 03:14:07.999999
+20 33 44 2038-01-19 03:14:07.999999
+40 33 44 2038-01-19 03:14:07.999999
+call test_02('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)');
+id x y vtq_commit_ts(sys_end)
+1 33 44 2038-01-19 03:14:07.999999
+20 33 44 2038-01-19 03:14:07.999999
+40 33 44 2038-01-19 03:14:07.999999
+call test_03('timestamp(6)', 'myisam', 'sys_end');
+x y sys_end
+8001 9001 2038-01-19 03:14:07.999999
+1001 2001 2038-01-19 03:14:07.999999
+1002 2002 2038-01-19 03:14:07.999999
+x y
+8001 9001
+1001 2001
+1002 2002
+drop table t1;
+drop view vt1_1;
+call test_03('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)');
+x y vtq_commit_ts(sys_end)
+8001 9001 2038-01-19 03:14:07.999999
+1001 2001 2038-01-19 03:14:07.999999
+1002 2002 2038-01-19 03:14:07.999999
+x y
+8001 9001
+1001 2001
+1002 2002
+drop table t1;
+drop view vt1_1;
+call test_04('timestamp(6)', 'myisam', 'sys_end');
+id a b
+1 1 1
+id a b C D
+2 2 2 1 1
+call test_04('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)');
+id a b
+1 1 1
+id a b C D
+2 2 2 1 1
+call test_05('timestamp(6)', 'myisam', 'sys_end');
+x y
+1 1001
+2 2001
+3 3001
+4 4001
+5 5001
+6 6001
+7 7001
+8 8001
+9 9001
+x y
+1 1000
+2 2000
+3 3000
+4 4000
+5 5000
+6 6000
+7 7000
+8 8000
+9 9000
+1 1001
+2 2001
+3 3001
+4 4001
+5 5001
+6 6001
+7 7001
+8 8001
+9 9001
+call test_05('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)');
+x y
+1 1001
+2 2001
+3 3001
+4 4001
+5 5001
+6 6001
+7 7001
+8 8001
+9 9001
+x y
+1 1000
+2 2000
+3 3000
+4 4000
+5 5000
+6 6000
+7 7000
+8 8000
+9 9000
+1 1001
+2 2001
+3 3001
+4 4001
+5 5001
+6 6001
+7 7001
+8 8001
+9 9001
+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
+6 1 1 1 1
+7 1 1 1 1
+8 1 1 1 1
+9 1 1 1 1
+10 1 1 1 1
+11 1 1 1 1
+12 1 1 1 1
+13 1 1 1 1
+14 1 1 1 1
+15 1 1 1 1
+16 1 1 1 1
+create table t1(
+x int unsigned,
+sys_start bigint unsigned as row start invisible,
+sys_end bigint unsigned as row end invisible,
+period for system_time (sys_start, sys_end))
+with system versioning engine=innodb;
+create table t2(x int unsigned) engine=innodb;
+start transaction;
+insert into t1(x) values(1);
+commit;
+call verify_vtq;
+No A B C D
+1 1 1 1 1
+start transaction;
+insert into t2(x) values(1);
+savepoint a;
+insert into t1(x) values(1);
+rollback to a;
+commit;
+call verify_vtq;
+No A B C D
+insert into t2(x) values (1);
+create or replace table t1 (
+x int,
+y int as (x) virtual,
+sys_trx_start bigint unsigned as row start invisible,
+sys_trx_end bigint unsigned as row end invisible,
+period for system_time (sys_trx_start, sys_trx_end)
+) engine=innodb with system versioning;
+insert into t1 values (1, null);
+update t1 set x= x + 1;
+select x, y, sys_trx_end = 18446744073709551615 as current from t1 for system_time all;
+x y current
+2 2 1
+1 1 0
+create or replace table t1 (x int) with system versioning engine innodb;
+insert into t1 values (1), (2);
+insert into t1 (row_start) select row_end from t1;
+ERROR HY000: The value specified for generated column 'row_start' in table 't1' ignored
+set sql_mode='';
+insert into t1 (row_start, row_end) values (DEFAULT, 1);
+Warnings:
+Warning 1906 The value specified for generated column 'row_end' in table 't1' ignored
+set sql_mode=default;
+select @@sql_mode into @saved_mode;
+set sql_mode= '';
+insert into t1 (x, row_start, row_end) values (3, 4, 5);
+Warnings:
+Warning 1906 The value specified for generated column 'row_start' in table 't1' ignored
+Warning 1906 The value specified for generated column 'row_end' in table 't1' ignored
+set sql_mode= @saved_mode;
+insert into t1 (row_start, row_end) values (DEFAULT, DEFAULT);
+select * from t1;
+x
+1
+2
+NULL
+3
+NULL
+# MDEV-14792 INSERT without column list into table with explicit versioning columns produces bad data
+create or replace table t1 (
+i int,
+s timestamp(6) as row start,
+e timestamp(6) as row end,
+c varchar(8),
+period for system_time(s, e))
+with system versioning;
+insert into t1 values (1, null, null, 'foo');
+select i, c, current_row(e) from t1;
+i c current_row(e)
+1 foo 1
+drop table t1;
+drop table t2;
+drop procedure test_01;
+drop procedure test_02;
+drop procedure test_03;
+drop procedure test_04;
+drop procedure test_05;
+set timestamp=1000000019;
+select now() < sysdate();
+now() < sysdate()
+1
+create table t1 (a int) with system versioning;
+insert t1 values (1);
+set @a=sysdate(6);
+select * from t1 for system_time as of now(6);
+a
+select * from t1 for system_time as of sysdate(6);
+a
+1
+update t1 set a=2;
+delete from t1;
+select *, row_start > @a, row_end > @a from t1 for system_time all;
+a row_start > @a row_end > @a
+1 0 1
+2 1 1
+#
+# MDEV-14871 Server crashes in fill_record / fill_record_n_invoke_before_triggers upon inserting into versioned table with trigger
+#
+create or replace table t1 (pk int primary key) with system versioning;
+create trigger tr before insert on t1 for each row select 1 into @a;
+insert into t1 values (1),(2);
+drop table t1;
diff --git a/mysql-test/suite/versioning/r/online.result b/mysql-test/suite/versioning/r/online.result
new file mode 100644
index 00000000000..b2a34481d63
--- /dev/null
+++ b/mysql-test/suite/versioning/r/online.result
@@ -0,0 +1,34 @@
+set system_versioning_alter_history=keep;
+create or replace table t (a int, b int) engine=innodb;
+alter table t add system versioning, lock=none;
+ERROR 0A000: LOCK=NONE is not supported. Reason: Not implemented for system-versioned tables. Try LOCK=SHARED
+alter table t add system versioning, lock=shared;
+alter table t drop column b, lock=none;
+ERROR 0A000: LOCK=NONE is not supported. Reason: Not implemented for system-versioned tables. Try LOCK=SHARED
+alter table t drop column b, algorithm=inplace;
+ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Not implemented for system-versioned tables. Try ALGORITHM=COPY
+alter table t add index idx(a), lock=none;
+alter table t drop system versioning, lock=none;
+ERROR 0A000: LOCK=NONE is not supported. Reason: Not implemented for system-versioned tables. Try LOCK=SHARED
+alter table t drop system versioning, algorithm=inplace;
+ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Not implemented for system-versioned tables. Try ALGORITHM=COPY
+create or replace table t (a int, b int) engine=innodb;
+alter table t
+add s bigint unsigned as row start,
+add e bigint unsigned as row end,
+add period for system_time(s, e),
+add system versioning,
+lock=none;
+ERROR 0A000: LOCK=NONE is not supported. Reason: Not implemented for system-versioned tables. Try LOCK=SHARED
+alter table t
+add s bigint unsigned as row start,
+add e bigint unsigned as row end,
+add period for system_time(s, e),
+add system versioning;
+alter table t drop column b, lock=none;
+ERROR 0A000: LOCK=NONE is not supported. Reason: Not implemented for system-versioned tables. Try LOCK=SHARED
+alter table t add index idx(a), lock=none;
+alter table t drop column s, drop column e;
+alter table t drop system versioning, lock=none;
+ERROR 0A000: LOCK=NONE is not supported. Reason: Not implemented for system-versioned tables. Try LOCK=SHARED
+drop table t;
diff --git a/mysql-test/suite/versioning/r/optimized.result b/mysql-test/suite/versioning/r/optimized.result
new file mode 100644
index 00000000000..443d0401771
--- /dev/null
+++ b/mysql-test/suite/versioning/r/optimized.result
@@ -0,0 +1,97 @@
+create table t (
+a int,
+b int without system versioning
+) with system versioning;
+insert into t values(1, 2);
+insert into t values(3, 4);
+select * from t;
+a b
+1 2
+3 4
+select a from t for system_time as of timestamp now(6);
+a
+1
+3
+select a, b, b+0 from t for system_time as of timestamp now(6);
+a b b+0
+1 2 2
+3 4 4
+Warnings:
+Note 4110 Non-versioned field `b` in historical query
+Note 4110 Non-versioned field `b` in historical query
+select * from t for system_time as of timestamp now(6);
+a b
+1 2
+3 4
+Warnings:
+Note 4110 Non-versioned field `b` in historical query
+select count(*) from t for system_time as of timestamp now(6) group by b;
+count(*)
+1
+1
+Warnings:
+Note 4110 Non-versioned field `b` in historical query
+select * from t for system_time as of timestamp now(6) order by b asc;
+a b
+1 2
+3 4
+Warnings:
+Note 4110 Non-versioned field `b` in historical query
+Note 4110 Non-versioned field `b` in historical query
+select * from t for system_time as of timestamp now(6) order by b desc;
+a b
+3 4
+1 2
+Warnings:
+Note 4110 Non-versioned field `b` in historical query
+Note 4110 Non-versioned field `b` in historical query
+select * from t for system_time as of timestamp now(6) group by a having a=2;
+a b
+Warnings:
+Note 4110 Non-versioned field `b` in historical query
+select * from t for system_time as of timestamp now(6) group by b having b=2;
+a b
+1 2
+Warnings:
+Note 4110 Non-versioned field `b` in historical query
+Note 4110 Non-versioned field `b` in historical query
+Note 4110 Non-versioned field `b` in historical query
+select a from t for system_time as of timestamp now(6) where b=2;
+a
+1
+Warnings:
+Note 4110 Non-versioned field `b` in historical query
+select a from t for system_time as of timestamp now(6) where b=NULL;
+a
+Warnings:
+Note 4110 Non-versioned field `b` in historical query
+select a from t for system_time as of timestamp now(6) where b is NULL;
+a
+Warnings:
+Note 4110 Non-versioned field `b` in historical query
+select count(*), b from t for system_time as of timestamp now(6) group by b having b=NULL;
+count(*) b
+Warnings:
+Note 4110 Non-versioned field `b` in historical query
+Note 4110 Non-versioned field `b` in historical query
+Note 4110 Non-versioned field `b` in historical query
+select a, b from t;
+a b
+1 2
+3 4
+create or replace table t (
+a int,
+b int not null without system versioning
+) with system versioning;
+insert into t values (1, 2), (3, 4);
+select * from t for system_time as of timestamp now(6);
+a b
+1 2
+3 4
+Warnings:
+Note 4110 Non-versioned field `b` in historical query
+select * from t for system_time as of timestamp now(6) where b is NULL;
+a b
+Warnings:
+Note 4110 Non-versioned field `b` in historical query
+drop table t;
diff --git a/mysql-test/suite/versioning/r/partition.result b/mysql-test/suite/versioning/r/partition.result
new file mode 100644
index 00000000000..2b275538fb9
--- /dev/null
+++ b/mysql-test/suite/versioning/r/partition.result
@@ -0,0 +1,420 @@
+# Check conventional partitioning on temporal tables
+create table t1 (x int)
+with system versioning
+partition by range columns (x) (
+partition p0 values less than (100),
+partition p1 values less than (1000));
+insert into t1 values (3), (300);
+select * from t1;
+x
+3
+300
+select * from t1 partition (p0);
+x
+3
+select * from t1 partition (p1);
+x
+300
+delete from t1;
+select * from t1;
+x
+select * from t1 partition (p0);
+x
+select * from t1 partition (p1);
+x
+select * from t1 for system_time all;
+x
+3
+300
+select * from t1 partition (p0) for system_time all;
+x
+3
+select * from t1 partition (p1) for system_time all;
+x
+300
+# Engine change native <-> non-native versioning prohibited
+create or replace table t1 (i int) engine=DEFAULT_ENGINE with system versioning partition by hash(i);
+alter table t1 engine=NON_DEFAULT_ENGINE;
+ERROR HY000: Not allowed for system-versioned `test`.`t1`. Change to/from native system versioning engine is prohibited.
+## CREATE TABLE
+create or replace table t1 (x int)
+partition by system_time (
+partition p0 history,
+partition pn current);
+ERROR HY000: Transaction system versioning for `t1` is not supported
+create or replace table t1 (x int);
+alter table t1
+partition by system_time (
+partition p0 history,
+partition pn current);
+Got one of the listed errors
+create or replace table t1 (x int)
+with system versioning
+partition by system_time (
+partition p0 current);
+ERROR HY000: Wrong partitions for `t1`: must have at least one HISTORY and exactly one last CURRENT
+create or replace table t1 (x int)
+with system versioning
+partition by system_time (
+partition p0 current,
+partition p1 current);
+ERROR HY000: Wrong partitions for `t1`: must have at least one HISTORY and exactly one last CURRENT
+create or replace table t1 (x int)
+with system versioning
+partition by system_time (
+partition p0 history,
+partition p1 history);
+ERROR HY000: Wrong partitions for `t1`: must have at least one HISTORY and exactly one last CURRENT
+create or replace table t1 (x int)
+with system versioning
+partition by system_time (
+partition pn current,
+partition p0 history);
+ERROR HY000: Wrong partitions for `t1`: must have at least one HISTORY and exactly one last CURRENT
+create or replace table t1 (x int)
+with system versioning
+partition by system_time (
+partition p0,
+partition pn current);
+ERROR HY000: Wrong partitions for `t1`: must have at least one HISTORY and exactly one last CURRENT
+create or replace table t1 (x int)
+with system versioning
+partition by system_time (
+partition p0 history,
+partition pn current);
+## ALTER TABLE
+alter table t1 add partition (
+partition p1 current);
+ERROR HY000: Wrong partitions for `t1`: must have at least one HISTORY and exactly one last CURRENT
+alter table t1 add partition (
+partition p1 history);
+Warnings:
+Warning 4113 Maybe missing parameters: no rotation condition for multiple HISTORY partitions.
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `x` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME
+(PARTITION `p0` HISTORY ENGINE = DEFAULT_ENGINE,
+ PARTITION `p1` HISTORY ENGINE = DEFAULT_ENGINE,
+ PARTITION `pn` CURRENT ENGINE = DEFAULT_ENGINE)
+insert into t1 values (1), (2);
+alter table t1 drop partition pn;
+ERROR HY000: Wrong partitions for `t1`: must have at least one HISTORY and exactly one last CURRENT
+alter table t1 drop partition p1;
+alter table t1 drop partition p0;
+ERROR HY000: Wrong partitions for `t1`: must have at least one HISTORY and exactly one last CURRENT
+select x from t1;
+x
+1
+2
+# Bug #260: incorrect IB partitioning warning
+create or replace table t1 (x int)
+with system versioning
+partition by system_time limit 1 (
+partition p0 history,
+partition pn current);
+alter table t1 change x big int;
+create or replace table t1 (i int) engine myisam partition by hash(i) partitions 2;
+alter table t1 add partition (partition px history);
+ERROR HY000: Wrong partitioning type, expected type: `SYSTEM_TIME`
+## INSERT, UPDATE, DELETE
+create or replace table t1 (x int)
+with system versioning
+partition by system_time (
+partition p0 history,
+partition pn current);
+set @now= now(6);
+insert into t1 values (1);
+set @str= concat('select x, row_start < @now as A, row_end > @now as B from t1 partition (p0)');
+prepare select_p0 from @str;
+set @str= concat('select x, row_start > @now as C, row_end = timestamp\'2038-01-19 03:14:07.999999\' as D from t1 partition (pn)');
+prepare select_pn from @str;
+execute select_p0;
+x A B
+execute select_pn;
+x C D
+1 1 1
+## pruning check
+explain partitions select * from tN;
+id select_type table partitions type possible_keys key key_len ref rows Extra
+N SIMPLE tN pN,pn system NULL NULL NULL NULL N
+set @str= concat('select row_start from t1 partition (pn) into @ts0');
+prepare stmt from @str;
+execute stmt;
+drop prepare stmt;
+set @now= now(6);
+delete from t1;
+execute select_p0;
+x A B
+1 1 1
+execute select_pn;
+x C D
+set @str= concat('select row_start from t1 partition (p0) into @ts1');
+prepare stmt from @str;
+execute stmt;
+drop prepare stmt;
+select @ts0 = @ts1;
+@ts0 = @ts1
+1
+set @now= now(6);
+insert into t1 values (2);
+execute select_p0;
+x A B
+1 1 0
+execute select_pn;
+x C D
+2 1 1
+set @str= concat('select row_start from t1 partition (pn) into @ts0');
+prepare stmt from @str;
+execute stmt;
+drop prepare stmt;
+set @now= now(6);
+update t1 set x = x + 1;
+execute select_p0;
+x A B
+1 1 0
+2 1 1
+execute select_pn;
+x C D
+3 1 1
+drop prepare select_p0;
+drop prepare select_pn;
+set @str= concat('select row_start from t1 partition (p0) where x = 2 into @ts1');
+prepare stmt from @str;
+execute stmt;
+drop prepare stmt;
+set @str= concat('select row_end from t1 partition (p0) where x = 2 into @ts2');
+prepare stmt from @str;
+execute stmt;
+drop prepare stmt;
+set @str= concat('select row_start from t1 partition (pn) into @ts3');
+prepare stmt from @str;
+execute stmt;
+drop prepare stmt;
+select @ts0 = @ts1;
+@ts0 = @ts1
+1
+select @ts2 = @ts3;
+@ts2 = @ts3
+1
+## rotation by LIMIT
+create or replace table t1 (x int)
+with system versioning
+partition by system_time limit 0 (
+partition p0 history,
+partition p1 history,
+partition pn current);
+ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for 'LIMIT'
+create or replace table t1 (x int)
+with system versioning
+partition by system_time limit 2 (
+partition p0 history,
+partition p1 history,
+partition pn current);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `x` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME LIMIT 2
+(PARTITION `p0` HISTORY ENGINE = DEFAULT_ENGINE,
+ PARTITION `p1` HISTORY ENGINE = DEFAULT_ENGINE,
+ PARTITION `pn` CURRENT ENGINE = DEFAULT_ENGINE)
+alter table t1 drop partition non_existent;
+ERROR HY000: Error in list of partitions to DROP
+insert into t1 values (1), (2), (3);
+select * from t1 partition (pn);
+x
+1
+2
+3
+### warn about partition switching
+delete from t1;
+Warnings:
+Note 4114 Versioned table `test`.`t1`: switching from partition `p0` to `p1`
+select * from t1 partition (p0);
+x
+1
+2
+select * from t1 partition (p1);
+x
+3
+insert into t1 values (4), (5);
+### warn about full partition
+delete from t1;
+Warnings:
+Warning 4112 Versioned table `test`.`t1`: partition `p1` is full, add more HISTORY partitions
+select * from t1 partition (p1) order by x;
+x
+3
+4
+5
+### Assertion in ALTER on warning from partitioning LIMIT [#446]
+create or replace table t1 (x int) with system versioning;
+insert into t1 values (1), (2);
+delete from t1;
+alter table t1 partition by system_time limit 1 (
+partition p1 history,
+partition pn current);
+Warnings:
+Note 4112 Versioned table `test`.`t1`: partition `p1` is full, add more HISTORY partitions
+## rotation by INTERVAL
+create or replace table t1 (x int)
+with system versioning
+partition by system_time interval 0 second (
+partition p0 history,
+partition p1 history,
+partition pn current);
+ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for 'INTERVAL'
+create or replace table t1 (x int)
+with system versioning
+partition by system_time interval 1 second (
+partition p0 history,
+partition p1 history,
+partition pn current);
+insert into t1 values (1), (2), (3);
+select * from t1 partition (pn);
+x
+1
+2
+3
+delete from t1;
+select * from t1 partition (p0);
+x
+1
+2
+3
+insert into t1 values (4);
+delete from t1;
+Warnings:
+Note 4114 Versioned table `test`.`t1`: switching from partition `p0` to `p1`
+select * from t1 partition (p1);
+x
+4
+## Subpartitions
+create or replace table t1 (x int)
+with system versioning
+partition by system_time limit 2
+subpartition by key (x)
+subpartitions 2 (
+partition p0 history,
+partition p1 history,
+partition pn current);
+insert into t1 (x) values (1), (2), (3), (4), (5);
+select * from t1 partition (pnsp0);
+x
+1
+3
+5
+select * from t1 partition (pnsp1);
+x
+2
+4
+### warn about partition switching and about full partition
+delete from t1;
+Warnings:
+Note 4114 Versioned table `test`.`t1`: switching from partition `p0` to `p1`
+Warning 4112 Versioned table `test`.`t1`: partition `p1` is full, add more HISTORY partitions
+select * from t1 partition (p0sp0);
+x
+1
+3
+select * from t1 partition (p0sp1);
+x
+select * from t1 partition (p1sp0);
+x
+5
+select * from t1 partition (p1sp1);
+x
+2
+4
+create or replace table t1 (a bigint)
+with system versioning
+partition by range (a)
+(partition p0 values less than (20) engine innodb,
+partition p1 values less than maxvalue engine innodb);
+insert into t1 values (1);
+create or replace table t1 (
+f_int1 integer default 0
+) with system versioning
+partition by range(f_int1)
+subpartition by hash(f_int1)
+( partition part1 values less than (1000)
+(subpartition subpart11 storage engine = 'innodb',
+subpartition subpart12 storage engine = 'innodb'));
+insert into t1 values (1);
+create or replace table t1 (i int) engine=innodb partition by key(i);
+alter table t1 add system versioning;
+insert into t1 values();
+# MDEV-14722 Assertion in ha_commit_trans for sub-statement
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day (
+partition p1 history,
+partition pc current);
+create or replace table t2 (f int);
+create or replace trigger tr before insert on t2
+for each row select table_rows from information_schema.tables
+where table_name = 't1' into @a;
+insert into t2 values (1);
+# MDEV-14740 Locking assertion for system_time partitioning
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 week (
+partition p1 history,
+partition pn current);
+create or replace table t2 (f int);
+create or replace trigger tr before insert on t2
+for each row select count(*) from t1 into @a;
+insert into t2 values (1);
+# MDEV-14741 Assertion `(trx)->start_file == 0' failed in row_truncate_table_for_mysql()
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 hour (
+partition p1 history,
+partition pn current);
+set autocommit= off;
+truncate table t1;
+set autocommit= on;
+# MDEV-14747 ALTER PARTITION BY SYSTEM_TIME after LOCK TABLES
+create or replace table t1 (x int) with system versioning;
+lock table t1 write;
+alter table t1 partition by system_time interval 1 week (
+partition p1 history,
+partition pn current);
+unlock tables;
+# MDEV-14748 Assertion in ha_myisammrg::attach_children()
+create or replace table t1 (x int) engine=myisam with system versioning
+partition by system_time interval 1 month (partition p1 history, partition pn current);
+create or replace table t2 (x int) engine=myisam;
+create or replace table t3 (x int) engine=merge union=(t2);
+create or replace table t4 (x int) engine=myisam;
+create or replace trigger tr after insert on t4 for each row insert into t2
+( select x from t3 ) union ( select x from t1 );
+insert into t4 values (1);
+# MDEV-14821 Assertion failure
+create or replace table t1 (x int) with system versioning;
+insert into t1 values (0), (1);
+update t1 set x= x + 1;
+alter table t1 partition by system_time limit 1 (
+partition p1 history,
+partition p2 history,
+partition pn current);
+Warnings:
+Note 4114 Versioned table `test`.`t1`: switching from partition `p1` to `p2`
+delete from t1 where x = 1;
+Warnings:
+Warning 4112 Versioned table `test`.`t1`: partition `p2` is full, add more HISTORY partitions
+delete from t1 where x = 2;
+Warnings:
+Warning 4112 Versioned table `test`.`t1`: partition `p2` is full, add more HISTORY partitions
+# MDEV-14923 Assertion upon INSERT into locked versioned partitioned table
+create or replace table t1 (x int) with system versioning
+partition by system_time (partition p1 history, partition pn current);
+lock table t1 write;
+alter table t1 add partition (partition p1 history);
+ERROR HY000: Duplicate partition name p1
+insert into t1 values (1);
+unlock tables;
+# Test cleanup
+drop database test;
+create database test;
diff --git a/mysql-test/suite/versioning/r/replace.result b/mysql-test/suite/versioning/r/replace.result
new file mode 100644
index 00000000000..94302c1adf4
--- /dev/null
+++ b/mysql-test/suite/versioning/r/replace.result
@@ -0,0 +1,10 @@
+call create_table('t', 'x int');
+insert t values (1, 2);
+replace t values (1, 3);
+select *, current_row(row_end) as current from t for system_time all
+order by x;
+id x current
+1 2 0
+1 3 1
+drop database test;
+create database test;
diff --git a/mysql-test/suite/versioning/r/rpl.result b/mysql-test/suite/versioning/r/rpl.result
new file mode 100644
index 00000000000..b91c8fd33c8
--- /dev/null
+++ b/mysql-test/suite/versioning/r/rpl.result
@@ -0,0 +1,118 @@
+include/master-slave.inc
+[connection master]
+connection slave;
+connection master;
+CREATE TABLE t1 (x int) with system versioning;
+insert into t1 values (1);
+SELECT * FROM t1;
+x
+1
+delete from t1;
+select * from t1;
+x
+select * from t1 for system_time all;
+x
+1
+connection slave;
+select * from t1;
+x
+select * from t1 for system_time all;
+x
+1
+connection master;
+insert into t1 values (2);
+connection slave;
+select * from t1;
+x
+2
+connection master;
+update t1 set x = 3;
+connection slave;
+select * from t1;
+x
+3
+select * from t1 for system_time all;
+x
+1
+3
+2
+connection master;
+create or replace table t1 (x int primary key);
+connection slave;
+alter table t1 with system versioning;
+connection master;
+insert into t1 values (1);
+connection slave;
+select * from t1;
+x
+1
+select * from t1 for system_time all;
+x
+1
+connection master;
+update t1 set x= 2 where x = 1;
+connection slave;
+select * from t1;
+x
+2
+select * from t1 for system_time all;
+x
+1
+2
+connection master;
+delete from t1;
+connection slave;
+select * from t1;
+x
+select * from t1 for system_time all;
+x
+1
+2
+connection master;
+create or replace table t1 (x int);
+connection slave;
+alter table t1 with system versioning;
+connection master;
+insert into t1 values (1);
+update t1 set x= 2 where x = 1;
+connection slave;
+select * from t1;
+x
+2
+select * from t1 for system_time all;
+x
+2
+1
+connection master;
+delete from t1;
+connection slave;
+select * from t1;
+x
+select * from t1 for system_time all;
+x
+2
+1
+connection master;
+create or replace table t1 (x int) with system versioning;
+create or replace table t2 (x int) with system versioning;
+insert into t1 values (1);
+insert into t2 values (2);
+update t1, t2 set t1.x=11, t2.x=22;
+connection slave;
+select * from t1;
+x
+11
+select * from t2;
+x
+22
+select * from t1 for system_time all;
+x
+11
+1
+select * from t2 for system_time all;
+x
+22
+2
+connection master;
+drop table t1, t2;
+include/rpl_end.inc
diff --git a/mysql-test/suite/versioning/r/select.result b/mysql-test/suite/versioning/r/select.result
new file mode 100644
index 00000000000..1f7e0306b9b
--- /dev/null
+++ b/mysql-test/suite/versioning/r/select.result
@@ -0,0 +1,515 @@
+create or replace table t1 (
+x int unsigned,
+y int unsigned,
+sys_trx_start SYS_DATATYPE as row start invisible,
+sys_trx_end SYS_DATATYPE as row end invisible,
+period for system_time (sys_trx_start, sys_trx_end)
+) with system versioning;
+insert into t1 (x, y) values
+(0, 100),
+(1, 101),
+(2, 102),
+(3, 103),
+(4, 104),
+(5, 105),
+(6, 106),
+(7, 107),
+(8, 108),
+(9, 109);
+set @t0= now(6);
+delete from t1 where x = 3;
+delete from t1 where x > 7;
+insert into t1(x, y) values(3, 33);
+select sys_trx_start from t1 where x = 3 and y = 33 into @t1;
+select x, y from t1;
+x y
+0 100
+1 101
+2 102
+4 104
+5 105
+6 106
+7 107
+3 33
+select x as ASOF_x, y from t1 for system_time as of timestamp @t0;
+ASOF_x y
+0 100
+1 101
+2 102
+3 103
+4 104
+5 105
+6 106
+7 107
+8 108
+9 109
+select x as FROMTO_x, y from t1 for system_time from timestamp '0-0-0 0:0:0' to timestamp @t1;
+FROMTO_x y
+0 100
+1 101
+2 102
+3 103
+4 104
+5 105
+6 106
+7 107
+8 108
+9 109
+select x as BETWAND_x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp @t1;
+BETWAND_x y
+0 100
+1 101
+2 102
+3 103
+4 104
+5 105
+6 106
+7 107
+8 108
+9 109
+3 33
+select x as ALL_x, y from t1 for system_time all;
+ALL_x y
+0 100
+1 101
+2 102
+3 103
+4 104
+5 105
+6 106
+7 107
+8 108
+9 109
+3 33
+ASOF2_x y
+0 100
+1 101
+2 102
+3 103
+4 104
+5 105
+6 106
+7 107
+8 108
+9 109
+FROMTO2_x y
+0 100
+1 101
+2 102
+3 103
+4 104
+5 105
+6 106
+7 107
+8 108
+9 109
+BETWAND2_x y
+0 100
+1 101
+2 102
+3 103
+4 104
+5 105
+6 106
+7 107
+8 108
+9 109
+3 33
+create or replace table t1 (
+x int unsigned,
+y int unsigned
+) with system versioning;
+create or replace table t2 (
+x int unsigned,
+y int unsigned
+) with system versioning;
+insert into t1 values (1, 1), (1, 2), (1, 3), (4, 4), (5, 5);
+insert into t2 values (1, 2), (2, 1), (3, 1);
+set @t0= now(6);
+select t1.x as IJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 inner join t2 on t1.x = t2.x;
+IJ1_x1 y1 x2 y2
+1 1 1 2
+1 2 1 2
+1 3 1 2
+select t1.x as LJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 left join t2 on t1.x = t2.x;
+LJ1_x1 y1 x2 y2
+1 1 1 2
+1 2 1 2
+1 3 1 2
+4 4 NULL NULL
+5 5 NULL NULL
+select t1.x as RJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 right join t2 on t1.x = t2.x;
+RJ1_x1 y1 x2 y2
+1 1 1 2
+1 2 1 2
+1 3 1 2
+NULL NULL 2 1
+NULL NULL 3 1
+delete from t1;
+delete from t2;
+explain extended select * from (select t1.x as IJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 inner join t2 on t1.x = t2.x)
+for system_time as of timestamp @t0 as t;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where; Using join buffer (flat, BNL join)
+Warnings:
+Note 1003 select `test`.`t1`.`x` AS `IJ2_x1`,`test`.`t1`.`y` AS `y1`,`test`.`t2`.`x` AS `x2`,`test`.`t2`.`y` AS `y2` from `test`.`t1` FOR SYSTEM_TIME ALL join `test`.`t2` FOR SYSTEM_TIME ALL where `test`.`t1`.`x` = `test`.`t2`.`x` and `test`.`t1`.`row_end` > <cache>(cast(@`t0` as datetime(6))) and `test`.`t1`.`row_start` <= <cache>(cast(@`t0` as datetime(6))) and `test`.`t2`.`row_end` > <cache>(cast(@`t0` as datetime(6))) and `test`.`t2`.`row_start` <= <cache>(cast(@`t0` as datetime(6)))
+explain extended select * from (select t1.x as LJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 left join t2 on t1.x = t2.x)
+for system_time as of timestamp @t0 as t;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
+Warnings:
+Note 1003 select `test`.`t1`.`x` AS `LJ2_x1`,`test`.`t1`.`y` AS `y1`,`test`.`t2`.`x` AS `x2`,`test`.`t2`.`y` AS `y2` from `test`.`t1` FOR SYSTEM_TIME ALL left join `test`.`t2` FOR SYSTEM_TIME ALL on(`test`.`t2`.`x` = `test`.`t1`.`x` and `test`.`t1`.`row_end` > <cache>(cast(@`t0` as datetime(6))) and `test`.`t1`.`row_start` <= <cache>(cast(@`t0` as datetime(6))) and `test`.`t2`.`row_end` > <cache>(cast(@`t0` as datetime(6))) and `test`.`t2`.`row_start` <= <cache>(cast(@`t0` as datetime(6)))) where 1
+explain extended select * from (select t1.x as RJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 right join t2 on t1.x = t2.x)
+for system_time as of timestamp @t0 as t;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where; Using join buffer (flat, BNL join)
+Warnings:
+Note 1003 select `test`.`t1`.`x` AS `RJ2_x1`,`test`.`t1`.`y` AS `y1`,`test`.`t2`.`x` AS `x2`,`test`.`t2`.`y` AS `y2` from `test`.`t2` FOR SYSTEM_TIME ALL left join `test`.`t1` FOR SYSTEM_TIME ALL on(`test`.`t1`.`x` = `test`.`t2`.`x` and `test`.`t1`.`row_end` > <cache>(cast(@`t0` as datetime(6))) and `test`.`t1`.`row_start` <= <cache>(cast(@`t0` as datetime(6))) and `test`.`t2`.`row_end` > <cache>(cast(@`t0` as datetime(6))) and `test`.`t2`.`row_start` <= <cache>(cast(@`t0` as datetime(6)))) where 1
+select * from (select t1.x as IJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 inner join t2 on t1.x = t2.x)
+for system_time as of timestamp @t0 as t;
+IJ2_x1 y1 x2 y2
+1 1 1 2
+1 2 1 2
+1 3 1 2
+select * from (select t1.x as LJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 left join t2 on t1.x = t2.x)
+for system_time as of timestamp @t0 as t;
+LJ2_x1 y1 x2 y2
+1 1 1 2
+1 2 1 2
+1 3 1 2
+4 4 NULL NULL
+5 5 NULL NULL
+select * from (select t1.x as RJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 right join t2 on t1.x = t2.x)
+for system_time as of timestamp @t0 as t;
+RJ2_x1 y1 x2 y2
+1 1 1 2
+1 2 1 2
+1 3 1 2
+NULL NULL 2 1
+NULL NULL 3 1
+drop table t1;
+drop table t2;
+create table t1(
+A int
+) with system versioning;
+insert into t1 values(1);
+select * from t1;
+A
+1
+create or replace table t1 (x int);
+insert into t1 values (1);
+select * from t1 for system_time all;
+ERROR HY000: Table `t1` is not system-versioned
+create or replace table t1 (x int) with system versioning;
+insert into t1 values (1);
+select * from t1 for system_time all for update;
+x
+1
+create or replace table t1 (a int not null auto_increment primary key) with system versioning;
+select * from (t1 as t2 left join t1 as t3 using (a)) natural left join t1;
+a
+create or replace table t1 (a int) with system versioning;
+create or replace table t2 (a int) with system versioning;
+insert into t1 values(1);
+insert into t2 values(1);
+create view v1 as select * from t2 inner join t1 using (a);
+select * from v1;
+a
+1
+drop view v1;
+create or replace table t1 (a int) with system versioning;
+insert into t1 values (1);
+create view vt1 as select a from t1;
+select * from t1 natural join vt1;
+a
+1
+drop view vt1;
+create or replace table t1(x int) with system versioning;
+select * from (t1 as r left join t1 as u using (x)), t1;
+x x
+create or replace table t1 (a int) with system versioning;
+insert into t1 values (1);
+create trigger read_end after update on t1
+for each row set @end = old.row_end;
+update t1 set a=2;
+select @end;
+@end
+MAX_RESULT
+create or replace table t1 (a int) with system versioning;
+create or replace table t2 (b int) with system versioning;
+insert into t1 values (1);
+insert into t2 values (2);
+select * from (select * from t1 cross join t2) as tmp;
+a b
+1 2
+select * from (select * from (select * from t1 cross join t2) as tmp1) as tmp2;
+a b
+1 2
+select * from (select * from t1 cross join t2 for system_time as of timestamp '0-0-0') as tmp;
+a b
+create or replace table t1(a1 int) with system versioning;
+create or replace table t2(a2 int) with system versioning;
+insert into t1 values(1),(2);
+insert into t2 values(1),(2);
+select * from t1 for system_time all natural left join t2 for system_time all;
+a1 a2
+1 1
+2 1
+1 2
+2 2
+create or replace table t1(a1 int) with system versioning;
+create or replace table t2(a2 int) with system versioning;
+insert into t1 values(1),(2);
+insert into t2 values(1),(2);
+create or replace view v1 as select a1 from t1;
+select * from v1 natural join t2;
+a1 a2
+1 1
+2 1
+1 2
+2 2
+select * from v1 natural left join t2;
+a1 a2
+1 1
+2 1
+1 2
+2 2
+select * from v1 natural right join t2;
+a2 a1
+1 1
+2 1
+1 2
+2 2
+create or replace table t1 (a int) with system versioning;
+insert into t1 values (1);
+insert into t1 values (2);
+insert into t1 values (3);
+select * from t1 left outer join (t1 as t2 left join t1 as t3 using (a)) on t1.a>1;
+a a
+2 1
+3 1
+2 2
+3 2
+2 3
+3 3
+1 NULL
+create or replace table t1 (x int) with system versioning;
+create or replace table t2 (y int) with system versioning;
+insert into t1 values (1), (2), (3);
+delete from t1 where x = 3;
+insert into t2 values (1);
+select * from t1, t2 for system_time all;
+x y
+1 1
+2 1
+select * from (select * from t1 for system_time all, t2 for system_time all)
+for system_time all as t;
+ERROR HY000: Table `t` is not system-versioned
+# TRANSACTION/TIMESTAMP specifier in SYSTEM_TIME [MDEV-14645, Issue #396]
+create or replace table t1 (x int) with system versioning engine myisam;
+select * from t1 for system_time as of transaction 1;
+ERROR HY000: Transaction system versioning for `t1` is not supported
+create or replace table t1 (
+x int,
+sys_trx_start bigint unsigned as row start invisible,
+sys_trx_end bigint unsigned as row end invisible,
+period for system_time (sys_trx_start, sys_trx_end)
+) with system versioning engine innodb;
+insert into t1 values (1);
+set @ts= now(6);
+delete from t1;
+select sys_trx_start from t1 for system_time all into @trx_start;
+## ensure @trx_start is much lower than unix timestamp
+select @trx_start < unix_timestamp(@ts) - 100 as trx_start_good;
+trx_start_good
+1
+## TIMESTAMP specifier
+select x from t1 for system_time as of timestamp @ts;
+x
+1
+select x from t1 for system_time as of timestamp unix_timestamp(@ts);
+x
+1
+select x from t1 for system_time as of timestamp @trx_start;
+x
+set @ts= timestamp'1-1-1 0:0:0';
+## TRANSACTION specifier
+select x from t1 for system_time as of transaction @ts;
+x
+select x from t1 for system_time as of transaction unix_timestamp(@ts);
+x
+select x from t1 for system_time as of transaction @trx_start;
+x
+1
+## no specifier (auto-detection)
+select x from t1 for system_time as of @ts;
+x
+select x from t1 for system_time as of unix_timestamp(@ts);
+x
+select x from t1 for system_time as of @trx_start;
+x
+1
+### Issue #365, bug 4 (related to #226, optimized fields)
+create or replace table t1 (i int, b int) with system versioning;
+insert into t1 values (0, 0), (0, 0);
+select min(i) over (partition by b) as f
+from (select i + 0 as i, b from t1) as tt
+order by i;
+f
+0
+0
+### Issue #365, bug 5 (dangling AND)
+create or replace table t1 (a int);
+create or replace table t2 (b int) with system versioning;
+select * from t1
+where exists (select 1 from t2 where t2.b = t1.a and t2.b = t1.a);
+a
+### Issue #365, bug 9 (not a derived subquery)
+create or replace table t1 (x int) with system versioning;
+select t1.x in (select x from t1) a from t1, (select x from t1) b;
+a
+### Issue #365, bug 10 (WHERE cond freed prematurely for PS)
+create or replace table t1 (x int) with system versioning;
+insert into t1 values (1);
+create or replace view v1 as select x from t1 where x = 1;
+prepare stmt from "
+select x from t1 where x in (select x from v1);";
+execute stmt;
+x
+1
+execute stmt;
+x
+1
+### Issue #365, bug 11 (WHERE cond not top level item)
+create or replace table t1 (a int, b int, key idx(a)) with system versioning;
+insert into t1 values (1, 1), (2, 2);
+select * from t1 where (a, 2) in ((1, 1), (2, 2)) and b = 1;
+a b
+### Issue #398, NOW is now non-magic
+create or replace table t1 (x int) with system versioning;
+select * from t1 for system_time as of current_timestamp;
+x
+select * from t1 for system_time as of now;
+ERROR 42S22: Unknown column 'now' in 'where clause'
+### Issue #405, NATURAL JOIN failure
+create or replace table t1 (a int) with system versioning;
+create or replace table t2 (b int);
+create or replace view v1 as select a, row_start, row_end from t1 where a > round(rand()*1000);
+select * from v1 natural join t2;
+a b
+### Issue #406, MDEV-14633 Assertion on TRT read
+create or replace table t1 (pk int primary key, i int, t time, key (i)) with system versioning;
+insert into t1 values (1, 10, '15:01:53'), (2, 20, '00:00:00');
+delete from t1;
+select * from t1 where t = '00:00:00' and i > 0 and row_end <> '2012-12-12 00:00:00';
+pk i t
+### MDEV-14816 Assertion `join->best_read < double(1.797...e+308L)' failed in bool greedy_search
+create or replace table t1 (f1 int) with system versioning;
+create or replace table t2 (f2 int) with system versioning;
+create or replace table t3 (f3 int);
+create or replace table t4 (f4 int);
+insert into t1 values (1), (2), (3), (4);
+insert into t2 values (1), (2), (3);
+insert into t3 values (1), (2);
+insert into t4 values (1);
+select * from
+t1 as t1a
+left join t2 as t2a left join (t3 as t3a inner join t1) on t2a.f2 = t3a.f3 on t1a.f1 = t2a.f2
+left join (t2 join t3 inner join t4) on t2a.f2 = t1a.f1;
+f1 f2 f3 f1 f2 f3 f4
+1 1 1 1 1 1 1
+2 2 2 1 1 1 1
+1 1 1 2 1 1 1
+2 2 2 2 1 1 1
+1 1 1 3 1 1 1
+2 2 2 3 1 1 1
+1 1 1 4 1 1 1
+2 2 2 4 1 1 1
+1 1 1 1 1 2 1
+2 2 2 1 1 2 1
+1 1 1 2 1 2 1
+2 2 2 2 1 2 1
+1 1 1 3 1 2 1
+2 2 2 3 1 2 1
+1 1 1 4 1 2 1
+2 2 2 4 1 2 1
+1 1 1 1 2 1 1
+2 2 2 1 2 1 1
+1 1 1 2 2 1 1
+2 2 2 2 2 1 1
+1 1 1 3 2 1 1
+2 2 2 3 2 1 1
+1 1 1 4 2 1 1
+2 2 2 4 2 1 1
+1 1 1 1 2 2 1
+2 2 2 1 2 2 1
+1 1 1 2 2 2 1
+2 2 2 2 2 2 1
+1 1 1 3 2 2 1
+2 2 2 3 2 2 1
+1 1 1 4 2 2 1
+2 2 2 4 2 2 1
+1 1 1 1 3 1 1
+2 2 2 1 3 1 1
+1 1 1 2 3 1 1
+2 2 2 2 3 1 1
+1 1 1 3 3 1 1
+2 2 2 3 3 1 1
+1 1 1 4 3 1 1
+2 2 2 4 3 1 1
+1 1 1 1 3 2 1
+2 2 2 1 3 2 1
+1 1 1 2 3 2 1
+2 2 2 2 3 2 1
+1 1 1 3 3 2 1
+2 2 2 3 3 2 1
+1 1 1 4 3 2 1
+2 2 2 4 3 2 1
+3 3 NULL NULL 1 1 1
+3 3 NULL NULL 1 2 1
+3 3 NULL NULL 2 1 1
+3 3 NULL NULL 2 2 1
+3 3 NULL NULL 3 1 1
+3 3 NULL NULL 3 2 1
+4 NULL NULL NULL NULL NULL NULL
+drop view v1;
+drop table t1, t2, t3, t4;
+call verify_vtq_dummy(34);
+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
+6 1 1 1 1
+7 1 1 1 1
+8 1 1 1 1
+9 1 1 1 1
+10 1 1 1 1
+11 1 1 1 1
+12 1 1 1 1
+13 1 1 1 1
+14 1 1 1 1
+15 1 1 1 1
+16 1 1 1 1
+17 1 1 1 1
+18 1 1 1 1
+19 1 1 1 1
+20 1 1 1 1
+21 1 1 1 1
+22 1 1 1 1
+23 1 1 1 1
+24 1 1 1 1
+25 1 1 1 1
+26 1 1 1 1
+27 1 1 1 1
+28 1 1 1 1
+29 1 1 1 1
+30 1 1 1 1
+31 1 1 1 1
+32 1 1 1 1
+33 1 1 1 1
+34 1 1 1 1
diff --git a/mysql-test/suite/versioning/r/select2,myisam.rdiff b/mysql-test/suite/versioning/r/select2,myisam.rdiff
new file mode 100644
index 00000000000..b24682fbb9f
--- /dev/null
+++ b/mysql-test/suite/versioning/r/select2,myisam.rdiff
@@ -0,0 +1,38 @@
+--- suite/versioning/r/select_sp.result
++++ suite/versioning/r/select_sp.result
+@@ -22,8 +22,6 @@
+ delete from t1 where x > 7;
+ insert into t1(x, y) values(3, 33);
+ select sys_start from t1 where x = 3 and y = 33 into @t1;
+-set @x1= @t1;
+-select vtq_commit_ts(@x1) into @t1;
+ select x, y from t1;
+ x y
+ 0 100
+@@ -84,7 +82,7 @@
+ 8 108
+ 9 109
+ 3 33
+-select x as ASOF2_x, y from t1 for system_time as of @x0;
++select x as ASOF2_x, y from t1 for system_time as of @t0;
+ ASOF2_x y
+ 0 100
+ 1 101
+@@ -96,7 +94,7 @@
+ 7 107
+ 8 108
+ 9 109
+-select x as FROMTO2_x, y from t1 for system_time from @x0 to @x1;
++select x as FROMTO2_x, y from t1 for system_time from '0-0-0 0:0:0' to @t1;
+ FROMTO2_x y
+ 0 100
+ 1 101
+@@ -108,7 +106,7 @@
+ 7 107
+ 8 108
+ 9 109
+-select x as BETWAND2_x, y from t1 for system_time between transaction @x0 and transaction @x1;
++select x as BETWAND2_x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp @t1;
+ BETWAND2_x y
+ 0 100
+ 1 101
diff --git a/mysql-test/suite/versioning/r/select2.result b/mysql-test/suite/versioning/r/select2.result
new file mode 100644
index 00000000000..79c4416a291
--- /dev/null
+++ b/mysql-test/suite/versioning/r/select2.result
@@ -0,0 +1,338 @@
+create table t1(
+x int unsigned,
+y int unsigned,
+sys_start SYS_TYPE as row start invisible,
+sys_end SYS_TYPE as row end invisible,
+period for system_time (sys_start, sys_end))
+with system versioning engine=ENGINE;
+insert into t1 (x, y) values
+(0, 100),
+(1, 101),
+(2, 102),
+(3, 103),
+(4, 104),
+(5, 105),
+(6, 106),
+(7, 107),
+(8, 108),
+(9, 109);
+set @t0= now(6);
+select sys_start from t1 limit 1 into @x0;
+delete from t1 where x = 3;
+delete from t1 where x > 7;
+insert into t1(x, y) values(3, 33);
+select sys_start from t1 where x = 3 and y = 33 into @t1;
+set @x1= @t1;
+select vtq_commit_ts(@x1) into @t1;
+select x, y from t1;
+x y
+0 100
+1 101
+2 102
+4 104
+5 105
+6 106
+7 107
+3 33
+select x as ASOF_x, y from t1 for system_time as of timestamp @t0;
+ASOF_x y
+0 100
+1 101
+2 102
+3 103
+4 104
+5 105
+6 106
+7 107
+8 108
+9 109
+select x as FROMTO_x, y from t1 for system_time from '0-0-0 0:0:0' to timestamp @t1;
+FROMTO_x y
+0 100
+1 101
+2 102
+3 103
+4 104
+5 105
+6 106
+7 107
+8 108
+9 109
+select x as BETWAND_x, y from t1 for system_time between '0-0-0 0:0:0' and timestamp @t1;
+BETWAND_x y
+0 100
+1 101
+2 102
+3 103
+4 104
+5 105
+6 106
+7 107
+8 108
+9 109
+3 33
+select x as ALL_x, y from t1 for system_time all;
+ALL_x y
+0 100
+1 101
+2 102
+3 103
+4 104
+5 105
+6 106
+7 107
+8 108
+9 109
+3 33
+select x as ASOF2_x, y from t1 for system_time as of @x0;
+ASOF2_x y
+0 100
+1 101
+2 102
+3 103
+4 104
+5 105
+6 106
+7 107
+8 108
+9 109
+select x as FROMTO2_x, y from t1 for system_time from @x0 to @x1;
+FROMTO2_x y
+0 100
+1 101
+2 102
+3 103
+4 104
+5 105
+6 106
+7 107
+8 108
+9 109
+select x as BETWAND2_x, y from t1 for system_time between transaction @x0 and transaction @x1;
+BETWAND2_x y
+0 100
+1 101
+2 102
+3 103
+4 104
+5 105
+6 106
+7 107
+8 108
+9 109
+3 33
+drop table t1;
+create table t1(
+x int,
+y int,
+sys_start SYS_TYPE as row start invisible,
+sys_end SYS_TYPE as row end invisible,
+period for system_time (sys_start, sys_end))
+with system versioning engine=ENGINE;
+create table t2 like t1;
+insert into t1 values (1, 1), (1, 2), (1, 3), (4, 4), (5, 5);
+insert into t2 values (1, 2), (2, 1), (3, 1);
+set @t0= now(6);
+select t1.x as IJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 inner join t2 on t1.x = t2.x;
+IJ1_x1 y1 x2 y2
+1 1 1 2
+1 2 1 2
+1 3 1 2
+select t1.x as LJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 left join t2 on t1.x = t2.x;
+LJ1_x1 y1 x2 y2
+1 1 1 2
+1 2 1 2
+1 3 1 2
+4 4 NULL NULL
+5 5 NULL NULL
+select t1.x as RJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 right join t2 on t1.x = t2.x;
+RJ1_x1 y1 x2 y2
+1 1 1 2
+1 2 1 2
+1 3 1 2
+NULL NULL 2 1
+NULL NULL 3 1
+delete from t1;
+delete from t2;
+select IJ2_x1,y1,x2,y2 from (select t1.x as IJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 inner join t2 on t1.x = t2.x)
+for system_time as of timestamp @t0 as t;
+IJ2_x1 y1 x2 y2
+1 1 1 2
+1 2 1 2
+1 3 1 2
+select LJ2_x1,y1,x2,y2 from (select t1.x as LJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 left join t2 on t1.x = t2.x)
+for system_time as of timestamp @t0 as t;
+LJ2_x1 y1 x2 y2
+1 1 1 2
+1 2 1 2
+1 3 1 2
+4 4 NULL NULL
+5 5 NULL NULL
+select RJ2_x1,y1,x2,y2 from (select t1.x as RJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 right join t2 on t1.x = t2.x)
+for system_time as of timestamp @t0 as t;
+RJ2_x1 y1 x2 y2
+1 1 1 2
+1 2 1 2
+1 3 1 2
+NULL NULL 2 1
+NULL NULL 3 1
+drop table t1;
+drop table t2;
+# MDEV-14686 Server crashes in Item_field::used_tables on 2nd call of SP [#422]
+create or replace table t1 (called int, bad int) with system versioning;
+create or replace procedure bad() select * from t1 where bad in (select called from t1);
+called bad
+called bad
+called bad
+called bad
+called bad
+called bad
+called bad
+called bad
+# bad() is good.
+# MDEV-14751 Server crashes in TABLE::versioned on 2nd execution of SP [#431]
+create or replace table t1 (called_bad int);
+create or replace table t2 (b int);
+create or replace procedure bad() select * from t1 where ( 5, 6 ) in ( select b, b from t2 ) and called_bad in ( select max(b) from t2 );
+called_bad
+called_bad
+called_bad
+called_bad
+called_bad
+called_bad
+called_bad
+called_bad
+# bad() is good.
+# MDEV-14786 Server crashes in Item_cond::transform on 2nd execution of SP querying from a view [#436]
+create or replace table t1 (called_bad int) with system versioning;
+create or replace view v1 as select called_bad from t1 where called_bad < 5;
+create or replace procedure bad() select called_bad from v1;
+called_bad
+called_bad
+called_bad
+called_bad
+called_bad
+called_bad
+called_bad
+called_bad
+# bad() is good.
+# wildcard expansion on hidden fields.
+create or replace table t1(
+A int
+) with system versioning;
+insert into t1 values(1);
+select * from t1;
+A
+1
+create or replace table t1 (x int);
+insert into t1 values (1);
+select * from t1 for system_time all;
+ERROR HY000: Table `t1` is not system-versioned
+create or replace table t1 (x int) with system versioning;
+insert into t1 values (1);
+select * from t1 for system_time as of now() for update;
+x
+1
+create or replace table t1 (a int not null auto_increment primary key) with system versioning;
+select * from (t1 as t2 left join t1 as t3 using (a)) natural left join t1;
+a
+create or replace table t1 (a int) with system versioning;
+create or replace table t2 (a int) with system versioning;
+insert into t1 values(1);
+insert into t2 values(1);
+create or replace view v1 as select * from t2 inner join t1 using (a);
+select * from v1;
+a
+1
+drop view v1;
+create or replace table t1 (a int) with system versioning;
+insert into t1 values (1);
+create view vt1 as select a from t1;
+select * from t1 natural join vt1;
+a
+1
+drop view vt1;
+create or replace table t1(x int) with system versioning;
+select * from (t1 as r left join t1 as u using (x)), t1;
+x x
+create or replace table t1 (a int) with system versioning;
+insert into t1 values (1);
+create trigger read_end after update on t1
+for each row set @end = old.row_end;
+update t1 set a=2;
+select @end;
+@end
+MAX_RESULT
+create or replace table t1 (a int) with system versioning;
+create or replace table t2 (b int) with system versioning;
+insert into t1 values (1);
+insert into t2 values (2);
+select * from (select * from t1 cross join t2) as tmp;
+a b
+1 2
+select * from (select * from (select * from t1 cross join t2) as tmp1) as tmp2;
+a b
+1 2
+select * from (select * from t1 cross join t2 for system_time as of timestamp '0-0-0') as tmp;
+a b
+create or replace table t1(a1 int) with system versioning;
+create or replace table t2(a2 int) with system versioning;
+insert into t1 values(1),(2);
+insert into t2 values(1),(2);
+select * from t1 for system_time all natural left join t2 for system_time all;
+a1 a2
+1 1
+2 1
+1 2
+2 2
+create or replace table t1(a1 int) with system versioning;
+create or replace table t2(a2 int) with system versioning;
+insert into t1 values(1),(2);
+insert into t2 values(1),(2);
+create or replace view v1 as select a1 from t1;
+select * from v1 natural join t2;
+a1 a2
+1 1
+2 1
+1 2
+2 2
+select * from v1 natural left join t2;
+a1 a2
+1 1
+2 1
+1 2
+2 2
+select * from v1 natural right join t2;
+a2 a1
+1 1
+2 1
+1 2
+2 2
+create or replace table t1 (a int) with system versioning;
+insert into t1 values (1);
+insert into t1 values (2);
+insert into t1 values (3);
+select * from t1 left outer join (t1 as t2 left join t1 as t3 using (a)) on t1.a>1;
+a a
+2 1
+3 1
+2 2
+3 2
+2 3
+3 3
+1 NULL
+create or replace table t1 (x int) with system versioning;
+create or replace table t2 (y int) with system versioning;
+insert into t1 values (1), (2), (3);
+delete from t1 where x = 3;
+insert into t2 values (1);
+select * from t1, t2 for system_time all;
+x y
+1 1
+2 1
+select * from (select * from t1 for system_time all, t2 for system_time all) for system_time all as t;
+ERROR HY000: Table `t` is not system-versioned
+select * from (t1 for system_time all join t2 for system_time all) for system_time all;
+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 '' at line 1
+drop view v1;
+drop table t1, t2;
diff --git a/mysql-test/suite/versioning/r/simple.result b/mysql-test/suite/versioning/r/simple.result
new file mode 100644
index 00000000000..f6a1ba37f53
--- /dev/null
+++ b/mysql-test/suite/versioning/r/simple.result
@@ -0,0 +1,73 @@
+set default_storage_engine=innodb;
+create or replace table dept (
+dept_id int(10) primary key,
+name varchar(100)
+)
+with system versioning;
+create or replace table emp (
+emp_id int(10) primary key,
+dept_id int(10),
+name varchar(100),
+salary int(10),
+constraint `dept-emp-fk`
+ foreign key (dept_id) references dept (dept_id)
+on delete cascade
+on update restrict
+)
+with system versioning;
+select now() into @ts_0;
+insert into dept (dept_id, name) values (10, "accounting");
+commit;
+select row_start into @ts_1 from dept where dept_id=10;
+insert into emp (emp_id, name, salary, dept_id) values (1, "bill", 1000, 10);
+commit;
+select row_start into @ts_2 from emp where name="bill";
+select * from emp;
+emp_id dept_id name salary
+1 10 bill 1000
+update emp set salary=2000 where name="bill";
+commit;
+select row_start into @ts_3 from emp where name="bill";
+select * from emp;
+emp_id dept_id name salary
+1 10 bill 2000
+select * from emp for system_time as of timestamp @ts_2;
+emp_id dept_id name salary
+1 10 bill 1000
+select * from emp for system_time as of timestamp @ts_3;
+emp_id dept_id name salary
+1 10 bill 2000
+select * from emp e, dept d
+where d.dept_id = 10
+and d.dept_id = e.dept_id;
+emp_id dept_id name salary dept_id name
+1 10 bill 2000 10 accounting
+select * from
+emp for system_time from timestamp @ts_1 to timestamp @ts_2 e,
+dept for system_time from timestamp @ts_1 to timestamp @ts_2 d
+where d.dept_id = 10
+and d.dept_id = e.dept_id;
+emp_id dept_id name salary dept_id name
+set statement system_versioning_asof=@ts_0 for
+select * from emp e, dept d
+where d.dept_id = 10
+and d.dept_id = e.dept_id;
+emp_id dept_id name salary dept_id name
+set statement system_versioning_asof=@ts_1 for
+select * from emp e, dept d
+where d.dept_id = 10
+and d.dept_id = e.dept_id;
+emp_id dept_id name salary dept_id name
+set statement system_versioning_asof=@ts_2 for
+select * from emp e, dept d
+where d.dept_id = 10
+and d.dept_id = e.dept_id;
+emp_id dept_id name salary dept_id name
+1 10 bill 1000 10 accounting
+set statement system_versioning_asof=@ts_3 for
+select * from emp e, dept d
+where d.dept_id = 10
+and d.dept_id = e.dept_id;
+emp_id dept_id name salary dept_id name
+1 10 bill 2000 10 accounting
+drop table emp, dept;
diff --git a/mysql-test/suite/versioning/r/sysvars.result b/mysql-test/suite/versioning/r/sysvars.result
new file mode 100644
index 00000000000..22f53ca6fbe
--- /dev/null
+++ b/mysql-test/suite/versioning/r/sysvars.result
@@ -0,0 +1,129 @@
+create table t (a int) with system versioning;
+insert into t values (1);
+update t set a= 2;
+show global variables like 'system_versioning_asof';
+Variable_name Value
+system_versioning_asof DEFAULT
+show variables like 'system_versioning_asof';
+Variable_name Value
+system_versioning_asof DEFAULT
+select * from t;
+a
+2
+set system_versioning_asof= '2031-1-1 0:0:0';
+show variables like 'system_versioning_asof';
+Variable_name Value
+system_versioning_asof 2031-01-01 00:00:00.000000
+select * from t;
+a
+2
+set system_versioning_asof= '2011-1-1 0:0:0';
+show variables like 'system_versioning_asof';
+Variable_name Value
+system_versioning_asof 2011-01-01 00:00:00.000000
+select * from t;
+a
+set global system_versioning_asof= 'alley';
+ERROR 42000: Variable 'system_versioning_asof' can't be set to the value of 'alley'
+set global system_versioning_asof= null;
+ERROR 42000: Variable 'system_versioning_asof' can't be set to the value of 'NULL'
+set global system_versioning_asof= 1;
+ERROR 42000: Incorrect argument type to variable 'system_versioning_asof'
+set global system_versioning_asof= 1.1;
+ERROR 42000: Incorrect argument type to variable 'system_versioning_asof'
+set system_versioning_asof= 'alley';
+ERROR 42000: Variable 'system_versioning_asof' can't be set to the value of 'alley'
+set system_versioning_asof= null;
+ERROR 42000: Variable 'system_versioning_asof' can't be set to the value of 'NULL'
+set system_versioning_asof= 1;
+ERROR 42000: Incorrect argument type to variable 'system_versioning_asof'
+set system_versioning_asof= 1.1;
+ERROR 42000: Incorrect argument type to variable 'system_versioning_asof'
+# GLOBAL @@system_versioning_asof
+set global system_versioning_asof= '1911-11-11 11:11:11.1111119';
+Warnings:
+Note 1292 Truncated incorrect datetime value: '1911-11-11 11:11:11.1111119'
+Note 1292 Truncated incorrect datetime value: '1911-11-11 11:11:11.1111119'
+show global variables like 'system_versioning_asof';
+Variable_name Value
+system_versioning_asof 1911-11-11 11:11:11.111111
+set global system_versioning_asof= '1900-01-01 00:00:00';
+show global variables like 'system_versioning_asof';
+Variable_name Value
+system_versioning_asof 1900-01-01 00:00:00.000000
+set global system_versioning_asof= timestamp'1911-11-11 11:11:11.1111119';
+Warnings:
+Note 1292 Truncated incorrect datetime value: '1911-11-11 11:11:11.1111119'
+show global variables like 'system_versioning_asof';
+Variable_name Value
+system_versioning_asof 1911-11-11 11:11:11.111111
+set @ts= timestamp'1900-01-01 00:00:00';
+set global system_versioning_asof= @ts;
+show global variables like 'system_versioning_asof';
+Variable_name Value
+system_versioning_asof 1900-01-01 00:00:00.000000
+set global system_versioning_asof= default;
+select @@global.system_versioning_asof;
+@@global.system_versioning_asof
+DEFAULT
+# SESSION @@system_versioning_asof
+set system_versioning_asof= '1911-11-11 11:11:11.1111119';
+Warnings:
+Note 1292 Truncated incorrect datetime value: '1911-11-11 11:11:11.1111119'
+Note 1292 Truncated incorrect datetime value: '1911-11-11 11:11:11.1111119'
+show variables like 'system_versioning_asof';
+Variable_name Value
+system_versioning_asof 1911-11-11 11:11:11.111111
+set system_versioning_asof= '1900-01-01 00:00:00';
+show variables like 'system_versioning_asof';
+Variable_name Value
+system_versioning_asof 1900-01-01 00:00:00.000000
+set system_versioning_asof= timestamp'1911-11-11 11:11:11.1111119';
+Warnings:
+Note 1292 Truncated incorrect datetime value: '1911-11-11 11:11:11.1111119'
+show variables like 'system_versioning_asof';
+Variable_name Value
+system_versioning_asof 1911-11-11 11:11:11.111111
+set @ts= timestamp'1900-01-01 00:00:00';
+set system_versioning_asof= @ts;
+show variables like 'system_versioning_asof';
+Variable_name Value
+system_versioning_asof 1900-01-01 00:00:00.000000
+# DEFAULT: value is copied from GLOBAL to SESSION
+set global system_versioning_asof= timestamp'1911-11-11 11:11:11.111111';
+set system_versioning_asof= '1900-01-01 00:00:00';
+select @@global.system_versioning_asof != @@system_versioning_asof as different;
+different
+1
+set system_versioning_asof= default;
+select @@global.system_versioning_asof = @@system_versioning_asof as equal;
+equal
+1
+set global system_versioning_asof= DEFAULT;
+set system_versioning_asof= DEFAULT;
+select @@global.system_versioning_asof, @@system_versioning_asof;
+@@global.system_versioning_asof @@system_versioning_asof
+DEFAULT DEFAULT
+select * from t for system_time all;
+a
+2
+1
+select * from t;
+a
+2
+select * from t for system_time as of timestamp current_timestamp(6);
+a
+2
+select * from t for system_time all;
+a
+2
+1
+select * from t for system_time from '0-0-0' to current_timestamp(6);
+a
+2
+1
+select * from t for system_time between '0-0-0' and current_timestamp(6);
+a
+2
+1
+drop table t;
diff --git a/mysql-test/suite/versioning/r/truncate.result b/mysql-test/suite/versioning/r/truncate.result
new file mode 100644
index 00000000000..48b7fbbcf55
--- /dev/null
+++ b/mysql-test/suite/versioning/r/truncate.result
@@ -0,0 +1,71 @@
+create table t (a int);
+delete history from t before system_time now();
+ERROR HY000: Table `t` is not system-versioned
+create or replace table t (a int) with system versioning;
+insert into t values (1);
+update t set a=2;
+set @test = 'correct';
+create trigger trg_before before delete on t for each row set @test = 'incorrect';
+create trigger trg_after after delete on t for each row set @test = 'incorrect';
+delete history from t;
+select @test from t;
+@test
+correct
+drop table t;
+create table t (a int) with system versioning;
+insert into t values (1), (2);
+update t set a=11 where a=1;
+set @ts1=now(6);
+update t set a=22 where a=2;
+select * from t for system_time all;
+a
+11
+22
+1
+2
+delete history from t before system_time timestamp @ts1;
+select * from t for system_time all;
+a
+11
+22
+2
+prepare stmt from 'delete history from t';
+execute stmt;
+drop prepare stmt;
+select * from t for system_time all;
+a
+11
+22
+delete from t;
+create or replace procedure truncate_sp()
+begin
+delete history from t before system_time timestamp now(6);
+end~~
+call truncate_sp;
+select * from t for system_time all;
+a
+drop procedure truncate_sp;
+### Issue #399, truncate partitioned table is now unimplemented
+create or replace table t (a int)
+with system versioning
+engine myisam
+partition by system_time (
+partition p0 history,
+partition pn current);
+delete history from t;
+ERROR 42000: The used command is not allowed with this MariaDB version
+create or replace table t (i int) with system versioning;
+delete history from t;
+create or replace view v as select * from t;
+delete history from v;
+ERROR HY000: DELETE HISTORY from VIEW is prohibited
+create or replace table t (i int);
+delete history from t;
+ERROR HY000: Table `t` is not system-versioned
+create or replace view v as select * from t;
+delete history from v;
+ERROR HY000: DELETE HISTORY from VIEW is prohibited
+prepare stmt from 'delete history from t';
+ERROR HY000: Table `t` is not system-versioned
+drop table t;
+drop view v;
diff --git a/mysql-test/suite/versioning/r/truncate_privilege.result b/mysql-test/suite/versioning/r/truncate_privilege.result
new file mode 100644
index 00000000000..e378407afde
--- /dev/null
+++ b/mysql-test/suite/versioning/r/truncate_privilege.result
@@ -0,0 +1,33 @@
+connect root,localhost,root,,test;
+connection root;
+create database mysqltest;
+create user mysqltest_1@localhost;
+connect user1,localhost,mysqltest_1,,test;
+connection user1;
+connection root;
+create table mysqltest.t (a int) with system versioning;
+connection user1;
+show grants;
+Grants for mysqltest_1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
+delete history from mysqltest.t before system_time now();
+ERROR 42000: DELETE VERSIONING ROWS command denied to user 'mysqltest_1'@'localhost' for table 't'
+connection root;
+grant delete history on mysqltest.* to mysqltest_1@localhost;
+grant delete history on mysqltest.t to mysqltest_1@localhost;
+connection user1;
+show grants;
+Grants for mysqltest_1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
+GRANT DELETE VERSIONING ROWS ON `mysqltest`.* TO 'mysqltest_1'@'localhost'
+GRANT DELETE VERSIONING ROWS ON `mysqltest`.`t` TO 'mysqltest_1'@'localhost'
+delete history from mysqltest.t before system_time now();
+connection root;
+grant all on *.* to mysqltest_1@localhost;
+show grants for mysqltest_1@localhost;
+Grants for mysqltest_1@localhost
+GRANT ALL PRIVILEGES ON *.* TO 'mysqltest_1'@'localhost'
+GRANT DELETE VERSIONING ROWS ON `mysqltest`.* TO 'mysqltest_1'@'localhost'
+GRANT DELETE VERSIONING ROWS ON `mysqltest`.`t` TO 'mysqltest_1'@'localhost'
+drop user mysqltest_1@localhost;
+drop database mysqltest;
diff --git a/mysql-test/suite/versioning/r/trx_id.result b/mysql-test/suite/versioning/r/trx_id.result
new file mode 100644
index 00000000000..a88ba7eec2b
--- /dev/null
+++ b/mysql-test/suite/versioning/r/trx_id.result
@@ -0,0 +1,72 @@
+create or replace table t1 (
+x int,
+sys_trx_start bigint(20) unsigned as row start invisible,
+sys_trx_end bigint(20) unsigned as row end invisible,
+period for system_time (sys_trx_start, sys_trx_end)
+) with system versioning engine innodb;
+insert into t1 (x) values (1);
+# ALTER ADD SYSTEM VERSIONING should write to mysql.transaction_registry
+create function check_result (cond boolean)
+returns char(50) deterministic
+return if(cond = 1, '[CORRECT]', '[INCORRECT]');
+set @@system_versioning_alter_history=keep;
+create or replace table t1 (x int) engine innodb;
+insert into t1 values (1);
+alter table t1
+add column s bigint unsigned as row start,
+add column e bigint unsigned as row end,
+add period for system_time(s, e),
+add system versioning,
+algorithm=inplace;
+select s from t1 into @trx_start;
+select check_result(count(*) = 1) from mysql.transaction_registry where transaction_id = @trx_start;
+check_result(count(*) = 1)
+[CORRECT]
+create or replace table t1 (x int) engine innodb;
+select count(*) from mysql.transaction_registry into @tmp;
+alter table t1
+add column s bigint unsigned as row start,
+add column e bigint unsigned as row end,
+add period for system_time(s, e),
+add system versioning,
+algorithm=inplace;
+select check_result(count(*) = @tmp) from mysql.transaction_registry;
+check_result(count(*) = @tmp)
+[CORRECT]
+create or replace table t1 (x int) engine innodb;
+insert into t1 values (1);
+alter table t1
+add column s bigint unsigned as row start,
+add column e bigint unsigned as row end,
+add period for system_time(s, e),
+add system versioning,
+algorithm=copy;
+select s from t1 into @trx_start;
+select check_result(count(*) = 1) from mysql.transaction_registry where transaction_id = @trx_start;
+check_result(count(*) = 1)
+[CORRECT]
+create or replace table t1 (x int) engine innodb;
+select count(*) from mysql.transaction_registry into @tmp;
+alter table t1
+add column s bigint unsigned as row start,
+add column e bigint unsigned as row end,
+add period for system_time(s, e),
+add system versioning,
+algorithm=copy;
+select check_result(count(*) = @tmp) from mysql.transaction_registry;
+check_result(count(*) = @tmp)
+[CORRECT]
+# TRX_ID to TIMESTAMP versioning switch
+create or replace table t1 (
+x int,
+sys_start bigint unsigned as row start invisible,
+sys_end bigint unsigned as row end invisible,
+period for system_time (sys_start, sys_end)
+) engine innodb with system versioning;
+insert into t1 values (1);
+alter table t1 drop column sys_start, drop column sys_end;
+select sys_end = 18446744073709551615 as transaction_based from t1 for system_time all;
+transaction_based
+1
+drop table t1;
+drop function check_result;
diff --git a/mysql-test/suite/versioning/r/update.result b/mysql-test/suite/versioning/r/update.result
new file mode 100644
index 00000000000..e0daf1d6588
--- /dev/null
+++ b/mysql-test/suite/versioning/r/update.result
@@ -0,0 +1,625 @@
+create procedure test_01(
+sys_type varchar(255),
+engine varchar(255),
+fields varchar(255))
+begin
+set @str= concat('
+ create table t1(
+ x int unsigned,
+ y int unsigned,
+ sys_trx_start ', sys_type, ' as row start invisible,
+ sys_trx_end ', sys_type, ' as row end invisible,
+ period for system_time (sys_trx_start, sys_trx_end))
+ with system versioning
+ engine ', engine);
+prepare stmt from @str; execute stmt; drop prepare stmt;
+insert into t1(x, y) values
+(1, 1000),
+(2, 2000),
+(3, 3000),
+(4, 4000),
+(5, 5000),
+(6, 6000),
+(7, 7000),
+(8, 8000),
+(9, 9000);
+select x, y from t1;
+update t1 set y = y + 1 where x > 7;
+select x, y from t1;
+select x, y from t1 for system_time
+between timestamp '0000-0-0 0:0:0'
+ and timestamp '2038-01-19 04:14:07';
+drop table t1;
+end~~
+create procedure test_02(
+sys_type varchar(255),
+engine varchar(255),
+fields varchar(255))
+begin
+set @str= concat('
+ create table t1 (
+ id bigint primary key,
+ x int,
+ y int without system versioning,
+ sys_trx_start ', sys_type, ' as row start invisible,
+ sys_trx_end ', sys_type, ' as row end invisible,
+ period for system_time (sys_trx_start, sys_trx_end))
+ with system versioning
+ engine ', engine);
+prepare stmt from @str; execute stmt; drop prepare stmt;
+insert into t1 values(1, 1, 1);
+set @ins_t= now(6);
+select sys_trx_start into @tmp1 from t1;
+update t1 set x= 11, y= 11 where id = 1;
+select @tmp1 < sys_trx_start as A1, x, y from t1;
+select sys_trx_start into @tmp1 from t1;
+update t1 set y= 1 where id = 1;
+select @tmp1 = sys_trx_start as A2, x from t1;
+drop table t1;
+end~~
+create procedure test_03(
+sys_type varchar(255),
+engine varchar(255),
+fields varchar(255))
+begin
+set @str= concat('
+ create table t1 (
+ x int,
+ y int,
+ sys_trx_start bigint unsigned as row start invisible,
+ sys_trx_end bigint unsigned as row end invisible,
+ period for system_time (sys_trx_start, sys_trx_end)
+ ) with system versioning
+ engine ', engine);
+prepare stmt from @str; execute stmt; drop prepare stmt;
+insert into t1 (x, y) values (1, 1), (2, 1), (3, 1), (4, 1), (5, 1);
+start transaction;
+update t1 set y= y + 1 where x = 3;
+update t1 set y= y + 1 where x = 2;
+update t1 set y= y + 1 where x = 3;
+update t1 set y= y + 1 where x > 3;
+update t1 set y= y + 1 where x > 4;
+commit;
+select x, y, sys_trx_end = 18446744073709551615 as current from t1 for system_time all;
+drop table t1;
+end~~
+create procedure test_04(
+sys_type varchar(255),
+engine varchar(255),
+fields varchar(255))
+begin
+set @str= concat('
+ create table t1 (
+ id int primary key auto_increment,
+ x int,
+ sys_trx_start ', sys_type, ' as row start invisible,
+ sys_trx_end ', sys_type, ' as row end invisible,
+ period for system_time (sys_trx_start, sys_trx_end))
+ with system versioning
+ engine ', engine);
+prepare stmt from @str; execute stmt; drop prepare stmt;
+set @t0= now(6);
+insert into t1 (x) values (1);
+set @t1= now(6);
+update t1 set x= 2 where id = 1;
+set @t2= now(6);
+update t1 set x= 3 where id = 1;
+select x from t1 for system_time as of timestamp @t0;
+select x from t1 for system_time as of timestamp @t1;
+select x from t1 for system_time as of timestamp @t2;
+select x from t1 for system_time as of timestamp now(6);
+drop table t1;
+end~~
+create procedure test_05(
+sys_type varchar(255),
+engine varchar(255),
+fields varchar(255))
+begin
+set @str= concat('
+ create table t1(
+ x int unsigned,
+ sys_trx_end ', sys_type, ' as row end invisible,
+ sys_trx_start ', sys_type, ' as row start invisible,
+ y int unsigned,
+ period for system_time (sys_trx_start, sys_trx_end),
+ primary key(x, y))
+ with system versioning
+ engine ', engine);
+prepare stmt from @str; execute stmt; drop prepare stmt;
+insert into t1(x, y) values
+(1, 1000),
+(3, 3000),
+(4, 4000),
+(5, 5000);
+insert into t1(x, y) values(3, 3000) on duplicate key update y = y+1;
+insert into t1(x, y) values(4, 4444) on duplicate key update y = y+1;
+select x, y from t1 for system_time all;
+select x, y from t1;
+drop table t1;
+end~~
+create procedure test_06(
+sys_type varchar(255),
+engine varchar(255),
+fields varchar(255))
+begin
+set @str= concat('(
+ x int unsigned,
+ y int unsigned,
+ sys_trx_start ', sys_type, ' as row start invisible,
+ sys_trx_end ', sys_type, ' as row end invisible,
+ period for system_time (sys_trx_start, sys_trx_end))
+ with system versioning
+ engine ', engine);
+set @str2= concat('create table t1', @str);
+prepare stmt from @str2; execute stmt; drop prepare stmt;
+set @str2= concat('create table t2', @str);
+prepare stmt from @str2; execute stmt; drop prepare stmt;
+insert into t1(x, y) values
+(1, 1000),
+(2, 2000),
+(3, 3000),
+(4, 4000),
+(5, 5000),
+(6, 6000),
+(7, 7000),
+(8, 8000),
+(9, 9000);
+insert into t2(x, y) values
+(1, 1010),
+(2, 2010),
+(3, 3010),
+(4, 4010),
+(5, 5010),
+(6, 6010),
+(7, 7010),
+(8, 8010),
+(9, 9010);
+update t1, t2 set t1.y = t1.x + t1.y, t2.y = t2.x + t2.y where t1.x > 7 and t2.x < 7;
+select x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp '9999-1-1 0:0:0';
+select x, y from t1;
+select x, y from t2 for system_time between timestamp '0-0-0 0:0:0' and timestamp '9999-1-1 0:0:0';
+select x, y from t2;
+drop table t1;
+drop table t2;
+end~~
+create procedure test_07(
+sys_type varchar(255),
+engine varchar(255),
+fields varchar(255))
+begin
+set @str= concat('(
+ id bigint primary key without system versioning,
+ name varchar(128),
+ salary bigint without system versioning,
+ sys_trx_start ', sys_type, ' as row start invisible,
+ sys_trx_end ', sys_type, ' as row end invisible,
+ period for system_time (sys_trx_start, sys_trx_end))
+ with system versioning
+ engine ', engine);
+set @str2= concat('create table t1', @str);
+prepare stmt from @str2; execute stmt; drop prepare stmt;
+set @str2= concat('create table t2', @str);
+prepare stmt from @str2; execute stmt; drop prepare stmt;
+insert into t1 values (1, "Jeremy", 3000);
+insert into t2 values (1, "Jeremy", 4000);
+select sys_trx_start into @tmp1 from t1;
+select sys_trx_start into @tmp2 from t2;
+update t1, t2 set t1.name= "Jerry", t2.name= "Jerry" where t1.id = t2.id and t1.name = "Jeremy";
+select @tmp1 < sys_trx_start as A1, name from t1;
+select @tmp2 < sys_trx_start as A2, name from t2;
+select sys_trx_start into @tmp1 from t1;
+select sys_trx_start into @tmp2 from t2;
+update t1, t2 set t1.salary= 2500, t2.salary= 2500 where t1.id = t2.id and t1.name = "Jerry";
+select @tmp1 = sys_trx_start as B1, salary from t1;
+select @tmp2 = sys_trx_start as B2, salary from t2;
+drop table t1;
+drop table t2;
+end~~
+call test_01('timestamp(6)', 'myisam', 'sys_trx_end');
+x y
+1 1000
+2 2000
+3 3000
+4 4000
+5 5000
+6 6000
+7 7000
+8 8000
+9 9000
+x y
+1 1000
+2 2000
+3 3000
+4 4000
+5 5000
+6 6000
+7 7000
+8 8001
+9 9001
+x y
+1 1000
+2 2000
+3 3000
+4 4000
+5 5000
+6 6000
+7 7000
+8 8001
+9 9001
+8 8000
+9 9000
+call test_01('timestamp(6)', 'innodb', 'vtq_commit_ts(sys_trx_end)');
+x y
+1 1000
+2 2000
+3 3000
+4 4000
+5 5000
+6 6000
+7 7000
+8 8000
+9 9000
+x y
+1 1000
+2 2000
+3 3000
+4 4000
+5 5000
+6 6000
+7 7000
+8 8001
+9 9001
+x y
+1 1000
+2 2000
+3 3000
+4 4000
+5 5000
+6 6000
+7 7000
+8 8001
+9 9001
+8 8000
+9 9000
+call test_01('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_trx_end)');
+x y
+1 1000
+2 2000
+3 3000
+4 4000
+5 5000
+6 6000
+7 7000
+8 8000
+9 9000
+x y
+1 1000
+2 2000
+3 3000
+4 4000
+5 5000
+6 6000
+7 7000
+8 8001
+9 9001
+x y
+1 1000
+2 2000
+3 3000
+4 4000
+5 5000
+6 6000
+7 7000
+8 8001
+9 9001
+8 8000
+9 9000
+call verify_vtq;
+No A B C D
+1 1 1 1 1
+2 1 1 1 1
+call test_02('timestamp(6)', 'myisam', 'sys_trx_end');
+A1 x y
+1 11 11
+A2 x
+1 11
+call test_02('timestamp(6)', 'innodb', 'vtq_commit_ts(sys_trx_end)');
+A1 x y
+1 11 11
+A2 x
+1 11
+call test_02('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_trx_end)');
+A1 x y
+1 11 11
+A2 x
+1 11
+call verify_vtq;
+No A B C D
+1 1 1 1 1
+2 1 1 1 1
+# Multiple UPDATE of same rows in single transaction create historical
+# rows only once (applicable to transaction-based only).
+call test_03('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_trx_end)');
+x y current
+1 1 1
+2 2 1
+3 3 1
+4 2 1
+5 3 1
+3 1 0
+2 1 0
+4 1 0
+5 1 0
+call verify_vtq;
+No A B C D
+1 1 1 1 1
+2 1 1 1 1
+call test_04('timestamp(6)', 'myisam', 'sys_trx_end');
+x
+x
+1
+x
+2
+x
+3
+call test_04('timestamp(6)', 'innodb', 'vtq_commit_ts(sys_trx_end)');
+x
+x
+1
+x
+2
+x
+3
+call test_04('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_trx_end)');
+x
+x
+1
+x
+2
+x
+3
+call verify_vtq;
+No A B C D
+1 1 1 1 1
+2 1 1 1 1
+3 1 1 1 1
+call test_05('timestamp(6)', 'myisam', 'sys_trx_end');
+x y
+1 1000
+3 3000
+3 3001
+4 4000
+4 4444
+5 5000
+x y
+1 1000
+3 3001
+4 4000
+4 4444
+5 5000
+call test_05('timestamp(6)', 'innodb', 'vtq_commit_ts(sys_trx_end)');
+x y
+1 1000
+3 3000
+3 3001
+4 4000
+4 4444
+5 5000
+x y
+1 1000
+3 3001
+4 4000
+4 4444
+5 5000
+call test_05('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_trx_end)');
+x y
+1 1000
+3 3000
+3 3001
+4 4000
+4 4444
+5 5000
+x y
+1 1000
+3 3001
+4 4000
+4 4444
+5 5000
+call verify_vtq;
+No A B C D
+1 1 1 1 1
+2 1 1 1 1
+3 1 1 1 1
+call test_06('timestamp(6)', 'myisam', 'sys_trx_end');
+x y
+1 1000
+2 2000
+3 3000
+4 4000
+5 5000
+6 6000
+7 7000
+8 8008
+9 9009
+8 8000
+9 9000
+x y
+1 1000
+2 2000
+3 3000
+4 4000
+5 5000
+6 6000
+7 7000
+8 8008
+9 9009
+x y
+1 1011
+2 2012
+3 3013
+4 4014
+5 5015
+6 6016
+7 7010
+8 8010
+9 9010
+1 1010
+2 2010
+3 3010
+4 4010
+5 5010
+6 6010
+x y
+1 1011
+2 2012
+3 3013
+4 4014
+5 5015
+6 6016
+7 7010
+8 8010
+9 9010
+call test_06('timestamp(6)', 'innodb', 'vtq_commit_ts(sys_trx_end)');
+x y
+1 1000
+2 2000
+3 3000
+4 4000
+5 5000
+6 6000
+7 7000
+8 8008
+9 9009
+8 8000
+9 9000
+x y
+1 1000
+2 2000
+3 3000
+4 4000
+5 5000
+6 6000
+7 7000
+8 8008
+9 9009
+x y
+1 1011
+2 2012
+3 3013
+4 4014
+5 5015
+6 6016
+7 7010
+8 8010
+9 9010
+1 1010
+2 2010
+3 3010
+4 4010
+5 5010
+6 6010
+x y
+1 1011
+2 2012
+3 3013
+4 4014
+5 5015
+6 6016
+7 7010
+8 8010
+9 9010
+call test_06('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_trx_end)');
+x y
+1 1000
+2 2000
+3 3000
+4 4000
+5 5000
+6 6000
+7 7000
+8 8008
+9 9009
+8 8000
+9 9000
+x y
+1 1000
+2 2000
+3 3000
+4 4000
+5 5000
+6 6000
+7 7000
+8 8008
+9 9009
+x y
+1 1011
+2 2012
+3 3013
+4 4014
+5 5015
+6 6016
+7 7010
+8 8010
+9 9010
+1 1010
+2 2010
+3 3010
+4 4010
+5 5010
+6 6010
+x y
+1 1011
+2 2012
+3 3013
+4 4014
+5 5015
+6 6016
+7 7010
+8 8010
+9 9010
+call verify_vtq;
+No A B C D
+1 1 1 1 1
+2 1 1 1 1
+3 1 1 1 1
+# Optimized fields
+call test_07('timestamp(6)', 'myisam', 'sys_trx_end');
+A1 name
+1 Jerry
+A2 name
+1 Jerry
+B1 salary
+1 2500
+B2 salary
+1 2500
+call test_07('timestamp(6)', 'innodb', 'vtq_commit_ts(sys_trx_end)');
+A1 name
+1 Jerry
+A2 name
+1 Jerry
+B1 salary
+1 2500
+B2 salary
+1 2500
+call test_07('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_trx_end)');
+A1 name
+1 Jerry
+A2 name
+1 Jerry
+B1 salary
+1 2500
+B2 salary
+1 2500
+call verify_vtq;
+No A B C D
+1 1 1 1 1
+2 1 1 1 1
+3 1 1 1 1
+### Issue #365, bug 7 (duplicate of historical row)
+create or replace table t1 (a int primary key, b int)
+with system versioning engine myisam;
+insert into t1 (a) values (1);
+replace t1 values (1,2),(1,3),(2,4);
+ERROR 23000: Duplicate entry '1-YYYY-MM-DD hh:mm:ss.uuuuuu' for key 'PRIMARY'
+drop database test;
+create database test;
diff --git a/mysql-test/suite/versioning/r/view.result b/mysql-test/suite/versioning/r/view.result
new file mode 100644
index 00000000000..209a7aa77a1
--- /dev/null
+++ b/mysql-test/suite/versioning/r/view.result
@@ -0,0 +1,120 @@
+create or replace table t1 (x int) with system versioning;
+insert into t1 values (1);
+select now(6) into @t1;
+update t1 set x= 2;
+select now(6) into @t2;
+delete from t1;
+set @vt1= concat("create or replace view vt1 as select * from t1 for system_time as of timestamp '", @t1, "'");
+prepare stmt from @vt1;
+execute stmt;
+drop prepare stmt;
+set @vt2= concat("create or replace view vt2 as select *, row_end from t1 for system_time as of timestamp '", @t2, "'");
+prepare stmt from @vt2;
+execute stmt;
+drop prepare stmt;
+select * from t1;
+x
+create or replace view vt1 as select * from t1;
+show create view vt1;
+View Create View character_set_client collation_connection
+vt1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `vt1` AS select `t1`.`x` AS `x` from `t1` FOR SYSTEM_TIME ALL where `t1`.`row_end` = MAX_RESULT or `t1`.`row_end` is null latin1 latin1_swedish_ci
+drop view vt1;
+drop view vt2;
+create or replace view vt1 as select * from t1 for system_time all;
+select * from vt1;
+x
+2
+1
+prepare stmt from 'select * from vt1';
+execute stmt;
+x
+2
+1
+drop prepare stmt;
+set @str= concat('create or replace view vt1 as
+select * from t1 for system_time as of timestamp "', @t1, '"');
+prepare stmt from @str;
+execute stmt;
+drop prepare stmt;
+select * from t1 for system_time as of timestamp @t1;
+x
+1
+select * from vt1;
+x
+1
+insert into vt1 values (3);
+select * from t1;
+x
+3
+select * from vt1;
+x
+1
+create or replace table t1 (x int) with system versioning;
+insert into t1 values (1), (2);
+set @t1=now(6);
+delete from t1 where x=2;
+set @t2=now(6);
+delete from t1 where x=1;
+set @t3=now(6);
+set @tmp= concat("create or replace view vt1 as select * from t1 for system_time as of timestamp '", @t1, "'");
+prepare stmt from @tmp;
+execute stmt;
+drop prepare stmt;
+select * from vt1;
+x
+1
+2
+# VIEW with parameters [#151]
+create or replace table t1 (x int) with system versioning;
+create or replace view vt1(c) as select x from t1;
+show create view vt1;
+View Create View character_set_client collation_connection
+vt1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `vt1` AS select `t1`.`x` AS `c` from `t1` FOR SYSTEM_TIME ALL where `t1`.`row_end` = MAX_RESULT or `t1`.`row_end` is null latin1 latin1_swedish_ci
+# VIEW over JOIN of versioned tables [#153]
+create or replace table t1 (a int) with system versioning;
+create or replace table t2 (b int) with system versioning;
+insert into t1 values (1);
+insert into t2 values (2);
+create or replace view vt12 as select * from t1 cross join t2;
+select * from vt12;
+a b
+1 2
+create or replace view vt12 as select * from t1 for system_time as of timestamp '0-0-0' cross join t2;
+select * from vt12;
+a b
+# VIEW improvements [#183]
+create or replace table t3 (x int);
+create or replace view vt1 as select * from t1, t2, t3;
+show create view vt1;
+View Create View character_set_client collation_connection
+vt1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `vt1` AS select `t1`.`a` AS `a`,`t2`.`b` AS `b`,`t3`.`x` AS `x` from ((`t1` FOR SYSTEM_TIME ALL join `t2` FOR SYSTEM_TIME ALL) join `t3`) where (`t1`.`row_end` = MAX_RESULT or `t1`.`row_end` is null) and (`t2`.`row_end` = MAX_RESULT or `t2`.`row_end` is null) latin1 latin1_swedish_ci
+create or replace view vt1 as select * from t3, t2, t1;
+show create view vt1;
+View Create View character_set_client collation_connection
+vt1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `vt1` AS select `t3`.`x` AS `x`,`t2`.`b` AS `b`,`t1`.`a` AS `a` from ((`t3` join `t2` FOR SYSTEM_TIME ALL) join `t1` FOR SYSTEM_TIME ALL) where (`t2`.`row_end` = MAX_RESULT or `t2`.`row_end` is null) and (`t1`.`row_end` = MAX_RESULT or `t1`.`row_end` is null) latin1 latin1_swedish_ci
+create or replace view vt1 as select a, t2.row_end as endo from t3, t1, t2;
+show create view vt1;
+View Create View character_set_client collation_connection
+vt1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `vt1` AS select `t1`.`a` AS `a`,`t2`.`row_end` AS `endo` from ((`t3` join `t1` FOR SYSTEM_TIME ALL) join `t2` FOR SYSTEM_TIME ALL) where (`t1`.`row_end` = MAX_RESULT or `t1`.`row_end` is null) and (`t2`.`row_end` = MAX_RESULT or `t2`.`row_end` is null) latin1 latin1_swedish_ci
+# VIEW over UNION [#269]
+create or replace view vt1 as select * from t1 union select * from t1;
+select * from vt1;
+a
+1
+# VIEW over UNION with non-versioned [#393]
+create or replace table t2 (a int);
+create or replace view vt1 as select * from t1 union select * from t2;
+select * from vt1;
+a
+1
+# MDEV-14689 crash on second PS execute
+create or replace table t1 (a int);
+create or replace view v1 as select * from t1;
+create or replace table t2 (b int) with system versioning;
+prepare stmt from 'select a from v1 inner join t2 group by a order by a';
+execute stmt;
+a
+execute stmt;
+a
+drop database test;
+create database test;
diff --git a/mysql-test/suite/versioning/r/vtmd.result b/mysql-test/suite/versioning/r/vtmd.result
new file mode 100644
index 00000000000..ece5f5af61a
--- /dev/null
+++ b/mysql-test/suite/versioning/r/vtmd.result
@@ -0,0 +1,365 @@
+create or replace procedure drop_archives (in vtmd_name varchar(64))
+begin
+declare archive_name varchar(64);
+declare cur_done bool default false;
+declare cur cursor for
+select cur_tmp.archive_name from cur_tmp;
+declare continue handler for not found set cur_done = true;
+set @tmp= concat('
+ create or replace temporary table
+ cur_tmp as
+ select vtmd.archive_name from ', vtmd_name, '
+ for system_time all as vtmd
+ where vtmd.archive_name is not null
+ group by vtmd.archive_name');
+prepare stmt from @tmp; execute stmt; drop prepare stmt;
+open cur;
+fetch_loop: loop
+fetch cur into archive_name;
+if cur_done then
+leave fetch_loop;
+end if;
+set @tmp= concat('drop table ', archive_name);
+prepare stmt from @tmp; execute stmt; drop prepare stmt;
+end loop;
+drop table cur_tmp;
+end~~
+create or replace procedure check_vtmd (in vtmd_name varchar(64))
+begin
+set @tmp= concat('
+ create or replace temporary table
+ tmp_vtmd with system versioning as
+ select * from ', vtmd_name, '
+ for system_time all as vtmd');
+prepare stmt from @tmp; execute stmt; drop prepare stmt;
+set @inf= 0xFFFFFFFFFFFFFFFF + 0;
+set @start= null;
+select start from tmp_vtmd for system_time all order by start limit 1 into @start;
+select @start > 0 and @start < @inf;
+select
+start >= @start as A_start,
+(@start:= end) and end = @inf as B_end,
+name,
+substr(archive_name, 1, instr(archive_name, '_')) as C_archive_name
+from tmp_vtmd for system_time all;
+drop table tmp_vtmd;
+end~~
+create or replace procedure show_tables()
+begin
+show tables;
+select table_name, table_schema from information_schema.tables
+where table_schema not in ('mysql', 'performance_schema', 'information_schema', 'mtr')
+order by table_name;
+end~~
+set versioning_alter_history= keep;
+create table t0 (z int) with system versioning;
+show tables;
+Tables_in_test
+t0
+set versioning_alter_history= survive;
+create or replace table t0 (y int) with system versioning;
+show tables;
+Tables_in_test
+t0
+t0_vtmd
+show create table t0_vtmd;
+Table Create Table
+t0_vtmd CREATE TABLE `t0_vtmd` (
+ `start` bigint(20) unsigned GENERATED ALWAYS AS ROW START COMMENT 'TRX_ID of table lifetime start',
+ `end` bigint(20) unsigned GENERATED ALWAYS AS ROW END NOT NULL COMMENT 'TRX_ID of table lifetime end',
+ `name` varchar(64) COLLATE utf8_bin NOT NULL COMMENT 'Table name during current lifetime period',
+ `archive_name` varchar(64) COLLATE utf8_bin DEFAULT NULL COMMENT 'Name of archive table',
+ `col_renames` blob DEFAULT NULL COMMENT 'Column name mappings from previous lifetime',
+ PRIMARY KEY (`end`),
+ KEY `archive_name` (`archive_name`),
+ PERIOD FOR SYSTEM_TIME (`start`, `end`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin STATS_PERSISTENT=0 WITH SYSTEM VERSIONING
+call check_vtmd('t0_vtmd');
+@start > 0 and @start < @inf
+1
+A_start B_end name C_archive_name
+1 1 t0 NULL
+set versioning_alter_history= keep;
+drop table t0;
+set versioning_alter_history= survive;
+create table t0 (x int) with system versioning;
+ERROR HY000: VTMD error: `test.t0_vtmd` exists and not empty!
+drop table t0_vtmd;
+create table t0 (y int) with system versioning;
+create or replace table t0 (x int) with system versioning;
+insert into t0 values (1);
+set @t0= now(6);
+alter table t0 add column (y int);
+select * from t0 for system_time as of @t0;
+x
+1
+select * from t0;
+x y
+1 NULL
+call check_vtmd('t0_vtmd');
+@start > 0 and @start < @inf
+1
+A_start B_end name C_archive_name
+1 0 t0 t0_
+1 0 t0 t0_
+1 1 t0 NULL
+call drop_archives('t0_vtmd');
+drop table t0_vtmd;
+alter table t0 drop column y;
+call check_vtmd('t0_vtmd');
+@start > 0 and @start < @inf
+1
+A_start B_end name C_archive_name
+1 1 t0 t0_
+call drop_archives('t0_vtmd');
+set versioning_alter_history= keep;
+drop tables t0, t0_vtmd;
+set versioning_alter_history= survive;
+set versioning_alter_history= keep;
+create or replace table x0 (x int) with system versioning;
+set versioning_alter_history= survive;
+rename table x0 to d0;
+show tables;
+Tables_in_test
+d0
+set versioning_alter_history= keep;
+drop table d0;
+set versioning_alter_history= survive;
+create or replace table x0 (x int) with system versioning;
+rename table x0 to d0;
+show tables;
+Tables_in_test
+d0
+d0_vtmd
+call check_vtmd('d0_vtmd');
+@start > 0 and @start < @inf
+1
+A_start B_end name C_archive_name
+1 0 x0 NULL
+1 1 d0 NULL
+set versioning_alter_history= keep;
+drop table d0;
+set versioning_alter_history= survive;
+create or replace table x0 (x int) with system versioning;
+rename table x0 to d0;
+ERROR HY000: VTMD error: `test.d0_vtmd` table already exists!
+show tables;
+Tables_in_test
+d0_vtmd
+x0
+x0_vtmd
+drop table x0_vtmd;
+rename table x0 to d0;
+Warnings:
+Warning 4122 `test.d0_vtmd` table already exists!
+show tables;
+Tables_in_test
+d0
+d0_vtmd
+rename table d0 to duck;
+rename table duck to bay;
+rename table bay to sheer;
+rename table sheer to t0;
+call check_vtmd('t0_vtmd');
+@start > 0 and @start < @inf
+1
+A_start B_end name C_archive_name
+1 0 x0 NULL
+1 0 d0 NULL
+1 0 duck NULL
+1 0 bay NULL
+1 0 sheer NULL
+1 1 t0 NULL
+alter table t0 add column (y int);
+call check_vtmd('t0_vtmd');
+@start > 0 and @start < @inf
+1
+A_start B_end name C_archive_name
+1 0 x0 t0_
+1 0 d0 t0_
+1 0 duck t0_
+1 0 bay t0_
+1 0 sheer t0_
+1 0 t0 t0_
+1 1 t0 NULL
+alter table t0 add column (z int);
+alter table t0 drop column y;
+alter table t0 drop column z;
+create database db0;
+rename table t0 to db0.t0;
+show tables;
+Tables_in_test
+use db0;
+show tables;
+Tables_in_db0
+t0
+t0_vtmd
+call test.check_vtmd('db0.t0_vtmd');
+@start > 0 and @start < @inf
+1
+A_start B_end name C_archive_name
+1 0 x0 t0_
+1 0 d0 t0_
+1 0 duck t0_
+1 0 bay t0_
+1 0 sheer t0_
+1 0 t0 t0_
+1 0 t0 t0_
+1 0 t0 t0_
+1 0 t0 t0_
+1 1 t0 NULL
+create database db1;
+rename table t0 to db1.other_name;
+show tables;
+Tables_in_db0
+use db1;
+show tables;
+Tables_in_db1
+other_name
+other_name_vtmd
+call test.check_vtmd('db1.other_name_vtmd');
+@start > 0 and @start < @inf
+1
+A_start B_end name C_archive_name
+1 0 x0 t0_
+1 0 d0 t0_
+1 0 duck t0_
+1 0 bay t0_
+1 0 sheer t0_
+1 0 t0 t0_
+1 0 t0 t0_
+1 0 t0 t0_
+1 0 t0 t0_
+1 0 t0 NULL
+1 1 other_name NULL
+alter table other_name rename to t1;
+call test.check_vtmd('db1.t1_vtmd');
+@start > 0 and @start < @inf
+1
+A_start B_end name C_archive_name
+1 0 x0 t0_
+1 0 d0 t0_
+1 0 duck t0_
+1 0 bay t0_
+1 0 sheer t0_
+1 0 t0 t0_
+1 0 t0 t0_
+1 0 t0 t0_
+1 0 t0 t0_
+1 0 t0 NULL
+1 0 other_name NULL
+1 1 t1 NULL
+alter table t1 rename to test.t2, add column (y int);
+use test;
+show tables;
+Tables_in_test
+t2
+t2_vtmd
+call check_vtmd('t2_vtmd');
+@start > 0 and @start < @inf
+1
+A_start B_end name C_archive_name
+1 0 x0 t0_
+1 0 d0 t0_
+1 0 duck t0_
+1 0 bay t0_
+1 0 sheer t0_
+1 0 t0 t0_
+1 0 t0 t0_
+1 0 t0 t0_
+1 0 t0 t0_
+1 0 t0 t1_
+1 0 other_name t1_
+1 0 t1 t1_
+1 1 t2 NULL
+create or replace table t3 (x int) with system versioning;
+alter table t3 change x x bigint;
+alter table t3 change x x bigint after sys_trx_start;
+call check_vtmd('t3_vtmd');
+@start > 0 and @start < @inf
+1
+A_start B_end name C_archive_name
+1 0 t3 t3_
+1 0 t3 t3_
+1 1 t3 NULL
+set versioning_hide= auto;
+call show_tables();
+Tables_in_test
+t2
+t2_vtmd
+t3
+t3_vtmd
+table_name table_schema
+t2 test
+t2_vtmd test
+t3 test
+t3_vtmd test
+set versioning_hide= implicit;
+call show_tables();
+Tables_in_test
+t2
+t2_vtmd
+t3
+t3_vtmd
+table_name table_schema
+t2 test
+t2_vtmd test
+t3 test
+t3_vtmd test
+set versioning_hide= full;
+call show_tables();
+Tables_in_test
+t2
+t2_vtmd
+t3
+t3_vtmd
+table_name table_schema
+t2 test
+t2_vtmd test
+t3 test
+t3_vtmd test
+set versioning_hide= never;
+call show_tables();
+Tables_in_test
+t0_TIMESTAMP_SUFFIX
+t0_TIMESTAMP_SUFFIX
+t0_TIMESTAMP_SUFFIX
+t0_TIMESTAMP_SUFFIX
+t2
+t2_vtmd
+t3
+t3_TIMESTAMP_SUFFIX
+t3_TIMESTAMP_SUFFIX
+t3_vtmd
+table_name table_schema
+t0_TIMESTAMP_SUFFIX test
+t0_TIMESTAMP_SUFFIX test
+t0_TIMESTAMP_SUFFIX test
+t0_TIMESTAMP_SUFFIX test
+t1_TIMESTAMP_SUFFIX db1
+t2 test
+t2_vtmd test
+t3 test
+t3_TIMESTAMP_SUFFIX test
+t3_TIMESTAMP_SUFFIX test
+t3_vtmd test
+set versioning_hide= auto;
+create or replace table u0_vtmd (x int) with system versioning;
+show tables;
+Tables_in_test
+t2
+t2_vtmd
+t3
+t3_vtmd
+u0_vtmd
+u0_vtmd_vtmd
+Warnings:
+Warning 4122 Table `test.u0_vtmd` is not a VTMD table
+set versioning_alter_history= survive;
+create or replace table t (x int) with system versioning;
+select * from t for system_time all;
+x sys_trx_start sys_trx_end
+drop database db0;
+drop database db1;
+drop database test;
+create database test;
diff --git a/mysql-test/suite/versioning/r/vtmd_show.result b/mysql-test/suite/versioning/r/vtmd_show.result
new file mode 100644
index 00000000000..4c77182c5de
--- /dev/null
+++ b/mysql-test/suite/versioning/r/vtmd_show.result
@@ -0,0 +1,229 @@
+create or replace procedure drop_archives (in vtmd_name varchar(64))
+begin
+declare archive_name varchar(64);
+declare cur_done bool default false;
+declare cur cursor for
+select cur_tmp.archive_name from cur_tmp;
+declare continue handler for not found set cur_done = true;
+set @tmp= concat('
+ create or replace temporary table
+ cur_tmp as
+ select vtmd.archive_name from ', vtmd_name, '
+ for system_time all as vtmd
+ where vtmd.archive_name is not null
+ group by vtmd.archive_name');
+prepare stmt from @tmp; execute stmt; drop prepare stmt;
+open cur;
+fetch_loop: loop
+fetch cur into archive_name;
+if cur_done then
+leave fetch_loop;
+end if;
+set @tmp= concat('drop table ', archive_name);
+prepare stmt from @tmp; execute stmt; drop prepare stmt;
+end loop;
+drop table cur_tmp;
+end~~
+create procedure test_01(in engine varchar(64))
+begin
+set @tmp = concat('create table t (a int) with system versioning engine ', engine);
+prepare stmt from @tmp; execute stmt; drop prepare stmt;
+set @tm1 = now(6);
+alter table t add column b int;
+set @tm2 = now(6);
+alter table t add column c int;
+show create table t for system_time as of timestamp @tm1;
+show create table t for system_time as of timestamp @tm2;
+show create table t for system_time as of now;
+show create table t for system_time as of timestamp now(6);
+show create table t;
+set @tm3 = now(6);
+rename table t to tt;
+show create table tt for system_time as of timestamp @tm3;
+set @tm4 = now(6);
+alter table tt add column d int;
+show create table tt for system_time as of timestamp @tm3;
+show create table tt for system_time as of timestamp @tm4;
+show create table tt;
+drop table tt;
+call drop_archives('tt_vtmd');
+drop table tt_vtmd;
+end~~
+create table t (a int) with system versioning;
+show create table t for system_time as of now;
+ERROR HY000: VTMD error: Table 'test.t_vtmd' doesn't exist
+set versioning_alter_history=survive;
+create or replace table t (a int) with system versioning;
+show create table t for system_time between timestamp @tm1 and timestamp @tm1;
+ERROR HY000: SYSTEM_TIME range selector is prohibited
+show create table t for system_time from timestamp @tm1 to timestamp @tm1;
+ERROR HY000: SYSTEM_TIME range selector is prohibited
+show create table t for system_time as of timestamp '01-01-1990';
+ERROR HY000: VTMD error: Table 'test.t' doesn't exist
+show create table t for system_time as of timestamp '01-01-2020';
+ERROR HY000: VTMD error: Table 'test.t' doesn't exist
+drop table t;
+call drop_archives('t_vtmd');
+drop table t_vtmd;
+call test_01('myisam');
+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
+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,
+ `b` int(11) DEFAULT NULL,
+ PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+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,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+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,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+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,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+Table Create Table
+tt CREATE TABLE `tt` (
+ `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,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+Table Create Table
+tt CREATE TABLE `tt` (
+ `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,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+Table Create Table
+tt CREATE TABLE `tt` (
+ `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,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+Table Create Table
+tt CREATE TABLE `tt` (
+ `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,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` int(11) DEFAULT NULL,
+ PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+call test_01('innodb');
+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
+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,
+ `b` int(11) DEFAULT NULL,
+ PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+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,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+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,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+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,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+Table Create Table
+tt CREATE TABLE `tt` (
+ `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,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+Table Create Table
+tt CREATE TABLE `tt` (
+ `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,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+Table Create Table
+tt CREATE TABLE `tt` (
+ `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,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+Table Create Table
+tt CREATE TABLE `tt` (
+ `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,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` int(11) DEFAULT NULL,
+ PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+drop procedure test_01;
+drop procedure drop_archives;
diff --git a/mysql-test/suite/versioning/t/alter.test b/mysql-test/suite/versioning/t/alter.test
new file mode 100644
index 00000000000..5e4efb036c6
--- /dev/null
+++ b/mysql-test/suite/versioning/t/alter.test
@@ -0,0 +1,395 @@
+select @@system_versioning_alter_history;
+
+create table t(
+ a int
+);
+show create table t;
+--error ER_VERS_NOT_VERSIONED
+alter table t drop system versioning;
+
+alter table t add system versioning;
+show create table t;
+
+--error ER_VERS_ALTER_NOT_ALLOWED
+alter table t add column y int;
+--error ER_VERS_ALTER_ENGINE_PROHIBITED
+alter table t engine innodb;
+
+alter table t drop system versioning;
+show create table t;
+
+set system_versioning_alter_history= keep;
+
+--error ER_VERS_FIELD_WRONG_TYPE
+alter table t
+ add column trx_start bigint(20) unsigned as row start invisible,
+ add column trx_end bigint(20) unsigned as row end invisible,
+ add period for system_time(trx_start, trx_end),
+ add system versioning;
+
+--error ER_VERS_FIELD_WRONG_TYPE
+alter table t
+ add column trx_start timestamp as row start invisible,
+ add column trx_end timestamp as row end invisible,
+ add period for system_time(trx_start, trx_end),
+ add system versioning;
+
+--error ER_PARSE_ERROR
+alter table t
+ add column trx_start timestamp(6) not null as row start invisible,
+ add column trx_end timestamp(6) not null as row end invisible,
+ add period for system_time(trx_start, trx_end),
+ add system versioning;
+
+alter table t
+ add column trx_start timestamp(6) as row start invisible,
+ add column trx_end timestamp(6) as row end invisible,
+ add period for system_time(trx_start, trx_end),
+ add system versioning;
+show create table t;
+
+alter table t drop column trx_start, drop column trx_end;
+alter table t drop system versioning;
+show create table t;
+
+alter table t add 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;
+
+alter table t drop column a;
+show create table t;
+
+create or replace table t (
+ a int,
+ row_start timestamp(6) as row start invisible,
+ row_end timestamp(6) as row end invisible,
+ period for system_time(row_start, row_end))
+with system versioning;
+
+select * from t for system_time all;
+--error ER_MISSING
+alter table t drop column row_start;
+--error ER_MISSING
+alter table t drop column row_end;
+alter table t drop column row_start, drop column row_end;
+select * from t for system_time all;
+
+--error ER_CANT_DROP_FIELD_OR_KEY
+alter table t drop column row_start;
+--error ER_CANT_DROP_FIELD_OR_KEY
+alter table t drop column row_end;
+
+create or replace table t (
+ a int,
+ row_start timestamp(6) as row start invisible,
+ row_end timestamp(6) as row end invisible,
+ period for system_time(row_start, row_end))
+with system versioning;
+
+select * from t for system_time all;
+alter table t drop column row_start, drop column row_end;
+select * from t for system_time all;
+
+create or replace table t(
+ a int
+);
+insert into t values(1);
+alter table t add 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 row_start from t where a=3 into @tm;
+alter table t add column b int;
+select @tm=row_start from t where a=3;
+show create table t;
+select * from t;
+select * from t for system_time all;
+
+alter table t drop system versioning;
+select * from t;
+show create table t;
+
+--error ER_VERS_NOT_VERSIONED
+alter table t modify a int with system versioning;
+--error ER_VERS_NOT_VERSIONED
+alter table t modify a int without system versioning;
+
+alter table t add 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;
+
+# TODO: move TRX_ID cases to separate test
+-- source suite/versioning/common.inc
+create or replace table t(
+ a int
+) engine=innodb;
+
+alter table t
+ add column trx_start timestamp(6) as row start invisible,
+ add column trx_end timestamp(6) as row end invisible,
+ add period for system_time(trx_start, trx_end),
+ add system versioning;
+
+show create table t;
+--echo # Issue #211: drop of system columns required before drop system versioning
+alter table t drop column trx_start, drop column trx_end;
+show create table t;
+
+alter table t drop system versioning;
+
+insert into t values(1);
+
+call verify_vtq;
+alter table t
+ add column trx_start bigint(20) unsigned as row start invisible,
+ add column trx_end bigint(20) unsigned as row end invisible,
+ add period for system_time(trx_start, trx_end),
+ add system versioning;
+call verify_vtq;
+
+show create table t;
+alter table t drop column trx_start, drop column trx_end;
+
+call verify_vtq;
+alter table t drop system versioning, algorithm=copy;
+call verify_vtq;
+
+alter table t add system versioning, algorithm=copy;
+call verify_vtq;
+
+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;
+call verify_vtq;
+
+alter table t drop column b, algorithm=copy;
+show create table t;
+select * from t for system_time all;
+call verify_vtq;
+
+## FIXME: #414 IB: inplace for VERS_TIMESTAMP versioning
+if (0)
+{
+alter table t drop system versioning, algorithm=inplace;
+call verify_vtq;
+
+alter table t add system versioning, algorithm=inplace;
+call verify_vtq;
+show create table t;
+
+update t set a= 1;
+select * from t for system_time all;
+call verify_vtq;
+
+alter table t add column b int, algorithm=inplace;
+show create table t;
+select * from t;
+call verify_vtq;
+
+alter table t drop column b, algorithm=inplace;
+show create table t;
+select * from t for system_time all;
+}
+## FIXME END
+
+alter table t drop system versioning, algorithm=copy;
+show create table t;
+call verify_vtq;
+
+# nullable autoinc test w/o versioning
+create or replace table t (a int);
+insert t values (1),(2),(3),(4);
+alter table t add b int auto_increment null unique;
+select * from t;
+drop table t;
+
+create or replace table t (a int) with system versioning engine=innodb;
+insert into t values (1), (2), (3);
+delete from t where a<3;
+--error ER_DUP_ENTRY, ER_DUP_ENTRY
+alter table t add b int not null unique;
+--error ER_UNSUPPORTED_EXTENSION, ER_UNSUPPORTED_EXTENSION
+alter table t add b int auto_increment unique;
+alter table t add b int auto_increment null unique;
+select * from t;
+select * from t for system_time all;
+insert into t values (4, 0);
+select * from t for system_time all;
+
+create or replace table t (a int) with system versioning;
+insert into t values (1), (2), (3);
+delete from t where a<3;
+--error ER_DUP_ENTRY, ER_DUP_ENTRY
+alter table t add b int not null unique;
+--error ER_UNSUPPORTED_EXTENSION, ER_UNSUPPORTED_EXTENSION
+alter table t add b int auto_increment unique;
+alter table t add b int auto_increment null unique;
+select * from t;
+select * from t for system_time all;
+insert into t values (4, 0);
+select * from t for system_time all;
+
+create or replace table t (
+ a int,
+ row_start timestamp(6) as row start invisible,
+ row_end timestamp(6) as row end invisible,
+ period for system_time(row_start, row_end)
+) with system versioning;
+--error ER_VERS_ALTER_SYSTEM_FIELD
+alter table t change column row_start asdf timestamp(6);
+insert into t values (1);
+--error ER_VERS_ALTER_SYSTEM_FIELD
+alter table t modify column row_start bigint unsigned;
+
+## These experimental options are now disabled
+
+--error ER_WRONG_VALUE_FOR_VAR
+set system_versioning_alter_history= SURVIVE;
+
+--error ER_WRONG_VALUE_FOR_VAR
+set system_versioning_alter_history= 'DROP';
+
+if (0)
+{
+create or replace table t (a int) with system versioning engine innodb;
+insert into t values (1);
+update t set a = 2;
+select * from t for system_time all;
+alter table t add column b int;
+select * from t for system_time all;
+
+create or replace table t (a int) with system versioning engine myisam;
+insert into t values (1);
+update t set a = 2;
+select * from t for system_time all;
+alter table t add column b int;
+select * from t for system_time all;
+
+create or replace table non_empty (
+ a int,
+ row_start bigint(20) unsigned,
+ row_end bigint(20) unsigned
+) engine innodb;
+insert into non_empty values (1, 100, 200);
+
+--error ER_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN
+alter table non_empty
+ change column row_start row_start bigint(20) unsigned as row start invisible;
+--error ER_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN
+alter table non_empty
+ change column row_end row_end bigint(20) unsigned as row end invisible;
+drop table non_empty;
+
+create or replace table t (a int primary key) with system versioning;
+insert into t values (1);
+update t set a=2;
+alter table t drop primary key, add primary key (a), drop system versioning;
+select * from t;
+--replace_result InnoDB INNODB_OR_MYISAM MyISAM INNODB_OR_MYISAM
+show create table t;
+
+create or replace table t (a int primary key) with system versioning;
+insert into t values (1);
+update t set a=2;
+alter table t drop system versioning;
+select * from t;
+--replace_result InnoDB INNODB_OR_MYISAM MyISAM INNODB_OR_MYISAM
+show create table t;
+
+
+call verify_vtq;
+}
+
+create or replace table t (a int) with system versioning;
+--error ER_VERS_ALREADY_VERSIONED
+alter table t add system versioning;
+--error ER_VERS_ALREADY_VERSIONED
+alter table t add system versioning, drop system versioning;
+
+set @@system_versioning_alter_history=keep;
+create or replace table t(x int, y int) with system versioning engine=innodb;
+alter table t modify y int without system versioning;
+insert into t values(1, 1);
+update t set y=2;
+
+--echo # MDEV-14681 Bogus ER_UNSUPPORTED_EXTENSION
+create or replace table t1 (pk int auto_increment unique) with system versioning;
+insert into t1 values (1);
+delete from t1;
+alter table t1 engine=myisam;
+
+--echo # MDEV-14692 crash in MDL_context::upgrade_shared_lock()
+create or replace temporary table t (a int);
+--error ER_VERS_TEMPORARY
+alter table t change column if exists b c bigint unsigned generated always as row start;
+--error ER_VERS_TEMPORARY
+alter table t change column if exists b c bigint unsigned generated always as row end;
+--error ER_VERS_TEMPORARY
+alter table t add system versioning;
+drop table t;
+
+--echo # MDEV-14744 trx_id-based and transaction-based mixup in assertion
+create or replace table t (c text) engine=innodb with system versioning;
+show create table t;
+alter table t add fulltext key (c);
+
+create or replace table t (a int) with system versioning;
+--error ER_VERS_TABLE_MUST_HAVE_COLUMNS
+alter table t drop column a;
+--error ER_CANT_DROP_FIELD_OR_KEY
+alter table t drop column a, drop column a;
+
+create or replace table t1 (row_start int);
+--error ER_DUP_FIELDNAME
+alter table t1 with system versioning;
+
+create or replace table t1 (row_end int);
+--error ER_DUP_FIELDNAME
+alter table t1 with system versioning;
+
+--error ER_DUP_FIELDNAME
+create or replace table t1 (a int, row_start int) with system versioning;
+
+create or replace table t1 (a int) with system versioning;
+
+--error ER_DUP_FIELDNAME
+set statement system_versioning_alter_history=keep for
+alter table t1 add column row_start int;
+
+--error ER_DUP_FIELDNAME
+set statement system_versioning_alter_history=keep for
+alter table t1 add column row_start timestamp(6);
+
+--echo # MDEV-14798 Add, drop system versioning semantic and syntax
+create or replace table t (a int) with system versioning;
+
+--error ER_VERS_ALREADY_VERSIONED
+alter table t add period for system_time(sys_trx_start, sys_trx_end);
+
+drop database test;
+create database test;
diff --git a/mysql-test/suite/versioning/t/auto_increment.test b/mysql-test/suite/versioning/t/auto_increment.test
new file mode 100644
index 00000000000..6108f6d9818
--- /dev/null
+++ b/mysql-test/suite/versioning/t/auto_increment.test
@@ -0,0 +1,68 @@
+-- source suite/versioning/common.inc
+
+delimiter ~~;
+create procedure test_01(
+ sys_type varchar(255),
+ engine varchar(255),
+ fields varchar(255))
+begin
+ set @str= concat('
+ create table t1(
+ id int unsigned auto_increment primary key,
+ x int unsigned,
+ y int unsigned,
+ sys_start ', sys_type, ' as row start invisible,
+ sys_end ', sys_type, ' as row end invisible,
+ period for system_time (sys_start, sys_end))
+ with system versioning
+ engine ', engine);
+ prepare stmt from @str; execute stmt; drop prepare stmt;
+
+ set @str= concat('
+ create table t2(
+ id int unsigned auto_increment primary key,
+ x int unsigned,
+ y int unsigned)
+ engine ', engine);
+ prepare stmt from @str; execute stmt; drop prepare stmt;
+
+ insert into t1(x, y) values(1, 11);
+ insert into t2(x, y) values(1, 11);
+ insert into t1(x, y) values(2, 12);
+ insert into t2(x, y) values(2, 12);
+ insert into t1(x, y) values(3, 13);
+ insert into t2(x, y) values(3, 13);
+ insert into t1(x, y) values(4, 14);
+ insert into t2(x, y) values(4, 14);
+ insert into t1(x, y) values(5, 15);
+ insert into t2(x, y) values(5, 15);
+ insert into t1(x, y) values(6, 16);
+ insert into t2(x, y) values(6, 16);
+ insert into t1(x, y) values(7, 17);
+ insert into t2(x, y) values(7, 17);
+ insert into t1(x, y) values(8, 18);
+ insert into t2(x, y) values(8, 18);
+ insert into t1(x, y) values(9, 19);
+ insert into t2(x, y) values(9, 19);
+
+ select t1.x = t2.x and t1.y = t2.y as A, t1.x, t1.y, t2.x, t2.y from t1 inner join t2 on t1.id = t2.id;
+ delete from t1 where x = 2;
+ delete from t2 where x = 2;
+
+ select t1.x = t2.x and t1.y = t2.y as A, t1.x, t1.y, t2.x, t2.y from t1 inner join t2 on t1.id = t2.id;
+ delete from t1 where x > 7;
+ delete from t2 where x > 7;
+
+ select t1.x = t2.x and t1.y = t2.y as A, t1.x, t1.y, t2.x, t2.y from t1 inner join t2 on t1.id = t2.id;
+ drop table t1;
+ drop table t2;
+end~~
+delimiter ;~~
+
+call test_01('timestamp(6)', 'myisam', 'sys_end');
+call test_01('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)');
+call verify_vtq;
+
+drop procedure test_01;
+
+-- source suite/versioning/common_finish.inc
diff --git a/mysql-test/suite/versioning/t/commit_id.test b/mysql-test/suite/versioning/t/commit_id.test
new file mode 100644
index 00000000000..66a9db64e10
--- /dev/null
+++ b/mysql-test/suite/versioning/t/commit_id.test
@@ -0,0 +1,94 @@
+-- source suite/versioning/common.inc
+
+create table t1(
+ id int auto_increment primary key,
+ sys_trx_start bigint unsigned as row start invisible,
+ sys_trx_end bigint unsigned as row end invisible,
+ period for system_time (sys_trx_start, sys_trx_end)
+)
+with system versioning
+engine innodb;
+
+
+# VTQ_TRX_ID, VTQ_COMMIT_ID, VTQ_TRX_SEES #
+
+insert into t1 values ();
+
+--real_sleep 0.01
+set @ts0= now(6);
+insert into t1 values ();
+select sys_trx_start from t1 where id = last_insert_id() into @tx0;
+select transaction_id = @tx0 from mysql.transaction_registry
+order by transaction_id desc limit 1;
+
+set @ts1= now(6);
+insert into t1 values ();
+select sys_trx_start from t1 where id = last_insert_id() into @tx1;
+select transaction_id = @tx1 from mysql.transaction_registry
+order by transaction_id desc limit 1;
+
+set @ts2= now(6);
+insert into t1 values ();
+select sys_trx_start from t1 where id = last_insert_id() into @tx2;
+select transaction_id = @tx2 from mysql.transaction_registry
+order by transaction_id desc limit 1;
+
+set @ts3= now(6);
+
+select
+ vtq_trx_id(@ts0) < @tx0 as A,
+ vtq_trx_id(@ts0, true) = @tx0 as B,
+ vtq_trx_id(@ts1) = @tx0 as C,
+ vtq_trx_id(@ts1, true) = @tx1 as D,
+ vtq_trx_id(@ts2) = @tx1 as E,
+ vtq_trx_id(@ts2, true) = @tx2 as F,
+ vtq_trx_id(@ts3) = @tx2 as G,
+ vtq_trx_id(@ts3, true) is null as H;
+
+select
+ vtq_commit_id(@ts0) < @tx0 as A,
+ vtq_commit_id(@ts0, true) = vtq_commit_id(null, @tx0) as B,
+ vtq_commit_id(@ts1) = vtq_commit_id(null, @tx0) as C,
+ vtq_commit_id(@ts1, true) = vtq_commit_id(null, @tx1) as D,
+ vtq_commit_id(@ts2) = vtq_commit_id(null, @tx1) as E,
+ vtq_commit_id(@ts2, true) = vtq_commit_id(null, @tx2) as F,
+ vtq_commit_id(@ts3) = vtq_commit_id(null, @tx2) as G,
+ vtq_commit_id(@ts3, true) is null as H;
+
+select
+ vtq_trx_sees(@tx1, @tx0) as A,
+ not vtq_trx_sees(@tx0, @tx1) as B,
+ vtq_trx_sees_eq(@tx1, @tx1) as C,
+ not vtq_trx_sees(@tx1, @tx1) as D,
+ vtq_trx_sees(@tx2, 0) as E,
+ vtq_trx_sees(0, @tx2) is null as F,
+ vtq_trx_sees(-1, @tx2) as H;
+
+
+# VTQ_ISO_LEVEL #
+
+set transaction isolation level read uncommitted;
+insert into t1 values ();
+select sys_trx_start from t1 where id = last_insert_id() into @tx3;
+select isolation_level = 'READ-UNCOMMITTED' from mysql.transaction_registry where transaction_id = @tx3;
+
+set transaction isolation level read committed;
+insert into t1 values ();
+select sys_trx_start from t1 where id = last_insert_id() into @tx4;
+select isolation_level = 'READ-COMMITTED' from mysql.transaction_registry where transaction_id = @tx4;
+
+set transaction isolation level serializable;
+insert into t1 values ();
+select sys_trx_start from t1 where id = last_insert_id() into @tx5;
+select isolation_level = 'SERIALIZABLE' from mysql.transaction_registry where transaction_id = @tx5;
+
+set transaction isolation level repeatable read;
+insert into t1 values ();
+select sys_trx_start from t1 where id = last_insert_id() into @tx6;
+select isolation_level = 'REPEATABLE-READ' from mysql.transaction_registry where transaction_id = @tx6;
+
+
+drop table t1;
+call verify_vtq;
+
+-- source suite/versioning/common_finish.inc
diff --git a/mysql-test/suite/versioning/t/create.test b/mysql-test/suite/versioning/t/create.test
new file mode 100644
index 00000000000..24d8d335020
--- /dev/null
+++ b/mysql-test/suite/versioning/t/create.test
@@ -0,0 +1,367 @@
+--source suite/versioning/engines.inc
+--source suite/versioning/common.inc
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype_expl SYS_DATATYPE NULL ''
+eval create table t1 (
+ x1 int unsigned,
+ Sys_start $sys_datatype_expl as row start invisible comment 'start',
+ Sys_end $sys_datatype_expl as row end invisible comment 'end',
+ period for system_time (Sys_start, Sys_end)
+) with system versioning;
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype_expl SYS_DATATYPE
+show create table t1;
+
+--query_vertical select table_catalog,table_schema,table_name,table_type,version,table_rows,avg_row_length,data_free,auto_increment,check_time,table_collation,checksum,create_options,table_comment from information_schema.tables where table_name='t1'
+--query_vertical select table_catalog,table_schema,table_name,column_name,ordinal_position,column_default,character_maximum_length,character_octet_length,character_set_name,collation_name,column_key,extra,column_comment,is_generated,generation_expression from information_schema.columns where table_name='t1'
+
+--echo # Implicit fields test
+create or replace table t1 (
+ x2 int unsigned
+) with system versioning;
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE
+show create table t1;
+
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE
+--error ER_VERS_PERIOD_COLUMNS
+eval create or replace table t1 (
+ x3 int unsigned,
+ Sys_start $sys_datatype as row start invisible,
+ Sys_end $sys_datatype as row end invisible,
+ period for system_time (x, Sys_end)
+) with system versioning;
+
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE
+--error ER_VERS_PERIOD_COLUMNS
+eval create or replace table t1 (
+ x4 int unsigned,
+ Sys_start $sys_datatype as row start invisible,
+ Sys_end2 $sys_datatype as row end invisible,
+ period for system_time (Sys_start, Sys_end)
+) with system versioning;
+
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE
+--error ER_VERS_PERIOD_COLUMNS
+eval create or replace table t1 (
+ x5 int unsigned,
+ Sys_start $sys_datatype as row start invisible,
+ Sys_end $sys_datatype as row end invisible,
+ period for system_time (Sys_start, x)
+) with system versioning;
+
+--error ER_MISSING
+create or replace table t1 (
+ x6 int unsigned,
+ period for system_time (Sys_start, Sys_end)
+) with system versioning;
+
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE
+--error ER_MISSING
+eval create or replace table t1 (
+ x7 int unsigned,
+ Sys_start $sys_datatype as row start invisible,
+ Sys_end $sys_datatype as row end invisible,
+ period for system_time (Sys_start, Sys_end)
+);
+
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE
+--error ER_VERS_PERIOD_COLUMNS
+eval create or replace table t1 (
+ x8 int unsigned,
+ Sys_start $sys_datatype as row start invisible,
+ Sys_end $sys_datatype as row end invisible,
+ period for system_time (sys_insert, sys_remove)
+) with system versioning;
+
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE
+--error ER_MISSING
+eval create or replace table t1 (
+ x9 int unsigned,
+ Sys_start $sys_datatype as row start invisible,
+ Sys_end $sys_datatype as row end invisible,
+ period for system_time (Sys_start, Sys_end)
+);
+
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE
+--error ER_MISSING
+eval create or replace table t1 (
+ x10 int unsigned,
+ Sys_start $sys_datatype as row start invisible,
+ Sys_end $sys_datatype as row end invisible,
+ period for system_time (Sys_start, Sys_start)
+);
+
+--error ER_VERS_FIELD_WRONG_TYPE, ER_VERS_FIELD_WRONG_TYPE
+create or replace table t1 (
+ x11 int unsigned,
+ Sys_start bigint unsigned as row start invisible,
+ Sys_end timestamp(6) as row end invisible,
+ period for system_time (Sys_start, Sys_end)
+) with system versioning;
+
+--error ER_VERS_FIELD_WRONG_TYPE, ER_VERS_FIELD_WRONG_TYPE
+create or replace table t1 (
+ x12 int unsigned,
+ Sys_start timestamp(6) as row start invisible,
+ Sys_end bigint unsigned as row end invisible,
+ period for system_time (Sys_start, Sys_end)
+) with system versioning;
+
+--error ER_VERS_FIELD_WRONG_TYPE
+create or replace table t1 (
+ x13 int unsigned,
+ Sys_start bigint as row start invisible,
+ Sys_end bigint unsigned as row end invisible,
+ period for system_time (Sys_start, Sys_end)
+) with system versioning engine innodb;
+
+--error ER_VERS_FIELD_WRONG_TYPE
+create or replace table t1 (
+ x14 int unsigned,
+ Sys_start bigint unsigned as row start invisible,
+ Sys_end bigint as row end invisible,
+ period for system_time (Sys_start, Sys_end)
+) with system versioning engine innodb;
+
+# columns with/without system versioning
+
+create or replace table t1 (
+ x15 int with system versioning,
+ B int
+);
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE
+show create table t1;
+
+create or replace table t1 (
+ x16 int with system versioning,
+ B int
+) with system versioning;
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE
+show create table t1;
+
+create or replace table t1 (
+ x17 int,
+ B int without system versioning
+);
+
+create or replace table t1 (
+ x18 int,
+ B int without system versioning
+) with system versioning;
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE
+show create table t1;
+
+create or replace table t1 (
+ x19 int with system versioning,
+ B int without system versioning
+);
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE
+show create table t1;
+
+create or replace table t1 (
+ x20 int with system versioning,
+ B int without system versioning
+) with system versioning;
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE
+show create table t1;
+
+create or replace table t1 (
+ x21 int without system versioning
+);
+
+--error ER_VERS_TABLE_MUST_HAVE_COLUMNS
+create or replace table t1 (
+ x22 int without system versioning
+) with system versioning;
+
+# CREATE TABLE ... LIKE
+create or replace table t1 (a int) with system versioning;
+create table tt1 like t1;
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE
+show create table tt1;
+drop table tt1;
+create temporary table tt1 like t1;
+--echo # Temporary is stripped from versioning
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE
+show create table tt1;
+
+--echo # CREATE TABLE ... SELECT
+create or replace table t1 (x23 int) with system versioning;
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE
+eval create or replace table t0(
+ y int,
+ st $sys_datatype as row start,
+ en $sys_datatype as row end,
+ period for system_time (st, en)
+) with system versioning;
+
+--echo ## For non-versioned table:
+--echo ### 1. invisible fields are not included
+create or replace table t2 as select * from t1;
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE
+show create table t2;
+
+--echo ### 2. all visible fields are included
+create or replace table t3 as select * from t0;
+select * from t0;
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE $sys_datatype_null SYS_DATATYPE $sys_datatype_not_null SYS_DATATYPE $sys_datatype_default_null SYS_DATATYPE
+show create table t3;
+
+--echo ## For versioned table
+insert into t1 values (1);
+select row_start from t1 into @row_start;
+insert into t0 (y) values (2);
+select st from t0 into @st;
+
+create or replace table t2 with system versioning as select * from t1;
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE
+show create table t2;
+--echo #### invisible fields are not copied
+select * from t2;
+select * from t2 where row_start <= @row_start;
+
+--echo ### 2. source table with visible system fields, target with invisible
+create or replace table t3 with system versioning as select * from t0;
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE $sys_datatype_null SYS_DATATYPE $sys_datatype_not_null SYS_DATATYPE $sys_datatype_default_null SYS_DATATYPE
+show create table t3;
+select * from t3 where y > 2;
+select y from t3 where st = @st and row_start > @st;
+
+--echo ### 3. source and target table with visible system fields
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE
+eval create or replace table t3 (
+ st $sys_datatype as row start invisible,
+ en $sys_datatype as row end invisible,
+ period for system_time (st, en)
+) with system versioning as select * from t0;
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE $sys_datatype_null SYS_DATATYPE $sys_datatype_not_null SYS_DATATYPE $sys_datatype_default_null SYS_DATATYPE
+show create table t3;
+select y from t3;
+select y from t3 where st = @st;
+
+--echo ### 4. system fields not or wrongly selected
+create or replace table t3 with system versioning select x23 from t1;
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE $sys_datatype_null SYS_DATATYPE $sys_datatype_not_null SYS_DATATYPE $sys_datatype_default_null SYS_DATATYPE
+show create table t3;
+select * from t3;
+--error ER_MISSING
+create or replace table t3 with system versioning select x23, row_start from t1;
+--error ER_MISSING
+create or replace table t3 with system versioning select x23, row_end from t1;
+
+--echo # Prepare checking for historical row
+delete from t1;
+select row_end from t1 for system_time all into @row_end;
+delete from t0;
+select en from t0 for system_time all into @en;
+
+--echo ## Combinations of versioned + non-versioned
+create or replace table t2 (y int);
+insert into t2 values (3);
+create or replace table t3 with system versioning select * from t1 for system_time all, t2;
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE
+show create table t3;
+select * from t3 for system_time all;
+select * from t3 for system_time all where row_start = @row_start and row_end = @row_end;
+
+create or replace table t2 like t0;
+insert into t2 (y) values (1), (2);
+delete from t2 where y = 2;
+
+create or replace table t3 select * from t2 for system_time all;
+select st, en from t3 where y = 1 into @st, @en;
+select y from t2 for system_time all where st = @st and en = @en;
+select st, en from t3 where y = 2 into @st, @en;
+select y from t2 for system_time all where st = @st and en = @en;
+
+--echo ## Default engine detection
+--replace_result $non_default_engine NON_DEFAULT_ENGINE $sys_datatype SYS_DATATYPE
+eval create or replace table t1 (x25 int) with system versioning engine $non_default_engine;
+create or replace table t2
+as select x25, row_start, row_end from t1 for system_time all;
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE $sys_datatype_null SYS_DATATYPE
+show create table t2;
+
+create or replace table t2 with system versioning
+as select x25, row_start, row_end from t1;
+--replace_result $non_default_engine NON_DEFAULT_ENGINE $sys_datatype SYS_DATATYPE
+show create table t2;
+
+create or replace table t1 (
+ x26 int,
+ st bigint unsigned as row start,
+ en bigint unsigned as row end,
+ period for system_time (st, en)
+) with system versioning engine innodb;
+--error ER_VERS_FIELD_WRONG_TYPE
+create or replace table t2 with system versioning engine myisam
+as select * from t1;
+
+--replace_result $non_default_engine NON_DEFAULT_ENGINE
+eval create or replace table t1 (x27 int, id int) with system versioning engine $non_default_engine;
+create or replace table t2 (b int, id int);
+create or replace table t3 with system versioning
+as select t2.b, t1.x27, t1.row_start, t1.row_end from t2 inner join t1 on t2.id=t1.id;
+--replace_result $non_default_engine NON_DEFAULT_ENGINE $sys_datatype SYS_DATATYPE $sys_datatype_null SYS_DATATYPE
+show create table t3;
+
+--echo ## Errors
+
+--error ER_VERS_TEMPORARY
+create or replace temporary table t (x28 int) with system versioning;
+
+--error ER_VERS_DUPLICATE_ROW_START_END
+create or replace table t1 (
+ x29 int unsigned,
+ Sys_start0 timestamp(6) as row start invisible,
+ Sys_start timestamp(6) as row start invisible,
+ Sys_end timestamp(6) as row end invisible,
+ period for system_time (Sys_start, Sys_end)
+) with system versioning;
+
+--error ER_VERS_DUPLICATE_ROW_START_END
+create or replace table t1 (
+ x29 int unsigned,
+ Sys_end0 timestamp(6) as row end invisible,
+ Sys_start timestamp(6) as row start invisible,
+ Sys_end timestamp(6) as row end invisible,
+ period for system_time (Sys_start, Sys_end)
+) with system versioning;
+
+--echo ## System fields detection
+create or replace table t1 (x30 int) with system versioning;
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE
+eval create or replace table t2 (
+ y int,
+ st $sys_datatype as row start invisible,
+ en $sys_datatype as row end invisible,
+ period for system_time (st, en)
+) with system versioning;
+
+create or replace table t3
+as select x30, y, row_start, row_end, st, en from t1, t2;
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE $sys_datatype_null SYS_DATATYPE $sys_datatype_not_null SYS_DATATYPE $sys_datatype_default_null SYS_DATATYPE
+show create table t3;
+
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE
+eval create or replace table t3 (
+ y int,
+ st $sys_datatype as row start invisible,
+ en $sys_datatype as row end invisible,
+ period for system_time (st, en)
+) with system versioning
+as select x30, y, row_start, row_end, st, en from t1, t2;
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE $sys_datatype_null SYS_DATATYPE $sys_datatype_not_null SYS_DATATYPE $sys_datatype_default_null SYS_DATATYPE
+show create table t3;
+
+--echo # MDEV-14828 Server crashes in JOIN::prepare / setup_fields on 2nd execution of PS [#437]
+create or replace table t1 (x int) with system versioning;
+prepare bad from 'create or replace table t2 with system versioning as select * from t1';
+execute bad; execute bad; execute bad; execute bad; execute bad; execute bad; execute bad; execute bad;
+--echo # bad is good.
+
+drop database test;
+create database test;
diff --git a/mysql-test/suite/versioning/t/cte.test b/mysql-test/suite/versioning/t/cte.test
new file mode 100644
index 00000000000..9df0bb3dfba
--- /dev/null
+++ b/mysql-test/suite/versioning/t/cte.test
@@ -0,0 +1,101 @@
+-- source include/have_innodb.inc
+set default_storage_engine=innodb;
+create or replace table dept (
+ dept_id int(10) primary key,
+ name varchar(100)
+)
+with system versioning;
+
+create or replace table emp (
+ emp_id int(10) primary key,
+ dept_id int(10) not null,
+ name varchar(100) not null,
+ mgr int(10),
+ salary int(10) not null,
+ constraint `dept-emp-fk`
+ foreign key (dept_id) references dept (dept_id)
+ on delete cascade
+ on update restrict,
+ constraint `mgr-fk`
+ foreign key (mgr) references emp (emp_id)
+ on delete restrict
+ on update restrict
+)
+with system versioning;
+
+insert into dept (dept_id, name) values (10, "accounting");
+
+insert into emp (emp_id, name, salary, dept_id, mgr) values
+(1, "bill", 1000, 10, null),
+(20, "john", 500, 10, 1),
+(30, "jane", 750, 10,1 );
+
+select max(sys_trx_start) into @ts_1 from emp;
+
+update emp set mgr=30 where name ="john";
+select sys_trx_start into @ts_2 from emp where name="john";
+
+/* All report to 'Bill' */
+with recursive
+ancestors
+as
+(
+ select e.emp_id, e.name, e.mgr, e.salary
+ from emp for system_time as of timestamp @ts_1 as e
+ where name = 'bill'
+ union
+ select e.emp_id, e.name, e.mgr, e.salary
+ from emp for system_time as of timestamp @ts_1 as e,
+ ancestors as a
+ where e.mgr = a.emp_id
+)
+select * from ancestors;
+
+/* Expected 3 rows */
+with recursive
+ancestors
+as
+(
+ select e.emp_id, e.name, e.mgr, e.salary
+ from emp for system_time as of timestamp @ts_2 as e
+ where name = 'bill'
+ union
+ select e.emp_id, e.name, e.mgr, e.salary
+ from emp for system_time as of timestamp @ts_2 as e,
+ ancestors as a
+ where e.mgr = a.emp_id
+)
+select * from ancestors;
+
+create or replace table emp ( emp_id int, name varchar(127), mgr int) with system versioning;
+create or replace table addr ( emp_id int, address varchar(100)) with system versioning;
+insert emp values (1, 'bill', 0), (2, 'bill', 1), (3, 'kate', 1);
+insert addr values (1, 'Moscow'), (2, 'New York'), (3, 'London');
+set @ts=now(6);
+delete from emp;
+delete from addr;
+
+with recursive
+ancestors
+as
+(
+ select e.emp_id, e.name, e.mgr
+ from emp for system_time as of timestamp @ts as e
+ where name = 'bill'
+ union
+ select ee.emp_id, ee.name, ee.mgr
+ from emp for system_time as of timestamp @ts as ee, ancestors as a
+ where ee.mgr = a.emp_id
+)
+select * from ancestors;
+
+insert emp values (4, 'john', 1);
+insert addr values (4, 'Paris');
+with ancestors as (select * from emp natural join addr) select * from ancestors;
+with ancestors as (select * from emp natural join addr) select * from ancestors for system_time all;
+with ancestors as (select * from (select * from emp natural join addr) for system_time all as t) select * from ancestors;
+select * from (select * from emp natural join addr) for system_time all as t;
+
+drop table emp;
+drop table dept;
+drop table addr;
diff --git a/mysql-test/suite/versioning/t/ddl.test b/mysql-test/suite/versioning/t/ddl.test
new file mode 100644
index 00000000000..5be62281a6d
--- /dev/null
+++ b/mysql-test/suite/versioning/t/ddl.test
@@ -0,0 +1,105 @@
+-- source suite/versioning/common.inc
+
+delimiter ~~;
+create function get_archive_table_name()
+returns varchar(255)
+begin
+ return (select archive_name from t_vtmd for system_time all where archive_name is not NULL
+ order by start desc limit 1);
+end~~
+
+create procedure drop_last_archive()
+begin
+ call concat_exec2('drop table ', get_archive_table_name());
+end~~
+delimiter ;~~
+
+set versioning_alter_history= survive;
+
+create or replace table t (a int) with system versioning;
+insert into t values (1);
+update t set a=2 where a=1;
+select sys_trx_start from t where a=2 into @tm;
+alter table t add column b int;
+
+select * from t;
+call concat_exec3('select * from ', get_archive_table_name(), ' for system_time all');
+
+call concat_exec3('select @tm=sys_trx_start from ', get_archive_table_name(), ' for system_time all where a=2');
+select @tm<sys_trx_start from t where a=2;
+select sys_trx_start from t where a=2 into @tm;
+call concat_exec3('select @tm=sys_trx_end from ', get_archive_table_name(), ' for system_time all where a=2');
+
+call drop_last_archive();
+
+
+set versioning_alter_history= keep;
+drop table t_vtmd;
+drop table t;
+set versioning_alter_history= survive;
+
+# same for INNODB ALGORITHM=COPY
+create or replace table t (a int) with system versioning;
+insert into t values (1);
+update t set a=2 where a=1;
+select sys_trx_start from t where a=2 into @tm;
+alter table t add column b int;
+
+select * from t;
+call concat_exec3('select * from ', get_archive_table_name(), ' for system_time all');
+
+call concat_exec3('select @tm=sys_trx_start from ', get_archive_table_name(), ' for system_time all where a=2');
+select @tm<sys_trx_start from t where a=2;
+select sys_trx_start from t where a=2 into @tm;
+call concat_exec3('select @tm=sys_trx_end from ', get_archive_table_name(), ' for system_time all where a=2');
+
+call drop_last_archive();
+
+
+set versioning_alter_history= keep;
+drop table t_vtmd;
+drop table t;
+set versioning_alter_history= survive;
+
+# same for INNODB default ALGORITHM
+create or replace table t (a int) with system versioning engine innodb;
+insert into t values (1);
+update t set a=2 where a=1;
+select sys_trx_start from t where a=2 into @tm;
+alter table t add column b int;
+
+select * from t;
+call concat_exec3('select * from ', get_archive_table_name(), ' for system_time all');
+
+call concat_exec3('select @tm=sys_trx_start from ', get_archive_table_name(), ' for system_time all where a=2');
+select @tm<sys_trx_start from t where a=2;
+select sys_trx_start from t where a=2 into @tm;
+call concat_exec3('select @tm=sys_trx_end from ', get_archive_table_name(), ' for system_time all where a=2');
+
+call drop_last_archive();
+
+
+set versioning_alter_history= keep;
+drop table t_vtmd;
+drop table t;
+set versioning_alter_history= survive;
+
+# no DDL for INNODB explicit ALGORITHM=INPLACE
+create or replace table t (a int) with system versioning engine innodb;
+insert into t values (1);
+update t set a=2 where a=1;
+alter table t add column b int, algorithm=inplace;
+
+set versioning_alter_history = keep;
+
+drop function get_archive_table_name;
+drop procedure drop_last_archive;
+
+select * from mysql.vtmd_template;
+show create table mysql.vtmd_template;
+
+call verify_vtq;
+drop table t;
+drop table t_vtmd;
+
+-- source suite/versioning/common_finish.inc
diff --git a/mysql-test/suite/versioning/t/debug.test b/mysql-test/suite/versioning/t/debug.test
new file mode 100644
index 00000000000..c6d5bd60861
--- /dev/null
+++ b/mysql-test/suite/versioning/t/debug.test
@@ -0,0 +1,35 @@
+--source include/have_debug.inc
+
+create table t1 (a int);
+show create table t1;
+
+--error ER_VERS_TEMPORARY
+create temporary table tt1 (a int) with system versioning;
+
+set @old_dbug=@@global.debug_dbug;
+set global debug_dbug='+d,sysvers_force';
+
+create table t2 (a int);
+show create table t2;
+
+create temporary table tt2 (a int) with system versioning;
+show create table tt2;
+
+--connect con1, localhost, root
+
+create table t3 (a int);
+show create table t3;
+
+create temporary table tt3 (a int) with system versioning;
+show create table tt3;
+--disconnect con1
+--connection default
+
+set debug_dbug='+d,sysvers_show';
+
+show create table t3;
+create table t4 (a int);
+show create table t4;
+
+set global debug_dbug=@old_dbug;
+drop table t1, t2, t3, t4;
diff --git a/mysql-test/suite/versioning/t/delete.test b/mysql-test/suite/versioning/t/delete.test
new file mode 100644
index 00000000000..55420a21185
--- /dev/null
+++ b/mysql-test/suite/versioning/t/delete.test
@@ -0,0 +1,129 @@
+-- source suite/versioning/common.inc
+
+delimiter ~~;
+create or replace procedure test_01(
+ sys_type varchar(255),
+ engine varchar(255),
+ fields varchar(255))
+begin
+ set @str= concat('
+ create or replace table t1(
+ XNo int unsigned,
+ sys_start ', sys_type, ' as row start invisible,
+ sys_end ', sys_type, ' as row end invisible,
+ period for system_time (sys_start, sys_end))
+ with system versioning
+ engine ', engine);
+ prepare stmt from @str; execute stmt; drop prepare stmt;
+ insert into t1(XNo) values(0);
+ insert into t1(XNo) values(1);
+ insert into t1(XNo) values(2);
+ insert into t1(XNo) values(3);
+ insert into t1(XNo) values(4);
+ insert into t1(XNo) values(5);
+ insert into t1(XNo) values(6);
+ insert into t1(XNo) values(7);
+ insert into t1(XNo) values(8);
+ insert into t1(XNo) values(9);
+ set @str= concat('select XNo, ',
+ fields, " < '2038-01-19 03:14:07'
+ from t1 for system_time
+ between timestamp '0000-0-0 0:0:0'
+ and timestamp '2038-01-19 04:14:07'");
+ prepare stmt from @str; execute stmt;
+ delete from t1 where XNo = 0;
+ select "Deleted 0";
+ execute stmt;
+ delete from t1 where XNo = 1;
+ select "Deleted 1";
+ execute stmt;
+ delete from t1 where XNo > 5;
+ select "Deleted >5";
+ create view vt1 as select XNo from t1;
+ select XNo as XNo_vt1 from vt1;
+ delete from vt1 where XNo = 3;
+ select "Deleted from VIEW 3";
+ select XNo as XNo_vt1 from vt1;
+ execute stmt; drop prepare stmt;
+ drop view vt1;
+ drop table t1;
+end~~
+
+create or replace procedure test_02(
+ sys_type varchar(255),
+ engine varchar(255),
+ fields varchar(255))
+begin
+ set @str= concat('create or replace table t1 (
+ x int,
+ sys_start ', sys_type, ' as row start invisible,
+ sys_end ', sys_type, ' as row end invisible,
+ period for system_time (sys_start, sys_end))
+ with system versioning
+ engine ', engine);
+ prepare stmt from @str; execute stmt; drop prepare stmt;
+ insert into t1(x) values (1);
+ select sys_start into @sys_start from t1;
+ delete from t1;
+ select * from t1;
+ select x = 1 as A, sys_start = @sys_start as B, sys_end > sys_start as C
+ from t1 for system_time between timestamp '0-0-0' and timestamp '2038-01-19 04:14:07';
+ drop table t1;
+end~~
+
+create or replace procedure test_03(
+ sys_type varchar(255),
+ engine varchar(255),
+ fields varchar(255))
+begin
+ set @str0= concat('(
+ x int,
+ y int,
+ sys_start ', sys_type, ' as row start invisible,
+ sys_end ', sys_type, ' as row end invisible,
+ period for system_time (sys_start, sys_end))
+ with system versioning
+ engine ', engine);
+ set @str= concat('create or replace table t1', @str0);
+ prepare stmt from @str; execute stmt; drop prepare stmt;
+ set @str= concat('create or replace table t2', @str0);
+ prepare stmt from @str; execute stmt; drop prepare stmt;
+ insert into t1(x, y) values (1, 1), (2, 2), (3, 3), (14, 4);
+ insert into t2(x, y) values (11, 1), (12, 2), (13, 32), (14, 4);
+ delete t1, t2 from t1 join t2 where t1.y = 3 and t2.y = 32;
+ select x as t1_x from t1;
+ select x as t2_x from t2;
+ delete t1, t2 from t1 join t2 where t1.x = t2.x;
+ select x as t1_x from t1;
+ select x as t2_x from t2;
+ select x as t1_x_all from t1 for system_time between timestamp '0-0-0' and timestamp '2038-01-19 04:14:07';
+ select x as t2_x_all from t2 for system_time between timestamp '0-0-0' and timestamp '2038-01-19 04:14:07';
+ drop table t1;
+ drop table t2;
+end~~
+delimiter ;~~
+
+--echo # Basic + delete from view
+call test_01('timestamp(6)', 'myisam', 'sys_end');
+call test_01('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)');
+call verify_vtq;
+
+--echo # Check sys_start, sys_end
+call test_02('timestamp(6)', 'myisam', 'sys_end');
+call test_02('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)');
+call verify_vtq;
+
+--echo # Multi-delete
+call test_03('timestamp(6)', 'myisam', 'sys_end');
+call test_03('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)');
+call verify_vtq;
+
+--echo # Update + delete
+create or replace table t1 (x int) with system versioning;
+insert into t1 values (1);
+update t1 set x= 2;
+delete from t1;
+select x from t1 for system_time all;
+
+drop database test;
+create database test;
diff --git a/mysql-test/suite/versioning/t/derived.test b/mysql-test/suite/versioning/t/derived.test
new file mode 100644
index 00000000000..9784a4a0d2f
--- /dev/null
+++ b/mysql-test/suite/versioning/t/derived.test
@@ -0,0 +1,236 @@
+create table emp
+(
+ emp_id int,
+ name varchar(127),
+ mgr int
+) with system versioning;
+
+insert into emp values (1, 'bill', 0),
+ (2, 'bill', 1),
+ (3, 'kate', 1);
+set @ts=now(6);
+delete from emp;
+insert into emp values (4, 'john', 1);
+
+with ancestors as (select * from emp) select * from ancestors;
+set @tmp= "with ancestors as (select * from emp) select * from ancestors";
+prepare stmt from @tmp; execute stmt; drop prepare stmt;
+
+with ancestors as (select * from emp for system_time all) select * from ancestors;
+set @tmp= "with ancestors as (select * from emp for system_time all) select * from ancestors";
+prepare stmt from @tmp; execute stmt; drop prepare stmt;
+
+with recursive ancestors as (select * from emp) select * from ancestors;
+set @tmp= "with recursive ancestors as (select * from emp) select * from ancestors";
+prepare stmt from @tmp; execute stmt; drop prepare stmt;
+
+select emp_id from (select emp_id from emp where row_end>'2031-1-1') as tmp;
+set @tmp= "select emp_id from (select emp_id from emp where row_end>'2031-1-1') as tmp";
+prepare stmt from @tmp; execute stmt; drop prepare stmt;
+
+with recursive
+ancestors
+as
+(
+ select e.emp_id, e.name, e.mgr
+ from emp as e
+ where name = 'john'
+ union
+ select ee.emp_id, ee.name, ee.mgr
+ from emp as ee, ancestors as a
+ where ee.mgr = a.emp_id
+)
+select * from ancestors;
+set @tmp= "
+with recursive
+ancestors
+as
+(
+ select e.emp_id, e.name, e.mgr
+ from emp as e
+ where name = 'john'
+ union
+ select ee.emp_id, ee.name, ee.mgr
+ from emp as ee, ancestors as a
+ where ee.mgr = a.emp_id
+)
+select * from ancestors";
+prepare stmt from @tmp; execute stmt; drop prepare stmt;
+
+#385
+with recursive
+ancestors
+as
+(
+ select e.emp_id, e.name, e.mgr
+ from emp for system_time as of timestamp @ts as e
+ where name = 'bill'
+ union
+ select ee.emp_id, ee.name, ee.mgr
+ from emp for system_time as of timestamp @ts as ee,
+ ancestors as a
+ where ee.mgr = a.emp_id
+)
+select * from ancestors;
+set @tmp= "
+with recursive
+ancestors
+as
+(
+ select e.emp_id, e.name, e.mgr
+ from emp for system_time as of timestamp @ts as e
+ where name = 'bill'
+ union
+ select ee.emp_id, ee.name, ee.mgr
+ from emp for system_time as of timestamp @ts as ee,
+ ancestors as a
+ where ee.mgr = a.emp_id
+)
+select * from ancestors";
+prepare stmt from @tmp; execute stmt; drop prepare stmt;
+
+drop table emp;
+
+create or replace table t1 (x int) with system versioning;
+create or replace table t2 (y int) with system versioning;
+insert into t1 values (1);
+set @t0= now(6);
+delete from t1;
+insert into t1 values (2);
+insert into t2 values (10);
+
+--replace_column 2 # 3 #
+select * from (select *, t1.row_end, t1.row_end as endo from t1) as s0;
+--replace_column 3 # 4 #
+select * from (select *, t1.row_end, t2.row_start from t1, t2) as s0;
+
+--echo # SYSTEM_TIME propagation from inner to outer
+select * from (select * from t1 for system_time as of timestamp @t0, t2) as s0;
+with s1 as (select * from t1 for system_time as of timestamp @t0, t2) select * from s1;
+--echo # leading table selection
+--replace_column 3 #
+select * from (select *, t1.row_end from t2, t1 for system_time as of timestamp @t0) as s2;
+--replace_column 3 #
+with s3 as (select *, t1.row_end from t2, t1 for system_time as of timestamp @t0) select * from s3;
+
+--echo ### VIEW instead of t1
+set @q= concat("create view vt1 as select * from t1 for system_time as of timestamp '", @t0, "'");
+prepare q from @q; execute q; drop prepare q;
+create view vt2 as select * from t1;
+
+--echo # SYSTEM_TIME propagation from view
+select * from vt1;
+--echo # SYSTEM_TIME propagation from inner to outer
+select * from (select * from vt1, t2) as s0;
+
+--echo ### SYSTEM_TIME clash
+--error ER_VERS_NOT_VERSIONED
+select * from (select * from t1 for system_time all) for system_time all as dt0;
+--error ER_VERS_NOT_VERSIONED
+select * from vt1 for system_time all;
+--error ER_VERS_NOT_VERSIONED
+with dt1 as (select * from t1 for system_time all)
+select * from dt1 for system_time all;
+
+--echo ### UNION
+set @t1= now(6);
+delete from t2;
+insert into t2 values (3);
+--echo # SYSTEM_TIME is not propagated
+select x from t1 union
+select y from t2;
+select x from t1 for system_time as of @t0 union
+select y from t2;
+select x from t1 union
+select y from t2 for system_time as of @t1;
+select x from t1 for system_time as of @t0 union
+select y from t2 for system_time as of @t1;
+
+--echo # LEFT/RIGHT JOIN
+create or replace table t1 (x int, y int) with system versioning;
+create or replace table t2 (x int, y int) with system versioning;
+
+insert into t1 values (1, 1), (1, 2), (1, 3), (4, 4), (5, 5);
+insert into t2 values (1, 2), (2, 1), (3, 1);
+
+--echo ## Outer or inner SYSTEM_TIME produces same expression
+
+--disable_warnings
+--disable_query_log
+explain extended
+select * from (
+ select t1.x, t1.y as y1, t2.x as x2, t2.y as y2
+ from t1 join t2 on t1.x = t2.x) for system_time as of now() as t;
+
+let $a=`show warnings`;
+--echo Query A:
+echo $a;
+
+explain extended
+select * from (
+ select t1.x, t1.y as y1, t2.x as x2, t2.y as y2
+ from t1 for system_time as of now()
+ join t2 for system_time as of now() on t1.x = t2.x) as t;
+
+let $b=`show warnings`;
+--echo Query B:
+echo $b;
+
+if ($a == $b)
+{
+ --echo Fine result: queries A and B are equal.
+}
+--enable_query_log
+--enable_warnings
+
+--echo ## LEFT JOIN: t1, t2 versioned
+select * from (
+ select t1.x as LJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2
+ from t1 left join t2 on t1.x = t2.x)
+as derived;
+
+alter table t2 drop system versioning;
+
+--echo ## LEFT JOIN: t1 versioned
+select * from (
+ select t1.x as LJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2
+ from t1 left join t2 on t1.x = t2.x)
+as derived;
+
+alter table t1 drop system versioning;
+alter table t2 add system versioning;
+
+--echo ## LEFT JOIN: t2 versioned
+select * from (
+ select t1.x as LJ3_x1, t1.y as y1, t2.x as x2, t2.y as y2
+ from t1 left join t2 on t1.x = t2.x)
+as derived;
+
+alter table t1 add system versioning;
+
+--echo ## RIGHT JOIN: t1, t2 versioned
+select * from (
+ select t1.x as RJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2
+ from t1 right join t2 on t1.x = t2.x)
+as derived;
+
+alter table t2 drop system versioning;
+
+--echo ## RIGHT JOIN: t1 versioned
+select * from (
+ select t1.x as RJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2
+ from t1 right join t2 on t1.x = t2.x)
+as derived;
+
+alter table t1 drop system versioning;
+alter table t2 add system versioning;
+
+--echo ## RIGHT JOIN: t2 versioned
+select * from (
+ select t1.x as RJ3_x1, t1.y as y1, t2.x as x2, t2.y as y2
+ from t1 right join t2 on t1.x = t2.x)
+as derived;
+
+drop table t1, t2;
+drop view vt1, vt2;
+
diff --git a/mysql-test/suite/versioning/t/engines.combinations b/mysql-test/suite/versioning/t/engines.combinations
new file mode 100644
index 00000000000..561c5656929
--- /dev/null
+++ b/mysql-test/suite/versioning/t/engines.combinations
@@ -0,0 +1,8 @@
+[timestamp]
+default-storage-engine=innodb
+
+[trx_id]
+default-storage-engine=innodb
+
+[myisam]
+default-storage-engine=myisam
diff --git a/mysql-test/suite/versioning/t/foreign.combinations b/mysql-test/suite/versioning/t/foreign.combinations
new file mode 100644
index 00000000000..1a0812cfafe
--- /dev/null
+++ b/mysql-test/suite/versioning/t/foreign.combinations
@@ -0,0 +1,5 @@
+[timestamp]
+default-storage-engine=innodb
+
+[trx_id]
+default-storage-engine=innodb
diff --git a/mysql-test/suite/versioning/t/foreign.test b/mysql-test/suite/versioning/t/foreign.test
new file mode 100644
index 00000000000..81d1caa2594
--- /dev/null
+++ b/mysql-test/suite/versioning/t/foreign.test
@@ -0,0 +1,282 @@
+--source suite/versioning/common.inc
+
+--echo #################
+--echo # Test RESTRICT #
+--echo #################
+
+create table parent(
+ id int unique key
+) engine innodb;
+
+--replace_result $sys_datatype_expl SYS_DATATYPE
+eval create table child(
+ parent_id int,
+ sys_start $sys_datatype_expl as row start invisible,
+ sys_end $sys_datatype_expl as row end invisible,
+ period for system_time(sys_start, sys_end),
+ foreign key(parent_id) references parent(id)
+ on delete restrict
+ on update restrict
+) engine innodb with system versioning;
+
+insert into parent values(1);
+insert into child values(1);
+
+-- error ER_ROW_IS_REFERENCED_2
+delete from parent where id = 1;
+delete from child where parent_id = 1;
+delete from parent where id = 1;
+
+insert into parent values(1);
+insert into child values(1);
+-- error ER_ROW_IS_REFERENCED_2
+update parent set id=id+1;
+delete from child;
+update parent set id=id+1;
+select * from child for system_time from timestamp '1-1-1' to timestamp now(6);
+
+drop table child;
+drop table parent;
+
+--echo ##############################################
+--echo # Test when clustered index is a foreign key #
+--echo ##############################################
+
+create table parent(
+ id int(10) unsigned unique key
+) engine innodb;
+
+--replace_result $sys_datatype_expl SYS_DATATYPE
+eval create table child(
+ parent_id int(10) unsigned primary key,
+ sys_start $sys_datatype_expl as row start invisible,
+ sys_end $sys_datatype_expl as row end invisible,
+ period for system_time(sys_start, sys_end),
+ foreign key(parent_id) references parent(id)
+) engine innodb with system versioning;
+
+insert into parent values(1);
+insert into child values(1);
+
+-- error ER_ROW_IS_REFERENCED_2
+delete from parent where id = 1;
+
+drop table child;
+drop table parent;
+
+--echo ################
+--echo # Test CASCADE #
+--echo ################
+
+create table parent(
+ id int unique key
+) engine innodb;
+
+--replace_result $sys_datatype_expl SYS_DATATYPE
+eval create table child(
+ parent_id int,
+ sys_start $sys_datatype_expl as row start invisible,
+ sys_end $sys_datatype_expl as row end invisible,
+ period for system_time(sys_start, sys_end),
+ foreign key(parent_id) references parent(id)
+ on delete cascade
+ on update cascade
+) engine innodb with system versioning;
+
+insert into parent values(1);
+insert into child values(1);
+
+--echo ## FIXME: #415 update of foreign constraints is disabled
+call mtr.add_suppression("foreign key constraints in timestamp-based temporal table");
+--error ER_UNSUPPORTED_EXTENSION
+delete from parent where id = 1;
+delete from child where parent_id = 1;
+--echo ## FIXME END
+delete from parent where id = 1;
+select * from child;
+select * from child for system_time all;
+
+insert into parent values(1);
+insert into child values(1);
+update parent set id = id + 1;
+select * from child;
+select * from child for system_time all;
+
+drop table child;
+drop table parent;
+
+--replace_result $sys_datatype_expl SYS_DATATYPE
+eval create or replace table parent (
+ id int primary key,
+ sys_start $sys_datatype_expl as row start invisible,
+ sys_end $sys_datatype_expl as row end invisible,
+ period for system_time(sys_start, sys_end)
+) with system versioning
+engine innodb;
+
+create or replace table child (
+ x int,
+ parent_id int not null,
+ constraint `parent-fk`
+ foreign key (parent_id) references parent (id)
+ on delete cascade
+ on update restrict
+)
+engine innodb;
+
+insert into parent (id) values (2);
+insert into child (x, parent_id) values (2, 2);
+delete from parent;
+select * from child;
+
+drop table child;
+drop table parent;
+
+create or replace table parent (
+ id int primary key
+)
+engine innodb;
+
+create or replace table child (
+ id int primary key,
+ parent_id int not null,
+ constraint `parent-fk`
+ foreign key (parent_id) references parent (id)
+ on delete cascade
+ on update restrict
+) with system versioning
+engine innodb;
+
+insert into parent (id) values (3);
+insert into child (id, parent_id) values (3, 3);
+--echo ## FIXME: #415 update of foreign constraints is disabled
+delete from child;
+--echo ## FIXME END
+delete from parent;
+select * from child;
+select * from child for system_time all;
+
+drop table child;
+drop table parent;
+
+--echo #################
+--echo # Test SET NULL #
+--echo #################
+
+create table parent(
+ id int unique key
+) engine innodb;
+
+--replace_result $sys_datatype_expl SYS_DATATYPE
+eval create table child(
+ parent_id int,
+ sys_start $sys_datatype_expl as row start invisible,
+ sys_end $sys_datatype_expl as row end invisible,
+ period for system_time(sys_start, sys_end),
+ foreign key(parent_id) references parent(id)
+ on delete set null
+ on update set null
+) engine innodb with system versioning;
+
+insert into parent values(1);
+insert into child values(1);
+delete from child;
+insert into child values(1);
+
+--echo ## FIXME: #415 update of foreign constraints is disabled
+delete from child where parent_id = 1;
+--echo ## FIXME END
+delete from parent where id = 1;
+select * from child;
+select * from child for system_time from timestamp '1-1-1' to timestamp now(6);
+delete from child;
+
+insert into parent values(1);
+insert into child values(1);
+## FIXME: #415 update of foreign constraints is disabled
+if (0)
+{
+update parent set id=id+1;
+select * from child;
+select * from child for system_time from timestamp '1-1-1' to timestamp now(6);
+}
+## FIXME END
+
+drop table child;
+drop table parent;
+
+--echo ###########################
+--echo # Parent table is foreign #
+--echo ###########################
+
+--replace_result $sys_datatype_expl SYS_DATATYPE
+eval create or replace table parent(
+ id int unique key,
+ sys_start $sys_datatype_expl as row start invisible,
+ sys_end $sys_datatype_expl as row end invisible,
+ period for system_time(sys_start, sys_end)
+) engine innodb with system versioning;
+
+create or replace table child(
+ parent_id int,
+ foreign key(parent_id) references parent(id)
+) engine innodb;
+
+insert into parent values(1);
+insert into child values(1);
+-- error ER_ROW_IS_REFERENCED_2
+delete from parent;
+-- error ER_ROW_IS_REFERENCED_2
+update parent set id=2;
+
+delete from child;
+delete from parent;
+
+-- error ER_NO_REFERENCED_ROW_2
+insert into child values(1);
+
+insert into parent values(1);
+insert into child values(1);
+-- error ER_ROW_IS_REFERENCED_2
+delete from parent;
+-- error ER_ROW_IS_REFERENCED_2
+update parent set id=2;
+
+drop table child;
+drop table parent;
+
+--echo ###################
+--echo # crash on DELETE #
+--echo ###################
+
+--replace_result $sys_datatype_expl SYS_DATATYPE
+eval create or replace table a (
+ cola int(10) primary key,
+ v_cola int(10) as (cola mod 10) virtual,
+ sys_start $sys_datatype_expl as row start invisible,
+ sys_end $sys_datatype_expl as row end invisible,
+ period for system_time(sys_start, sys_end)
+) engine=innodb with system versioning;
+
+create index v_cola on a (v_cola);
+
+--replace_result $sys_datatype_expl SYS_DATATYPE
+eval create or replace table b(
+ cola int(10),
+ v_cola int(10),
+ sys_start $sys_datatype_expl as row start invisible,
+ sys_end $sys_datatype_expl as row end invisible,
+ period for system_time(sys_start, sys_end)
+) engine=innodb with system versioning;
+
+alter table b add constraint `v_cola_fk`
+foreign key (v_cola) references a (v_cola);
+
+insert into a(cola) values (12);
+insert into b(cola, v_cola) values (10,2);
+--error ER_ROW_IS_REFERENCED_2
+delete from a;
+
+drop table b, a;
+
+--source suite/versioning/common_finish.inc
diff --git a/mysql-test/suite/versioning/t/insert.test b/mysql-test/suite/versioning/t/insert.test
new file mode 100644
index 00000000000..482f0dd77ce
--- /dev/null
+++ b/mysql-test/suite/versioning/t/insert.test
@@ -0,0 +1,266 @@
+-- source suite/versioning/common.inc
+
+delimiter ~~;
+create procedure test_01(
+ sys_type varchar(255),
+ engine varchar(255),
+ fields varchar(255))
+begin
+ set @str= concat('
+ create table t1(
+ x int unsigned,
+ y int unsigned,
+ sys_start ', sys_type, ' as row start invisible,
+ sys_end ', sys_type, ' as row end invisible,
+ period for system_time (sys_start, sys_end))
+ with system versioning
+ engine ', engine);
+ prepare stmt from @str; execute stmt; drop prepare stmt;
+ insert into t1(x, y) values(3, 4);
+ insert delayed into t1(x, y) values(2, 3);
+ insert into t1 values(40, 33);
+ set @str= concat('select x, y, ', fields, ' from t1');
+ prepare stmt from @str; execute stmt; drop prepare stmt;
+ drop table t1;
+end~~
+
+create procedure test_02(
+ sys_type varchar(255),
+ engine varchar(255),
+ fields varchar(255))
+begin
+ set @str= concat('
+ create table t1(
+ id int unsigned auto_increment primary key,
+ x int unsigned,
+ y int unsigned,
+ sys_start ', sys_type, ' as row start invisible,
+ sys_end ', sys_type, ' as row end invisible,
+ period for system_time (sys_start, sys_end))
+ with system versioning
+ engine ', engine);
+ prepare stmt from @str; execute stmt; drop prepare stmt;
+ insert into t1(x, y) values(33, 44);
+ insert into t1(id, x, y) values(20, 33, 44);
+ insert into t1 values(40, 33, 44);
+ set @str= concat('select id, x, y, ', fields, ' from t1');
+ prepare stmt from @str; execute stmt; drop prepare stmt;
+ drop table t1;
+end~~
+
+create procedure test_03(
+ sys_type varchar(255),
+ engine varchar(255),
+ fields varchar(255))
+begin
+ set @str= concat('
+ create table t1(
+ x int unsigned,
+ y int unsigned,
+ sys_start ', sys_type, ' as row start invisible,
+ sys_end ', sys_type, ' as row end invisible,
+ period for system_time (sys_start, sys_end))
+ with system versioning
+ engine ', engine);
+ prepare stmt from @str; execute stmt; drop prepare stmt;
+ create view vt1_1 as select x, y from t1;
+ insert into t1(x, y) values(8001, 9001);
+ insert into vt1_1(x, y) values(1001, 2001);
+ insert into vt1_1 values(1002, 2002);
+ set @str= concat('select x, y, ', fields, ' from t1');
+ prepare stmt from @str; execute stmt; drop prepare stmt;
+ select x, y from vt1_1;
+end~~
+
+create procedure test_04(
+ sys_type varchar(255),
+ engine varchar(255),
+ fields varchar(255))
+begin
+ set @str= concat('
+ create table t1(
+ id bigint primary key,
+ a int,
+ b int)
+ with system versioning
+ engine ', engine);
+ prepare stmt from @str; execute stmt; drop prepare stmt;
+ insert into t1 values(1, 1, 1);
+ select row_start, row_end from t1 into @sys_start, @sys_end;
+ select id, a, b from t1;
+ insert into t1 values(2, 2, 2);
+ select id, a, b, row_start > @sys_start as C, row_end = @sys_end as D from t1 where id = 2;
+ drop table t1;
+end~~
+
+create procedure test_05(
+ sys_type varchar(255),
+ engine varchar(255),
+ fields varchar(255))
+begin
+ set @str= concat('(
+ x int unsigned,
+ y int unsigned,
+ sys_start ', sys_type, ' as row start invisible,
+ sys_end ', sys_type, ' as row end invisible,
+ period for system_time (sys_start, sys_end))
+ with system versioning
+ engine ', engine);
+ set @str2= concat('create table t1', @str);
+ prepare stmt from @str2; execute stmt; drop prepare stmt;
+ set @str2= concat('create table t2', @str);
+ prepare stmt from @str2; execute stmt; drop prepare stmt;
+ insert into t1(x, y) values
+ (1, 1000),
+ (2, 2000),
+ (3, 3000),
+ (4, 4000),
+ (5, 5000),
+ (6, 6000),
+ (7, 7000),
+ (8, 8000),
+ (9, 9000);
+ delete from t1 where x >= 1;
+ insert into t1(x, y) values
+ (1, 1001),
+ (2, 2001),
+ (3, 3001),
+ (4, 4001),
+ (5, 5001),
+ (6, 6001);
+ insert into t1(x, y, sys_start) values
+ (7, 7001, DEFAULT);
+ insert into t1(x, y, sys_end) values
+ (8, 8001, DEFAULT);
+ insert into t1(x, y, sys_start, sys_end) values
+ (9, 9001, DEFAULT, DEFAULT);
+ insert into t2 select x, y from t1 for system_time between timestamp '0000-0-0 0:0:0' and timestamp '9999-1-1 0:0:0';
+ select x, y from t1;
+ select x, y from t2;
+ drop table t1;
+ drop table t2;
+end~~
+delimiter ;~~
+
+call test_01('timestamp(6)', 'myisam', 'sys_end');
+call test_01('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)');
+
+call test_02('timestamp(6)', 'myisam', 'sys_end');
+call test_02('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)');
+
+call test_03('timestamp(6)', 'myisam', 'sys_end');
+drop table t1;
+drop view vt1_1;
+
+call test_03('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)');
+drop table t1;
+drop view vt1_1;
+
+call test_04('timestamp(6)', 'myisam', 'sys_end');
+call test_04('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)');
+
+call test_05('timestamp(6)', 'myisam', 'sys_end');
+call test_05('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)');
+
+# VTQ test
+
+call verify_vtq;
+
+create table t1(
+ x int unsigned,
+ sys_start bigint unsigned as row start invisible,
+ sys_end bigint unsigned as row end invisible,
+ period for system_time (sys_start, sys_end))
+with system versioning engine=innodb;
+
+create table t2(x int unsigned) engine=innodb;
+
+start transaction;
+insert into t1(x) values(1);
+commit;
+call verify_vtq;
+
+start transaction;
+insert into t2(x) values(1);
+savepoint a;
+insert into t1(x) values(1);
+rollback to a;
+commit;
+call verify_vtq;
+
+insert into t2(x) values (1);
+
+# virtual columns
+create or replace table t1 (
+ x int,
+ y int as (x) virtual,
+ sys_trx_start bigint unsigned as row start invisible,
+ sys_trx_end bigint unsigned as row end invisible,
+ period for system_time (sys_trx_start, sys_trx_end)
+) engine=innodb with system versioning;
+insert into t1 values (1, null);
+update t1 set x= x + 1;
+select x, y, sys_trx_end = 18446744073709551615 as current from t1 for system_time all;
+
+create or replace table t1 (x int) with system versioning engine innodb;
+insert into t1 values (1), (2);
+--error ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN
+insert into t1 (row_start) select row_end from t1;
+set sql_mode='';
+insert into t1 (row_start, row_end) values (DEFAULT, 1);
+set sql_mode=default;
+select @@sql_mode into @saved_mode;
+set sql_mode= '';
+insert into t1 (x, row_start, row_end) values (3, 4, 5);
+set sql_mode= @saved_mode;
+insert into t1 (row_start, row_end) values (DEFAULT, DEFAULT);
+select * from t1;
+
+--echo # MDEV-14792 INSERT without column list into table with explicit versioning columns produces bad data
+create or replace table t1 (
+ i int,
+ s timestamp(6) as row start,
+ e timestamp(6) as row end,
+ c varchar(8),
+ period for system_time(s, e))
+with system versioning;
+insert into t1 values (1, null, null, 'foo');
+select i, c, current_row(e) from t1;
+
+drop table t1;
+drop table t2;
+
+drop procedure test_01;
+drop procedure test_02;
+drop procedure test_03;
+drop procedure test_04;
+drop procedure test_05;
+
+-- source suite/versioning/common_finish.inc
+
+#
+# MDEV-14788 System versioning cannot be based on local timestamps, as it is now
+#
+set timestamp=1000000019;
+select now() < sysdate();
+create table t1 (a int) with system versioning;
+insert t1 values (1);
+
+--source suite/versioning/wait_system_clock.inc
+set @a=sysdate(6);
+
+select * from t1 for system_time as of now(6);
+select * from t1 for system_time as of sysdate(6);
+update t1 set a=2;
+delete from t1;
+--sorted_result
+select *, row_start > @a, row_end > @a from t1 for system_time all;
+
+--echo #
+--echo # MDEV-14871 Server crashes in fill_record / fill_record_n_invoke_before_triggers upon inserting into versioned table with trigger
+--echo #
+create or replace table t1 (pk int primary key) with system versioning;
+create trigger tr before insert on t1 for each row select 1 into @a;
+insert into t1 values (1),(2);
+
+drop table t1;
diff --git a/mysql-test/suite/versioning/t/online.test b/mysql-test/suite/versioning/t/online.test
new file mode 100644
index 00000000000..4fbd5d85100
--- /dev/null
+++ b/mysql-test/suite/versioning/t/online.test
@@ -0,0 +1,42 @@
+--source include/have_innodb.inc
+
+set system_versioning_alter_history=keep;
+
+create or replace table t (a int, b int) engine=innodb;
+
+--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
+alter table t add system versioning, lock=none;
+alter table t add system versioning, lock=shared;
+--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
+alter table t drop column b, lock=none;
+--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
+alter table t drop column b, algorithm=inplace;
+alter table t add index idx(a), lock=none;
+--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
+alter table t drop system versioning, lock=none;
+--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
+alter table t drop system versioning, algorithm=inplace;
+
+
+create or replace table t (a int, b int) engine=innodb;
+
+--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
+alter table t
+ add s bigint unsigned as row start,
+ add e bigint unsigned as row end,
+ add period for system_time(s, e),
+ add system versioning,
+ lock=none;
+alter table t
+ add s bigint unsigned as row start,
+ add e bigint unsigned as row end,
+ add period for system_time(s, e),
+ add system versioning;
+--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
+alter table t drop column b, lock=none;
+alter table t add index idx(a), lock=none;
+alter table t drop column s, drop column e;
+--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
+alter table t drop system versioning, lock=none;
+
+drop table t;
diff --git a/mysql-test/suite/versioning/t/optimized.test b/mysql-test/suite/versioning/t/optimized.test
new file mode 100644
index 00000000000..93dd6ed6fc6
--- /dev/null
+++ b/mysql-test/suite/versioning/t/optimized.test
@@ -0,0 +1,33 @@
+create table t (
+ a int,
+ b int without system versioning
+) with system versioning;
+
+insert into t values(1, 2);
+insert into t values(3, 4);
+select * from t;
+select a from t for system_time as of timestamp now(6);
+select a, b, b+0 from t for system_time as of timestamp now(6);
+select * from t for system_time as of timestamp now(6);
+select count(*) from t for system_time as of timestamp now(6) group by b;
+select * from t for system_time as of timestamp now(6) order by b asc;
+select * from t for system_time as of timestamp now(6) order by b desc;
+select * from t for system_time as of timestamp now(6) group by a having a=2;
+select * from t for system_time as of timestamp now(6) group by b having b=2;
+select a from t for system_time as of timestamp now(6) where b=2;
+select a from t for system_time as of timestamp now(6) where b=NULL;
+select a from t for system_time as of timestamp now(6) where b is NULL;
+select count(*), b from t for system_time as of timestamp now(6) group by b having b=NULL;
+select a, b from t;
+
+create or replace table t (
+ a int,
+ b int not null without system versioning
+) with system versioning;
+
+insert into t values (1, 2), (3, 4);
+
+select * from t for system_time as of timestamp now(6);
+select * from t for system_time as of timestamp now(6) where b is NULL;
+
+drop table t;
diff --git a/mysql-test/suite/versioning/t/partition.combinations b/mysql-test/suite/versioning/t/partition.combinations
new file mode 100644
index 00000000000..4d73ef5a5ea
--- /dev/null
+++ b/mysql-test/suite/versioning/t/partition.combinations
@@ -0,0 +1,5 @@
+[timestamp]
+default-storage-engine=innodb
+
+[myisam]
+default-storage-engine=myisam
diff --git a/mysql-test/suite/versioning/t/partition.opt b/mysql-test/suite/versioning/t/partition.opt
new file mode 100644
index 00000000000..71be6744916
--- /dev/null
+++ b/mysql-test/suite/versioning/t/partition.opt
@@ -0,0 +1 @@
+--system-versioning-alter-history=keep
diff --git a/mysql-test/suite/versioning/t/partition.test b/mysql-test/suite/versioning/t/partition.test
new file mode 100644
index 00000000000..1dea9f7c69c
--- /dev/null
+++ b/mysql-test/suite/versioning/t/partition.test
@@ -0,0 +1,373 @@
+-- source include/have_partition.inc
+-- source suite/versioning/common.inc
+
+--echo # Check conventional partitioning on temporal tables
+
+create table t1 (x int)
+with system versioning
+partition by range columns (x) (
+ partition p0 values less than (100),
+ partition p1 values less than (1000));
+
+insert into t1 values (3), (300);
+select * from t1;
+select * from t1 partition (p0);
+select * from t1 partition (p1);
+
+delete from t1;
+select * from t1;
+select * from t1 partition (p0);
+select * from t1 partition (p1);
+select * from t1 for system_time all;
+select * from t1 partition (p0) for system_time all;
+select * from t1 partition (p1) for system_time all;
+
+--echo # Engine change native <-> non-native versioning prohibited
+--replace_result $default_engine DEFAULT_ENGINE
+eval create or replace table t1 (i int) engine=$default_engine with system versioning partition by hash(i);
+--replace_result $non_default_engine NON_DEFAULT_ENGINE
+--error ER_VERS_ALTER_ENGINE_PROHIBITED
+eval alter table t1 engine=$non_default_engine;
+
+
+--echo ## CREATE TABLE
+
+--error ER_VERS_ENGINE_UNSUPPORTED
+create or replace table t1 (x int)
+partition by system_time (
+ partition p0 history,
+ partition pn current);
+
+create or replace table t1 (x int);
+--error ER_VERS_ENGINE_UNSUPPORTED,ER_VERS_ENGINE_UNSUPPORTED
+alter table t1
+partition by system_time (
+ partition p0 history,
+ partition pn current);
+
+--error ER_VERS_WRONG_PARTS
+create or replace table t1 (x int)
+with system versioning
+partition by system_time (
+ partition p0 current);
+
+--error ER_VERS_WRONG_PARTS
+create or replace table t1 (x int)
+with system versioning
+partition by system_time (
+ partition p0 current,
+ partition p1 current);
+
+--error ER_VERS_WRONG_PARTS
+create or replace table t1 (x int)
+with system versioning
+partition by system_time (
+ partition p0 history,
+ partition p1 history);
+
+--error ER_VERS_WRONG_PARTS
+create or replace table t1 (x int)
+with system versioning
+partition by system_time (
+ partition pn current,
+ partition p0 history);
+
+--error ER_VERS_WRONG_PARTS
+create or replace table t1 (x int)
+with system versioning
+partition by system_time (
+ partition p0,
+ partition pn current);
+
+create or replace table t1 (x int)
+with system versioning
+partition by system_time (
+ partition p0 history,
+ partition pn current);
+
+
+--echo ## ALTER TABLE
+
+--error ER_VERS_WRONG_PARTS
+alter table t1 add partition (
+ partition p1 current);
+
+alter table t1 add partition (
+ partition p1 history);
+
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE
+show create table t1;
+
+insert into t1 values (1), (2);
+
+--error ER_VERS_WRONG_PARTS
+alter table t1 drop partition pn;
+alter table t1 drop partition p1;
+--error ER_VERS_WRONG_PARTS
+alter table t1 drop partition p0;
+
+select x from t1;
+
+--echo # Bug #260: incorrect IB partitioning warning
+create or replace table t1 (x int)
+with system versioning
+partition by system_time limit 1 (
+ partition p0 history,
+ partition pn current);
+alter table t1 change x big int;
+
+create or replace table t1 (i int) engine myisam partition by hash(i) partitions 2;
+--error ER_PARTITION_WRONG_TYPE
+alter table t1 add partition (partition px history);
+
+
+--echo ## INSERT, UPDATE, DELETE
+
+create or replace table t1 (x int)
+with system versioning
+partition by system_time (
+ partition p0 history,
+ partition pn current);
+
+set @now= now(6);
+insert into t1 values (1);
+set @str= concat('select x, row_start < @now as A, row_end > @now as B from t1 partition (p0)');
+prepare select_p0 from @str;
+set @str= concat('select x, row_start > @now as C, row_end = timestamp\'2038-01-19 03:14:07.999999\' as D from t1 partition (pn)');
+prepare select_pn from @str;
+
+execute select_p0;
+execute select_pn;
+
+--echo ## pruning check
+--replace_regex /\d/N/ /ALL/system/ /Using where//
+explain partitions select * from t1;
+
+set @str= concat('select row_start from t1 partition (pn) into @ts0');
+prepare stmt from @str; execute stmt; drop prepare stmt;
+
+--source suite/versioning/wait_system_clock.inc
+
+set @now= now(6);
+delete from t1;
+execute select_p0;
+execute select_pn;
+
+set @str= concat('select row_start from t1 partition (p0) into @ts1');
+prepare stmt from @str; execute stmt; drop prepare stmt;
+
+select @ts0 = @ts1;
+
+set @now= now(6);
+insert into t1 values (2);
+
+--source suite/versioning/wait_system_clock.inc
+
+execute select_p0;
+execute select_pn;
+
+set @str= concat('select row_start from t1 partition (pn) into @ts0');
+prepare stmt from @str; execute stmt; drop prepare stmt;
+
+set @now= now(6);
+update t1 set x = x + 1;
+
+--source suite/versioning/wait_system_clock.inc
+
+execute select_p0;
+execute select_pn;
+
+drop prepare select_p0;
+drop prepare select_pn;
+
+set @str= concat('select row_start from t1 partition (p0) where x = 2 into @ts1');
+prepare stmt from @str; execute stmt; drop prepare stmt;
+set @str= concat('select row_end from t1 partition (p0) where x = 2 into @ts2');
+prepare stmt from @str; execute stmt; drop prepare stmt;
+set @str= concat('select row_start from t1 partition (pn) into @ts3');
+prepare stmt from @str; execute stmt; drop prepare stmt;
+
+select @ts0 = @ts1;
+select @ts2 = @ts3;
+
+--echo ## rotation by LIMIT
+--error ER_PART_WRONG_VALUE
+create or replace table t1 (x int)
+with system versioning
+partition by system_time limit 0 (
+ partition p0 history,
+ partition p1 history,
+ partition pn current);
+
+create or replace table t1 (x int)
+with system versioning
+partition by system_time limit 2 (
+ partition p0 history,
+ partition p1 history,
+ partition pn current);
+
+--replace_result $default_engine DEFAULT_ENGINE $sys_datatype SYS_DATATYPE
+show create table t1;
+
+--error ER_DROP_PARTITION_NON_EXISTENT
+alter table t1 drop partition non_existent;
+
+insert into t1 values (1), (2), (3);
+select * from t1 partition (pn);
+--echo ### warn about partition switching
+delete from t1;
+select * from t1 partition (p0);
+select * from t1 partition (p1);
+
+insert into t1 values (4), (5);
+--echo ### warn about full partition
+delete from t1;
+select * from t1 partition (p1) order by x;
+
+--echo ### Assertion in ALTER on warning from partitioning LIMIT [#446]
+create or replace table t1 (x int) with system versioning;
+insert into t1 values (1), (2);
+delete from t1;
+alter table t1 partition by system_time limit 1 (
+ partition p1 history,
+ partition pn current);
+
+--echo ## rotation by INTERVAL
+--error ER_PART_WRONG_VALUE
+create or replace table t1 (x int)
+with system versioning
+partition by system_time interval 0 second (
+ partition p0 history,
+ partition p1 history,
+ partition pn current);
+
+create or replace table t1 (x int)
+with system versioning
+partition by system_time interval 1 second (
+ partition p0 history,
+ partition p1 history,
+ partition pn current);
+
+insert into t1 values (1), (2), (3);
+select * from t1 partition (pn);
+delete from t1;
+select * from t1 partition (p0);
+
+--sleep 2
+insert into t1 values (4);
+delete from t1;
+select * from t1 partition (p1);
+
+--echo ## Subpartitions
+create or replace table t1 (x int)
+with system versioning
+partition by system_time limit 2
+subpartition by key (x)
+subpartitions 2 (
+ partition p0 history,
+ partition p1 history,
+ partition pn current);
+
+insert into t1 (x) values (1), (2), (3), (4), (5);
+select * from t1 partition (pnsp0);
+select * from t1 partition (pnsp1);
+
+--echo ### warn about partition switching and about full partition
+delete from t1;
+select * from t1 partition (p0sp0);
+select * from t1 partition (p0sp1);
+select * from t1 partition (p1sp0);
+select * from t1 partition (p1sp1);
+
+create or replace table t1 (a bigint)
+with system versioning
+partition by range (a)
+(partition p0 values less than (20) engine innodb,
+ partition p1 values less than maxvalue engine innodb);
+insert into t1 values (1);
+
+create or replace table t1 (
+ f_int1 integer default 0
+) with system versioning
+partition by range(f_int1)
+subpartition by hash(f_int1)
+( partition part1 values less than (1000)
+(subpartition subpart11 storage engine = 'innodb',
+subpartition subpart12 storage engine = 'innodb'));
+insert into t1 values (1);
+
+create or replace table t1 (i int) engine=innodb partition by key(i);
+alter table t1 add system versioning;
+insert into t1 values();
+
+--echo # MDEV-14722 Assertion in ha_commit_trans for sub-statement
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day (
+ partition p1 history,
+ partition pc current);
+create or replace table t2 (f int);
+create or replace trigger tr before insert on t2
+for each row select table_rows from information_schema.tables
+where table_name = 't1' into @a;
+insert into t2 values (1);
+
+--echo # MDEV-14740 Locking assertion for system_time partitioning
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 week (
+ partition p1 history,
+ partition pn current);
+create or replace table t2 (f int);
+create or replace trigger tr before insert on t2
+for each row select count(*) from t1 into @a;
+insert into t2 values (1);
+
+--echo # MDEV-14741 Assertion `(trx)->start_file == 0' failed in row_truncate_table_for_mysql()
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 hour (
+ partition p1 history,
+ partition pn current);
+set autocommit= off;
+truncate table t1;
+set autocommit= on;
+
+--echo # MDEV-14747 ALTER PARTITION BY SYSTEM_TIME after LOCK TABLES
+create or replace table t1 (x int) with system versioning;
+lock table t1 write;
+alter table t1 partition by system_time interval 1 week (
+ partition p1 history,
+ partition pn current);
+unlock tables;
+
+--echo # MDEV-14748 Assertion in ha_myisammrg::attach_children()
+create or replace table t1 (x int) engine=myisam with system versioning
+ partition by system_time interval 1 month (partition p1 history, partition pn current);
+create or replace table t2 (x int) engine=myisam;
+create or replace table t3 (x int) engine=merge union=(t2);
+create or replace table t4 (x int) engine=myisam;
+create or replace trigger tr after insert on t4 for each row insert into t2
+ ( select x from t3 ) union ( select x from t1 );
+insert into t4 values (1);
+
+--echo # MDEV-14821 Assertion failure
+create or replace table t1 (x int) with system versioning;
+insert into t1 values (0), (1);
+update t1 set x= x + 1;
+alter table t1 partition by system_time limit 1 (
+ partition p1 history,
+ partition p2 history,
+ partition pn current);
+delete from t1 where x = 1;
+delete from t1 where x = 2;
+
+--echo # MDEV-14923 Assertion upon INSERT into locked versioned partitioned table
+create or replace table t1 (x int) with system versioning
+partition by system_time (partition p1 history, partition pn current);
+lock table t1 write;
+--error ER_SAME_NAME_PARTITION
+alter table t1 add partition (partition p1 history);
+insert into t1 values (1);
+unlock tables;
+
+--echo # Test cleanup
+drop database test;
+create database test;
diff --git a/mysql-test/suite/versioning/t/replace.test b/mysql-test/suite/versioning/t/replace.test
new file mode 100644
index 00000000000..8f1c2d8d637
--- /dev/null
+++ b/mysql-test/suite/versioning/t/replace.test
@@ -0,0 +1,13 @@
+--source suite/versioning/common.inc
+--source suite/versioning/key_type.inc
+--source suite/versioning/engines.inc
+
+call create_table('t', 'x int');
+
+insert t values (1, 2);
+replace t values (1, 3);
+select *, current_row(row_end) as current from t for system_time all
+order by x;
+
+drop database test;
+create database test;
diff --git a/mysql-test/suite/versioning/t/rpl.test b/mysql-test/suite/versioning/t/rpl.test
new file mode 100644
index 00000000000..342d58626b7
--- /dev/null
+++ b/mysql-test/suite/versioning/t/rpl.test
@@ -0,0 +1,108 @@
+--source include/master-slave.inc
+
+if ($MTR_COMBINATION_STMT)
+{
+ --source include/have_binlog_format_statement.inc
+}
+if ($MTR_COMBINATION_ROW)
+{
+ --source include/have_binlog_format_row.inc
+}
+if ($MTR_COMBINATION_MIX)
+{
+ --source include/have_binlog_format_mixed.inc
+}
+--source suite/versioning/engines.inc
+
+#BUG#12662190 - COM_COMMIT IS NOT INCREMENTED FROM THE BINARY LOGS ON SLAVE, COM_BEGIN IS
+#Testing command counters -BEFORE.
+#Storing the before counts of Slave
+connection slave;
+let $slave_com_commit_before= query_get_value(SHOW GLOBAL STATUS LIKE 'com_commit', Value, 1);
+let $slave_com_insert_before= query_get_value(SHOW GLOBAL STATUS LIKE 'com_insert', Value, 1);
+let $slave_com_delete_before= query_get_value(SHOW GLOBAL STATUS LIKE 'com_delete', Value, 1);
+let $slave_com_update_before= query_get_value(SHOW GLOBAL STATUS LIKE 'com_update', Value, 1);
+
+connection master;
+CREATE TABLE t1 (x int) with system versioning;
+insert into t1 values (1);
+SELECT * FROM t1;
+delete from t1;
+select * from t1;
+select * from t1 for system_time all;
+sync_slave_with_master;
+select * from t1;
+select * from t1 for system_time all;
+
+connection master;
+insert into t1 values (2);
+sync_slave_with_master;
+select * from t1;
+
+connection master;
+update t1 set x = 3;
+sync_slave_with_master;
+select * from t1;
+select * from t1 for system_time all;
+
+# check unversioned -> versioned replication
+connection master;
+create or replace table t1 (x int primary key);
+sync_slave_with_master;
+alter table t1 with system versioning;
+
+connection master;
+insert into t1 values (1);
+sync_slave_with_master;
+select * from t1;
+select * from t1 for system_time all;
+
+connection master;
+update t1 set x= 2 where x = 1;
+sync_slave_with_master;
+select * from t1;
+select * from t1 for system_time all;
+
+connection master;
+delete from t1;
+sync_slave_with_master;
+select * from t1;
+select * from t1 for system_time all;
+
+# same thing (UPDATE, DELETE), but without PK
+connection master;
+create or replace table t1 (x int);
+sync_slave_with_master;
+alter table t1 with system versioning;
+
+connection master;
+insert into t1 values (1);
+update t1 set x= 2 where x = 1;
+sync_slave_with_master;
+select * from t1;
+select * from t1 for system_time all;
+
+connection master;
+delete from t1;
+sync_slave_with_master;
+select * from t1;
+select * from t1 for system_time all;
+
+# multi-update
+connection master;
+create or replace table t1 (x int) with system versioning;
+create or replace table t2 (x int) with system versioning;
+insert into t1 values (1);
+insert into t2 values (2);
+update t1, t2 set t1.x=11, t2.x=22;
+sync_slave_with_master;
+select * from t1;
+select * from t2;
+select * from t1 for system_time all;
+select * from t2 for system_time all;
+
+
+connection master;
+drop table t1, t2;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/versioning/t/select.test b/mysql-test/suite/versioning/t/select.test
new file mode 100644
index 00000000000..356406e0947
--- /dev/null
+++ b/mysql-test/suite/versioning/t/select.test
@@ -0,0 +1,306 @@
+--source suite/versioning/engines.inc
+--source suite/versioning/common.inc
+
+# test_01
+
+--replace_result $sys_datatype_expl SYS_DATATYPE
+eval create or replace table t1 (
+ x int unsigned,
+ y int unsigned,
+ sys_trx_start $sys_datatype_expl as row start invisible,
+ sys_trx_end $sys_datatype_expl as row end invisible,
+ period for system_time (sys_trx_start, sys_trx_end)
+) with system versioning;
+
+insert into t1 (x, y) values
+ (0, 100),
+ (1, 101),
+ (2, 102),
+ (3, 103),
+ (4, 104),
+ (5, 105),
+ (6, 106),
+ (7, 107),
+ (8, 108),
+ (9, 109);
+
+set @t0= now(6);
+if ($MTR_COMBINATION_TRX_ID)
+{
+--disable_query_log
+ select sys_trx_start from t1 limit 1 into @x0;
+--enable_query_log
+}
+
+delete from t1 where x = 3;
+delete from t1 where x > 7;
+
+insert into t1(x, y) values(3, 33);
+select sys_trx_start from t1 where x = 3 and y = 33 into @t1;
+if ($MTR_COMBINATION_TRX_ID)
+{
+--disable_query_log
+ set @x1= @t1;
+ select vtq_commit_ts(@x1) into @t1;
+--enable_query_log
+}
+
+select x, y from t1;
+select x as ASOF_x, y from t1 for system_time as of timestamp @t0;
+select x as FROMTO_x, y from t1 for system_time from timestamp '0-0-0 0:0:0' to timestamp @t1;
+select x as BETWAND_x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp @t1;
+select x as ALL_x, y from t1 for system_time all;
+
+--disable_query_log
+if ($MTR_COMBINATION_TRX_ID)
+{
+ select x as ASOF2_x, y from t1 for system_time as of @x0;
+ select x as FROMTO2_x, y from t1 for system_time from @x0 to @x1;
+ select x as BETWAND2_x, y from t1 for system_time between transaction @x0 and transaction @x1;
+}
+if ($MTR_COMBINATION_TIMESTAMP)
+{
+ select x as ASOF2_x, y from t1 for system_time as of @t0;
+ select x as FROMTO2_x, y from t1 for system_time from timestamp '0-0-0 0:0:0' to timestamp @t1;
+ select x as BETWAND2_x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp @t1;
+}
+--enable_query_log
+
+# test_02
+
+create or replace table t1 (
+ x int unsigned,
+ y int unsigned
+) with system versioning;
+create or replace table t2 (
+ x int unsigned,
+ y int unsigned
+) with system versioning;
+
+insert into t1 values (1, 1), (1, 2), (1, 3), (4, 4), (5, 5);
+insert into t2 values (1, 2), (2, 1), (3, 1);
+set @t0= now(6);
+
+select t1.x as IJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 inner join t2 on t1.x = t2.x;
+select t1.x as LJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 left join t2 on t1.x = t2.x;
+select t1.x as RJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 right join t2 on t1.x = t2.x;
+
+delete from t1;
+delete from t2;
+
+#384
+explain extended select * from (select t1.x as IJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 inner join t2 on t1.x = t2.x)
+for system_time as of timestamp @t0 as t;
+explain extended select * from (select t1.x as LJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 left join t2 on t1.x = t2.x)
+for system_time as of timestamp @t0 as t;
+#383
+explain extended select * from (select t1.x as RJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 right join t2 on t1.x = t2.x)
+for system_time as of timestamp @t0 as t;
+
+select * from (select t1.x as IJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 inner join t2 on t1.x = t2.x)
+for system_time as of timestamp @t0 as t;
+select * from (select t1.x as LJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 left join t2 on t1.x = t2.x)
+for system_time as of timestamp @t0 as t;
+select * from (select t1.x as RJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 right join t2 on t1.x = t2.x)
+for system_time as of timestamp @t0 as t;
+
+drop table t1;
+drop table t2;
+
+# Wildcard expansion on hidden fields
+
+create table t1(
+ A int
+) with system versioning;
+insert into t1 values(1);
+select * from t1;
+
+create or replace table t1 (x int);
+insert into t1 values (1);
+--error ER_VERS_NOT_VERSIONED
+select * from t1 for system_time all;
+
+create or replace table t1 (x int) with system versioning;
+insert into t1 values (1);
+select * from t1 for system_time all for update;
+
+create or replace table t1 (a int not null auto_increment primary key) with system versioning;
+select * from (t1 as t2 left join t1 as t3 using (a)) natural left join t1;
+
+create or replace table t1 (a int) with system versioning;
+create or replace table t2 (a int) with system versioning;
+insert into t1 values(1);
+insert into t2 values(1);
+create view v1 as select * from t2 inner join t1 using (a);
+select * from v1;
+drop view v1;
+
+create or replace table t1 (a int) with system versioning;
+insert into t1 values (1);
+create view vt1 as select a from t1;
+select * from t1 natural join vt1;
+drop view vt1;
+
+create or replace table t1(x int) with system versioning;
+select * from (t1 as r left join t1 as u using (x)), t1;
+
+# @end should be max
+create or replace table t1 (a int) with system versioning;
+insert into t1 values (1);
+create trigger read_end after update on t1
+ for each row set @end = old.row_end;
+update t1 set a=2;
+--replace_result 18446744073709551615 MAX_RESULT "2038-01-19 03:14:07.999999" MAX_RESULT
+select @end;
+
+create or replace table t1 (a int) with system versioning;
+create or replace table t2 (b int) with system versioning;
+insert into t1 values (1);
+insert into t2 values (2);
+select * from (select * from t1 cross join t2) as tmp;
+select * from (select * from (select * from t1 cross join t2) as tmp1) as tmp2;
+select * from (select * from t1 cross join t2 for system_time as of timestamp '0-0-0') as tmp;
+
+create or replace table t1(a1 int) with system versioning;
+create or replace table t2(a2 int) with system versioning;
+insert into t1 values(1),(2);
+insert into t2 values(1),(2);
+select * from t1 for system_time all natural left join t2 for system_time all;
+
+# natural join of a view and table
+create or replace table t1(a1 int) with system versioning;
+create or replace table t2(a2 int) with system versioning;
+insert into t1 values(1),(2);
+insert into t2 values(1),(2);
+create or replace view v1 as select a1 from t1;
+
+select * from v1 natural join t2;
+select * from v1 natural left join t2;
+select * from v1 natural right join t2;
+
+create or replace table t1 (a int) with system versioning;
+insert into t1 values (1);
+insert into t1 values (2);
+insert into t1 values (3);
+select * from t1 left outer join (t1 as t2 left join t1 as t3 using (a)) on t1.a>1;
+
+create or replace table t1 (x int) with system versioning;
+create or replace table t2 (y int) with system versioning;
+insert into t1 values (1), (2), (3);
+delete from t1 where x = 3;
+insert into t2 values (1);
+select * from t1, t2 for system_time all;
+
+--error ER_VERS_NOT_VERSIONED
+select * from (select * from t1 for system_time all, t2 for system_time all)
+for system_time all as t;
+
+--echo # TRANSACTION/TIMESTAMP specifier in SYSTEM_TIME [MDEV-14645, Issue #396]
+create or replace table t1 (x int) with system versioning engine myisam;
+--error ER_VERS_ENGINE_UNSUPPORTED
+select * from t1 for system_time as of transaction 1;
+
+create or replace table t1 (
+ x int,
+ sys_trx_start bigint unsigned as row start invisible,
+ sys_trx_end bigint unsigned as row end invisible,
+ period for system_time (sys_trx_start, sys_trx_end)
+) with system versioning engine innodb;
+insert into t1 values (1);
+set @ts= now(6);
+delete from t1;
+select sys_trx_start from t1 for system_time all into @trx_start;
+
+--echo ## ensure @trx_start is much lower than unix timestamp
+select @trx_start < unix_timestamp(@ts) - 100 as trx_start_good;
+
+--echo ## TIMESTAMP specifier
+select x from t1 for system_time as of timestamp @ts;
+select x from t1 for system_time as of timestamp unix_timestamp(@ts);
+select x from t1 for system_time as of timestamp @trx_start;
+
+set @ts= timestamp'1-1-1 0:0:0';
+
+--echo ## TRANSACTION specifier
+select x from t1 for system_time as of transaction @ts;
+select x from t1 for system_time as of transaction unix_timestamp(@ts);
+select x from t1 for system_time as of transaction @trx_start;
+
+--echo ## no specifier (auto-detection)
+select x from t1 for system_time as of @ts;
+select x from t1 for system_time as of unix_timestamp(@ts);
+select x from t1 for system_time as of @trx_start;
+
+
+--echo ### Issue #365, bug 4 (related to #226, optimized fields)
+create or replace table t1 (i int, b int) with system versioning;
+insert into t1 values (0, 0), (0, 0);
+select min(i) over (partition by b) as f
+from (select i + 0 as i, b from t1) as tt
+order by i;
+
+--echo ### Issue #365, bug 5 (dangling AND)
+create or replace table t1 (a int);
+create or replace table t2 (b int) with system versioning;
+select * from t1
+where exists (select 1 from t2 where t2.b = t1.a and t2.b = t1.a);
+
+--echo ### Issue #365, bug 9 (not a derived subquery)
+create or replace table t1 (x int) with system versioning;
+select t1.x in (select x from t1) a from t1, (select x from t1) b;
+
+--echo ### Issue #365, bug 10 (WHERE cond freed prematurely for PS)
+create or replace table t1 (x int) with system versioning;
+insert into t1 values (1);
+create or replace view v1 as select x from t1 where x = 1;
+prepare stmt from "
+select x from t1 where x in (select x from v1);";
+execute stmt;
+execute stmt;
+
+--echo ### Issue #365, bug 11 (WHERE cond not top level item)
+create or replace table t1 (a int, b int, key idx(a)) with system versioning;
+insert into t1 values (1, 1), (2, 2);
+select * from t1 where (a, 2) in ((1, 1), (2, 2)) and b = 1;
+
+--echo ### Issue #398, NOW is now non-magic
+create or replace table t1 (x int) with system versioning;
+select * from t1 for system_time as of current_timestamp;
+--error ER_BAD_FIELD_ERROR
+select * from t1 for system_time as of now;
+
+--echo ### Issue #405, NATURAL JOIN failure
+create or replace table t1 (a int) with system versioning;
+create or replace table t2 (b int);
+create or replace view v1 as select a, row_start, row_end from t1 where a > round(rand()*1000);
+select * from v1 natural join t2;
+
+--echo ### Issue #406, MDEV-14633 Assertion on TRT read
+create or replace table t1 (pk int primary key, i int, t time, key (i)) with system versioning;
+insert into t1 values (1, 10, '15:01:53'), (2, 20, '00:00:00');
+delete from t1;
+--disable_warnings
+select * from t1 where t = '00:00:00' and i > 0 and row_end <> '2012-12-12 00:00:00';
+--enable_warnings
+
+--echo ### MDEV-14816 Assertion `join->best_read < double(1.797...e+308L)' failed in bool greedy_search
+create or replace table t1 (f1 int) with system versioning;
+create or replace table t2 (f2 int) with system versioning;
+create or replace table t3 (f3 int);
+create or replace table t4 (f4 int);
+insert into t1 values (1), (2), (3), (4);
+insert into t2 values (1), (2), (3);
+insert into t3 values (1), (2);
+insert into t4 values (1);
+select * from
+ t1 as t1a
+ left join t2 as t2a left join (t3 as t3a inner join t1) on t2a.f2 = t3a.f3 on t1a.f1 = t2a.f2
+ left join (t2 join t3 inner join t4) on t2a.f2 = t1a.f1;
+
+
+drop view v1;
+drop table t1, t2, t3, t4;
+
+call verify_vtq_dummy(34);
+
+-- source suite/versioning/common_finish.inc
diff --git a/mysql-test/suite/versioning/t/select2.test b/mysql-test/suite/versioning/t/select2.test
new file mode 100644
index 00000000000..81070a960ee
--- /dev/null
+++ b/mysql-test/suite/versioning/t/select2.test
@@ -0,0 +1,211 @@
+--source suite/versioning/engines.inc
+--source suite/versioning/common.inc
+
+let $engine=`select default_engine()`;
+let $sys_type=`select sys_datatype(default_engine())`;
+
+replace_result $engine ENGINE $sys_type SYS_TYPE;
+eval create table t1(
+ x int unsigned,
+ y int unsigned,
+ sys_start $sys_type as row start invisible,
+ sys_end $sys_type as row end invisible,
+ period for system_time (sys_start, sys_end))
+with system versioning engine=$engine;
+
+insert into t1 (x, y) values
+ (0, 100),
+ (1, 101),
+ (2, 102),
+ (3, 103),
+ (4, 104),
+ (5, 105),
+ (6, 106),
+ (7, 107),
+ (8, 108),
+ (9, 109);
+set @t0= now(6);
+select sys_start from t1 limit 1 into @x0;
+
+delete from t1 where x = 3;
+delete from t1 where x > 7;
+
+insert into t1(x, y) values(3, 33);
+select sys_start from t1 where x = 3 and y = 33 into @t1;
+if(`select '$engine' = 'innodb'`) {
+ set @x1= @t1;
+ select vtq_commit_ts(@x1) into @t1;
+}
+
+select x, y from t1;
+select x as ASOF_x, y from t1 for system_time as of timestamp @t0;
+select x as FROMTO_x, y from t1 for system_time from '0-0-0 0:0:0' to timestamp @t1;
+select x as BETWAND_x, y from t1 for system_time between '0-0-0 0:0:0' and timestamp @t1;
+select x as ALL_x, y from t1 for system_time all;
+
+if(`select '$engine' = 'innodb'`) {
+ select x as ASOF2_x, y from t1 for system_time as of @x0;
+ select x as FROMTO2_x, y from t1 for system_time from @x0 to @x1;
+ select x as BETWAND2_x, y from t1 for system_time between transaction @x0 and transaction @x1;
+}
+if(`select '$engine' != 'innodb'`) {
+ select x as ASOF2_x, y from t1 for system_time as of @t0;
+ select x as FROMTO2_x, y from t1 for system_time from '0-0-0 0:0:0' to @t1;
+ select x as BETWAND2_x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp @t1;
+}
+
+drop table t1;
+
+replace_result $engine ENGINE $sys_type SYS_TYPE;
+eval create table t1(
+ x int,
+ y int,
+ sys_start $sys_type as row start invisible,
+ sys_end $sys_type as row end invisible,
+ period for system_time (sys_start, sys_end))
+with system versioning engine=$engine;
+
+create table t2 like t1;
+
+insert into t1 values (1, 1), (1, 2), (1, 3), (4, 4), (5, 5);
+insert into t2 values (1, 2), (2, 1), (3, 1);
+set @t0= now(6);
+
+select t1.x as IJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 inner join t2 on t1.x = t2.x;
+select t1.x as LJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 left join t2 on t1.x = t2.x;
+select t1.x as RJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 right join t2 on t1.x = t2.x;
+
+delete from t1;
+delete from t2;
+
+select IJ2_x1,y1,x2,y2 from (select t1.x as IJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 inner join t2 on t1.x = t2.x)
+for system_time as of timestamp @t0 as t;
+select LJ2_x1,y1,x2,y2 from (select t1.x as LJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 left join t2 on t1.x = t2.x)
+for system_time as of timestamp @t0 as t;
+select RJ2_x1,y1,x2,y2 from (select t1.x as RJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 from t1 right join t2 on t1.x = t2.x)
+for system_time as of timestamp @t0 as t;
+
+drop table t1;
+drop table t2;
+
+--echo # MDEV-14686 Server crashes in Item_field::used_tables on 2nd call of SP [#422]
+create or replace table t1 (called int, bad int) with system versioning;
+create or replace procedure bad() select * from t1 where bad in (select called from t1);
+--disable_query_log
+call bad; call bad; call bad; call bad; call bad; call bad; call bad; call bad;
+drop procedure bad;
+--enable_query_log
+--echo # bad() is good.
+
+--echo # MDEV-14751 Server crashes in TABLE::versioned on 2nd execution of SP [#431]
+create or replace table t1 (called_bad int);
+create or replace table t2 (b int);
+create or replace procedure bad() select * from t1 where ( 5, 6 ) in ( select b, b from t2 ) and called_bad in ( select max(b) from t2 );
+--disable_query_log
+call bad; call bad; call bad; call bad; call bad; call bad; call bad; call bad;
+drop procedure bad;
+--enable_query_log
+--echo # bad() is good.
+
+--echo # MDEV-14786 Server crashes in Item_cond::transform on 2nd execution of SP querying from a view [#436]
+create or replace table t1 (called_bad int) with system versioning;
+create or replace view v1 as select called_bad from t1 where called_bad < 5;
+create or replace procedure bad() select called_bad from v1;
+--disable_query_log
+call bad; call bad; call bad; call bad; call bad; call bad; call bad; call bad;
+drop procedure bad;
+--enable_query_log
+--echo # bad() is good.
+
+--echo # wildcard expansion on hidden fields.
+create or replace table t1(
+ A int
+) with system versioning;
+insert into t1 values(1);
+select * from t1;
+
+create or replace table t1 (x int);
+insert into t1 values (1);
+--error ER_VERS_NOT_VERSIONED
+select * from t1 for system_time all;
+
+create or replace table t1 (x int) with system versioning;
+insert into t1 values (1);
+select * from t1 for system_time as of now() for update;
+
+create or replace table t1 (a int not null auto_increment primary key) with system versioning;
+select * from (t1 as t2 left join t1 as t3 using (a)) natural left join t1;
+
+create or replace table t1 (a int) with system versioning;
+create or replace table t2 (a int) with system versioning;
+insert into t1 values(1);
+insert into t2 values(1);
+create or replace view v1 as select * from t2 inner join t1 using (a);
+select * from v1;
+drop view v1;
+
+create or replace table t1 (a int) with system versioning;
+insert into t1 values (1);
+create view vt1 as select a from t1;
+select * from t1 natural join vt1;
+drop view vt1;
+
+create or replace table t1(x int) with system versioning;
+select * from (t1 as r left join t1 as u using (x)), t1;
+
+# @end should be max
+create or replace table t1 (a int) with system versioning;
+insert into t1 values (1);
+create trigger read_end after update on t1
+ for each row set @end = old.row_end;
+update t1 set a=2;
+--replace_result 18446744073709551615 MAX_RESULT "2038-01-19 03:14:07.999999" MAX_RESULT
+select @end;
+
+create or replace table t1 (a int) with system versioning;
+create or replace table t2 (b int) with system versioning;
+insert into t1 values (1);
+insert into t2 values (2);
+select * from (select * from t1 cross join t2) as tmp;
+select * from (select * from (select * from t1 cross join t2) as tmp1) as tmp2;
+select * from (select * from t1 cross join t2 for system_time as of timestamp '0-0-0') as tmp;
+
+create or replace table t1(a1 int) with system versioning;
+create or replace table t2(a2 int) with system versioning;
+insert into t1 values(1),(2);
+insert into t2 values(1),(2);
+select * from t1 for system_time all natural left join t2 for system_time all;
+
+# natural join of a view and table
+create or replace table t1(a1 int) with system versioning;
+create or replace table t2(a2 int) with system versioning;
+insert into t1 values(1),(2);
+insert into t2 values(1),(2);
+create or replace view v1 as select a1 from t1;
+
+select * from v1 natural join t2;
+select * from v1 natural left join t2;
+select * from v1 natural right join t2;
+
+create or replace table t1 (a int) with system versioning;
+insert into t1 values (1);
+insert into t1 values (2);
+insert into t1 values (3);
+select * from t1 left outer join (t1 as t2 left join t1 as t3 using (a)) on t1.a>1;
+
+create or replace table t1 (x int) with system versioning;
+create or replace table t2 (y int) with system versioning;
+insert into t1 values (1), (2), (3);
+delete from t1 where x = 3;
+insert into t2 values (1);
+select * from t1, t2 for system_time all;
+
+--error ER_VERS_NOT_VERSIONED
+select * from (select * from t1 for system_time all, t2 for system_time all) for system_time all as t;
+--error ER_PARSE_ERROR
+select * from (t1 for system_time all join t2 for system_time all) for system_time all;
+
+drop view v1;
+drop table t1, t2;
+
+-- source suite/versioning/common_finish.inc
diff --git a/mysql-test/suite/versioning/t/simple.test b/mysql-test/suite/versioning/t/simple.test
new file mode 100644
index 00000000000..3790f0b8978
--- /dev/null
+++ b/mysql-test/suite/versioning/t/simple.test
@@ -0,0 +1,73 @@
+-- source include/have_innodb.inc
+set default_storage_engine=innodb;
+create or replace table dept (
+ dept_id int(10) primary key,
+ name varchar(100)
+)
+with system versioning;
+
+create or replace table emp (
+ emp_id int(10) primary key,
+ dept_id int(10),
+ name varchar(100),
+ salary int(10),
+ constraint `dept-emp-fk`
+ foreign key (dept_id) references dept (dept_id)
+ on delete cascade
+ on update restrict
+)
+with system versioning;
+
+select now() into @ts_0;
+
+insert into dept (dept_id, name) values (10, "accounting");
+commit;
+
+select row_start into @ts_1 from dept where dept_id=10;
+
+insert into emp (emp_id, name, salary, dept_id) values (1, "bill", 1000, 10);
+commit;
+
+select row_start into @ts_2 from emp where name="bill";
+
+select * from emp;
+
+update emp set salary=2000 where name="bill";
+commit;
+
+select row_start into @ts_3 from emp where name="bill";
+
+select * from emp;
+select * from emp for system_time as of timestamp @ts_2;
+select * from emp for system_time as of timestamp @ts_3;
+select * from emp e, dept d
+where d.dept_id = 10
+ and d.dept_id = e.dept_id;
+
+select * from
+ emp for system_time from timestamp @ts_1 to timestamp @ts_2 e,
+ dept for system_time from timestamp @ts_1 to timestamp @ts_2 d
+where d.dept_id = 10
+ and d.dept_id = e.dept_id;
+
+set statement system_versioning_asof=@ts_0 for
+select * from emp e, dept d
+where d.dept_id = 10
+ and d.dept_id = e.dept_id;
+
+set statement system_versioning_asof=@ts_1 for
+select * from emp e, dept d
+where d.dept_id = 10
+ and d.dept_id = e.dept_id;
+
+set statement system_versioning_asof=@ts_2 for
+select * from emp e, dept d
+where d.dept_id = 10
+ and d.dept_id = e.dept_id;
+
+set statement system_versioning_asof=@ts_3 for
+select * from emp e, dept d
+where d.dept_id = 10
+ and d.dept_id = e.dept_id;
+
+drop table emp, dept;
diff --git a/mysql-test/suite/versioning/t/sysvars.test b/mysql-test/suite/versioning/t/sysvars.test
new file mode 100644
index 00000000000..08b520e959e
--- /dev/null
+++ b/mysql-test/suite/versioning/t/sysvars.test
@@ -0,0 +1,87 @@
+create table t (a int) with system versioning;
+insert into t values (1);
+update t set a= 2;
+
+show global variables like 'system_versioning_asof';
+show variables like 'system_versioning_asof';
+select * from t;
+
+set system_versioning_asof= '2031-1-1 0:0:0';
+show variables like 'system_versioning_asof';
+select * from t;
+
+set system_versioning_asof= '2011-1-1 0:0:0';
+show variables like 'system_versioning_asof';
+select * from t;
+
+# global
+--error ER_WRONG_VALUE_FOR_VAR
+set global system_versioning_asof= 'alley';
+--error ER_WRONG_VALUE_FOR_VAR
+set global system_versioning_asof= null;
+--error ER_WRONG_TYPE_FOR_VAR
+set global system_versioning_asof= 1;
+--error ER_WRONG_TYPE_FOR_VAR
+set global system_versioning_asof= 1.1;
+
+# session
+--error ER_WRONG_VALUE_FOR_VAR
+set system_versioning_asof= 'alley';
+--error ER_WRONG_VALUE_FOR_VAR
+set system_versioning_asof= null;
+--error ER_WRONG_TYPE_FOR_VAR
+set system_versioning_asof= 1;
+--error ER_WRONG_TYPE_FOR_VAR
+set system_versioning_asof= 1.1;
+
+--echo # GLOBAL @@system_versioning_asof
+set global system_versioning_asof= '1911-11-11 11:11:11.1111119';
+show global variables like 'system_versioning_asof';
+
+set global system_versioning_asof= '1900-01-01 00:00:00';
+show global variables like 'system_versioning_asof';
+
+set global system_versioning_asof= timestamp'1911-11-11 11:11:11.1111119';
+show global variables like 'system_versioning_asof';
+
+set @ts= timestamp'1900-01-01 00:00:00';
+set global system_versioning_asof= @ts;
+show global variables like 'system_versioning_asof';
+
+set global system_versioning_asof= default;
+select @@global.system_versioning_asof;
+
+--echo # SESSION @@system_versioning_asof
+set system_versioning_asof= '1911-11-11 11:11:11.1111119';
+show variables like 'system_versioning_asof';
+
+set system_versioning_asof= '1900-01-01 00:00:00';
+show variables like 'system_versioning_asof';
+
+set system_versioning_asof= timestamp'1911-11-11 11:11:11.1111119';
+show variables like 'system_versioning_asof';
+
+set @ts= timestamp'1900-01-01 00:00:00';
+set system_versioning_asof= @ts;
+show variables like 'system_versioning_asof';
+
+--echo # DEFAULT: value is copied from GLOBAL to SESSION
+set global system_versioning_asof= timestamp'1911-11-11 11:11:11.111111';
+set system_versioning_asof= '1900-01-01 00:00:00';
+select @@global.system_versioning_asof != @@system_versioning_asof as different;
+set system_versioning_asof= default;
+select @@global.system_versioning_asof = @@system_versioning_asof as equal;
+
+set global system_versioning_asof= DEFAULT;
+set system_versioning_asof= DEFAULT;
+select @@global.system_versioning_asof, @@system_versioning_asof;
+
+select * from t for system_time all;
+
+select * from t;
+select * from t for system_time as of timestamp current_timestamp(6);
+select * from t for system_time all;
+select * from t for system_time from '0-0-0' to current_timestamp(6);
+select * from t for system_time between '0-0-0' and current_timestamp(6);
+
+drop table t;
diff --git a/mysql-test/suite/versioning/t/truncate.opt b/mysql-test/suite/versioning/t/truncate.opt
new file mode 100644
index 00000000000..b0c5b9c8188
--- /dev/null
+++ b/mysql-test/suite/versioning/t/truncate.opt
@@ -0,0 +1 @@
+--partition
diff --git a/mysql-test/suite/versioning/t/truncate.test b/mysql-test/suite/versioning/t/truncate.test
new file mode 100644
index 00000000000..0f9e7052511
--- /dev/null
+++ b/mysql-test/suite/versioning/t/truncate.test
@@ -0,0 +1,72 @@
+--source suite/versioning/engines.inc
+
+create table t (a int);
+--error ER_VERS_NOT_VERSIONED
+delete history from t before system_time now();
+
+# TRUNCATE is not DELETE and trigger must not be called.
+create or replace table t (a int) with system versioning;
+insert into t values (1);
+update t set a=2;
+set @test = 'correct';
+create trigger trg_before before delete on t for each row set @test = 'incorrect';
+create trigger trg_after after delete on t for each row set @test = 'incorrect';
+delete history from t;
+select @test from t;
+drop table t;
+
+create table t (a int) with system versioning;
+insert into t values (1), (2);
+update t set a=11 where a=1;
+--real_sleep 0.01
+set @ts1=now(6);
+--real_sleep 0.01
+update t set a=22 where a=2;
+select * from t for system_time all;
+delete history from t before system_time timestamp @ts1;
+select * from t for system_time all;
+prepare stmt from 'delete history from t';
+execute stmt; drop prepare stmt;
+select * from t for system_time all;
+delete from t;
+
+delimiter ~~;
+create or replace procedure truncate_sp()
+begin
+ delete history from t before system_time timestamp now(6);
+end~~
+delimiter ;~~
+call truncate_sp;
+select * from t for system_time all;
+
+drop procedure truncate_sp;
+
+--echo ### Issue #399, truncate partitioned table is now unimplemented
+
+create or replace table t (a int)
+with system versioning
+engine myisam
+partition by system_time (
+ partition p0 history,
+ partition pn current);
+
+--error ER_NOT_ALLOWED_COMMAND
+delete history from t;
+
+create or replace table t (i int) with system versioning;
+delete history from t;
+create or replace view v as select * from t;
+--error ER_VERS_TRUNCATE_VIEW
+delete history from v;
+
+create or replace table t (i int);
+--error ER_VERS_NOT_VERSIONED
+delete history from t;
+create or replace view v as select * from t;
+--error ER_VERS_TRUNCATE_VIEW
+delete history from v;
+--error ER_VERS_NOT_VERSIONED
+prepare stmt from 'delete history from t';
+
+drop table t;
+drop view v;
diff --git a/mysql-test/suite/versioning/t/truncate_privilege.test b/mysql-test/suite/versioning/t/truncate_privilege.test
new file mode 100644
index 00000000000..dcdad59039a
--- /dev/null
+++ b/mysql-test/suite/versioning/t/truncate_privilege.test
@@ -0,0 +1,41 @@
+# Can't test with embedded server
+-- source include/not_embedded.inc
+
+--source include/have_innodb.inc
+
+# Save the initial number of concurrent sessions
+--source include/count_sessions.inc
+
+connect (root,localhost,root,,test);
+connection root;
+
+--disable_warnings
+create database mysqltest;
+--enable_warnings
+
+create user mysqltest_1@localhost;
+connect (user1,localhost,mysqltest_1,,test);
+connection user1;
+
+connection root;
+create table mysqltest.t (a int) with system versioning;
+
+connection user1;
+show grants;
+--error ER_TABLEACCESS_DENIED_ERROR
+delete history from mysqltest.t before system_time now();
+
+connection root;
+grant delete history on mysqltest.* to mysqltest_1@localhost;
+grant delete history on mysqltest.t to mysqltest_1@localhost;
+
+connection user1;
+show grants;
+delete history from mysqltest.t before system_time now();
+
+connection root;
+grant all on *.* to mysqltest_1@localhost;
+show grants for mysqltest_1@localhost;
+
+drop user mysqltest_1@localhost;
+drop database mysqltest;
diff --git a/mysql-test/suite/versioning/t/trx_id.test b/mysql-test/suite/versioning/t/trx_id.test
new file mode 100644
index 00000000000..ee4e927b506
--- /dev/null
+++ b/mysql-test/suite/versioning/t/trx_id.test
@@ -0,0 +1,75 @@
+-- source include/have_innodb.inc
+-- source include/not_embedded.inc
+
+create or replace table t1 (
+ x int,
+ sys_trx_start bigint(20) unsigned as row start invisible,
+ sys_trx_end bigint(20) unsigned as row end invisible,
+ period for system_time (sys_trx_start, sys_trx_end)
+) with system versioning engine innodb;
+
+insert into t1 (x) values (1);
+
+--echo # ALTER ADD SYSTEM VERSIONING should write to mysql.transaction_registry
+create function check_result (cond boolean)
+ returns char(50) deterministic
+ return if(cond = 1, '[CORRECT]', '[INCORRECT]');
+
+set @@system_versioning_alter_history=keep;
+
+create or replace table t1 (x int) engine innodb;
+insert into t1 values (1);
+alter table t1
+ add column s bigint unsigned as row start,
+ add column e bigint unsigned as row end,
+ add period for system_time(s, e),
+ add system versioning,
+ algorithm=inplace;
+select s from t1 into @trx_start;
+select check_result(count(*) = 1) from mysql.transaction_registry where transaction_id = @trx_start;
+
+create or replace table t1 (x int) engine innodb;
+select count(*) from mysql.transaction_registry into @tmp;
+alter table t1
+ add column s bigint unsigned as row start,
+ add column e bigint unsigned as row end,
+ add period for system_time(s, e),
+ add system versioning,
+ algorithm=inplace;
+select check_result(count(*) = @tmp) from mysql.transaction_registry;
+
+create or replace table t1 (x int) engine innodb;
+insert into t1 values (1);
+alter table t1
+ add column s bigint unsigned as row start,
+ add column e bigint unsigned as row end,
+ add period for system_time(s, e),
+ add system versioning,
+ algorithm=copy;
+select s from t1 into @trx_start;
+select check_result(count(*) = 1) from mysql.transaction_registry where transaction_id = @trx_start;
+
+create or replace table t1 (x int) engine innodb;
+select count(*) from mysql.transaction_registry into @tmp;
+alter table t1
+ add column s bigint unsigned as row start,
+ add column e bigint unsigned as row end,
+ add period for system_time(s, e),
+ add system versioning,
+ algorithm=copy;
+select check_result(count(*) = @tmp) from mysql.transaction_registry;
+
+
+--echo # TRX_ID to TIMESTAMP versioning switch
+create or replace table t1 (
+ x int,
+ sys_start bigint unsigned as row start invisible,
+ sys_end bigint unsigned as row end invisible,
+ period for system_time (sys_start, sys_end)
+) engine innodb with system versioning;
+insert into t1 values (1);
+alter table t1 drop column sys_start, drop column sys_end;
+select sys_end = 18446744073709551615 as transaction_based from t1 for system_time all;
+
+drop table t1;
+drop function check_result;
diff --git a/mysql-test/suite/versioning/t/update.test b/mysql-test/suite/versioning/t/update.test
new file mode 100644
index 00000000000..60f20705276
--- /dev/null
+++ b/mysql-test/suite/versioning/t/update.test
@@ -0,0 +1,288 @@
+-- source suite/versioning/common.inc
+
+delimiter ~~;
+create procedure test_01(
+ sys_type varchar(255),
+ engine varchar(255),
+ fields varchar(255))
+begin
+ set @str= concat('
+ create table t1(
+ x int unsigned,
+ y int unsigned,
+ sys_trx_start ', sys_type, ' as row start invisible,
+ sys_trx_end ', sys_type, ' as row end invisible,
+ period for system_time (sys_trx_start, sys_trx_end))
+ with system versioning
+ engine ', engine);
+ prepare stmt from @str; execute stmt; drop prepare stmt;
+ insert into t1(x, y) values
+ (1, 1000),
+ (2, 2000),
+ (3, 3000),
+ (4, 4000),
+ (5, 5000),
+ (6, 6000),
+ (7, 7000),
+ (8, 8000),
+ (9, 9000);
+ select x, y from t1;
+ update t1 set y = y + 1 where x > 7;
+ select x, y from t1;
+ select x, y from t1 for system_time
+ between timestamp '0000-0-0 0:0:0'
+ and timestamp '2038-01-19 04:14:07';
+ drop table t1;
+end~~
+
+create procedure test_02(
+ sys_type varchar(255),
+ engine varchar(255),
+ fields varchar(255))
+begin
+ set @str= concat('
+ create table t1 (
+ id bigint primary key,
+ x int,
+ y int without system versioning,
+ sys_trx_start ', sys_type, ' as row start invisible,
+ sys_trx_end ', sys_type, ' as row end invisible,
+ period for system_time (sys_trx_start, sys_trx_end))
+ with system versioning
+ engine ', engine);
+ prepare stmt from @str; execute stmt; drop prepare stmt;
+ insert into t1 values(1, 1, 1);
+ set @ins_t= now(6);
+ select sys_trx_start into @tmp1 from t1;
+ update t1 set x= 11, y= 11 where id = 1;
+ select @tmp1 < sys_trx_start as A1, x, y from t1;
+
+ select sys_trx_start into @tmp1 from t1;
+ update t1 set y= 1 where id = 1;
+ select @tmp1 = sys_trx_start as A2, x from t1;
+
+ drop table t1;
+end~~
+
+create procedure test_03(
+ sys_type varchar(255),
+ engine varchar(255),
+ fields varchar(255))
+begin
+ set @str= concat('
+ create table t1 (
+ x int,
+ y int,
+ sys_trx_start bigint unsigned as row start invisible,
+ sys_trx_end bigint unsigned as row end invisible,
+ period for system_time (sys_trx_start, sys_trx_end)
+ ) with system versioning
+ engine ', engine);
+ prepare stmt from @str; execute stmt; drop prepare stmt;
+
+ insert into t1 (x, y) values (1, 1), (2, 1), (3, 1), (4, 1), (5, 1);
+
+ start transaction;
+ update t1 set y= y + 1 where x = 3;
+ update t1 set y= y + 1 where x = 2;
+ update t1 set y= y + 1 where x = 3;
+ update t1 set y= y + 1 where x > 3;
+ update t1 set y= y + 1 where x > 4;
+ commit;
+
+ select x, y, sys_trx_end = 18446744073709551615 as current from t1 for system_time all;
+
+ drop table t1;
+end~~
+
+create procedure test_04(
+ sys_type varchar(255),
+ engine varchar(255),
+ fields varchar(255))
+begin
+ set @str= concat('
+ create table t1 (
+ id int primary key auto_increment,
+ x int,
+ sys_trx_start ', sys_type, ' as row start invisible,
+ sys_trx_end ', sys_type, ' as row end invisible,
+ period for system_time (sys_trx_start, sys_trx_end))
+ with system versioning
+ engine ', engine);
+ prepare stmt from @str; execute stmt; drop prepare stmt;
+
+ set @t0= now(6);
+ insert into t1 (x) values (1);
+ set @t1= now(6);
+ update t1 set x= 2 where id = 1;
+ set @t2= now(6);
+ update t1 set x= 3 where id = 1;
+
+ select x from t1 for system_time as of timestamp @t0;
+ select x from t1 for system_time as of timestamp @t1;
+ select x from t1 for system_time as of timestamp @t2;
+ select x from t1 for system_time as of timestamp now(6);
+
+ drop table t1;
+end~~
+
+create procedure test_05(
+ sys_type varchar(255),
+ engine varchar(255),
+ fields varchar(255))
+begin
+ set @str= concat('
+ create table t1(
+ x int unsigned,
+ sys_trx_end ', sys_type, ' as row end invisible,
+ sys_trx_start ', sys_type, ' as row start invisible,
+ y int unsigned,
+ period for system_time (sys_trx_start, sys_trx_end),
+ primary key(x, y))
+ with system versioning
+ engine ', engine);
+ prepare stmt from @str; execute stmt; drop prepare stmt;
+ insert into t1(x, y) values
+ (1, 1000),
+ (3, 3000),
+ (4, 4000),
+ (5, 5000);
+ insert into t1(x, y) values(3, 3000) on duplicate key update y = y+1;
+ insert into t1(x, y) values(4, 4444) on duplicate key update y = y+1;
+ select x, y from t1 for system_time all;
+ select x, y from t1;
+ drop table t1;
+end~~
+
+create procedure test_06(
+ sys_type varchar(255),
+ engine varchar(255),
+ fields varchar(255))
+begin
+ set @str= concat('(
+ x int unsigned,
+ y int unsigned,
+ sys_trx_start ', sys_type, ' as row start invisible,
+ sys_trx_end ', sys_type, ' as row end invisible,
+ period for system_time (sys_trx_start, sys_trx_end))
+ with system versioning
+ engine ', engine);
+ set @str2= concat('create table t1', @str);
+ prepare stmt from @str2; execute stmt; drop prepare stmt;
+ set @str2= concat('create table t2', @str);
+ prepare stmt from @str2; execute stmt; drop prepare stmt;
+ insert into t1(x, y) values
+ (1, 1000),
+ (2, 2000),
+ (3, 3000),
+ (4, 4000),
+ (5, 5000),
+ (6, 6000),
+ (7, 7000),
+ (8, 8000),
+ (9, 9000);
+ insert into t2(x, y) values
+ (1, 1010),
+ (2, 2010),
+ (3, 3010),
+ (4, 4010),
+ (5, 5010),
+ (6, 6010),
+ (7, 7010),
+ (8, 8010),
+ (9, 9010);
+ update t1, t2 set t1.y = t1.x + t1.y, t2.y = t2.x + t2.y where t1.x > 7 and t2.x < 7;
+ select x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp '9999-1-1 0:0:0';
+ select x, y from t1;
+ select x, y from t2 for system_time between timestamp '0-0-0 0:0:0' and timestamp '9999-1-1 0:0:0';
+ select x, y from t2;
+ drop table t1;
+ drop table t2;
+end~~
+
+create procedure test_07(
+ sys_type varchar(255),
+ engine varchar(255),
+ fields varchar(255))
+begin
+ set @str= concat('(
+ id bigint primary key without system versioning,
+ name varchar(128),
+ salary bigint without system versioning,
+ sys_trx_start ', sys_type, ' as row start invisible,
+ sys_trx_end ', sys_type, ' as row end invisible,
+ period for system_time (sys_trx_start, sys_trx_end))
+ with system versioning
+ engine ', engine);
+
+ set @str2= concat('create table t1', @str);
+ prepare stmt from @str2; execute stmt; drop prepare stmt;
+ set @str2= concat('create table t2', @str);
+ prepare stmt from @str2; execute stmt; drop prepare stmt;
+
+ insert into t1 values (1, "Jeremy", 3000);
+ insert into t2 values (1, "Jeremy", 4000);
+
+ select sys_trx_start into @tmp1 from t1;
+ select sys_trx_start into @tmp2 from t2;
+ update t1, t2 set t1.name= "Jerry", t2.name= "Jerry" where t1.id = t2.id and t1.name = "Jeremy";
+ select @tmp1 < sys_trx_start as A1, name from t1;
+ select @tmp2 < sys_trx_start as A2, name from t2;
+
+ select sys_trx_start into @tmp1 from t1;
+ select sys_trx_start into @tmp2 from t2;
+ update t1, t2 set t1.salary= 2500, t2.salary= 2500 where t1.id = t2.id and t1.name = "Jerry";
+ select @tmp1 = sys_trx_start as B1, salary from t1;
+ select @tmp2 = sys_trx_start as B2, salary from t2;
+
+ drop table t1;
+ drop table t2;
+end~~
+delimiter ;~~
+
+call test_01('timestamp(6)', 'myisam', 'sys_trx_end');
+call test_01('timestamp(6)', 'innodb', 'vtq_commit_ts(sys_trx_end)');
+call test_01('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_trx_end)');
+call verify_vtq;
+
+call test_02('timestamp(6)', 'myisam', 'sys_trx_end');
+call test_02('timestamp(6)', 'innodb', 'vtq_commit_ts(sys_trx_end)');
+call test_02('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_trx_end)');
+call verify_vtq;
+
+--echo # Multiple UPDATE of same rows in single transaction create historical
+--echo # rows only once (applicable to transaction-based only).
+call test_03('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_trx_end)');
+call verify_vtq;
+
+call test_04('timestamp(6)', 'myisam', 'sys_trx_end');
+call test_04('timestamp(6)', 'innodb', 'vtq_commit_ts(sys_trx_end)');
+call test_04('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_trx_end)');
+call verify_vtq;
+
+call test_05('timestamp(6)', 'myisam', 'sys_trx_end');
+call test_05('timestamp(6)', 'innodb', 'vtq_commit_ts(sys_trx_end)');
+call test_05('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_trx_end)');
+call verify_vtq;
+
+call test_06('timestamp(6)', 'myisam', 'sys_trx_end');
+call test_06('timestamp(6)', 'innodb', 'vtq_commit_ts(sys_trx_end)');
+call test_06('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_trx_end)');
+call verify_vtq;
+
+--echo # Optimized fields
+call test_07('timestamp(6)', 'myisam', 'sys_trx_end');
+call test_07('timestamp(6)', 'innodb', 'vtq_commit_ts(sys_trx_end)');
+call test_07('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_trx_end)');
+call verify_vtq;
+
+--echo ### Issue #365, bug 7 (duplicate of historical row)
+create or replace table t1 (a int primary key, b int)
+with system versioning engine myisam;
+insert into t1 (a) values (1);
+--replace_regex /'1-[- .\d:]+'/'1-YYYY-MM-DD hh:mm:ss.uuuuuu'/
+--error ER_DUP_ENTRY
+replace t1 values (1,2),(1,3),(2,4);
+
+drop database test;
+create database test;
diff --git a/mysql-test/suite/versioning/t/view.test b/mysql-test/suite/versioning/t/view.test
new file mode 100644
index 00000000000..56e322477e7
--- /dev/null
+++ b/mysql-test/suite/versioning/t/view.test
@@ -0,0 +1,102 @@
+--source suite/versioning/engines.inc
+--source suite/versioning/common.inc
+
+create or replace table t1 (x int) with system versioning;
+insert into t1 values (1);
+
+select now(6) into @t1;
+update t1 set x= 2;
+
+select now(6) into @t2;
+delete from t1;
+
+set @vt1= concat("create or replace view vt1 as select * from t1 for system_time as of timestamp '", @t1, "'");
+prepare stmt from @vt1; execute stmt; drop prepare stmt;
+
+set @vt2= concat("create or replace view vt2 as select *, row_end from t1 for system_time as of timestamp '", @t2, "'");
+prepare stmt from @vt2; execute stmt; drop prepare stmt;
+
+select * from t1;
+
+create or replace view vt1 as select * from t1;
+--replace_result 18446744073709551615 MAX_RESULT "TIMESTAMP'2038-01-19 03:14:07.999999'" MAX_RESULT
+show create view vt1;
+
+drop view vt1;
+drop view vt2;
+
+create or replace view vt1 as select * from t1 for system_time all;
+select * from vt1;
+prepare stmt from 'select * from vt1'; execute stmt; drop prepare stmt;
+
+set @str= concat('create or replace view vt1 as
+select * from t1 for system_time as of timestamp "', @t1, '"');
+prepare stmt from @str; execute stmt; drop prepare stmt;
+select * from t1 for system_time as of timestamp @t1;
+select * from vt1;
+
+insert into vt1 values (3);
+select * from t1;
+select * from vt1;
+
+create or replace table t1 (x int) with system versioning;
+insert into t1 values (1), (2);
+set @t1=now(6);
+delete from t1 where x=2;
+set @t2=now(6);
+delete from t1 where x=1;
+set @t3=now(6);
+
+set @tmp= concat("create or replace view vt1 as select * from t1 for system_time as of timestamp '", @t1, "'");
+prepare stmt from @tmp; execute stmt; drop prepare stmt;
+
+select * from vt1;
+
+--echo # VIEW with parameters [#151]
+create or replace table t1 (x int) with system versioning;
+create or replace view vt1(c) as select x from t1;
+--replace_result 18446744073709551615 MAX_RESULT "TIMESTAMP'2038-01-19 03:14:07.999999'" MAX_RESULT
+show create view vt1;
+
+--echo # VIEW over JOIN of versioned tables [#153]
+create or replace table t1 (a int) with system versioning;
+create or replace table t2 (b int) with system versioning;
+insert into t1 values (1);
+insert into t2 values (2);
+create or replace view vt12 as select * from t1 cross join t2;
+select * from vt12;
+create or replace view vt12 as select * from t1 for system_time as of timestamp '0-0-0' cross join t2;
+select * from vt12;
+
+--echo # VIEW improvements [#183]
+create or replace table t3 (x int);
+create or replace view vt1 as select * from t1, t2, t3;
+--replace_result 18446744073709551615 MAX_RESULT "TIMESTAMP'2038-01-19 03:14:07.999999'" MAX_RESULT
+show create view vt1;
+create or replace view vt1 as select * from t3, t2, t1;
+--replace_result 18446744073709551615 MAX_RESULT "TIMESTAMP'2038-01-19 03:14:07.999999'" MAX_RESULT
+show create view vt1;
+create or replace view vt1 as select a, t2.row_end as endo from t3, t1, t2;
+--replace_result 18446744073709551615 MAX_RESULT "TIMESTAMP'2038-01-19 03:14:07.999999'" MAX_RESULT
+show create view vt1;
+
+--echo # VIEW over UNION [#269]
+create or replace view vt1 as select * from t1 union select * from t1;
+select * from vt1;
+
+--echo # VIEW over UNION with non-versioned [#393]
+create or replace table t2 (a int);
+create or replace view vt1 as select * from t1 union select * from t2;
+select * from vt1;
+
+--echo # MDEV-14689 crash on second PS execute
+create or replace table t1 (a int);
+create or replace view v1 as select * from t1;
+create or replace table t2 (b int) with system versioning;
+prepare stmt from 'select a from v1 inner join t2 group by a order by a';
+execute stmt;
+execute stmt;
+
+
+drop database test;
+create database test;
diff --git a/mysql-test/suite/versioning/t/vtmd.opt b/mysql-test/suite/versioning/t/vtmd.opt
new file mode 100644
index 00000000000..3596fc4d3bd
--- /dev/null
+++ b/mysql-test/suite/versioning/t/vtmd.opt
@@ -0,0 +1 @@
+--innodb --default-storage-engine=innodb
diff --git a/mysql-test/suite/versioning/t/vtmd.test b/mysql-test/suite/versioning/t/vtmd.test
new file mode 100644
index 00000000000..56bdb3d2546
--- /dev/null
+++ b/mysql-test/suite/versioning/t/vtmd.test
@@ -0,0 +1,204 @@
+-- source include/have_innodb.inc
+delimiter ~~;
+create or replace procedure drop_archives (in vtmd_name varchar(64))
+begin
+ declare archive_name varchar(64);
+ declare cur_done bool default false;
+ declare cur cursor for
+ select cur_tmp.archive_name from cur_tmp;
+ declare continue handler for not found set cur_done = true;
+
+ set @tmp= concat('
+ create or replace temporary table
+ cur_tmp as
+ select vtmd.archive_name from ', vtmd_name, '
+ for system_time all as vtmd
+ where vtmd.archive_name is not null
+ group by vtmd.archive_name');
+ prepare stmt from @tmp; execute stmt; drop prepare stmt;
+
+ open cur;
+ fetch_loop: loop
+ fetch cur into archive_name;
+ if cur_done then
+ leave fetch_loop;
+ end if;
+ set @tmp= concat('drop table ', archive_name);
+ prepare stmt from @tmp; execute stmt; drop prepare stmt;
+ end loop;
+
+ drop table cur_tmp;
+end~~
+delimiter ;~~
+
+delimiter ~~;
+create or replace procedure check_vtmd (in vtmd_name varchar(64))
+begin
+ set @tmp= concat('
+ create or replace temporary table
+ tmp_vtmd with system versioning as
+ select * from ', vtmd_name, '
+ for system_time all as vtmd');
+ prepare stmt from @tmp; execute stmt; drop prepare stmt;
+
+ set @inf= 0xFFFFFFFFFFFFFFFF + 0;
+ set @start= null;
+ select start from tmp_vtmd for system_time all order by start limit 1 into @start;
+ select @start > 0 and @start < @inf;
+ select
+ start >= @start as A_start,
+ (@start:= end) and end = @inf as B_end,
+ name,
+ substr(archive_name, 1, instr(archive_name, '_')) as C_archive_name
+ from tmp_vtmd for system_time all;
+
+ drop table tmp_vtmd;
+end~~
+delimiter ;~~
+
+delimiter ~~;
+create or replace procedure show_tables()
+begin
+ show tables;
+ select table_name, table_schema from information_schema.tables
+ where table_schema not in ('mysql', 'performance_schema', 'information_schema', 'mtr')
+ order by table_name;
+end~~
+delimiter ;~~
+
+# create
+set versioning_alter_history= keep;
+create table t0 (z int) with system versioning;
+show tables;
+set versioning_alter_history= survive;
+create or replace table t0 (y int) with system versioning;
+show tables;
+show create table t0_vtmd;
+call check_vtmd('t0_vtmd');
+
+set versioning_alter_history= keep;
+drop table t0;
+set versioning_alter_history= survive;
+--error ER_VERS_VTMD_ERROR
+create table t0 (x int) with system versioning;
+
+drop table t0_vtmd;
+create table t0 (y int) with system versioning;
+create or replace table t0 (x int) with system versioning;
+
+# alter
+insert into t0 values (1);
+set @t0= now(6);
+alter table t0 add column (y int);
+select * from t0 for system_time as of @t0;
+select * from t0;
+call check_vtmd('t0_vtmd');
+
+call drop_archives('t0_vtmd');
+drop table t0_vtmd;
+alter table t0 drop column y;
+call check_vtmd('t0_vtmd');
+
+call drop_archives('t0_vtmd');
+set versioning_alter_history= keep;
+drop tables t0, t0_vtmd;
+set versioning_alter_history= survive;
+
+# rename
+set versioning_alter_history= keep;
+create or replace table x0 (x int) with system versioning;
+set versioning_alter_history= survive;
+rename table x0 to d0;
+show tables;
+
+set versioning_alter_history= keep;
+drop table d0;
+set versioning_alter_history= survive;
+create or replace table x0 (x int) with system versioning;
+rename table x0 to d0;
+show tables;
+call check_vtmd('d0_vtmd');
+
+set versioning_alter_history= keep;
+drop table d0;
+set versioning_alter_history= survive;
+create or replace table x0 (x int) with system versioning;
+
+--error ER_VERS_VTMD_ERROR
+rename table x0 to d0;
+show tables;
+
+drop table x0_vtmd;
+rename table x0 to d0;
+show tables;
+
+rename table d0 to duck;
+rename table duck to bay;
+rename table bay to sheer;
+rename table sheer to t0;
+call check_vtmd('t0_vtmd');
+
+alter table t0 add column (y int);
+call check_vtmd('t0_vtmd');
+
+# rename to different schema
+alter table t0 add column (z int);
+alter table t0 drop column y;
+alter table t0 drop column z;
+
+create database db0;
+rename table t0 to db0.t0;
+show tables;
+use db0;
+show tables;
+call test.check_vtmd('db0.t0_vtmd');
+
+create database db1;
+rename table t0 to db1.other_name;
+show tables;
+use db1;
+show tables;
+call test.check_vtmd('db1.other_name_vtmd');
+
+# alter rename
+alter table other_name rename to t1;
+call test.check_vtmd('db1.t1_vtmd');
+
+# alter rename and modify to different schema
+alter table t1 rename to test.t2, add column (y int);
+use test;
+show tables;
+call check_vtmd('t2_vtmd');
+
+create or replace table t3 (x int) with system versioning;
+alter table t3 change x x bigint;
+alter table t3 change x x bigint after sys_trx_start;
+call check_vtmd('t3_vtmd');
+
+# hide archive tables
+set versioning_hide= auto;
+call show_tables();
+
+set versioning_hide= implicit;
+call show_tables();
+
+set versioning_hide= full;
+call show_tables();
+
+set versioning_hide= never;
+--replace_regex /\d{8}_\d{6}_\d{6}/TIMESTAMP_SUFFIX/
+call show_tables();
+
+# wrong VTMD handling
+set versioning_hide= auto;
+create or replace table u0_vtmd (x int) with system versioning;
+show tables;
+
+set versioning_alter_history= survive;
+create or replace table t (x int) with system versioning;
+select * from t for system_time all;
+
+drop database db0;
+drop database db1;
+drop database test;
+create database test;
diff --git a/mysql-test/suite/versioning/t/vtmd_show.opt b/mysql-test/suite/versioning/t/vtmd_show.opt
new file mode 100644
index 00000000000..627becdbfb5
--- /dev/null
+++ b/mysql-test/suite/versioning/t/vtmd_show.opt
@@ -0,0 +1 @@
+--innodb
diff --git a/mysql-test/suite/versioning/t/vtmd_show.test b/mysql-test/suite/versioning/t/vtmd_show.test
new file mode 100644
index 00000000000..4397198c839
--- /dev/null
+++ b/mysql-test/suite/versioning/t/vtmd_show.test
@@ -0,0 +1,90 @@
+delimiter ~~;
+create or replace procedure drop_archives (in vtmd_name varchar(64))
+begin
+ declare archive_name varchar(64);
+ declare cur_done bool default false;
+ declare cur cursor for
+ select cur_tmp.archive_name from cur_tmp;
+ declare continue handler for not found set cur_done = true;
+
+ set @tmp= concat('
+ create or replace temporary table
+ cur_tmp as
+ select vtmd.archive_name from ', vtmd_name, '
+ for system_time all as vtmd
+ where vtmd.archive_name is not null
+ group by vtmd.archive_name');
+ prepare stmt from @tmp; execute stmt; drop prepare stmt;
+
+ open cur;
+ fetch_loop: loop
+ fetch cur into archive_name;
+ if cur_done then
+ leave fetch_loop;
+ end if;
+ set @tmp= concat('drop table ', archive_name);
+ prepare stmt from @tmp; execute stmt; drop prepare stmt;
+ end loop;
+
+ drop table cur_tmp;
+end~~
+delimiter ;~~
+
+delimiter ~~;
+create procedure test_01(in engine varchar(64))
+begin
+ set @tmp = concat('create table t (a int) with system versioning engine ', engine);
+ prepare stmt from @tmp; execute stmt; drop prepare stmt;
+
+ set @tm1 = now(6);
+ alter table t add column b int;
+
+ set @tm2 = now(6);
+ alter table t add column c int;
+
+ show create table t for system_time as of timestamp @tm1;
+ show create table t for system_time as of timestamp @tm2;
+ show create table t for system_time as of now;
+ show create table t for system_time as of timestamp now(6);
+ show create table t;
+
+ set @tm3 = now(6);
+ rename table t to tt;
+ show create table tt for system_time as of timestamp @tm3;
+
+ set @tm4 = now(6);
+ alter table tt add column d int;
+ show create table tt for system_time as of timestamp @tm3;
+ show create table tt for system_time as of timestamp @tm4;
+ show create table tt;
+
+ drop table tt;
+ call drop_archives('tt_vtmd');
+ drop table tt_vtmd;
+end~~
+delimiter ;~~
+
+create table t (a int) with system versioning;
+--error ER_VERS_VTMD_ERROR
+show create table t for system_time as of now;
+
+set versioning_alter_history=survive;
+
+create or replace table t (a int) with system versioning;
+--error ER_VERS_RANGE_PROHIBITED
+show create table t for system_time between timestamp @tm1 and timestamp @tm1;
+--error ER_VERS_RANGE_PROHIBITED
+show create table t for system_time from timestamp @tm1 to timestamp @tm1;
+--error ER_VERS_VTMD_ERROR
+show create table t for system_time as of timestamp '01-01-1990';
+--error ER_VERS_VTMD_ERROR
+show create table t for system_time as of timestamp '01-01-2020';
+drop table t;
+call drop_archives('t_vtmd');
+drop table t_vtmd;
+
+call test_01('myisam');
+call test_01('innodb');
+
+drop procedure test_01;
+drop procedure drop_archives;
diff --git a/mysql-test/suite/versioning/wait_system_clock.inc b/mysql-test/suite/versioning/wait_system_clock.inc
new file mode 100644
index 00000000000..21bbe7aea21
--- /dev/null
+++ b/mysql-test/suite/versioning/wait_system_clock.inc
@@ -0,0 +1,10 @@
+#
+# windows has a rather low-resolution system clock
+# wait until the event from the past will actually be in the past
+#
+if (`select @@version_compile_os in ("win32","win64","windows")`)
+{
+ let $_past=`select max(row_start) from t1`;
+ --let $wait_condition=select TIMESTAMP'$_past' < sysdate(6)
+ --source include/wait_condition.inc
+}