summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/my_base.h2
-rw-r--r--mysql-test/suite/versioning/common.inc1
-rw-r--r--mysql-test/suite/versioning/common_finish.inc1
-rw-r--r--mysql-test/suite/versioning/r/delete_history.result20
-rw-r--r--mysql-test/suite/versioning/r/not_embedded.result (renamed from mysql-test/suite/versioning/r/truncate_privilege.result)29
-rw-r--r--mysql-test/suite/versioning/r/partition,heap.rdiff140
-rw-r--r--mysql-test/suite/versioning/r/partition.result1104
-rw-r--r--mysql-test/suite/versioning/r/rpl.result27
-rw-r--r--mysql-test/suite/versioning/r/rpl_mix.result55
-rw-r--r--mysql-test/suite/versioning/r/rpl_row.result55
-rw-r--r--mysql-test/suite/versioning/r/rpl_stmt.result50
-rw-r--r--mysql-test/suite/versioning/r/update-big.result74
-rw-r--r--mysql-test/suite/versioning/t/delete_history.test14
-rw-r--r--mysql-test/suite/versioning/t/load_data.test2
-rw-r--r--mysql-test/suite/versioning/t/not_embedded.test (renamed from mysql-test/suite/versioning/t/truncate_privilege.test)39
-rw-r--r--mysql-test/suite/versioning/t/partition.test616
-rw-r--r--mysql-test/suite/versioning/t/rpl.test18
-rw-r--r--mysql-test/suite/versioning/t/rpl_common.inc29
-rw-r--r--mysql-test/suite/versioning/t/rpl_mix.test2
-rw-r--r--mysql-test/suite/versioning/t/rpl_row.test2
-rw-r--r--mysql-test/suite/versioning/t/rpl_stmt.test4
-rw-r--r--mysql-test/suite/versioning/t/update-big.test74
-rw-r--r--sql/ha_partition.cc20
-rw-r--r--sql/ha_partition.h9
-rw-r--r--sql/handler.cc3
-rw-r--r--sql/handler.h7
-rw-r--r--sql/lock.cc32
-rw-r--r--sql/lock.h2
-rw-r--r--sql/log_event.cc13
-rw-r--r--sql/log_event.h9
-rw-r--r--sql/log_event_server.cc22
-rw-r--r--sql/partition_info.cc210
-rw-r--r--sql/partition_info.h23
-rw-r--r--sql/rpl_rli.h2
-rw-r--r--sql/share/errmsg-utf8.txt4
-rw-r--r--sql/sql_base.cc285
-rw-r--r--sql/sql_base.h6
-rw-r--r--sql/sql_class.cc4
-rw-r--r--sql/sql_class.h8
-rw-r--r--sql/sql_lex.cc6
-rw-r--r--sql/sql_parse.cc3
-rw-r--r--sql/sql_partition.cc36
-rw-r--r--sql/sql_truncate.cc2
-rw-r--r--sql/sql_yacc.yy30
-rw-r--r--sql/table.cc2
-rw-r--r--sql/table.h19
-rw-r--r--sql/transaction.cc2
47 files changed, 2907 insertions, 210 deletions
diff --git a/include/my_base.h b/include/my_base.h
index 80ee527ccf0..a2c7af3e9ee 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -35,7 +35,7 @@
#define HA_OPEN_ABORT_IF_LOCKED 0U /* default */
#define HA_OPEN_WAIT_IF_LOCKED 1U
-#define HA_OPEN_IGNORE_IF_LOCKED 2U
+#define HA_OPEN_IGNORE_IF_LOCKED 2U /* Ignore lock error */
#define HA_OPEN_TMP_TABLE 4U /* Table is a temp table */
#define HA_OPEN_DELAY_KEY_WRITE 8U /* Don't update index */
#define HA_OPEN_ABORT_IF_CRASHED 16U
diff --git a/mysql-test/suite/versioning/common.inc b/mysql-test/suite/versioning/common.inc
index 25adf15dd50..4b06e6de279 100644
--- a/mysql-test/suite/versioning/common.inc
+++ b/mysql-test/suite/versioning/common.inc
@@ -6,6 +6,7 @@ if (!$TEST_VERSIONING_SO)
source include/have_innodb.inc;
set @@session.time_zone='+00:00';
+set @@global.time_zone='+00:00';
select ifnull(max(transaction_id), 0) into @start_trx_id from mysql.transaction_registry;
set @test_start=now(6);
diff --git a/mysql-test/suite/versioning/common_finish.inc b/mysql-test/suite/versioning/common_finish.inc
index 3c4e7b66ff3..255daa1963a 100644
--- a/mysql-test/suite/versioning/common_finish.inc
+++ b/mysql-test/suite/versioning/common_finish.inc
@@ -6,5 +6,6 @@ drop function if exists current_row;
drop function if exists check_row;
drop function if exists current_row_ts;
drop function if exists check_row_ts;
+set @@global.time_zone= default;
--enable_warnings
--enable_query_log
diff --git a/mysql-test/suite/versioning/r/delete_history.result b/mysql-test/suite/versioning/r/delete_history.result
index a5a6de19bc6..0dfaa44870c 100644
--- a/mysql-test/suite/versioning/r/delete_history.result
+++ b/mysql-test/suite/versioning/r/delete_history.result
@@ -63,8 +63,6 @@ insert into t values (1);
update t set a= 2;
update t set a= 3;
delete history from t;
-Warnings:
-Warning 4114 Versioned table `test`.`t`: last HISTORY partition (`p1`) is out of LIMIT, need more HISTORY partitions
# The above warning is one command late (MDEV-20345) ^^^
select * from t for system_time all;
a
@@ -187,3 +185,21 @@ x
1
drop prepare stmt;
drop table t1;
+#
+# MDEV-17554 Auto-create new partition for system versioned tables with history partitioned by INTERVAL/LIMIT
+#
+# Don't auto-create new partition on DELETE HISTORY:
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t (a int) with system versioning
+partition by system_time interval 1 hour auto;
+set timestamp= unix_timestamp('2000-01-01 10:00:00');
+delete history from t;
+set timestamp= default;
+show create table t;
+Table Create Table
+t CREATE TABLE `t` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 2
+drop table t;
diff --git a/mysql-test/suite/versioning/r/truncate_privilege.result b/mysql-test/suite/versioning/r/not_embedded.result
index e2b48c494be..1bd745ecab3 100644
--- a/mysql-test/suite/versioning/r/truncate_privilege.result
+++ b/mysql-test/suite/versioning/r/not_embedded.result
@@ -1,3 +1,6 @@
+#
+# DELETE HISTORY and privileges
+#
connect root,localhost,root,,test;
connection root;
create database mysqltest;
@@ -31,3 +34,29 @@ GRANT DELETE HISTORY ON `mysqltest`.* TO `mysqltest_1`@`localhost`
GRANT DELETE HISTORY ON `mysqltest`.`t` TO `mysqltest_1`@`localhost`
drop user mysqltest_1@localhost;
drop database mysqltest;
+disconnect user1;
+disconnect root;
+connection default;
+#
+# MDEV-25559 Auto-create: infinite loop after interrupted lock wait
+#
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create table t (pk int primary key, a int) engine innodb with system versioning
+partition by system_time interval 1 hour auto;
+insert into t values (1, 0);
+begin;
+update t set a= a + 1;
+connect con1,localhost,root,,;
+set max_statement_time= 1;
+set timestamp= unix_timestamp('2000-01-01 01:00:00');
+update t set a= a + 2;
+connection default;
+set timestamp= unix_timestamp('2000-01-01 01:00:00');
+update t set a= a + 3;
+connection con1;
+ERROR 70100: Query execution was interrupted (max_statement_time exceeded)
+disconnect con1;
+connection default;
+commit;
+drop table t;
+set timestamp= default;
diff --git a/mysql-test/suite/versioning/r/partition,heap.rdiff b/mysql-test/suite/versioning/r/partition,heap.rdiff
index f7b534bb114..779b715f813 100644
--- a/mysql-test/suite/versioning/r/partition,heap.rdiff
+++ b/mysql-test/suite/versioning/r/partition,heap.rdiff
@@ -1,6 +1,6 @@
--- partition.result
+++ partition,heap.reject
-@@ -1545,82 +1545,3 @@
+@@ -1582,85 +1582,6 @@
(PARTITION `p0` HISTORY ENGINE = X,
PARTITION `pn` CURRENT ENGINE = X)
drop tables t1, tp1;
@@ -83,3 +83,141 @@
-(PARTITION `p0` VALUES LESS THAN (10) ENGINE = X,
- PARTITION `pn` VALUES LESS THAN MAXVALUE ENGINE = X)
-drop tables t1, tp1;
+ #
+ # MDEV-17554 Auto-create new partition for system versioned tables with history partitioned by INTERVAL/LIMIT
+ #
+@@ -2193,134 +2114,6 @@
+ Warning 4114 Versioned table `test`.`t1`: last HISTORY partition (`p0`) is out of INTERVAL, need more HISTORY partitions
+ drop prepare s;
+ affected rows: 0
+-# Complex table
+-set timestamp= unix_timestamp('2000-01-01 00:00:00');
+-affected rows: 0
+-create or replace table t1 (
+-x int primary key auto_increment,
+-t timestamp(6) default '2001-11-11 11:11:11',
+-b blob(4096) compressed null,
+-c varchar(1033) character set utf8 not null,
+-u int unique,
+-m enum('a', 'b', 'c') not null default 'a' comment 'absolute',
+-i1 tinyint, i2 smallint, i3 bigint,
+-index three(i1, i2, i3),
+-v1 timestamp(6) generated always as (t + interval 1 day),
+-v2 timestamp(6) generated always as (t + interval 1 month) stored,
+-s timestamp(6) as row start,
+-e timestamp(6) as row end,
+-period for system_time (s, e),
+-ps date, pe date,
+-period for app_time (ps, pe),
+-constraint check_constr check (u > -1))
+-with system versioning default charset=ucs2
+-partition by system_time interval 1 hour auto (
+-partition p2 history,
+-partition pn current);
+-affected rows: 0
+-show create table t1;
+-Table Create Table
+-t1 CREATE TABLE `t1` (
+- `x` int(11) NOT NULL AUTO_INCREMENT,
+- `t` timestamp(6) NOT NULL DEFAULT '2001-11-11 11:11:11.000000',
+- `b` blob /*!100301 COMPRESSED*/ DEFAULT NULL,
+- `c` varchar(1033) CHARACTER SET utf8mb3 NOT NULL,
+- `u` int(11) DEFAULT NULL,
+- `m` enum('a','b','c') NOT NULL DEFAULT 'a' COMMENT 'absolute',
+- `i1` tinyint(4) DEFAULT NULL,
+- `i2` smallint(6) DEFAULT NULL,
+- `i3` bigint(20) DEFAULT NULL,
+- `v1` timestamp(6) GENERATED ALWAYS AS (`t` + interval 1 day) VIRTUAL,
+- `v2` timestamp(6) GENERATED ALWAYS AS (`t` + interval 1 month) STORED,
+- `s` timestamp(6) GENERATED ALWAYS AS ROW START,
+- `e` timestamp(6) GENERATED ALWAYS AS ROW END,
+- `ps` date NOT NULL,
+- `pe` date NOT NULL,
+- PERIOD FOR `app_time` (`ps`, `pe`),
+- PRIMARY KEY (`x`,`e`),
+- UNIQUE KEY `u` (`u`,`e`),
+- KEY `three` (`i1`,`i2`,`i3`),
+- PERIOD FOR SYSTEM_TIME (`s`, `e`),
+- CONSTRAINT `check_constr` CHECK (`u` > -1)
+-) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=ucs2 WITH SYSTEM VERSIONING
+- PARTITION BY SYSTEM_TIME INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+-(PARTITION `p2` HISTORY ENGINE = DEFAULT_ENGINE,
+- PARTITION `pn` CURRENT ENGINE = DEFAULT_ENGINE)
+-affected rows: 1
+-insert into t1 (x, c, u, i1, i2, i3, ps, pe)
+-values (1, 'cc', 0, 1, 2, 3, '1999-01-01', '2000-01-01');
+-affected rows: 1
+-set timestamp= unix_timestamp('2000-01-01 01:00:00');
+-affected rows: 0
+-update t1 set x= x + 8;
+-affected rows: 1
+-info: Rows matched: 1 Changed: 1 Inserted: 1 Warnings: 0
+-show create table t1;
+-Table Create Table
+-t1 CREATE TABLE `t1` (
+- `x` int(11) NOT NULL AUTO_INCREMENT,
+- `t` timestamp(6) NOT NULL DEFAULT '2001-11-11 11:11:11.000000',
+- `b` blob /*!100301 COMPRESSED*/ DEFAULT NULL,
+- `c` varchar(1033) CHARACTER SET utf8mb3 NOT NULL,
+- `u` int(11) DEFAULT NULL,
+- `m` enum('a','b','c') NOT NULL DEFAULT 'a' COMMENT 'absolute',
+- `i1` tinyint(4) DEFAULT NULL,
+- `i2` smallint(6) DEFAULT NULL,
+- `i3` bigint(20) DEFAULT NULL,
+- `v1` timestamp(6) GENERATED ALWAYS AS (`t` + interval 1 day) VIRTUAL,
+- `v2` timestamp(6) GENERATED ALWAYS AS (`t` + interval 1 month) STORED,
+- `s` timestamp(6) GENERATED ALWAYS AS ROW START,
+- `e` timestamp(6) GENERATED ALWAYS AS ROW END,
+- `ps` date NOT NULL,
+- `pe` date NOT NULL,
+- PERIOD FOR `app_time` (`ps`, `pe`),
+- PRIMARY KEY (`x`,`e`),
+- UNIQUE KEY `u` (`u`,`e`),
+- KEY `three` (`i1`,`i2`,`i3`),
+- PERIOD FOR SYSTEM_TIME (`s`, `e`),
+- CONSTRAINT `check_constr` CHECK (`u` > -1)
+-) ENGINE=DEFAULT_ENGINE AUTO_INCREMENT=10 DEFAULT CHARSET=ucs2 WITH SYSTEM VERSIONING
+- PARTITION BY SYSTEM_TIME INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+-(PARTITION `p2` HISTORY ENGINE = DEFAULT_ENGINE,
+- PARTITION `p1` HISTORY ENGINE = DEFAULT_ENGINE,
+- PARTITION `pn` CURRENT ENGINE = DEFAULT_ENGINE)
+-affected rows: 1
+-set timestamp= unix_timestamp('2000-01-01 02:00:00');
+-affected rows: 0
+-update t1 set x= x - 8;
+-affected rows: 1
+-info: Rows matched: 1 Changed: 1 Inserted: 1 Warnings: 0
+-show create table t1;
+-Table Create Table
+-t1 CREATE TABLE `t1` (
+- `x` int(11) NOT NULL AUTO_INCREMENT,
+- `t` timestamp(6) NOT NULL DEFAULT '2001-11-11 11:11:11.000000',
+- `b` blob /*!100301 COMPRESSED*/ DEFAULT NULL,
+- `c` varchar(1033) CHARACTER SET utf8mb3 NOT NULL,
+- `u` int(11) DEFAULT NULL,
+- `m` enum('a','b','c') NOT NULL DEFAULT 'a' COMMENT 'absolute',
+- `i1` tinyint(4) DEFAULT NULL,
+- `i2` smallint(6) DEFAULT NULL,
+- `i3` bigint(20) DEFAULT NULL,
+- `v1` timestamp(6) GENERATED ALWAYS AS (`t` + interval 1 day) VIRTUAL,
+- `v2` timestamp(6) GENERATED ALWAYS AS (`t` + interval 1 month) STORED,
+- `s` timestamp(6) GENERATED ALWAYS AS ROW START,
+- `e` timestamp(6) GENERATED ALWAYS AS ROW END,
+- `ps` date NOT NULL,
+- `pe` date NOT NULL,
+- PERIOD FOR `app_time` (`ps`, `pe`),
+- PRIMARY KEY (`x`,`e`),
+- UNIQUE KEY `u` (`u`,`e`),
+- KEY `three` (`i1`,`i2`,`i3`),
+- PERIOD FOR SYSTEM_TIME (`s`, `e`),
+- CONSTRAINT `check_constr` CHECK (`u` > -1)
+-) ENGINE=DEFAULT_ENGINE AUTO_INCREMENT=10 DEFAULT CHARSET=ucs2 WITH SYSTEM VERSIONING
+- PARTITION BY SYSTEM_TIME INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+-(PARTITION `p2` HISTORY ENGINE = DEFAULT_ENGINE,
+- PARTITION `p1` HISTORY ENGINE = DEFAULT_ENGINE,
+- PARTITION `p3` HISTORY ENGINE = DEFAULT_ENGINE,
+- PARTITION `pn` CURRENT ENGINE = DEFAULT_ENGINE)
+-affected rows: 1
+ # INSERT .. ON DUPLICATE KEY UPDATE (ODKU)
+ set timestamp= unix_timestamp('2000-01-01 00:00:00');
+ create or replace table t1 (x int primary key) with system versioning
diff --git a/mysql-test/suite/versioning/r/partition.result b/mysql-test/suite/versioning/r/partition.result
index c8d95ac0063..0c93c9d810e 100644
--- a/mysql-test/suite/versioning/r/partition.result
+++ b/mysql-test/suite/versioning/r/partition.result
@@ -237,11 +237,13 @@ select @ts0 = @ts1;
select @ts2 = @ts3;
@ts2 = @ts3
1
-## rotation by LIMIT
+#
+# Rotation by LIMIT
+#
create or replace table t1 (x int)
with system versioning
partition by system_time limit 0 partitions 3;
-ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for 'LIMIT'
+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 partitions 3;
@@ -276,8 +278,6 @@ x
5
6
insert into t1 values (7), (8);
-Warnings:
-Warning 4114 Versioned table `test`.`t1`: last HISTORY partition (`p1`) is out of LIMIT, need more HISTORY partitions
### warn about full partition
delete from t1;
Warnings:
@@ -289,11 +289,13 @@ x
6
7
8
-## rotation by INTERVAL
+#
+# Rotation by INTERVAL
+#
create or replace table t1 (x int)
with system versioning
partition by system_time interval 0 second partitions 3;
-ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for 'INTERVAL'
+ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for INTERVAL
create table t1 (i int) with system versioning
partition by system_time interval 6 day limit 98;
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 'limit 98' at line 2
@@ -349,19 +351,25 @@ delete from t1;
set timestamp=unix_timestamp('2001-02-04 10:20:50');
insert t1 values (2);
delete from t1;
-select subpartition_name,partition_description,table_rows from information_schema.partitions where table_schema='test' and table_name='t1';
+Warnings:
+Warning 4114 Versioned table `test`.`t1`: last HISTORY partition (`p1`) is out of INTERVAL, need more HISTORY partitions
+select subpartition_name, partition_description, table_rows from information_schema.partitions where table_schema='test' and table_name='t1';
subpartition_name partition_description table_rows
p1sp0 2001-02-04 00:00:00 1
p1sp1 2001-02-04 00:00:00 1
pnsp0 CURRENT 0
pnsp1 CURRENT 0
+select * from t1 partition (p1);
+i
+1
+2
set timestamp=unix_timestamp('2001-02-04 10:20:55');
alter table t1 add partition (partition p0 history, partition p2 history);
set timestamp=unix_timestamp('2001-02-04 10:30:00');
insert t1 values (4),(5);
set timestamp=unix_timestamp('2001-02-04 10:30:10');
update t1 set i=6 where i=5;
-select subpartition_name,partition_description,table_rows from information_schema.partitions where table_schema='test' and table_name='t1';
+select subpartition_name, partition_description, table_rows from information_schema.partitions where table_schema='test' and table_name='t1';
subpartition_name partition_description table_rows
p1sp0 2001-02-04 00:00:00 1
p1sp1 2001-02-04 00:00:00 0
@@ -371,6 +379,25 @@ p2sp0 2001-02-06 00:00:00 0
p2sp1 2001-02-06 00:00:00 0
pnsp0 CURRENT 0
pnsp1 CURRENT 2
+select * from t1 partition (p1);
+i
+1
+select * from t1 partition (p0);
+i
+5
+2
+select * from t1 partition (p2);
+i
+alter table t1 rebuild partition p0, p1, p2;
+select * from t1 partition (p1);
+i
+1
+select * from t1 partition (p0);
+i
+5
+2
+select * from t1 partition (p2);
+i
## pruning check
set @ts=(select partition_description from information_schema.partitions
where table_schema='test' and table_name='t1' and partition_name='p0' limit 1);
@@ -410,16 +437,16 @@ set timestamp= default;
## INTERVAL ... STARTS
create or replace table t1 (i int) with system versioning
partition by system_time interval 1 day starts 'a';
-ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for 'STARTS'
+ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for STARTS
create or replace table t1 (i int) with system versioning
partition by system_time interval 1 day starts '00:00:00';
-ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for 'STARTS'
+ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for STARTS
create or replace table t1 (i int) with system versioning
partition by system_time interval 1 day starts '2000-00-01 00:00:00';
-ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for 'STARTS'
+ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for STARTS
create or replace table t1 (i int) with system versioning
partition by system_time interval 1 day starts 946684800;
-ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for 'STARTS'
+ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for STARTS
create or replace table t1 (i int) with system versioning
partition by system_time interval 1 day starts '2000-01-01 00:00:00';
show create table t1;
@@ -554,12 +581,15 @@ set timestamp= unix_timestamp('2001-01-01 00:00:00');
create or replace table t1 (i int) with system versioning
partition by system_time interval 1 day starts '2000-01-01 00:00:00'
partitions 3;
-# we are warned when we push to present:
insert into t1 values (0);
set timestamp= unix_timestamp('2001-01-01 00:00:01');
update t1 set i= i + 1;
+Warnings:
+Warning 4114 Versioned table `test`.`t1`: last HISTORY partition (`p1`) is out of INTERVAL, need more HISTORY partitions
set timestamp= unix_timestamp('2001-01-01 00:00:02');
update t1 set i= i + 1;
+Warnings:
+Warning 4114 Versioned table `test`.`t1`: last HISTORY partition (`p1`) is out of INTERVAL, need more HISTORY partitions
select *, row_end from t1 partition (p0);
i row_end
select *, row_end from t1 partition (p1);
@@ -590,8 +620,8 @@ i row_end
select *, row_end from t1 partition (p1);
i row_end
3 2000-01-04 00:00:01.000000
-set timestamp= unix_timestamp('2000-01-01 00:00:00');
# and this is how it usually goes:
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
create or replace table t1 (i int) with system versioning
partition by system_time interval 1 day
partitions 3;
@@ -602,8 +632,12 @@ set timestamp= unix_timestamp('2000-01-02 00:00:01');
update t1 set i= i + 1;
set timestamp= unix_timestamp('2000-01-03 00:00:01');
update t1 set i= i + 1;
+Warnings:
+Warning 4114 Versioned table `test`.`t1`: last HISTORY partition (`p1`) is out of INTERVAL, need more HISTORY partitions
set timestamp= unix_timestamp('2000-01-04 00:00:01');
update t1 set i= i + 1;
+Warnings:
+Warning 4114 Versioned table `test`.`t1`: last HISTORY partition (`p1`) is out of INTERVAL, need more HISTORY partitions
alter table t1 add partition (partition p2 history, partition p3 history);
select *, row_end from t1 partition (p0);
i row_end
@@ -634,9 +668,9 @@ select * from t1 partition (pnsp1);
x
2
4
-### warn about full partition
delete from t1 where x < 3;
delete from t1;
+### warn about full partition
delete from t1;
Warnings:
Warning 4114 Versioned table `test`.`t1`: last HISTORY partition (`p1`) is out of LIMIT, need more HISTORY partitions
@@ -1105,11 +1139,11 @@ f varchar(45000)
partition by system_time interval 1 year (partition p1 history,
partition pn current);
insert into t1 () values (),(),(),(),(),(),(),(),(),(),(),(),(),(),(),();
-select * into outfile 'load.data' from t1;
-load data infile 'load.data' replace into table t1;
-load data infile 'load.data' replace into table t1;
+select * into outfile 'MDEV-17891.data' from t1;
+load data infile 'MDEV-17891.data' replace into table t1;
+load data infile 'MDEV-17891.data' replace into table t1;
ERROR HY000: The table 't1' is full
-load data infile 'load.data' replace into table t1;
+load data infile 'MDEV-17891.data' replace into table t1;
ERROR HY000: The table 't1' is full
set @@max_heap_table_size= 1048576;
drop table t1;
@@ -1131,6 +1165,8 @@ insert into t1 values (0);
update t1 set x= x + 1;
set timestamp= unix_timestamp('2000-01-01 02:00:01');
update t1 set x= x + 1;
+Warnings:
+Warning 4114 Versioned table `test`.`t1`: last HISTORY partition (`p1`) is out of INTERVAL, need more HISTORY partitions
select *, row_start, row_end from t1 for system_time as of '2000-01-01 02:00:00';
x row_start row_end
1 2000-01-01 00:00:00.000000 2000-01-01 02:00:01.000000
@@ -1259,31 +1295,7 @@ t1 CREATE TABLE `t1` (
PARTITION `p5` HISTORY ENGINE = DEFAULT_ENGINE,
PARTITION `pn` CURRENT ENGINE = DEFAULT_ENGINE)
alter table t1 add partition partitions 8;
-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 1
-(PARTITION `p2` HISTORY ENGINE = DEFAULT_ENGINE,
- PARTITION `p8` HISTORY ENGINE = DEFAULT_ENGINE,
- PARTITION `p3` HISTORY ENGINE = DEFAULT_ENGINE,
- PARTITION `p4` HISTORY ENGINE = DEFAULT_ENGINE,
- PARTITION `p5` HISTORY ENGINE = DEFAULT_ENGINE,
- PARTITION `p9` HISTORY ENGINE = DEFAULT_ENGINE,
- PARTITION `p10` HISTORY ENGINE = DEFAULT_ENGINE,
- PARTITION `p11` HISTORY ENGINE = DEFAULT_ENGINE,
- PARTITION `p12` HISTORY ENGINE = DEFAULT_ENGINE,
- PARTITION `p13` HISTORY ENGINE = DEFAULT_ENGINE,
- PARTITION `p14` HISTORY ENGINE = DEFAULT_ENGINE,
- PARTITION `p15` HISTORY ENGINE = DEFAULT_ENGINE,
- PARTITION `p16` HISTORY ENGINE = DEFAULT_ENGINE,
- PARTITION `pn` CURRENT ENGINE = DEFAULT_ENGINE)
-drop tables t1;
-#
-# End of 10.5 tests
-#
-SET GLOBAL innodb_stats_persistent=@save_persistent;
+drop table t1;
# End of 10.6 tests
#
# MDEV-22166 MIGRATE PARTITION: move out partition into a table
@@ -1649,3 +1661,1007 @@ t1 CREATE TABLE `t1` (
(PARTITION `p0` VALUES LESS THAN (10) ENGINE = X,
PARTITION `pn` VALUES LESS THAN MAXVALUE ENGINE = X)
drop tables t1, tp1;
+#
+# MDEV-17554 Auto-create new partition for system versioned tables with history partitioned by INTERVAL/LIMIT
+#
+create or replace table t1 (x int) with system versioning
+partition by system_time limit 1 auto;
+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 1 AUTO
+PARTITIONS 2
+insert into t1 values (1);
+create or replace table t2 (y int);
+insert into t2 values (2);
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+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 1 AUTO
+PARTITIONS 2
+# Too many partitions error
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t1 (x int) with system versioning
+partition by system_time interval 1 hour auto;
+set timestamp= unix_timestamp('2001-01-01 00:01:00');
+update t1 set x= x + 1;
+ERROR HY000: Versioned table `test`.`t1`: adding HISTORY partition(s) failed
+show warnings;
+Level Code Message
+Warning 1499 Too many partitions (including subpartitions) were defined
+Error 4186 Versioned table `test`.`t1`: adding HISTORY partition(s) failed
+# Auto-create failed error
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t1 (x int) with system versioning engine innodb
+partition by system_time interval 1 hour auto;
+insert into t1 values (1);
+call mtr.add_suppression("rror number .*(File exists|file operation)");
+call mtr.add_suppression("InnoDB: Cannot create file");
+set timestamp= unix_timestamp('2000-01-01 01:00:00');
+update t1 set x= x + 2;
+ERROR HY000: Got error 184 "Tablespace already exists" from storage engine InnoDB
+show warnings;
+Level Code Message
+Error 1030 Got error 184 "Tablespace already exists" from storage engine InnoDB
+Warning 4186 Versioned table `test`.`t1`: adding HISTORY partition(s) failed
+# Partition overflow error and manual fix
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t1 (x int) with system versioning
+partition by system_time interval 1 hour;
+insert into t1 values (440);
+set timestamp= unix_timestamp('2000-01-01 00:10:00');
+update t1 set x= x + 1;
+# Check how pruning boundaries work
+explain partitions select * from t1 for system_time as of '2000-01-01 00:59:58';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0,pn # NULL NULL NULL NULL # #
+explain partitions select * from t1 for system_time as of '2000-01-01 00:59:59';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0,pn # NULL NULL NULL NULL # #
+explain partitions select * from t1 for system_time as of '2000-01-01 01:00:00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0,pn # NULL NULL NULL NULL # #
+select * from t1 for system_time as of '2000-01-01 00:09:59';
+x
+440
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+update t1 set x= x + 1;
+Warnings:
+Warning 4114 Versioned table `test`.`t1`: last HISTORY partition (`p0`) is out of INTERVAL, need more HISTORY partitions
+select * from t1 for system_time as of '2000-01-01 01:00:00';
+x
+441
+select * from t1 partition (p0) order by x;
+x
+440
+441
+# Here is how manual fix works: just add new partitions there
+alter table t1 add partition partitions 3;
+select * from t1 for system_time as of '2000-01-01 01:00:00';
+x
+441
+select * from t1 partition (p0) order by x;
+x
+440
+# Check pruning after ALTER
+explain partitions select * from t1 for system_time as of '2000-01-01 00:59:58';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0,p1,p2,p3,pn # NULL NULL NULL NULL # #
+explain partitions select * from t1 for system_time as of '2000-01-01 00:59:59';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p1,p2,p3,pn # NULL NULL NULL NULL # #
+explain partitions select * from t1 for system_time as of '2000-01-01 01:00:00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p1,p2,p3,pn # NULL NULL NULL NULL # #
+drop table t1;
+create or replace table t1 (x int) with system versioning
+partition by system_time interval 3600 second
+starts '2000-01-01 00:00:00' auto partitions 3;
+affected rows: 0
+insert into t1 values (1);
+affected rows: 1
+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 INTERVAL 3600 SECOND STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 3
+affected rows: 1
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+affected rows: 0
+update t1 set x= x + 1;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Inserted: 1 Warnings: 0
+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 INTERVAL 3600 SECOND STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 4
+affected rows: 1
+set timestamp= unix_timestamp('2000-01-01 03:00:00');
+affected rows: 0
+update t1 set x= x + 2;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Inserted: 1 Warnings: 0
+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 INTERVAL 3600 SECOND STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 5
+affected rows: 1
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+affected rows: 0
+create or replace table t1 (x int) with system versioning
+partition by system_time interval 1 hour auto (
+partition p1 history,
+partition p3 history,
+partition pn current);
+affected rows: 0
+insert into t1 values (1);
+affected rows: 1
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+(PARTITION `p1` HISTORY ENGINE = DEFAULT_ENGINE,
+ PARTITION `p3` HISTORY ENGINE = DEFAULT_ENGINE,
+ PARTITION `pn` CURRENT ENGINE = DEFAULT_ENGINE)
+affected rows: 1
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+affected rows: 0
+update t1 set x= x + 3;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Inserted: 1 Warnings: 0
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+(PARTITION `p1` HISTORY ENGINE = DEFAULT_ENGINE,
+ PARTITION `p3` HISTORY ENGINE = DEFAULT_ENGINE,
+ PARTITION `p2` HISTORY ENGINE = DEFAULT_ENGINE,
+ PARTITION `pn` CURRENT ENGINE = DEFAULT_ENGINE)
+affected rows: 1
+set timestamp= unix_timestamp('2000-01-01 03:00:00');
+affected rows: 0
+update t1 set x= x + 4;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Inserted: 1 Warnings: 0
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+(PARTITION `p1` HISTORY ENGINE = DEFAULT_ENGINE,
+ PARTITION `p3` HISTORY ENGINE = DEFAULT_ENGINE,
+ PARTITION `p2` HISTORY ENGINE = DEFAULT_ENGINE,
+ PARTITION `p4` HISTORY ENGINE = DEFAULT_ENGINE,
+ PARTITION `pn` CURRENT ENGINE = DEFAULT_ENGINE)
+affected rows: 1
+set timestamp= unix_timestamp('2000-01-01 04:00:00');
+affected rows: 0
+lock tables t1 write;
+affected rows: 0
+update t1 set x= x + 5;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Inserted: 1 Warnings: 0
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+(PARTITION `p1` HISTORY ENGINE = DEFAULT_ENGINE,
+ PARTITION `p3` HISTORY ENGINE = DEFAULT_ENGINE,
+ PARTITION `p2` HISTORY ENGINE = DEFAULT_ENGINE,
+ PARTITION `p4` HISTORY ENGINE = DEFAULT_ENGINE,
+ PARTITION `p5` HISTORY ENGINE = DEFAULT_ENGINE,
+ PARTITION `pn` CURRENT ENGINE = DEFAULT_ENGINE)
+affected rows: 1
+unlock tables;
+affected rows: 0
+set timestamp= default;
+affected rows: 0
+# Couple of more LOCK TABLES cases
+create or replace table t1 (x int) with system versioning
+partition by system_time limit 1 auto;
+affected rows: 0
+lock tables t1 write;
+affected rows: 0
+insert into t1 values (1);
+affected rows: 1
+update t1 set x= x + 1;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Inserted: 1 Warnings: 0
+update t1 set x= x + 1;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Inserted: 1 Warnings: 0
+update t1 set x= x + 1;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Inserted: 1 Warnings: 0
+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 1 AUTO
+PARTITIONS 4
+affected rows: 1
+unlock tables;
+affected rows: 0
+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 1 AUTO
+PARTITIONS 4
+affected rows: 1
+# Overflow prevention under LOCK TABLES
+create or replace table t1 (x int)
+with system versioning partition by system_time
+limit 10 auto;
+affected rows: 0
+insert into t1 values (1), (2), (3), (4), (5), (6), (7), (8), (9);
+affected rows: 9
+info: Records: 9 Duplicates: 0 Warnings: 0
+update t1 set x= x + 10;
+affected rows: 9
+info: Rows matched: 9 Changed: 9 Inserted: 9 Warnings: 0
+lock tables t1 write;
+affected rows: 0
+update t1 set x= 1 where x = 11;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Inserted: 1 Warnings: 0
+update t1 set x= 2 where x = 12;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Inserted: 1 Warnings: 0
+update t1 set x= 3 where x = 13;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Inserted: 1 Warnings: 0
+unlock tables;
+affected rows: 0
+select count(x) from t1 partition (p0);
+count(x)
+10
+affected rows: 1
+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 10 AUTO
+PARTITIONS 3
+affected rows: 1
+drop tables t1;
+affected rows: 0
+# Test VIEW, LOCK TABLES
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+affected rows: 0
+create or replace table t1 (x int) with system versioning
+partition by system_time interval 1 hour auto;
+affected rows: 0
+create or replace view v1 as select * from t1;
+affected rows: 0
+insert into t1 values (1);
+affected rows: 1
+set timestamp= unix_timestamp('2000-01-01 01:00:00');
+affected rows: 0
+update v1 set x= x + 2;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Inserted: 1 Warnings: 0
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 3
+affected rows: 1
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+affected rows: 0
+lock tables v1 write;
+affected rows: 0
+update v1 set x= x + 3;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Inserted: 1 Warnings: 0
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 4
+affected rows: 1
+unlock tables;
+affected rows: 0
+drop view v1;
+affected rows: 0
+drop tables t1;
+affected rows: 0
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+affected rows: 0
+create or replace table t1 (x int) with system versioning
+partition by system_time interval 1 hour auto partitions 3;
+affected rows: 0
+create or replace table t2 (y int) with system versioning
+partition by system_time interval 1 hour auto;
+affected rows: 0
+insert into t1 values (1);
+affected rows: 1
+insert into t2 values (2);
+affected rows: 1
+set timestamp= unix_timestamp('2000-01-01 01:00:00');
+affected rows: 0
+update t1, t2 set x= x + 1, y= y + 1;
+affected rows: 2
+info: Rows matched: 2 Changed: 2 Warnings: 0
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 3
+affected rows: 1
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `y` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 3
+affected rows: 1
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+affected rows: 0
+update t1, t2 set x= x + 1, y= y + 1;
+affected rows: 2
+info: Rows matched: 2 Changed: 2 Warnings: 0
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 4
+affected rows: 1
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `y` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 4
+affected rows: 1
+set timestamp= unix_timestamp('2000-01-01 03:00:00');
+affected rows: 0
+update t1, t2 set t1.x= 0 where t1.x< t2.y;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Warnings: 0
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 5
+affected rows: 1
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `y` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS ok
+affected rows: 1
+drop tables t1, t2;
+affected rows: 0
+# PS, SP, LOCK TABLES
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+affected rows: 0
+create or replace table t1 (x int) with system versioning
+partition by system_time interval 1 hour auto;
+affected rows: 0
+insert into t1 values (1);
+affected rows: 1
+set timestamp= unix_timestamp('2000-01-01 01:00:00');
+affected rows: 0
+execute immediate 'update t1 set x= x + 5';
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Inserted: 1 Warnings: 0
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 3
+affected rows: 1
+prepare s from 'update t1 set x= x + 6';
+affected rows: 0
+info: Statement prepared
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+affected rows: 0
+execute s;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Inserted: 1 Warnings: 0
+execute s;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Inserted: 1 Warnings: 0
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 4
+affected rows: 1
+set timestamp= unix_timestamp('2000-01-01 03:00:00');
+affected rows: 0
+lock tables t1 write;
+affected rows: 0
+execute s;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Inserted: 1 Warnings: 0
+execute s;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Inserted: 1 Warnings: 0
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 5
+affected rows: 1
+unlock tables;
+affected rows: 0
+drop prepare s;
+affected rows: 0
+create procedure sp() update t1 set x= x + 7;
+affected rows: 0
+set timestamp= unix_timestamp('2000-01-01 04:00:00');
+affected rows: 0
+call sp;
+affected rows: 1
+call sp;
+affected rows: 1
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 6
+affected rows: 1
+set timestamp= unix_timestamp('2000-01-01 05:00:00');
+affected rows: 0
+lock tables t1 write;
+affected rows: 0
+call sp;
+affected rows: 1
+call sp;
+affected rows: 1
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 7
+affected rows: 1
+unlock tables;
+affected rows: 0
+drop procedure sp;
+affected rows: 0
+set timestamp= unix_timestamp('2001-01-01 00:00:00');
+affected rows: 0
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day starts '2001-01-01 00:00:00';
+affected rows: 0
+insert into t1 values (0);
+affected rows: 1
+set timestamp= unix_timestamp('2001-01-01 00:00:01');
+affected rows: 0
+prepare s from 'update t1 set i= i + 1';
+affected rows: 0
+info: Statement prepared
+execute s;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Inserted: 1 Warnings: 0
+set timestamp= unix_timestamp('2001-01-02 00:00:01');
+affected rows: 0
+execute s;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Inserted: 1 Warnings: 1
+Warnings:
+Warning 4114 Versioned table `test`.`t1`: last HISTORY partition (`p0`) is out of INTERVAL, need more HISTORY partitions
+drop prepare s;
+affected rows: 0
+# Complex table
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+affected rows: 0
+create or replace table t1 (
+x int primary key auto_increment,
+t timestamp(6) default '2001-11-11 11:11:11',
+b blob(4096) compressed null,
+c varchar(1033) character set utf8 not null,
+u int unique,
+m enum('a', 'b', 'c') not null default 'a' comment 'absolute',
+i1 tinyint, i2 smallint, i3 bigint,
+index three(i1, i2, i3),
+v1 timestamp(6) generated always as (t + interval 1 day),
+v2 timestamp(6) generated always as (t + interval 1 month) stored,
+s timestamp(6) as row start,
+e timestamp(6) as row end,
+period for system_time (s, e),
+ps date, pe date,
+period for app_time (ps, pe),
+constraint check_constr check (u > -1))
+with system versioning default charset=ucs2
+partition by system_time interval 1 hour auto (
+partition p2 history,
+partition pn current);
+affected rows: 0
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `x` int(11) NOT NULL AUTO_INCREMENT,
+ `t` timestamp(6) NOT NULL DEFAULT '2001-11-11 11:11:11.000000',
+ `b` blob /*!100301 COMPRESSED*/ DEFAULT NULL,
+ `c` varchar(1033) CHARACTER SET utf8mb3 NOT NULL,
+ `u` int(11) DEFAULT NULL,
+ `m` enum('a','b','c') NOT NULL DEFAULT 'a' COMMENT 'absolute',
+ `i1` tinyint(4) DEFAULT NULL,
+ `i2` smallint(6) DEFAULT NULL,
+ `i3` bigint(20) DEFAULT NULL,
+ `v1` timestamp(6) GENERATED ALWAYS AS (`t` + interval 1 day) VIRTUAL,
+ `v2` timestamp(6) GENERATED ALWAYS AS (`t` + interval 1 month) STORED,
+ `s` timestamp(6) GENERATED ALWAYS AS ROW START,
+ `e` timestamp(6) GENERATED ALWAYS AS ROW END,
+ `ps` date NOT NULL,
+ `pe` date NOT NULL,
+ PERIOD FOR `app_time` (`ps`, `pe`),
+ PRIMARY KEY (`x`,`e`),
+ UNIQUE KEY `u` (`u`,`e`),
+ KEY `three` (`i1`,`i2`,`i3`),
+ PERIOD FOR SYSTEM_TIME (`s`, `e`),
+ CONSTRAINT `check_constr` CHECK (`u` > -1)
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=ucs2 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+(PARTITION `p2` HISTORY ENGINE = DEFAULT_ENGINE,
+ PARTITION `pn` CURRENT ENGINE = DEFAULT_ENGINE)
+affected rows: 1
+insert into t1 (x, c, u, i1, i2, i3, ps, pe)
+values (1, 'cc', 0, 1, 2, 3, '1999-01-01', '2000-01-01');
+affected rows: 1
+set timestamp= unix_timestamp('2000-01-01 01:00:00');
+affected rows: 0
+update t1 set x= x + 8;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Inserted: 1 Warnings: 0
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `x` int(11) NOT NULL AUTO_INCREMENT,
+ `t` timestamp(6) NOT NULL DEFAULT '2001-11-11 11:11:11.000000',
+ `b` blob /*!100301 COMPRESSED*/ DEFAULT NULL,
+ `c` varchar(1033) CHARACTER SET utf8mb3 NOT NULL,
+ `u` int(11) DEFAULT NULL,
+ `m` enum('a','b','c') NOT NULL DEFAULT 'a' COMMENT 'absolute',
+ `i1` tinyint(4) DEFAULT NULL,
+ `i2` smallint(6) DEFAULT NULL,
+ `i3` bigint(20) DEFAULT NULL,
+ `v1` timestamp(6) GENERATED ALWAYS AS (`t` + interval 1 day) VIRTUAL,
+ `v2` timestamp(6) GENERATED ALWAYS AS (`t` + interval 1 month) STORED,
+ `s` timestamp(6) GENERATED ALWAYS AS ROW START,
+ `e` timestamp(6) GENERATED ALWAYS AS ROW END,
+ `ps` date NOT NULL,
+ `pe` date NOT NULL,
+ PERIOD FOR `app_time` (`ps`, `pe`),
+ PRIMARY KEY (`x`,`e`),
+ UNIQUE KEY `u` (`u`,`e`),
+ KEY `three` (`i1`,`i2`,`i3`),
+ PERIOD FOR SYSTEM_TIME (`s`, `e`),
+ CONSTRAINT `check_constr` CHECK (`u` > -1)
+) ENGINE=DEFAULT_ENGINE AUTO_INCREMENT=10 DEFAULT CHARSET=ucs2 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+(PARTITION `p2` HISTORY ENGINE = DEFAULT_ENGINE,
+ PARTITION `p1` HISTORY ENGINE = DEFAULT_ENGINE,
+ PARTITION `pn` CURRENT ENGINE = DEFAULT_ENGINE)
+affected rows: 1
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+affected rows: 0
+update t1 set x= x - 8;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Inserted: 1 Warnings: 0
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `x` int(11) NOT NULL AUTO_INCREMENT,
+ `t` timestamp(6) NOT NULL DEFAULT '2001-11-11 11:11:11.000000',
+ `b` blob /*!100301 COMPRESSED*/ DEFAULT NULL,
+ `c` varchar(1033) CHARACTER SET utf8mb3 NOT NULL,
+ `u` int(11) DEFAULT NULL,
+ `m` enum('a','b','c') NOT NULL DEFAULT 'a' COMMENT 'absolute',
+ `i1` tinyint(4) DEFAULT NULL,
+ `i2` smallint(6) DEFAULT NULL,
+ `i3` bigint(20) DEFAULT NULL,
+ `v1` timestamp(6) GENERATED ALWAYS AS (`t` + interval 1 day) VIRTUAL,
+ `v2` timestamp(6) GENERATED ALWAYS AS (`t` + interval 1 month) STORED,
+ `s` timestamp(6) GENERATED ALWAYS AS ROW START,
+ `e` timestamp(6) GENERATED ALWAYS AS ROW END,
+ `ps` date NOT NULL,
+ `pe` date NOT NULL,
+ PERIOD FOR `app_time` (`ps`, `pe`),
+ PRIMARY KEY (`x`,`e`),
+ UNIQUE KEY `u` (`u`,`e`),
+ KEY `three` (`i1`,`i2`,`i3`),
+ PERIOD FOR SYSTEM_TIME (`s`, `e`),
+ CONSTRAINT `check_constr` CHECK (`u` > -1)
+) ENGINE=DEFAULT_ENGINE AUTO_INCREMENT=10 DEFAULT CHARSET=ucs2 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+(PARTITION `p2` HISTORY ENGINE = DEFAULT_ENGINE,
+ PARTITION `p1` HISTORY ENGINE = DEFAULT_ENGINE,
+ PARTITION `p3` HISTORY ENGINE = DEFAULT_ENGINE,
+ PARTITION `pn` CURRENT ENGINE = DEFAULT_ENGINE)
+affected rows: 1
+# INSERT .. ON DUPLICATE KEY UPDATE (ODKU)
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t1 (x int primary key) with system versioning
+partition by system_time interval 1 hour auto;
+insert into t1 values (1);
+set timestamp= unix_timestamp('2000-01-01 01:00:00');
+insert into t1 values (1) on duplicate key update x= x + 1;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `x` int(11) NOT NULL,
+ PRIMARY KEY (`x`)
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 3
+# LOAD DATA .. REPLACE
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t1 (x int primary key) with system versioning
+partition by system_time interval 1 hour auto;
+insert t1 values (1), (2), (3);
+select x into outfile 'MDEV-17554.data' from t1;
+set timestamp= unix_timestamp('2000-01-01 01:00:00');
+load data infile 'MDEV-17554.data' replace into table t1 (x);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `x` int(11) NOT NULL,
+ PRIMARY KEY (`x`)
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 3
+# Concurrent DML
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t1 (x int) with system versioning
+partition by system_time interval 1 hour auto partitions 3;
+insert into t1 values (1);
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 3
+connect con8, localhost, root;
+connect con7, localhost, root;
+connect con6, localhost, root;
+connect con5, localhost, root;
+connect con4, localhost, root;
+connect con3, localhost, root;
+connect con2, localhost, root;
+connect con1, localhost, root;
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+update t1 set x= x + 10;
+connection con2;
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+update t1 set x= x + 20;
+connection con3;
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+update t1 set x= x + 30;
+connection con4;
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+update t1 set x= x + 40;
+connection con5;
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+update t1 set x= x + 50;
+connection con6;
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+update t1 set x= x + 60;
+connection con7;
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+update t1 set x= x + 70;
+connection con8;
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+update t1 set x= x + 80;
+connection con1;
+disconnect con1;
+connection con2;
+disconnect con2;
+connection con3;
+disconnect con3;
+connection con4;
+disconnect con4;
+connection con5;
+disconnect con5;
+connection con6;
+disconnect con6;
+connection con7;
+disconnect con7;
+disconnect con8;
+connection default;
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 4
+drop tables t1;
+set timestamp= default;
+# Transaction
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t1 (x int) with system versioning engine innodb
+partition by system_time interval 1 hour auto;
+insert into t1 values (1);
+set timestamp= unix_timestamp('2000-01-01 01:00:00');
+start transaction;
+update t1 set x= 0;
+connect con1, localhost, root;
+select * from t1;
+x
+1
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `x` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 3
+connection default;
+commit;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `x` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 3
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+start transaction;
+update t1 set x= 1;
+connection con1;
+select * from t1;
+x
+0
+connection default;
+rollback;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `x` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 4
+disconnect con1;
+connection default;
+drop table t1;
+#
+# MDEV-25479 Auto-create: 2nd and further executions of PS or SP fail to create partition
+#
+create table t (a int) with system versioning
+partition by system_time interval 1 hour auto;
+insert into t values (1), (2);
+prepare stmt from "update t set a= a + 1";
+set @@timestamp= @@timestamp + 3601;
+execute stmt;
+set @@timestamp= @@timestamp + 3601;
+execute stmt;
+drop prepare stmt;
+show create table t;
+Table Create Table
+t CREATE TABLE `t` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 02:00:00' AUTO
+PARTITIONS 4
+create procedure sp() update t set a= a + 1;
+set @@timestamp= @@timestamp + 3601;
+call sp();
+set @@timestamp= @@timestamp + 3601;
+call sp();
+drop procedure sp;
+show create table t;
+Table Create Table
+t CREATE TABLE `t` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 02:00:00' AUTO
+PARTITIONS 6
+drop table t;
+#
+# MDEV-23639 Auto-create does not work under LOCK TABLES or inside triggers
+#
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t1 (x int) with system versioning
+partition by system_time interval 1 hour auto
+partitions 3;
+create table t2 (x int);
+create table t3 (x int);
+insert into t3 values (3);
+create trigger tr after insert on t2 for each row update t1 set x= x + 11;
+create or replace procedure sp() update t1 set x= x + 5;
+create or replace procedure sp2() insert into t2 values (5);
+prepare ps from 'update t1 set x= x + 6';
+prepare ps2 from 'insert into t2 values (6)';
+insert into t1 values (1);
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 3
+insert into t2 values (2);
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 4
+set timestamp= unix_timestamp('2000-01-01 03:00:00');
+call sp;
+call sp;
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 5
+set timestamp= unix_timestamp('2000-01-01 04:00:00');
+call sp2;
+call sp2;
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 6
+set timestamp= unix_timestamp('2000-01-01 05:00:00');
+execute ps;
+execute ps;
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 7
+set timestamp= unix_timestamp('2000-01-01 06:00:00');
+execute ps2;
+execute ps2;
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 8
+set timestamp= unix_timestamp('2000-01-01 08:00:00');
+lock tables t1 write, t2 write;
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 10
+set timestamp= unix_timestamp('2000-01-01 09:00:00');
+update t1 set x= x + 1;
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 11
+set timestamp= unix_timestamp('2000-01-01 10:00:00');
+update t1 set x= x + 2;
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 12
+update t2 set x= x + 1;
+set timestamp= unix_timestamp('2000-01-01 11:00:00');
+insert into t2 values (4);
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 13
+update t3 set x= x + 1;
+ERROR HY000: Table 't3' was not locked with LOCK TABLES
+set timestamp= unix_timestamp('2000-01-01 12:00:00');
+call sp;
+call sp;
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 14
+set timestamp= unix_timestamp('2000-01-01 13:00:00');
+call sp2;
+call sp2;
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 15
+set timestamp= unix_timestamp('2000-01-01 14:00:00');
+execute ps;
+execute ps;
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 16
+set timestamp= unix_timestamp('2000-01-01 15:00:00');
+execute ps2;
+execute ps2;
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 17
+unlock tables;
+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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 17
+drop tables t1, t2, t3;
+drop procedure sp;
+drop procedure sp2;
+drop prepare ps;
+drop prepare ps2;
+SET GLOBAL innodb_stats_persistent=@save_persistent;
diff --git a/mysql-test/suite/versioning/r/rpl.result b/mysql-test/suite/versioning/r/rpl.result
index 627f3991499..0169d73769e 100644
--- a/mysql-test/suite/versioning/r/rpl.result
+++ b/mysql-test/suite/versioning/r/rpl.result
@@ -164,4 +164,31 @@ update t1 set i = 0;
connection slave;
connection master;
drop table t1;
+#
+# MDEV-17554 Auto-create new partition for system versioned tables with history partitioned by INTERVAL/LIMIT
+#
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t1 (x int) with system versioning
+partition by system_time interval 1 hour auto;
+insert t1 values ();
+set timestamp= unix_timestamp('2000-01-01 01:00:00');
+delete from t1;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `x` int(11) DEFAULT NULL
+) ENGINE=ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 3
+connection slave;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `x` int(11) DEFAULT NULL
+) ENGINE=ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
+PARTITIONS 3
+connection master;
+drop table t1;
+set timestamp= default;
include/rpl_end.inc
diff --git a/mysql-test/suite/versioning/r/rpl_mix.result b/mysql-test/suite/versioning/r/rpl_mix.result
index 68eded0faf7..56af76b8fc2 100644
--- a/mysql-test/suite/versioning/r/rpl_mix.result
+++ b/mysql-test/suite/versioning/r/rpl_mix.result
@@ -8,4 +8,59 @@ DELETE HISTORY FROM t1;
connection slave;
connection master;
drop table t1;
+#
+# MDEV-25347 DML events for auto-partitioned tables are written into binary log twice
+#
+flush binary logs;
+create table t1 (a int) with system versioning
+partition by system_time limit 1 auto;
+insert into t1 values (1);
+update t1 set a= a + 1;
+update t1 set a= a + 2;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME LIMIT 1 AUTO
+PARTITIONS 3
+select * from t1;
+a
+4
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000002 # Binlog_checkpoint # # master-bin.000002
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; create table t1 (a int) with system versioning
+partition by system_time limit 1 auto
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Annotate_rows # # insert into t1 values (1)
+master-bin.000002 # Table_map # # table_id: # (test.t1)
+master-bin.000002 # Write_rows_v1 # # table_id: # flags: STMT_END_F
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Annotate_rows # # update t1 set a= a + 1
+master-bin.000002 # Table_map # # table_id: # (test.t1)
+master-bin.000002 # Update_rows_v1 # # table_id: #
+master-bin.000002 # Write_rows_v1 # # table_id: # flags: STMT_END_F
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Annotate_rows # # update t1 set a= a + 2
+master-bin.000002 # Table_map # # table_id: # (test.t1)
+master-bin.000002 # Update_rows_v1 # # table_id: #
+master-bin.000002 # Write_rows_v1 # # table_id: # flags: STMT_END_F
+master-bin.000002 # Query # # COMMIT
+connection slave;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME LIMIT 1 AUTO
+PARTITIONS 3
+select * from t1;
+a
+4
+connection master;
+drop table t1;
include/rpl_end.inc
diff --git a/mysql-test/suite/versioning/r/rpl_row.result b/mysql-test/suite/versioning/r/rpl_row.result
index 03ac8dc9eb8..124993423e7 100644
--- a/mysql-test/suite/versioning/r/rpl_row.result
+++ b/mysql-test/suite/versioning/r/rpl_row.result
@@ -11,4 +11,59 @@ connection slave;
connection master;
drop table t1;
set binlog_row_image= @old_row_image;
+#
+# MDEV-25347 DML events for auto-partitioned tables are written into binary log twice
+#
+flush binary logs;
+create table t1 (a int) with system versioning
+partition by system_time limit 1 auto;
+insert into t1 values (1);
+update t1 set a= a + 1;
+update t1 set a= a + 2;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME LIMIT 1 AUTO
+PARTITIONS 3
+select * from t1;
+a
+4
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000002 # Binlog_checkpoint # # master-bin.000002
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; create table t1 (a int) with system versioning
+partition by system_time limit 1 auto
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Annotate_rows # # insert into t1 values (1)
+master-bin.000002 # Table_map # # table_id: # (test.t1)
+master-bin.000002 # Write_rows_v1 # # table_id: # flags: STMT_END_F
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Annotate_rows # # update t1 set a= a + 1
+master-bin.000002 # Table_map # # table_id: # (test.t1)
+master-bin.000002 # Update_rows_v1 # # table_id: #
+master-bin.000002 # Write_rows_v1 # # table_id: # flags: STMT_END_F
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Annotate_rows # # update t1 set a= a + 2
+master-bin.000002 # Table_map # # table_id: # (test.t1)
+master-bin.000002 # Update_rows_v1 # # table_id: #
+master-bin.000002 # Write_rows_v1 # # table_id: # flags: STMT_END_F
+master-bin.000002 # Query # # COMMIT
+connection slave;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME LIMIT 1 AUTO
+PARTITIONS 3
+select * from t1;
+a
+4
+connection master;
+drop table t1;
include/rpl_end.inc
diff --git a/mysql-test/suite/versioning/r/rpl_stmt.result b/mysql-test/suite/versioning/r/rpl_stmt.result
new file mode 100644
index 00000000000..1a5087dfa74
--- /dev/null
+++ b/mysql-test/suite/versioning/r/rpl_stmt.result
@@ -0,0 +1,50 @@
+include/master-slave.inc
+[connection master]
+#
+# MDEV-25347 DML events for auto-partitioned tables are written into binary log twice
+#
+flush binary logs;
+create table t1 (a int) with system versioning
+partition by system_time limit 1 auto;
+insert into t1 values (1);
+update t1 set a= a + 1;
+update t1 set a= a + 2;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME LIMIT 1 AUTO
+PARTITIONS 3
+select * from t1;
+a
+4
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000002 # Binlog_checkpoint # # master-bin.000002
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; create table t1 (a int) with system versioning
+partition by system_time limit 1 auto
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; insert into t1 values (1)
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; update t1 set a= a + 1
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; update t1 set a= a + 2
+master-bin.000002 # Query # # COMMIT
+connection slave;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
+ PARTITION BY SYSTEM_TIME LIMIT 1 AUTO
+PARTITIONS 3
+select * from t1;
+a
+4
+connection master;
+drop table t1;
+include/rpl_end.inc
diff --git a/mysql-test/suite/versioning/r/update-big.result b/mysql-test/suite/versioning/r/update-big.result
index 89297fe5d89..506d1d23c5d 100644
--- a/mysql-test/suite/versioning/r/update-big.result
+++ b/mysql-test/suite/versioning/r/update-big.result
@@ -22,4 +22,78 @@ update t1 set a= 1 where a = 5;
update t1 set a= 8 where a = 1;
update t1 set a= 4 where a = 8;
update t1 set a= 6;
+disconnect con1;
drop table t1;
+call mtr.add_suppression("need more HISTORY partitions");
+#
+# MDEV-23642 Locking timeout caused by auto-creation affects original DML
+#
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t1 (x int primary key) with system versioning engine innodb
+partition by system_time interval 1 hour auto;
+insert into t1 values (1);
+start transaction;
+insert into t1 values (2);
+connect con1, localhost, root;
+set lock_wait_timeout= 1;
+set innodb_lock_wait_timeout= 1;
+set timestamp= unix_timestamp('2000-01-01 01:00:01');
+update t1 set x= x + 122 where x = 1;
+Warnings:
+Error 1205 Lock wait timeout exceeded; try restarting transaction
+Warning 4114 Versioned table `test`.`t1`: last HISTORY partition (`p0`) is out of INTERVAL, need more HISTORY partitions
+disconnect con1;
+connection default;
+select * from t1;
+x
+2
+123
+drop table t1;
+set timestamp= default;
+#
+# MDEV-25339 Assertion `thd->transaction.stmt.is_empty() || thd->in_sub_stmt' failed
+#
+create or replace table t1 (x int) with system versioning engine innodb
+partition by system_time interval 1 hour auto;
+start transaction;
+insert into t1 values (1);
+select * from t1;
+x
+1
+connect con1, localhost, root;
+set lock_wait_timeout= 1;
+set innodb_lock_wait_timeout= 1;
+update t1 set x= x + 111;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+select * from t1;
+x
+disconnect con1;
+connection default;
+drop table t1;
+#
+# MDEV-25482 Auto-create: Server hangs after a failed attempt to create partition
+#
+set timestamp= default;
+create table t (pk int primary key, a int) engine=InnoDB
+with system versioning partition by system_time interval 1 hour auto;
+insert into t values (1,1),(2,2),(3,3),(4,4),(5,5);
+start transaction;
+update t set a= 20 where pk = 2;
+connect con1,localhost,root,,;
+set lock_wait_timeout= 1;
+set @@timestamp= @@timestamp+3601;
+update t set a= 40 where pk = 4;
+Warnings:
+Error 1205 Lock wait timeout exceeded; try restarting transaction
+Warning 4114 Versioned table `test`.`t`: last HISTORY partition (`p0`) is out of INTERVAL, need more HISTORY partitions
+update t set a= 400 where pk = 4;
+Warnings:
+Error 1205 Lock wait timeout exceeded; try restarting transaction
+Warning 4114 Versioned table `test`.`t`: last HISTORY partition (`p0`) is out of INTERVAL, need more HISTORY partitions
+disconnect con1;
+connection default;
+select * from t where pk = 4;
+pk a
+4 400
+rollback;
+drop tables t;
diff --git a/mysql-test/suite/versioning/t/delete_history.test b/mysql-test/suite/versioning/t/delete_history.test
index e3b60011644..9ab4225feed 100644
--- a/mysql-test/suite/versioning/t/delete_history.test
+++ b/mysql-test/suite/versioning/t/delete_history.test
@@ -191,4 +191,18 @@ select * from t1;
drop prepare stmt;
drop table t1;
+--echo #
+--echo # MDEV-17554 Auto-create new partition for system versioned tables with history partitioned by INTERVAL/LIMIT
+--echo #
+--echo # Don't auto-create new partition on DELETE HISTORY:
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t (a int) with system versioning
+partition by system_time interval 1 hour auto;
+set timestamp= unix_timestamp('2000-01-01 10:00:00');
+delete history from t;
+set timestamp= default;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t;
+drop table t;
+
--source suite/versioning/common_finish.inc
diff --git a/mysql-test/suite/versioning/t/load_data.test b/mysql-test/suite/versioning/t/load_data.test
index 3bac2942a81..d4a1fa1a736 100644
--- a/mysql-test/suite/versioning/t/load_data.test
+++ b/mysql-test/suite/versioning/t/load_data.test
@@ -1,6 +1,7 @@
#
# MDEV-15330 Server crash or assertion `table->insert_values' failure in write_record upon LOAD DATA
#
+--let $datadir= `select @@datadir`
CREATE TABLE t1 (a INT, b INT, c INT, vc INT AS (c), UNIQUE(a), UNIQUE(b)) WITH SYSTEM VERSIONING;
INSERT IGNORE INTO t1 (a,b,c) VALUES (1,2,3);
@@ -12,3 +13,4 @@ LOAD DATA INFILE '15330.data' REPLACE INTO TABLE t1 (a,b,c);
# Cleanup
DROP TABLE t1;
+--remove_file $datadir/test/15330.data
diff --git a/mysql-test/suite/versioning/t/truncate_privilege.test b/mysql-test/suite/versioning/t/not_embedded.test
index dcdad59039a..d63c7bd4476 100644
--- a/mysql-test/suite/versioning/t/truncate_privilege.test
+++ b/mysql-test/suite/versioning/t/not_embedded.test
@@ -1,7 +1,10 @@
-# Can't test with embedded server
--- source include/not_embedded.inc
-
+--source include/not_embedded.inc
--source include/have_innodb.inc
+--source include/have_partition.inc
+
+--echo #
+--echo # DELETE HISTORY and privileges
+--echo #
# Save the initial number of concurrent sessions
--source include/count_sessions.inc
@@ -39,3 +42,33 @@ show grants for mysqltest_1@localhost;
drop user mysqltest_1@localhost;
drop database mysqltest;
+--disconnect user1
+--disconnect root
+--connection default
+
+--echo #
+--echo # MDEV-25559 Auto-create: infinite loop after interrupted lock wait
+--echo #
+
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create table t (pk int primary key, a int) engine innodb with system versioning
+partition by system_time interval 1 hour auto;
+insert into t values (1, 0);
+begin;
+update t set a= a + 1;
+--connect (con1,localhost,root,,)
+set max_statement_time= 1;
+set timestamp= unix_timestamp('2000-01-01 01:00:00');
+send update t set a= a + 2;
+--connection default
+set timestamp= unix_timestamp('2000-01-01 01:00:00');
+send update t set a= a + 3;
+--connection con1
+--error ER_STATEMENT_TIMEOUT
+reap;
+--disconnect con1
+--connection default
+reap;
+commit;
+drop table t;
+set timestamp= default;
diff --git a/mysql-test/suite/versioning/t/partition.test b/mysql-test/suite/versioning/t/partition.test
index ce41e0c96b3..4110247c21f 100644
--- a/mysql-test/suite/versioning/t/partition.test
+++ b/mysql-test/suite/versioning/t/partition.test
@@ -10,6 +10,7 @@ call mtr.add_suppression("need more HISTORY partitions");
--enable_prepare_warnings
set system_versioning_alter_history=keep;
+--let $datadir= `select @@datadir`
--echo # Check conventional partitioning on temporal tables
--replace_result $sys_datatype_expl SYS_DATATYPE
@@ -218,7 +219,9 @@ prepare stmt from @str; execute stmt; drop prepare stmt;
select @ts0 = @ts1;
select @ts2 = @ts3;
---echo ## rotation by LIMIT
+--echo #
+--echo # Rotation by LIMIT
+--echo #
--error ER_PART_WRONG_VALUE
create or replace table t1 (x int)
with system versioning
@@ -246,8 +249,9 @@ insert into t1 values (7), (8);
delete from t1;
select * from t1 partition (p1) order by x;
-
---echo ## rotation by INTERVAL
+--echo #
+--echo # Rotation by INTERVAL
+--echo #
--error ER_PART_WRONG_VALUE
create or replace table t1 (x int)
with system versioning
@@ -291,7 +295,8 @@ insert t1 values (1); delete from t1;
set timestamp=unix_timestamp('2001-02-04 10:20:50');
insert t1 values (2); delete from t1;
-select subpartition_name,partition_description,table_rows from information_schema.partitions where table_schema='test' and table_name='t1';
+select subpartition_name, partition_description, table_rows from information_schema.partitions where table_schema='test' and table_name='t1';
+select * from t1 partition (p1);
set timestamp=unix_timestamp('2001-02-04 10:20:55');
alter table t1 add partition (partition p0 history, partition p2 history);
@@ -300,7 +305,15 @@ insert t1 values (4),(5);
set timestamp=unix_timestamp('2001-02-04 10:30:10');
update t1 set i=6 where i=5;
-select subpartition_name,partition_description,table_rows from information_schema.partitions where table_schema='test' and table_name='t1';
+select subpartition_name, partition_description, table_rows from information_schema.partitions where table_schema='test' and table_name='t1';
+select * from t1 partition (p1);
+select * from t1 partition (p0);
+select * from t1 partition (p2);
+
+alter table t1 rebuild partition p0, p1, p2;
+select * from t1 partition (p1);
+select * from t1 partition (p0);
+select * from t1 partition (p2);
--echo ## pruning check
set @ts=(select partition_description from information_schema.partitions
@@ -431,7 +444,6 @@ create or replace table t1 (i int) with system versioning
partition by system_time interval 1 day starts '2000-01-01 00:00:00'
partitions 3;
---echo # we are warned when we push to present:
insert into t1 values (0);
set timestamp= unix_timestamp('2001-01-01 00:00:01');
update t1 set i= i + 1;
@@ -460,8 +472,8 @@ update t1 set i= i + 1;
select *, row_end from t1 partition (p0);
select *, row_end from t1 partition (p1);
-set timestamp= unix_timestamp('2000-01-01 00:00:00');
--echo # and this is how it usually goes:
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
create or replace table t1 (i int) with system versioning
partition by system_time interval 1 day
partitions 3;
@@ -477,7 +489,6 @@ set timestamp= unix_timestamp('2000-01-04 00:00:01');
update t1 set i= i + 1;
alter table t1 add partition (partition p2 history, partition p3 history);
-
select *, row_end from t1 partition (p0);
select *, row_end from t1 partition (p1);
select *, row_end from t1 partition (p2);
@@ -496,9 +507,9 @@ insert into t1 (x) values (1), (2), (3), (4), (5);
select * from t1 partition (pnsp0);
select * from t1 partition (pnsp1);
---echo ### warn about full partition
delete from t1 where x < 3;
delete from t1;
+--echo ### warn about full partition
delete from t1;
select * from t1 partition (p0sp0);
select * from t1 partition (p0sp1);
@@ -976,16 +987,15 @@ create or replace table t1 (
insert into t1 () values (),(),(),(),(),(),(),(),(),(),(),(),(),(),(),();
-select * into outfile 'load.data' from t1;
-load data infile 'load.data' replace into table t1;
+select * into outfile 'MDEV-17891.data' from t1;
+load data infile 'MDEV-17891.data' replace into table t1;
--error ER_RECORD_FILE_FULL
-load data infile 'load.data' replace into table t1;
+load data infile 'MDEV-17891.data' replace into table t1;
--error ER_RECORD_FILE_FULL
-load data infile 'load.data' replace into table t1;
+load data infile 'MDEV-17891.data' replace into table t1;
# Cleanup
---let $datadir= `select @@datadir`
---remove_file $datadir/test/load.data
+--remove_file $datadir/test/MDEV-17891.data
eval set @@max_heap_table_size= $max_heap_table_size_orig;
drop table t1;
@@ -1095,18 +1105,7 @@ alter table t1 add partition partitions 2;
--replace_result $default_engine DEFAULT_ENGINE
show create table t1;
alter table t1 add partition partitions 8;
---replace_result $default_engine DEFAULT_ENGINE
-show create table t1;
-
-drop tables t1;
-
---disable_prepare_warnings
-
---echo #
---echo # End of 10.5 tests
---echo #
-
-SET GLOBAL innodb_stats_persistent=@save_persistent;
+drop table t1;
--echo # End of 10.6 tests
@@ -1309,4 +1308,567 @@ show create table t1;
drop tables t1, tp1;
}
+--echo #
+--echo # MDEV-17554 Auto-create new partition for system versioned tables with history partitioned by INTERVAL/LIMIT
+--echo #
+create or replace table t1 (x int) with system versioning
+partition by system_time limit 1 auto;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+insert into t1 values (1);
+
+create or replace table t2 (y int);
+insert into t2 values (2);
+
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+--echo # Too many partitions error
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t1 (x int) with system versioning
+partition by system_time interval 1 hour auto;
+set timestamp= unix_timestamp('2001-01-01 00:01:00');
+--error ER_VERS_HIST_PART_FAILED
+update t1 set x= x + 1;
+show warnings;
+
+--echo # Auto-create failed error
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t1 (x int) with system versioning engine innodb
+partition by system_time interval 1 hour auto;
+
+insert into t1 values (1);
+
+call mtr.add_suppression("rror number .*(File exists|file operation)");
+call mtr.add_suppression("InnoDB: Cannot create file");
+
+--let $datadir= `select @@datadir`
+--let $dummy= $datadir/test/t1#P#p1.ibd
+--write_file $dummy
+EOF
+
+set timestamp= unix_timestamp('2000-01-01 01:00:00');
+--error ER_GET_ERRNO
+update t1 set x= x + 2;
+show warnings;
+--remove_file $dummy
+
+--echo # Partition overflow error and manual fix
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t1 (x int) with system versioning
+partition by system_time interval 1 hour;
+
+insert into t1 values (440);
+set timestamp= unix_timestamp('2000-01-01 00:10:00');
+update t1 set x= x + 1;
+
+--echo # Check how pruning boundaries work
+--replace_column 5 # 10 # 11 #
+explain partitions select * from t1 for system_time as of '2000-01-01 00:59:58';
+--replace_column 5 # 10 # 11 #
+explain partitions select * from t1 for system_time as of '2000-01-01 00:59:59';
+--replace_column 5 # 10 # 11 #
+explain partitions select * from t1 for system_time as of '2000-01-01 01:00:00';
+select * from t1 for system_time as of '2000-01-01 00:09:59';
+
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+update t1 set x= x + 1;
+
+select * from t1 for system_time as of '2000-01-01 01:00:00';
+select * from t1 partition (p0) order by x;
+
+--echo # Here is how manual fix works: just add new partitions there
+alter table t1 add partition partitions 3;
+select * from t1 for system_time as of '2000-01-01 01:00:00';
+select * from t1 partition (p0) order by x;
+
+--echo # Check pruning after ALTER
+--replace_column 5 # 10 # 11 #
+explain partitions select * from t1 for system_time as of '2000-01-01 00:59:58';
+--replace_column 5 # 10 # 11 #
+explain partitions select * from t1 for system_time as of '2000-01-01 00:59:59';
+--replace_column 5 # 10 # 11 #
+explain partitions select * from t1 for system_time as of '2000-01-01 01:00:00';
+
+drop table t1;
+
+--enable_info
+create or replace table t1 (x int) with system versioning
+partition by system_time interval 3600 second
+starts '2000-01-01 00:00:00' auto partitions 3;
+
+insert into t1 values (1);
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+update t1 set x= x + 1;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+set timestamp= unix_timestamp('2000-01-01 03:00:00');
+update t1 set x= x + 2;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t1 (x int) with system versioning
+partition by system_time interval 1 hour auto (
+ partition p1 history,
+ partition p3 history,
+ partition pn current);
+
+insert into t1 values (1);
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+update t1 set x= x + 3;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+set timestamp= unix_timestamp('2000-01-01 03:00:00');
+update t1 set x= x + 4;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+set timestamp= unix_timestamp('2000-01-01 04:00:00');
+lock tables t1 write;
+update t1 set x= x + 5;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+unlock tables;
+set timestamp= default;
+
+--echo # Couple of more LOCK TABLES cases
+create or replace table t1 (x int) with system versioning
+partition by system_time limit 1 auto;
+lock tables t1 write;
+insert into t1 values (1);
+update t1 set x= x + 1;
+update t1 set x= x + 1;
+update t1 set x= x + 1;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+unlock tables;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+--echo # Overflow prevention under LOCK TABLES
+create or replace table t1 (x int)
+with system versioning partition by system_time
+limit 10 auto;
+
+insert into t1 values (1), (2), (3), (4), (5), (6), (7), (8), (9);
+update t1 set x= x + 10;
+
+lock tables t1 write;
+update t1 set x= 1 where x = 11;
+update t1 set x= 2 where x = 12;
+update t1 set x= 3 where x = 13;
+unlock tables;
+
+select count(x) from t1 partition (p0);
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+drop tables t1;
+
+--echo # Test VIEW, LOCK TABLES
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t1 (x int) with system versioning
+partition by system_time interval 1 hour auto;
+create or replace view v1 as select * from t1;
+
+insert into t1 values (1);
+set timestamp= unix_timestamp('2000-01-01 01:00:00');
+update v1 set x= x + 2;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+lock tables v1 write;
+update v1 set x= x + 3;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+unlock tables;
+
+drop view v1;
+drop tables t1;
+
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t1 (x int) with system versioning
+partition by system_time interval 1 hour auto partitions 3;
+
+create or replace table t2 (y int) with system versioning
+partition by system_time interval 1 hour auto;
+
+insert into t1 values (1);
+insert into t2 values (2);
+
+set timestamp= unix_timestamp('2000-01-01 01:00:00');
+update t1, t2 set x= x + 1, y= y + 1;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t2;
+
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+update t1, t2 set x= x + 1, y= y + 1;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t2;
+
+set timestamp= unix_timestamp('2000-01-01 03:00:00');
+update t1, t2 set t1.x= 0 where t1.x< t2.y;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+# Multiupdate_prelocking_strategy::handle_end() is processed after table open.
+# For PS it is possible to skip unneeded auto-creation because the above happens at
+# prepare stage and auto-creation is done at execute stage.
+--replace_result $default_engine DEFAULT_ENGINE 'PARTITIONS 4' 'PARTITIONS ok' 'PARTITIONS 5' 'PARTITIONS ok'
+show create table t2;
+
+drop tables t1, t2;
+
+--echo # PS, SP, LOCK TABLES
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t1 (x int) with system versioning
+partition by system_time interval 1 hour auto;
+
+insert into t1 values (1);
+
+set timestamp= unix_timestamp('2000-01-01 01:00:00');
+execute immediate 'update t1 set x= x + 5';
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+prepare s from 'update t1 set x= x + 6';
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+execute s; execute s;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+set timestamp= unix_timestamp('2000-01-01 03:00:00');
+lock tables t1 write;
+execute s; execute s;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+unlock tables;
+drop prepare s;
+
+create procedure sp() update t1 set x= x + 7;
+set timestamp= unix_timestamp('2000-01-01 04:00:00');
+call sp; call sp;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+set timestamp= unix_timestamp('2000-01-01 05:00:00');
+lock tables t1 write;
+call sp; call sp;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+unlock tables;
+drop procedure sp;
+
+set timestamp= unix_timestamp('2001-01-01 00:00:00');
+create or replace table t1 (i int) with system versioning
+partition by system_time interval 1 day starts '2001-01-01 00:00:00';
+insert into t1 values (0);
+set timestamp= unix_timestamp('2001-01-01 00:00:01');
+prepare s from 'update t1 set i= i + 1';
+execute s;
+set timestamp= unix_timestamp('2001-01-02 00:00:01');
+execute s;
+drop prepare s;
+
+# Because of blobs:
+if (!$MTR_COMBINATION_HEAP)
+{
+--echo # Complex table
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t1 (
+ x int primary key auto_increment,
+ t timestamp(6) default '2001-11-11 11:11:11',
+ b blob(4096) compressed null,
+ c varchar(1033) character set utf8 not null,
+ u int unique,
+ m enum('a', 'b', 'c') not null default 'a' comment 'absolute',
+ i1 tinyint, i2 smallint, i3 bigint,
+ index three(i1, i2, i3),
+ v1 timestamp(6) generated always as (t + interval 1 day),
+ v2 timestamp(6) generated always as (t + interval 1 month) stored,
+ s timestamp(6) as row start,
+ e timestamp(6) as row end,
+ period for system_time (s, e),
+ ps date, pe date,
+ period for app_time (ps, pe),
+ constraint check_constr check (u > -1))
+with system versioning default charset=ucs2
+partition by system_time interval 1 hour auto (
+ partition p2 history,
+ partition pn current);
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+insert into t1 (x, c, u, i1, i2, i3, ps, pe)
+values (1, 'cc', 0, 1, 2, 3, '1999-01-01', '2000-01-01');
+set timestamp= unix_timestamp('2000-01-01 01:00:00');
+update t1 set x= x + 8;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+update t1 set x= x - 8;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+}
+--disable_info
+
+--echo # INSERT .. ON DUPLICATE KEY UPDATE (ODKU)
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t1 (x int primary key) with system versioning
+partition by system_time interval 1 hour auto;
+insert into t1 values (1);
+set timestamp= unix_timestamp('2000-01-01 01:00:00');
+insert into t1 values (1) on duplicate key update x= x + 1;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+--echo # LOAD DATA .. REPLACE
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t1 (x int primary key) with system versioning
+partition by system_time interval 1 hour auto;
+
+insert t1 values (1), (2), (3);
+select x into outfile 'MDEV-17554.data' from t1;
+
+set timestamp= unix_timestamp('2000-01-01 01:00:00');
+load data infile 'MDEV-17554.data' replace into table t1 (x);
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+--remove_file $datadir/test/MDEV-17554.data
+
+--echo # Concurrent DML
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t1 (x int) with system versioning
+partition by system_time interval 1 hour auto partitions 3;
+
+insert into t1 values (1);
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+--connect con8, localhost, root
+--connect con7, localhost, root
+--connect con6, localhost, root
+--connect con5, localhost, root
+--connect con4, localhost, root
+--connect con3, localhost, root
+--connect con2, localhost, root
+--connect con1, localhost, root
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+send update t1 set x= x + 10;
+--connection con2
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+send update t1 set x= x + 20;
+--connection con3
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+send update t1 set x= x + 30;
+--connection con4
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+send update t1 set x= x + 40;
+--connection con5
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+send update t1 set x= x + 50;
+--connection con6
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+send update t1 set x= x + 60;
+--connection con7
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+send update t1 set x= x + 70;
+--connection con8
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+update t1 set x= x + 80;
+--connection con1
+reap;
+--disconnect con1
+--connection con2
+reap;
+--disconnect con2
+--connection con3
+reap;
+--disconnect con3
+--connection con4
+reap;
+--disconnect con4
+--connection con5
+reap;
+--disconnect con5
+--connection con6
+reap;
+--disconnect con6
+--connection con7
+reap;
+--disconnect con7
+--disconnect con8
+--connection default
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+drop tables t1;
+set timestamp= default;
+
+--echo # Transaction
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t1 (x int) with system versioning engine innodb
+partition by system_time interval 1 hour auto;
+
+insert into t1 values (1);
+set timestamp= unix_timestamp('2000-01-01 01:00:00');
+start transaction;
+update t1 set x= 0;
+--connect con1, localhost, root
+select * from t1;
+show create table t1;
+--connection default
+commit;
+show create table t1;
+
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+start transaction;
+update t1 set x= 1;
+--connection con1
+select * from t1;
+--connection default
+rollback;
+show create table t1;
+--disconnect con1
+--connection default
+drop table t1;
+
+--echo #
+--echo # MDEV-25479 Auto-create: 2nd and further executions of PS or SP fail to create partition
+--echo #
+create table t (a int) with system versioning
+ partition by system_time interval 1 hour auto;
+
+insert into t values (1), (2);
+prepare stmt from "update t set a= a + 1";
+set @@timestamp= @@timestamp + 3601;
+execute stmt;
+set @@timestamp= @@timestamp + 3601;
+execute stmt;
+drop prepare stmt;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t;
+
+create procedure sp() update t set a= a + 1;
+set @@timestamp= @@timestamp + 3601;
+call sp();
+set @@timestamp= @@timestamp + 3601;
+call sp();
+drop procedure sp;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t;
+
+# Cleanup
+drop table t;
+
+--echo #
+--echo # MDEV-23639 Auto-create does not work under LOCK TABLES or inside triggers
+--echo #
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t1 (x int) with system versioning
+partition by system_time interval 1 hour auto
+partitions 3;
+
+create table t2 (x int);
+create table t3 (x int);
+insert into t3 values (3);
+
+create trigger tr after insert on t2 for each row update t1 set x= x + 11;
+create or replace procedure sp() update t1 set x= x + 5;
+create or replace procedure sp2() insert into t2 values (5);
+prepare ps from 'update t1 set x= x + 6';
+prepare ps2 from 'insert into t2 values (6)';
+
+insert into t1 values (1);
+set timestamp= unix_timestamp('2000-01-01 02:00:00');
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+insert into t2 values (2);
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+set timestamp= unix_timestamp('2000-01-01 03:00:00');
+call sp; call sp;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+set timestamp= unix_timestamp('2000-01-01 04:00:00');
+call sp2; call sp2;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+set timestamp= unix_timestamp('2000-01-01 05:00:00');
+execute ps; execute ps;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+set timestamp= unix_timestamp('2000-01-01 06:00:00');
+execute ps2; execute ps2;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+set timestamp= unix_timestamp('2000-01-01 08:00:00');
+lock tables t1 write, t2 write;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+set timestamp= unix_timestamp('2000-01-01 09:00:00');
+update t1 set x= x + 1;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+set timestamp= unix_timestamp('2000-01-01 10:00:00');
+update t1 set x= x + 2;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+update t2 set x= x + 1;
+set timestamp= unix_timestamp('2000-01-01 11:00:00');
+insert into t2 values (4);
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+--error ER_TABLE_NOT_LOCKED
+update t3 set x= x + 1;
+
+set timestamp= unix_timestamp('2000-01-01 12:00:00');
+call sp; call sp;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+set timestamp= unix_timestamp('2000-01-01 13:00:00');
+call sp2; call sp2;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+set timestamp= unix_timestamp('2000-01-01 14:00:00');
+execute ps; execute ps;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+set timestamp= unix_timestamp('2000-01-01 15:00:00');
+execute ps2; execute ps2;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+unlock tables;
+--replace_result $default_engine DEFAULT_ENGINE
+show create table t1;
+
+# Cleanup
+drop tables t1, t2, t3;
+drop procedure sp;
+drop procedure sp2;
+drop prepare ps;
+drop prepare ps2;
+
+--disable_prepare_warnings
+SET GLOBAL innodb_stats_persistent=@save_persistent;
--source suite/versioning/common_finish.inc
diff --git a/mysql-test/suite/versioning/t/rpl.test b/mysql-test/suite/versioning/t/rpl.test
index b5be68feece..0d0a50f71da 100644
--- a/mysql-test/suite/versioning/t/rpl.test
+++ b/mysql-test/suite/versioning/t/rpl.test
@@ -133,4 +133,22 @@ sync_slave_with_master;
connection master;
drop table t1;
+--echo #
+--echo # MDEV-17554 Auto-create new partition for system versioned tables with history partitioned by INTERVAL/LIMIT
+--echo #
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t1 (x int) with system versioning
+partition by system_time interval 1 hour auto;
+insert t1 values ();
+set timestamp= unix_timestamp('2000-01-01 01:00:00');
+delete from t1;
+--replace_result InnoDB ENGINE MyISAM ENGINE MEMORY ENGINE
+show create table t1;
+--sync_slave_with_master
+--replace_result InnoDB ENGINE MyISAM ENGINE MEMORY ENGINE
+show create table t1;
+--connection master
+drop table t1;
+set timestamp= default;
+
--source include/rpl_end.inc
diff --git a/mysql-test/suite/versioning/t/rpl_common.inc b/mysql-test/suite/versioning/t/rpl_common.inc
new file mode 100644
index 00000000000..c37e58f0f96
--- /dev/null
+++ b/mysql-test/suite/versioning/t/rpl_common.inc
@@ -0,0 +1,29 @@
+--source include/have_partition.inc
+
+--echo #
+--echo # MDEV-25347 DML events for auto-partitioned tables are written into binary log twice
+--echo #
+flush binary logs;
+create table t1 (a int) with system versioning
+partition by system_time limit 1 auto;
+
+insert into t1 values (1);
+update t1 set a= a + 1;
+update t1 set a= a + 2;
+--replace_result InnoDB ENGINE MyISAM ENGINE MEMORY ENGINE
+show create table t1;
+select * from t1;
+
+--let $binlog_file=master-bin.000002
+--source include/show_binlog_events.inc
+
+--sync_slave_with_master
+--replace_result InnoDB ENGINE MyISAM ENGINE MEMORY ENGINE
+show create table t1;
+
+select * from t1;
+--connection master
+# cleanup
+drop table t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/versioning/t/rpl_mix.test b/mysql-test/suite/versioning/t/rpl_mix.test
index 64025c74625..bf4e0b93422 100644
--- a/mysql-test/suite/versioning/t/rpl_mix.test
+++ b/mysql-test/suite/versioning/t/rpl_mix.test
@@ -16,4 +16,4 @@ DELETE HISTORY FROM t1;
connection master;
drop table t1;
---source include/rpl_end.inc
+--source rpl_common.inc
diff --git a/mysql-test/suite/versioning/t/rpl_row.test b/mysql-test/suite/versioning/t/rpl_row.test
index 17ce2dfdcf8..a9b12e52a41 100644
--- a/mysql-test/suite/versioning/t/rpl_row.test
+++ b/mysql-test/suite/versioning/t/rpl_row.test
@@ -15,4 +15,4 @@ update t1 set i = 0;
drop table t1;
set binlog_row_image= @old_row_image;
---source include/rpl_end.inc
+--source rpl_common.inc
diff --git a/mysql-test/suite/versioning/t/rpl_stmt.test b/mysql-test/suite/versioning/t/rpl_stmt.test
new file mode 100644
index 00000000000..dca4e8cb4a2
--- /dev/null
+++ b/mysql-test/suite/versioning/t/rpl_stmt.test
@@ -0,0 +1,4 @@
+--source include/have_binlog_format_statement.inc
+--source include/master-slave.inc
+
+--source rpl_common.inc
diff --git a/mysql-test/suite/versioning/t/update-big.test b/mysql-test/suite/versioning/t/update-big.test
index 175bfc79a48..98767cefaad 100644
--- a/mysql-test/suite/versioning/t/update-big.test
+++ b/mysql-test/suite/versioning/t/update-big.test
@@ -1,6 +1,7 @@
source include/big_test.inc;
source suite/versioning/engines.inc;
source suite/versioning/common.inc;
+source include/have_partition.inc;
--echo #
--echo # MDEV-15458 Segfault in heap_scan() upon UPDATE after ADD SYSTEM VERSIONING
@@ -29,6 +30,79 @@ update t1 set a= 8 where a = 1;
update t1 set a= 4 where a = 8;
update t1 set a= 6;
+--disconnect con1
drop table t1;
+call mtr.add_suppression("need more HISTORY partitions");
+
+--echo #
+--echo # MDEV-23642 Locking timeout caused by auto-creation affects original DML
+--echo #
+set timestamp= unix_timestamp('2000-01-01 00:00:00');
+create or replace table t1 (x int primary key) with system versioning engine innodb
+partition by system_time interval 1 hour auto;
+
+insert into t1 values (1);
+start transaction;
+insert into t1 values (2);
+
+--connect con1, localhost, root
+set lock_wait_timeout= 1;
+set innodb_lock_wait_timeout= 1;
+set timestamp= unix_timestamp('2000-01-01 01:00:01');
+update t1 set x= x + 122 where x = 1;
+--disconnect con1
+--connection default
+select * from t1;
+
+# cleanup
+drop table t1;
+set timestamp= default;
+
+--echo #
+--echo # MDEV-25339 Assertion `thd->transaction.stmt.is_empty() || thd->in_sub_stmt' failed
+--echo #
+create or replace table t1 (x int) with system versioning engine innodb
+partition by system_time interval 1 hour auto;
+start transaction;
+insert into t1 values (1);
+select * from t1;
+
+--connect con1, localhost, root
+set lock_wait_timeout= 1;
+set innodb_lock_wait_timeout= 1;
+--error ER_LOCK_WAIT_TIMEOUT
+update t1 set x= x + 111;
+select * from t1;
+
+# cleanup
+--disconnect con1
+--connection default
+drop table t1;
+
+--echo #
+--echo # MDEV-25482 Auto-create: Server hangs after a failed attempt to create partition
+--echo #
+set timestamp= default;
+create table t (pk int primary key, a int) engine=InnoDB
+ with system versioning partition by system_time interval 1 hour auto;
+
+insert into t values (1,1),(2,2),(3,3),(4,4),(5,5);
+
+start transaction;
+update t set a= 20 where pk = 2;
+
+--connect (con1,localhost,root,,)
+set lock_wait_timeout= 1;
+set @@timestamp= @@timestamp+3601;
+update t set a= 40 where pk = 4;
+update t set a= 400 where pk = 4;
+
+# Cleanup
+--disconnect con1
+--connection default
+select * from t where pk = 4;
+rollback;
+drop tables t;
+
source suite/versioning/common_finish.inc;
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index f17abed82ff..9ab9f2a9552 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -4097,18 +4097,9 @@ int ha_partition::external_lock(THD *thd, int lock_type)
(void) (*file)->ha_external_lock(thd, lock_type);
} while (*(++file));
}
- if (lock_type == F_WRLCK)
- {
- if (m_part_info->part_expr)
- m_part_info->part_expr->walk(&Item::register_field_in_read_map, 1, 0);
- if (m_part_info->part_type == VERSIONING_PARTITION &&
- /* TODO: MDEV-20345 exclude more inapproriate commands like INSERT
- These commands may be excluded because working history partition is needed
- only for versioned DML. */
- thd->lex->sql_command != SQLCOM_SELECT &&
- thd->lex->sql_command != SQLCOM_INSERT_SELECT)
- m_part_info->vers_set_hist_part(thd);
- }
+ if (lock_type == F_WRLCK && m_part_info->part_expr)
+ m_part_info->part_expr->walk(&Item::register_field_in_read_map, 1, 0);
+
DBUG_RETURN(0);
err_handler:
@@ -4252,11 +4243,6 @@ int ha_partition::start_stmt(THD *thd, thr_lock_type lock_type)
{
if (m_part_info->part_expr)
m_part_info->part_expr->walk(&Item::register_field_in_read_map, 1, 0);
- if (m_part_info->part_type == VERSIONING_PARTITION &&
- // TODO: MDEV-20345 (see above)
- thd->lex->sql_command != SQLCOM_SELECT &&
- thd->lex->sql_command != SQLCOM_INSERT_SELECT)
- m_part_info->vers_set_hist_part(thd);
}
DBUG_RETURN(error);
}
diff --git a/sql/ha_partition.h b/sql/ha_partition.h
index 14f68b36c0b..90c556635a3 100644
--- a/sql/ha_partition.h
+++ b/sql/ha_partition.h
@@ -1608,6 +1608,13 @@ public:
}
bool partition_engine() override { return 1;}
+
+ /**
+ Get the number of records in part_elem and its subpartitions, if any.
+ Also sets read_partitions bit for each partition id it uses (that is needed
+ for vers_set_hist_part() because it is called before read_partitions bitmap
+ is initialized).
+ */
ha_rows part_records(partition_element *part_elem)
{
DBUG_ASSERT(m_part_info);
@@ -1619,7 +1626,7 @@ public:
for (; part_id < part_id_end; ++part_id)
{
handler *file= m_file[part_id];
- DBUG_ASSERT(bitmap_is_set(&(m_part_info->read_partitions), part_id));
+ bitmap_set_bit(&(m_part_info->read_partitions), part_id);
file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_OPEN);
part_recs+= file->stats.records;
}
diff --git a/sql/handler.cc b/sql/handler.cc
index 57992d98c04..cf3abe06f38 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -1635,9 +1635,10 @@ int ha_commit_trans(THD *thd, bool all)
DBUG_ASSERT(thd->transaction->stmt.ha_list == NULL ||
trans == &thd->transaction->stmt);
+ DBUG_ASSERT(!thd->in_sub_stmt);
+
if (thd->in_sub_stmt)
{
- DBUG_ASSERT(0);
/*
Since we don't support nested statement transactions in 5.0,
we can't commit or rollback stmt transactions while we are inside
diff --git a/sql/handler.h b/sql/handler.h
index fe61666bf20..40f5eb0f1ab 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -832,6 +832,8 @@ typedef bool Log_func(THD*, TABLE*, bool, const uchar*, const uchar*);
#define ALTER_PARTITION_TABLE_REORG (1ULL << 12)
#define ALTER_PARTITION_CONVERT_IN (1ULL << 13)
#define ALTER_PARTITION_CONVERT_OUT (1ULL << 14)
+// Set for vers_add_auto_hist_parts() operation
+#define ALTER_PARTITION_AUTO_HIST (1ULL << 15)
/*
This is master database for most of system tables. However there
@@ -2148,7 +2150,6 @@ struct Vers_parse_info: public Table_period_info
Table_period_info::start_end_t as_row;
-protected:
friend struct Table_scope_and_contents_source_st;
void set_start(const LEX_CSTRING field_name)
{
@@ -2160,6 +2161,8 @@ protected:
as_row.end= field_name;
period.end= field_name;
}
+
+protected:
bool is_start(const char *name) const;
bool is_end(const char *name) const;
bool is_start(const Create_field &f) const;
@@ -4257,6 +4260,8 @@ public:
*/
virtual uint lock_count(void) const { return 1; }
/**
+ Get the lock(s) for the table and perform conversion of locks if needed.
+
Is not invoked for non-transactional temporary tables.
@note store_lock() can return more than one lock if the table is MERGE
diff --git a/sql/lock.cc b/sql/lock.cc
index 2eba5df35f1..bfa3e7baa0f 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -654,7 +654,7 @@ bool mysql_lock_abort_for_thread(THD *thd, TABLE *table)
a and b are freed with my_free()
*/
-MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b)
+MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a, MYSQL_LOCK *b, THD *thd)
{
MYSQL_LOCK *sql_lock;
TABLE **table, **end_table;
@@ -662,16 +662,28 @@ MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b)
DBUG_PRINT("enter", ("a->lock_count: %u b->lock_count: %u",
a->lock_count, b->lock_count));
- if (!(sql_lock= (MYSQL_LOCK*)
- my_malloc(key_memory_MYSQL_LOCK, sizeof(*sql_lock) +
- sizeof(THR_LOCK_DATA*)*((a->lock_count+b->lock_count)*2) +
- sizeof(TABLE*)*(a->table_count+b->table_count),MYF(MY_WME))))
- DBUG_RETURN(0); // Fatal error
+ const size_t lock_size= sizeof(*sql_lock) +
+ sizeof(THR_LOCK_DATA *) * ((a->lock_count + b->lock_count) * 2) +
+ sizeof(TABLE *) * (a->table_count + b->table_count);
+ if (thd)
+ {
+ sql_lock= (MYSQL_LOCK *) thd->alloc(lock_size);
+ if (!sql_lock)
+ DBUG_RETURN(0);
+ sql_lock->flags= GET_LOCK_ON_THD;
+ }
+ else
+ {
+ sql_lock= (MYSQL_LOCK *)
+ my_malloc(key_memory_MYSQL_LOCK, lock_size, MYF(MY_WME));
+ if (!sql_lock)
+ DBUG_RETURN(0);
+ sql_lock->flags= 0;
+ }
sql_lock->lock_count=a->lock_count+b->lock_count;
sql_lock->table_count=a->table_count+b->table_count;
sql_lock->locks=(THR_LOCK_DATA**) (sql_lock+1);
sql_lock->table=(TABLE**) (sql_lock->locks+sql_lock->lock_count*2);
- sql_lock->flags= 0;
memcpy(sql_lock->locks,a->locks,a->lock_count*sizeof(*a->locks));
memcpy(sql_lock->locks+a->lock_count,b->locks,
b->lock_count*sizeof(*b->locks));
@@ -705,8 +717,10 @@ MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b)
a->lock_count, b->lock_count);
/* Delete old, not needed locks */
- my_free(a);
- my_free(b);
+ if (!(a->flags & GET_LOCK_ON_THD))
+ my_free(a);
+ if (!(b->flags & GET_LOCK_ON_THD))
+ my_free(b);
DBUG_RETURN(sql_lock);
}
diff --git a/sql/lock.h b/sql/lock.h
index 0b23ddd3846..85a93b9a7e3 100644
--- a/sql/lock.h
+++ b/sql/lock.h
@@ -34,7 +34,7 @@ int mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock);
int mysql_unlock_some_tables(THD *thd, TABLE **table,uint count, uint flag);
int mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table);
bool mysql_lock_abort_for_thread(THD *thd, TABLE *table);
-MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b);
+MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a, MYSQL_LOCK *b, THD *thd= NULL);
/* Lock based on name */
bool lock_schema_name(THD *thd, const char *db);
/* Lock based on stored routine name */
diff --git a/sql/log_event.cc b/sql/log_event.cc
index afca79b008a..5206b1834fe 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -4108,3 +4108,16 @@ bool copy_event_cache_to_file_and_reinit(IO_CACHE *cache, FILE *file)
return (my_b_copy_all_to_file(cache, file) ||
reinit_io_cache(cache, WRITE_CACHE, 0, FALSE, TRUE));
}
+
+#if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION)
+int Log_event::apply_event(rpl_group_info* rgi)
+{
+ int res;
+ THD_STAGE_INFO(thd, stage_apply_event);
+ rgi->current_event= this;
+ res= do_apply_event(rgi);
+ rgi->current_event= NULL;
+ THD_STAGE_INFO(thd, stage_after_apply_event);
+ return res;
+}
+#endif
diff --git a/sql/log_event.h b/sql/log_event.h
index 3adc7a26d93..e2479724972 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -1509,14 +1509,7 @@ public:
@see do_apply_event
*/
- int apply_event(rpl_group_info *rgi)
- {
- int res;
- THD_STAGE_INFO(thd, stage_apply_event);
- res= do_apply_event(rgi);
- THD_STAGE_INFO(thd, stage_after_apply_event);
- return res;
- }
+ int apply_event(rpl_group_info *rgi);
/**
diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc
index 2e4992a021e..179d1f067f0 100644
--- a/sql/log_event_server.cc
+++ b/sql/log_event_server.cc
@@ -5475,6 +5475,18 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
lex->query_tables_last= &tables->next_global;
}
}
+
+ /*
+ It is needed to set_time():
+ 1) it continues the property that "Time" in SHOW PROCESSLIST shows how
+ much slave is behind
+ 2) it will be needed when we allow replication from a table with no
+ TIMESTAMP column to a table with one.
+ So we call set_time(), like in SBR. Presently it changes nothing.
+ 3) vers_set_hist_part() requires proper query time.
+ */
+ thd->set_time(when, when_sec_part);
+
if (unlikely(open_and_lock_tables(thd, rgi->tables_to_lock, FALSE, 0)))
{
#ifdef WITH_WSREP
@@ -5651,16 +5663,6 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
which tested replicate-* rules).
*/
- /*
- It's not needed to set_time() but
- 1) it continues the property that "Time" in SHOW PROCESSLIST shows how
- much slave is behind
- 2) it will be needed when we allow replication from a table with no
- TIMESTAMP column to a table with one.
- So we call set_time(), like in SBR. Presently it changes nothing.
- */
- thd->set_time(when, when_sec_part);
-
if (m_width == table->s->fields && bitmap_is_set_all(&m_cols))
set_flags(COMPLETE_ROWS_F);
diff --git a/sql/partition_info.cc b/sql/partition_info.cc
index 62a3092f369..23194e43d06 100644
--- a/sql/partition_info.cc
+++ b/sql/partition_info.cc
@@ -38,6 +38,8 @@
#ifdef WITH_PARTITION_STORAGE_ENGINE
#include "ha_partition.h"
+#include "sql_table.h"
+#include "transaction.h"
partition_info *partition_info::get_clone(THD *thd)
@@ -324,13 +326,11 @@ bool partition_info::set_partition_bitmaps_from_table(TABLE_LIST *table_list)
The external routine needing this code is check_partition_info
*/
-#define MAX_PART_NAME_SIZE 8
-
char *partition_info::create_default_partition_names(THD *thd, uint part_no,
uint num_parts_arg,
uint start_no)
{
- char *ptr= (char*) thd->calloc(num_parts_arg * MAX_PART_NAME_SIZE);
+ char *ptr= (char*) thd->calloc(num_parts_arg * MAX_PART_NAME_SIZE + 1);
char *move_ptr= ptr;
uint i= 0;
DBUG_ENTER("create_default_partition_names");
@@ -819,10 +819,15 @@ bool partition_info::has_unique_name(partition_element *element)
vers_info->interval Limit by fixed time interval
vers_info->hist_part (out) Working history partition
*/
-void partition_info::vers_set_hist_part(THD *thd)
+bool partition_info::vers_set_hist_part(THD *thd, uint *create_count)
{
+ DBUG_ASSERT(!thd->lex->last_table() ||
+ !thd->lex->last_table()->vers_conditions.delete_history);
+ const bool auto_hist= create_count && vers_info->auto_hist;
+
if (vers_info->limit)
{
+ DBUG_ASSERT(!vers_info->interval.is_set());
ha_partition *hp= (ha_partition*)(table->file);
partition_element *next= NULL;
List_iterator<partition_element> it(partitions);
@@ -841,22 +846,22 @@ void partition_info::vers_set_hist_part(THD *thd)
{
if (next == vers_info->now_part)
{
- my_error(WARN_VERS_PART_FULL, MYF(ME_WARNING|ME_ERROR_LOG),
- table->s->db.str, table->s->table_name.str,
- vers_info->hist_part->partition_name, "LIMIT");
+ if (auto_hist)
+ *create_count= 1;
+ else
+ my_error(WARN_VERS_PART_FULL, MYF(ME_WARNING|ME_ERROR_LOG),
+ table->s->db.str, table->s->table_name.str,
+ vers_info->hist_part->partition_name, "LIMIT");
}
else
vers_info->hist_part= next;
}
- return;
}
-
- if (vers_info->interval.is_set())
+ else if (vers_info->interval.is_set() &&
+ vers_info->hist_part->range_value <= thd->query_start())
{
- if (vers_info->hist_part->range_value > thd->query_start())
- return;
-
partition_element *next= NULL;
+ bool error= true;
List_iterator<partition_element> it(partitions);
while (next != vers_info->hist_part)
next= it++;
@@ -865,9 +870,166 @@ void partition_info::vers_set_hist_part(THD *thd)
{
vers_info->hist_part= next;
if (next->range_value > thd->query_start())
- return;
+ {
+ error= false;
+ break;
+ }
+ }
+ if (error)
+ {
+ if (auto_hist)
+ {
+ *create_count= 0;
+ const my_time_t hist_end= (my_time_t) vers_info->hist_part->range_value;
+ DBUG_ASSERT(thd->query_start() >= hist_end);
+ MYSQL_TIME h0, q0;
+ my_tz_OFFSET0->gmt_sec_to_TIME(&h0, hist_end);
+ my_tz_OFFSET0->gmt_sec_to_TIME(&q0, thd->query_start());
+ longlong q= pack_time(&q0);
+ longlong h= pack_time(&h0);
+ while (h <= q)
+ {
+ if (date_add_interval(thd, &h0, vers_info->interval.type,
+ vers_info->interval.step))
+ return true;
+ h= pack_time(&h0);
+ ++*create_count;
+ if (*create_count == MAX_PARTITIONS - 2)
+ {
+ my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(ME_WARNING));
+ my_error(ER_VERS_HIST_PART_FAILED, MYF(0),
+ table->s->db.str, table->s->table_name.str);
+ return true;
+ }
+ }
+ }
+ else
+ {
+ my_error(WARN_VERS_PART_FULL, MYF(ME_WARNING|ME_ERROR_LOG),
+ table->s->db.str, table->s->table_name.str,
+ vers_info->hist_part->partition_name, "INTERVAL");
+ }
+ }
+ }
+
+ return false;
+}
+
+
+/**
+ @brief Run fast_alter_partition_table() to add new history partitions
+ for tables requiring them.
+*/
+bool vers_create_partitions(THD *thd, TABLE_LIST* tl, uint num_parts)
+{
+ bool result= true;
+ HA_CREATE_INFO create_info;
+ Alter_info alter_info;
+ partition_info *save_part_info= thd->work_part_info;
+ Query_tables_list save_query_tables;
+ Reprepare_observer *save_reprepare_observer= thd->m_reprepare_observer;
+ bool save_no_write_to_binlog= thd->lex->no_write_to_binlog;
+ thd->m_reprepare_observer= NULL;
+ thd->lex->reset_n_backup_query_tables_list(&save_query_tables);
+ thd->lex->no_write_to_binlog= true;
+ TABLE *table= tl->table;
+
+ DBUG_ASSERT(!thd->is_error());
+
+ {
+ DBUG_ASSERT(table->s->get_table_ref_type() == TABLE_REF_BASE_TABLE);
+ DBUG_ASSERT(table->versioned());
+ DBUG_ASSERT(table->part_info);
+ DBUG_ASSERT(table->part_info->vers_info);
+ alter_info.reset();
+ alter_info.partition_flags= ALTER_PARTITION_ADD|ALTER_PARTITION_AUTO_HIST;
+ create_info.init();
+ create_info.alter_info= &alter_info;
+ Alter_table_ctx alter_ctx(thd, tl, 1, &table->s->db, &table->s->table_name);
+
+ MDL_REQUEST_INIT(&tl->mdl_request, MDL_key::TABLE, tl->db.str,
+ tl->table_name.str, MDL_SHARED_NO_WRITE, MDL_TRANSACTION);
+ if (thd->mdl_context.acquire_lock(&tl->mdl_request,
+ thd->variables.lock_wait_timeout))
+ goto exit;
+ table->mdl_ticket= tl->mdl_request.ticket;
+
+ create_info.db_type= table->s->db_type();
+ create_info.options|= HA_VERSIONED_TABLE;
+ DBUG_ASSERT(create_info.db_type);
+
+ create_info.vers_info.set_start(table->s->vers_start_field()->field_name);
+ create_info.vers_info.set_end(table->s->vers_end_field()->field_name);
+
+ partition_info *part_info= new partition_info();
+ if (unlikely(!part_info))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ goto exit;
+ }
+ part_info->use_default_num_partitions= false;
+ part_info->use_default_num_subpartitions= false;
+ part_info->num_parts= num_parts;
+ part_info->num_subparts= table->part_info->num_subparts;
+ part_info->subpart_type= table->part_info->subpart_type;
+ if (unlikely(part_info->vers_init_info(thd)))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ goto exit;
+ }
+
+ thd->work_part_info= part_info;
+ if (part_info->set_up_defaults_for_partitioning(thd, table->file, NULL,
+ table->part_info->next_part_no(num_parts)))
+ {
+ my_error(ER_VERS_HIST_PART_FAILED, MYF(ME_WARNING),
+ tl->db.str, tl->table_name.str);
+ goto exit;
+ }
+ bool partition_changed= false;
+ bool fast_alter_partition= false;
+ if (prep_alter_part_table(thd, table, &alter_info, &create_info,
+ &partition_changed, &fast_alter_partition))
+ {
+ my_error(ER_VERS_HIST_PART_FAILED, MYF(ME_WARNING),
+ tl->db.str, tl->table_name.str);
+ goto exit;
+ }
+ if (!fast_alter_partition)
+ {
+ my_error(ER_VERS_HIST_PART_FAILED, MYF(ME_WARNING),
+ tl->db.str, tl->table_name.str);
+ goto exit;
+ }
+ DBUG_ASSERT(partition_changed);
+ if (mysql_prepare_alter_table(thd, table, &create_info, &alter_info,
+ &alter_ctx))
+ {
+ my_error(ER_VERS_HIST_PART_FAILED, MYF(ME_WARNING),
+ tl->db.str, tl->table_name.str);
+ goto exit;
+ }
+
+ if (fast_alter_partition_table(thd, table, &alter_info, &alter_ctx,
+ &create_info, tl))
+ {
+ my_error(ER_VERS_HIST_PART_FAILED, MYF(ME_WARNING),
+ tl->db.str, tl->table_name.str);
+ goto exit;
}
}
+
+ result= false;
+ // NOTE: we have to return DA_EMPTY for new command
+ DBUG_ASSERT(thd->get_stmt_da()->is_ok());
+ thd->get_stmt_da()->reset_diagnostics_area();
+
+exit:
+ thd->work_part_info= save_part_info;
+ thd->m_reprepare_observer= save_reprepare_observer;
+ thd->lex->restore_backup_query_tables_list(&save_query_tables);
+ thd->lex->no_write_to_binlog= save_no_write_to_binlog;
+ return result;
}
@@ -2642,13 +2804,14 @@ bool partition_info::vers_init_info(THD * thd)
bool partition_info::vers_set_interval(THD* thd, Item* interval,
interval_type int_type, Item* starts,
- const char *table_name)
+ bool auto_hist, const char *table_name)
{
DBUG_ASSERT(part_type == VERSIONING_PARTITION);
MYSQL_TIME ltime;
uint err;
vers_info->interval.type= int_type;
+ vers_info->auto_hist= auto_hist;
/* 1. assign INTERVAL to interval.step */
if (interval->fix_fields_if_needed_for_scalar(thd, &interval))
@@ -2730,6 +2893,23 @@ interval_starts_error:
}
+bool partition_info::vers_set_limit(ulonglong limit, bool auto_hist,
+ const char *table_name)
+{
+ DBUG_ASSERT(part_type == VERSIONING_PARTITION);
+
+ if (limit < 1)
+ {
+ my_error(ER_PART_WRONG_VALUE, MYF(0), table_name, "LIMIT");
+ return true;
+ }
+
+ vers_info->limit= limit;
+ vers_info->auto_hist= auto_hist;
+ return !limit;
+}
+
+
bool partition_info::error_if_requires_values() const
{
switch (part_type) {
diff --git a/sql/partition_info.h b/sql/partition_info.h
index 995147d6766..cbd6ace8fa4 100644
--- a/sql/partition_info.h
+++ b/sql/partition_info.h
@@ -36,11 +36,11 @@ struct st_ddl_log_memory_entry;
#define MAX_PART_NAME_SIZE 8
-
struct Vers_part_info : public Sql_alloc
{
Vers_part_info() :
limit(0),
+ auto_hist(false),
now_part(NULL),
hist_part(NULL)
{
@@ -49,6 +49,7 @@ struct Vers_part_info : public Sql_alloc
Vers_part_info(Vers_part_info &src) :
interval(src.interval),
limit(src.limit),
+ auto_hist(src.auto_hist),
now_part(NULL),
hist_part(NULL)
{
@@ -72,9 +73,10 @@ struct Vers_part_info : public Sql_alloc
my_time_t start;
INTERVAL step;
enum interval_type type;
- bool is_set() { return type < INTERVAL_LAST; }
+ bool is_set() const { return type < INTERVAL_LAST; }
} interval;
ulonglong limit;
+ bool auto_hist;
partition_element *now_part;
partition_element *hist_part;
};
@@ -393,14 +395,9 @@ public:
bool vers_init_info(THD *thd);
bool vers_set_interval(THD *thd, Item *interval,
interval_type int_type, Item *starts,
- const char *table_name);
- bool vers_set_limit(ulonglong limit)
- {
- DBUG_ASSERT(part_type == VERSIONING_PARTITION);
- vers_info->limit= limit;
- return !limit;
- }
- void vers_set_hist_part(THD *thd);
+ bool auto_part, const char *table_name);
+ bool vers_set_limit(ulonglong limit, bool auto_part, const char *table_name);
+ bool vers_set_hist_part(THD* thd, uint *create_count);
bool vers_fix_field_list(THD *thd);
void vers_update_el_ids();
partition_element *get_partition(uint part_id)
@@ -419,6 +416,7 @@ public:
uint32 get_next_partition_id_range(struct st_partition_iter* part_iter);
bool check_partition_dirs(partition_info *part_info);
+bool vers_create_partitions(THD* thd, TABLE_LIST* tl, uint num_parts);
/* Initialize the iterator to return a single partition with given part_id */
@@ -474,11 +472,6 @@ bool partition_info::vers_fix_field_list(THD * thd)
}
-/**
- @brief Update partition_element's id
-
- @returns true on error; false on success
-*/
inline
void partition_info::vers_update_el_ids()
{
diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h
index cc807852bf2..056f484f3b0 100644
--- a/sql/rpl_rli.h
+++ b/sql/rpl_rli.h
@@ -668,6 +668,8 @@ struct rpl_group_info
*/
uint64 gtid_sub_id;
rpl_gtid current_gtid;
+ /* Currently applied event or NULL */
+ Log_event *current_event;
uint64 commit_id;
/*
This is used to keep transaction commit order.
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index f31f21faeb0..a25705ff785 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -7861,7 +7861,7 @@ ER_VERS_PERIOD_COLUMNS
eng "PERIOD FOR SYSTEM_TIME must use columns %`s and %`s"
ER_PART_WRONG_VALUE
- eng "Wrong parameters for partitioned %`s: wrong value for '%s'"
+ eng "Wrong parameters for partitioned %`s: wrong value for %s"
ER_VERS_WRONG_PARTS
eng "Wrong partitions for %`s: must have at least one HISTORY and exactly one last CURRENT"
@@ -7996,3 +7996,5 @@ ER_PARTITION_CONVERT_SUBPARTITIONED
eng "Convert partition is not supported for subpartitioned table."
ER_PROVIDER_NOT_LOADED
eng "MariaDB tried to use the %s, but its provider plugin is not loaded"
+ER_VERS_HIST_PART_FAILED
+ eng "Versioned table %`s.%`s: adding HISTORY partition(s) failed"
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index d983fe9a332..b3d717dfc07 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -63,7 +63,6 @@
#include "wsrep_trans_observer.h"
#endif /* WITH_WSREP */
-
bool
No_such_table_error_handler::handle_condition(THD *,
uint sql_errno,
@@ -933,7 +932,7 @@ void close_thread_table(THD *thd, TABLE **table_ptr)
DBUG_PRINT("tcache", ("table: '%s'.'%s' %p", table->s->db.str,
table->s->table_name.str, table));
DBUG_ASSERT(!table->file->keyread_enabled());
- DBUG_ASSERT(!table->file || table->file->inited == handler::NONE);
+ DBUG_ASSERT(table->file->inited == handler::NONE);
/*
The metadata lock must be released after giving back
@@ -945,11 +944,8 @@ void close_thread_table(THD *thd, TABLE **table_ptr)
MDL_SHARED));
table->mdl_ticket= NULL;
- if (table->file)
- {
- table->file->update_global_table_stats();
- table->file->update_global_index_stats();
- }
+ table->file->update_global_table_stats();
+ table->file->update_global_index_stats();
/*
This look is needed to allow THD::notify_shared_lock() to
@@ -1627,6 +1623,138 @@ bool is_locked_view(THD *thd, TABLE_LIST *t)
}
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+/**
+ Switch part_info->hist_part and request partition creation if needed.
+
+ @retval true Error or partition creation was requested.
+ @retval false No error
+*/
+bool TABLE::vers_switch_partition(THD *thd, TABLE_LIST *table_list,
+ Open_table_context *ot_ctx)
+{
+ if (!part_info || part_info->part_type != VERSIONING_PARTITION ||
+ table_list->vers_conditions.delete_history ||
+ thd->stmt_arena->is_stmt_prepare() ||
+ table_list->lock_type < TL_WRITE_ALLOW_WRITE ||
+ table_list->mdl_request.type < MDL_SHARED_WRITE ||
+ table_list->mdl_request.type == MDL_EXCLUSIVE)
+ {
+ return false;
+ }
+
+ /*
+ NOTE: we need this condition of prelocking_placeholder because we cannot do
+ auto-create after the transaction is started. Auto-create does
+ close_tables_for_reopen() and that is not possible under started transaction.
+ Also the transaction may not be cancelled at that moment: f.ex. trigger
+ after insert is run when some data is already written.
+
+ We must do auto-creation for PRELOCK_ROUTINE tables at the initial
+ open_tables() no matter what initiating sql_command is.
+ */
+ if (table_list->prelocking_placeholder != TABLE_LIST::PRELOCK_ROUTINE)
+ {
+ switch (thd->lex->sql_command)
+ {
+ case SQLCOM_INSERT:
+ if (thd->lex->duplicates != DUP_UPDATE)
+ return false;
+ break;
+ case SQLCOM_LOAD:
+ if (thd->lex->duplicates != DUP_REPLACE)
+ return false;
+ break;
+ case SQLCOM_LOCK_TABLES:
+ case SQLCOM_DELETE:
+ case SQLCOM_UPDATE:
+ case SQLCOM_REPLACE:
+ case SQLCOM_REPLACE_SELECT:
+ case SQLCOM_DELETE_MULTI:
+ case SQLCOM_UPDATE_MULTI:
+ break;
+ default:
+ /*
+ TODO: make row events set thd->lex->sql_command appropriately.
+
+ Sergei Golubchik: f.ex. currently row events increment
+ thd->status_var.com_stat[] each event for its own SQLCOM_xxx, it won't be
+ needed if they'll just set thd->lex->sql_command.
+ */
+ if (thd->rgi_slave && thd->rgi_slave->current_event &&
+ thd->lex->sql_command == SQLCOM_END)
+ {
+ switch (thd->rgi_slave->current_event->get_type_code())
+ {
+ case UPDATE_ROWS_EVENT:
+ case UPDATE_ROWS_EVENT_V1:
+ case DELETE_ROWS_EVENT:
+ case DELETE_ROWS_EVENT_V1:
+ break;
+ default:;
+ return false;
+ }
+ }
+ break;
+ }
+ }
+
+ TABLE *table= this;
+
+ /*
+ NOTE: The semantics of vers_set_hist_part() is twofold: even when we
+ don't need auto-create, we need to update part_info->hist_part.
+ */
+ uint *create_count= (table_list->vers_skip_create == thd->query_id) ?
+ NULL : &ot_ctx->vers_create_count;
+ table_list->vers_skip_create= thd->query_id;
+ if (table->part_info->vers_set_hist_part(thd, create_count))
+ {
+ MYSQL_UNBIND_TABLE(table->file);
+ tc_release_table(table);
+ return true;
+ }
+ if (ot_ctx->vers_create_count)
+ {
+ Open_table_context::enum_open_table_action action;
+ TABLE_LIST *table_arg;
+ mysql_mutex_lock(&table->s->LOCK_share);
+ if (!table->s->vers_skip_auto_create)
+ {
+ table->s->vers_skip_auto_create= true;
+ action= Open_table_context::OT_ADD_HISTORY_PARTITION;
+ table_arg= table_list;
+ }
+ else
+ {
+ /*
+ NOTE: this may repeat multiple times until creating thread acquires
+ MDL_EXCLUSIVE. Since auto-creation is rare operation this is acceptable.
+ We could suspend this thread on cond-var but we must first exit
+ MDL_SHARED_WRITE first and we cannot store cond-var into TABLE_SHARE
+ because it is already released and there is no guarantee that it will
+ be same instance if we acquire it again.
+ */
+ table_list->vers_skip_create= 0;
+ ot_ctx->vers_create_count= 0;
+ action= Open_table_context::OT_REOPEN_TABLES;
+ table_arg= NULL;
+ }
+ mysql_mutex_unlock(&table->s->LOCK_share);
+ if (!thd->locked_tables_mode)
+ {
+ MYSQL_UNBIND_TABLE(table->file);
+ tc_release_table(table);
+ }
+ ot_ctx->request_backoff_action(action, table_arg);
+ return true;
+ }
+
+ return false;
+}
+#endif /* WITH_PARTITION_STORAGE_ENGINE */
+
+
/**
Open a base table.
@@ -1779,6 +1907,8 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx)
DBUG_PRINT("info",("Using locked table"));
#ifdef WITH_PARTITION_STORAGE_ENGINE
part_names_error= set_partitions_as_used(table_list, table);
+ if (table->vers_switch_partition(thd, table_list, ot_ctx))
+ DBUG_RETURN(true);
#endif
goto reset;
}
@@ -2034,6 +2164,11 @@ retry_share:
tc_add_table(thd, table);
}
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ if (table->vers_switch_partition(thd, table_list, ot_ctx))
+ DBUG_RETURN(true);
+#endif /* WITH_PARTITION_STORAGE_ENGINE */
+
if (!(flags & MYSQL_OPEN_HAS_MDL_LOCK) &&
table->s->table_category < TABLE_CATEGORY_INFORMATION)
{
@@ -2111,6 +2246,7 @@ retry_share:
table->init(thd, table_list);
+ DBUG_ASSERT(table != thd->open_tables);
table->next= thd->open_tables; /* Link into simple list */
thd->set_open_tables(table);
@@ -2576,7 +2712,7 @@ unlink_all_closed_tables(THD *thd, MYSQL_LOCK *lock, size_t reopen_count)
This is only needed when LOCK TABLES is active
*/
-void Locked_tables_list::mark_table_for_reopen(THD *thd, TABLE *table)
+void Locked_tables_list::mark_table_for_reopen(TABLE *table)
{
TABLE_SHARE *share= table->s;
@@ -2589,11 +2725,13 @@ void Locked_tables_list::mark_table_for_reopen(THD *thd, TABLE *table)
close_all_tables_for_name().
*/
if (table_list->table && table_list->table->s == share)
+ {
table_list->table->internal_set_needs_reopen(true);
+ some_table_marked_for_reopen= 1;
+ }
}
/* This is needed in the case where lock tables where not used */
table->internal_set_needs_reopen(true);
- some_table_marked_for_reopen= 1;
}
@@ -3048,7 +3186,8 @@ Open_table_context::Open_table_context(THD *thd, uint flags)
m_flags(flags),
m_action(OT_NO_ACTION),
m_has_locks(thd->mdl_context.has_locks()),
- m_has_protection_against_grl(0)
+ m_has_protection_against_grl(0),
+ vers_create_count(0)
{}
@@ -3128,13 +3267,15 @@ request_backoff_action(enum_open_table_action action_arg,
*/
if (table)
{
- DBUG_ASSERT(action_arg == OT_DISCOVER || action_arg == OT_REPAIR);
+ DBUG_ASSERT(action_arg == OT_DISCOVER || action_arg == OT_REPAIR ||
+ action_arg == OT_ADD_HISTORY_PARTITION);
m_failed_table= (TABLE_LIST*) m_thd->alloc(sizeof(TABLE_LIST));
if (m_failed_table == NULL)
return TRUE;
m_failed_table->init_one_table(&table->db, &table->table_name, &table->alias, TL_WRITE);
m_failed_table->open_strategy= table->open_strategy;
m_failed_table->mdl_request.set_type(MDL_EXCLUSIVE);
+ m_failed_table->vers_skip_create= table->vers_skip_create;
}
m_action= action_arg;
return FALSE;
@@ -3195,13 +3336,49 @@ Open_table_context::recover_from_failed_open()
break;
case OT_DISCOVER:
case OT_REPAIR:
- if ((result= lock_table_names(m_thd, m_thd->lex->create_info,
- m_failed_table, NULL,
- get_timeout(), 0)))
+ case OT_ADD_HISTORY_PARTITION:
+ if (!m_thd->locked_tables_mode)
+ result= lock_table_names(m_thd, m_thd->lex->create_info, m_failed_table,
+ NULL, get_timeout(), 0);
+ else
+ {
+ DBUG_ASSERT(!result);
+ DBUG_ASSERT(m_action == OT_ADD_HISTORY_PARTITION);
+ }
+ /*
+ We are now under MDL_EXCLUSIVE mode. Other threads have no table share
+ acquired: they are blocked either at open_table_get_mdl_lock() in
+ open_table() or at lock_table_names() here.
+ */
+ if (result)
+ {
+ if (m_action == OT_ADD_HISTORY_PARTITION)
+ {
+ TABLE_SHARE *share= tdc_acquire_share(m_thd, m_failed_table,
+ GTS_TABLE, NULL);
+ if (share)
+ {
+ share->vers_skip_auto_create= false;
+ tdc_release_share(share);
+ }
+ if (m_thd->get_stmt_da()->sql_errno() == ER_LOCK_WAIT_TIMEOUT)
+ {
+ // MDEV-23642 Locking timeout caused by auto-creation affects original DML
+ m_thd->clear_error();
+ vers_create_count= 0;
+ result= false;
+ }
+ }
break;
+ }
- tdc_remove_table(m_thd, m_failed_table->db.str,
- m_failed_table->table_name.str);
+ /*
+ We don't need to remove share under OT_ADD_HISTORY_PARTITION.
+ Moreover fast_alter_partition_table() works with TABLE instance.
+ */
+ if (m_action != OT_ADD_HISTORY_PARTITION)
+ tdc_remove_table(m_thd, m_failed_table->db.str,
+ m_failed_table->table_name.str);
switch (m_action)
{
@@ -3229,6 +3406,70 @@ Open_table_context::recover_from_failed_open()
case OT_REPAIR:
result= auto_repair_table(m_thd, m_failed_table);
break;
+ case OT_ADD_HISTORY_PARTITION:
+ {
+ result= false;
+ TABLE *table= open_ltable(m_thd, m_failed_table, TL_WRITE,
+ MYSQL_OPEN_HAS_MDL_LOCK | MYSQL_OPEN_IGNORE_LOGGING_FORMAT);
+ if (table == NULL)
+ {
+ m_thd->clear_error();
+ break;
+ }
+
+ DBUG_ASSERT(vers_create_count);
+ result= vers_create_partitions(m_thd, m_failed_table, vers_create_count);
+ vers_create_count= 0;
+ if (!m_thd->transaction->stmt.is_empty())
+ trans_commit_stmt(m_thd);
+ DBUG_ASSERT(!result ||
+ !m_thd->locked_tables_mode ||
+ m_thd->lock->lock_count);
+ if (result)
+ break;
+ if (!m_thd->locked_tables_mode)
+ {
+ /*
+ alter_partition_lock_handling() does mysql_lock_remove() but
+ does not clear thd->lock completely.
+ */
+ DBUG_ASSERT(m_thd->lock->lock_count == 0);
+ if (!(m_thd->lock->flags & GET_LOCK_ON_THD))
+ my_free(m_thd->lock);
+ m_thd->lock= NULL;
+ }
+ else if (m_thd->locked_tables_mode == LTM_PRELOCKED)
+ {
+ MYSQL_LOCK *lock;
+ MYSQL_LOCK *merged_lock;
+
+ /*
+ In LTM_LOCK_TABLES table was reopened via locked_tables_list,
+ but not in prelocked environment where we have to reopen
+ the table manually.
+ */
+ Open_table_context ot_ctx(m_thd, MYSQL_OPEN_REOPEN);
+ if (open_table(m_thd, m_failed_table, &ot_ctx))
+ {
+ result= true;
+ break;
+ }
+ TABLE *table= m_failed_table->table;
+ table->reginfo.lock_type= m_thd->update_lock_default;
+ m_thd->in_lock_tables= 1;
+ lock= mysql_lock_tables(m_thd, &table, 1,
+ MYSQL_OPEN_REOPEN | MYSQL_LOCK_USE_MALLOC);
+ m_thd->in_lock_tables= 0;
+ if (lock == NULL ||
+ !(merged_lock= mysql_lock_merge(m_thd->lock, lock, m_thd)))
+ {
+ result= true;
+ break;
+ }
+ m_thd->lock= merged_lock;
+ }
+ break;
+ }
case OT_BACKOFF_AND_RETRY:
case OT_REOPEN_TABLES:
case OT_NO_ACTION:
@@ -4203,6 +4444,7 @@ bool open_tables(THD *thd, const DDL_options_st &options,
}
thd->current_tablenr= 0;
+
restart:
/*
Close HANDLER tables which are marked for flush or against which there
@@ -4283,6 +4525,9 @@ restart:
/*
For every table in the list of tables to open, try to find or open
a table.
+
+ NOTE: there can be duplicates in the list. F.ex. table specified in
+ LOCK TABLES and prelocked via another table (like when used in a trigger).
*/
for (tables= *table_to_open; tables;
table_to_open= &tables->next_global, tables= tables->next_global)
@@ -4377,6 +4622,8 @@ restart:
{
if (ot_ctx.can_recover_from_failed_open())
{
+ // FIXME: is this really used?
+ DBUG_ASSERT(0);
close_tables_for_reopen(thd, start,
ot_ctx.start_of_statement_svp());
if (ot_ctx.recover_from_failed_open())
@@ -5149,16 +5396,14 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type,
if (table_list->table)
DBUG_RETURN(table_list->table);
- /* should not be used in a prelocked_mode context, see NOTE above */
- DBUG_ASSERT(thd->locked_tables_mode < LTM_PRELOCKED);
-
THD_STAGE_INFO(thd, stage_opening_tables);
thd->current_tablenr= 0;
/* open_ltable can be used only for BASIC TABLEs */
table_list->required_type= TABLE_TYPE_NORMAL;
/* This function can't properly handle requests for such metadata locks. */
- DBUG_ASSERT(table_list->mdl_request.type < MDL_SHARED_UPGRADABLE);
+ DBUG_ASSERT(lock_flags & MYSQL_OPEN_HAS_MDL_LOCK ||
+ table_list->mdl_request.type < MDL_SHARED_UPGRADABLE);
while ((error= open_table(thd, table_list, &ot_ctx)) &&
ot_ctx.can_recover_from_failed_open())
diff --git a/sql/sql_base.h b/sql/sql_base.h
index 5b449fdddac..a98ec297c78 100644
--- a/sql/sql_base.h
+++ b/sql/sql_base.h
@@ -532,7 +532,8 @@ public:
OT_BACKOFF_AND_RETRY,
OT_REOPEN_TABLES,
OT_DISCOVER,
- OT_REPAIR
+ OT_REPAIR,
+ OT_ADD_HISTORY_PARTITION
};
Open_table_context(THD *thd, uint flags);
@@ -605,6 +606,9 @@ private:
protection against global read lock.
*/
mdl_bitmap_t m_has_protection_against_grl;
+
+public:
+ uint vers_create_count;
};
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 29824301e9d..16bbc48d73b 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -844,7 +844,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
wsrep_info[sizeof(wsrep_info) - 1] = '\0'; /* make sure it is 0-terminated */
#endif
/* Call to init() below requires fully initialized Open_tables_state. */
- reset_open_tables_state(this);
+ reset_open_tables_state();
init();
debug_sync_init_thread(this);
@@ -4535,7 +4535,7 @@ void THD::reset_n_backup_open_tables_state(Open_tables_backup *backup)
DBUG_ENTER("reset_n_backup_open_tables_state");
backup->set_open_tables_state(this);
backup->mdl_system_tables_svp= mdl_context.mdl_savepoint();
- reset_open_tables_state(this);
+ reset_open_tables_state();
state_flags|= Open_tables_state::BACKUPS_AVAIL;
DBUG_VOID_RETURN;
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index df9d89b5aff..686e6e70766 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1596,6 +1596,10 @@ enum enum_locked_tables_mode
LTM_NONE= 0,
LTM_LOCK_TABLES,
LTM_PRELOCKED,
+ /*
+ TODO: remove LTM_PRELOCKED_UNDER_LOCK_TABLES: it is never used apart from
+ LTM_LOCK_TABLES.
+ */
LTM_PRELOCKED_UNDER_LOCK_TABLES,
LTM_always_last
};
@@ -1778,7 +1782,7 @@ public:
*this= *state;
}
- void reset_open_tables_state(THD *thd)
+ void reset_open_tables_state()
{
open_tables= 0;
temporary_tables= 0;
@@ -2126,7 +2130,7 @@ public:
bool restore_lock(THD *thd, TABLE_LIST *dst_table_list, TABLE *table,
MYSQL_LOCK *lock);
void add_back_last_deleted_lock(TABLE_LIST *dst_table_list);
- void mark_table_for_reopen(THD *thd, TABLE *table);
+ void mark_table_for_reopen(TABLE *table);
};
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index b5f8cf4a886..e2b6909bc5d 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -9666,7 +9666,11 @@ bool LEX::part_values_history(THD *thd)
}
else
{
- part_info->vers_init_info(thd);
+ if (unlikely(part_info->vers_init_info(thd)))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
elem->id= UINT_MAX32;
}
DBUG_ASSERT(part_info->vers_info);
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index b9d3eec5a60..078ea0dae9b 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -84,6 +84,7 @@
#include "events.h"
#include "sql_trigger.h"
#include "transaction.h"
+#include "sql_alter.h"
#include "sql_audit.h"
#include "sql_prepare.h"
#include "sql_cte.h"
@@ -6054,7 +6055,6 @@ finish:
/* Free tables. Set stage 'closing tables' */
close_thread_tables(thd);
-
#ifndef DBUG_OFF
if (lex->sql_command != SQLCOM_SET_OPTION && ! thd->in_sub_stmt)
DEBUG_SYNC(thd, "execute_command_after_close_tables");
@@ -7566,6 +7566,7 @@ void THD::reset_for_next_command(bool do_clear_error)
global_system_variables.auto_increment_increment;
}
#endif /* WITH_WSREP */
+
query_start_sec_part_used= 0;
is_fatal_error= time_zone_used= 0;
log_current_statement= 0;
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index b75a318ab65..2e23662349f 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -2580,11 +2580,17 @@ char *generate_partition_syntax(THD *thd, partition_info *part_info,
err+= str.append('\'');
}
}
- if (vers_info->limit)
+ else if (vers_info->limit)
{
err+= str.append(STRING_WITH_LEN("LIMIT "));
err+= str.append_ulonglong(vers_info->limit);
}
+ if (vers_info->auto_hist)
+ {
+ DBUG_ASSERT(vers_info->interval.is_set() ||
+ vers_info->limit);
+ err+= str.append(STRING_WITH_LEN(" AUTO"));
+ }
}
else if (part_info->part_expr)
{
@@ -5326,7 +5332,9 @@ that are reorganised.
now_part= el;
}
}
- if (*fast_alter_table && tab_part_info->vers_info->interval.is_set())
+ if (*fast_alter_table &&
+ !(alter_info->partition_flags & ALTER_PARTITION_AUTO_HIST) &&
+ tab_part_info->vers_info->interval.is_set())
{
partition_element *hist_part= tab_part_info->vers_info->hist_part;
if (hist_part->range_value <= thd->query_start())
@@ -6038,7 +6046,7 @@ err:
records are added
*/
-static bool mysql_change_partitions(ALTER_PARTITION_PARAM_TYPE *lpt)
+static bool mysql_change_partitions(ALTER_PARTITION_PARAM_TYPE *lpt, bool copy_data)
{
char path[FN_REFLEN+1];
int error;
@@ -6048,7 +6056,7 @@ static bool mysql_change_partitions(ALTER_PARTITION_PARAM_TYPE *lpt)
build_table_filename(path, sizeof(path) - 1, lpt->db.str, lpt->table_name.str, "", 0);
- if(mysql_trans_prepare_alter_copy_data(thd))
+ if(copy_data && mysql_trans_prepare_alter_copy_data(thd))
DBUG_RETURN(TRUE);
/* TODO: test if bulk_insert would increase the performance */
@@ -6062,7 +6070,9 @@ static bool mysql_change_partitions(ALTER_PARTITION_PARAM_TYPE *lpt)
file->print_error(error, MYF(error != ER_OUTOFMEMORY ? 0 : ME_FATAL));
}
- if (mysql_trans_commit_alter_copy_data(thd))
+ DBUG_ASSERT(copy_data || (!lpt->copied && !lpt->deleted));
+
+ if (copy_data && mysql_trans_commit_alter_copy_data(thd))
error= 1; /* The error has been reported */
DBUG_RETURN(MY_TEST(error));
@@ -7341,7 +7351,8 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
thd->variables.option_bits|= OPTION_IF_EXISTS;
if (table->file->alter_table_flags(alter_info->flags) &
- HA_PARTITION_ONE_PHASE)
+ HA_PARTITION_ONE_PHASE &&
+ !(alter_info->partition_flags & ALTER_PARTITION_AUTO_HIST))
{
/*
In the case where the engine supports one phase online partition
@@ -7383,7 +7394,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
2) Perform the change within the handler
*/
if (mysql_write_frm(lpt, WFRM_WRITE_SHADOW) ||
- mysql_change_partitions(lpt))
+ mysql_change_partitions(lpt, true))
{
goto err;
}
@@ -7570,9 +7581,14 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
ERROR_INJECT("convert_partition_11"))
goto err;
}
+ /*
+ TODO: would be good if adding new empty VERSIONING partitions would always
+ go this way, auto or not.
+ */
else if ((alter_info->partition_flags & ALTER_PARTITION_ADD) &&
(part_info->part_type == RANGE_PARTITION ||
- part_info->part_type == LIST_PARTITION))
+ part_info->part_type == LIST_PARTITION ||
+ alter_info->partition_flags & ALTER_PARTITION_AUTO_HIST))
{
DBUG_ASSERT(!(alter_info->partition_flags & ALTER_PARTITION_CONVERT_IN));
/*
@@ -7613,7 +7629,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
ERROR_INJECT("add_partition_3") ||
write_log_add_change_partition(lpt) ||
ERROR_INJECT("add_partition_4") ||
- mysql_change_partitions(lpt) ||
+ mysql_change_partitions(lpt, false) ||
ERROR_INJECT("add_partition_5") ||
alter_close_table(lpt) ||
ERROR_INJECT("add_partition_6") ||
@@ -7700,7 +7716,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
ERROR_INJECT("change_partition_2") ||
write_log_add_change_partition(lpt) ||
ERROR_INJECT("change_partition_3") ||
- mysql_change_partitions(lpt) ||
+ mysql_change_partitions(lpt, true) ||
ERROR_INJECT("change_partition_4") ||
wait_while_table_is_used(thd, table, HA_EXTRA_NOT_USED) ||
ERROR_INJECT("change_partition_5") ||
diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc
index c6af72c5979..a0ef89ff0f5 100644
--- a/sql/sql_truncate.cc
+++ b/sql/sql_truncate.cc
@@ -511,7 +511,7 @@ bool Sql_cmd_truncate_table::truncate_table(THD *thd, TABLE_LIST *table_ref)
(HTON_REQUIRES_CLOSE_AFTER_TRUNCATE |
HTON_TRUNCATE_REQUIRES_EXCLUSIVE_USE)))
{
- thd->locked_tables_list.mark_table_for_reopen(thd, table_ref->table);
+ thd->locked_tables_list.mark_table_for_reopen(table_ref->table);
if (unlikely(thd->locked_tables_list.reopen_tables(thd, false)))
thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0);
}
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 442644eddd6..f9c575d39c6 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1506,6 +1506,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
condition_number
opt_versioning_interval_start
+%type <num> opt_vers_auto_part
+
%type <item_param> param_marker
%type <item_num>
@@ -5093,24 +5095,20 @@ opt_part_option:
opt_versioning_rotation:
/* empty */ {}
- | INTERVAL_SYM expr interval opt_versioning_interval_start
+ | INTERVAL_SYM expr interval opt_versioning_interval_start opt_vers_auto_part
{
partition_info *part_info= Lex->part_info;
const char *table_name= Lex->create_last_non_select_table->table_name.str;
- if (unlikely(part_info->vers_set_interval(thd, $2, $3, $4, table_name)))
+ if (unlikely(part_info->vers_set_interval(thd, $2, $3, $4, $5, table_name)))
MYSQL_YYABORT;
}
- | LIMIT ulonglong_num
- {
- partition_info *part_info= Lex->part_info;
- if (unlikely(part_info->vers_set_limit($2)))
+ | LIMIT ulonglong_num opt_vers_auto_part
{
- my_error(ER_PART_WRONG_VALUE, MYF(0),
- Lex->create_last_non_select_table->table_name.str,
- "LIMIT");
- MYSQL_YYABORT;
+ partition_info *part_info= Lex->part_info;
+ const char *table_name= Lex->create_last_non_select_table->table_name.str;
+ if (unlikely(part_info->vers_set_limit($2, $3, table_name)))
+ MYSQL_YYABORT;
}
- }
;
@@ -5125,6 +5123,16 @@ opt_versioning_interval_start:
}
;
+opt_vers_auto_part:
+ /* empty */
+ {
+ $$= 0;
+ }
+ | AUTO_SYM
+ {
+ $$= 1;
+ }
+ ;
/*
End of partition parser part
*/
diff --git a/sql/table.cc b/sql/table.cc
index b1a7b6bfe2b..38d48100359 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -10123,5 +10123,5 @@ void TABLE::mark_table_for_reopen()
{
THD *thd= in_use;
DBUG_ASSERT(thd);
- thd->locked_tables_list.mark_table_for_reopen(thd, this);
+ thd->locked_tables_list.mark_table_for_reopen(this);
}
diff --git a/sql/table.h b/sql/table.h
index 6aa75df39c6..c8ea4094409 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -64,6 +64,7 @@ class derived_handler;
class Pushdown_derived;
struct Name_resolution_context;
class Table_function_json_table;
+class Open_table_context;
/*
Used to identify NESTED_JOIN structures within a join (applicable only to
@@ -910,6 +911,13 @@ struct TABLE_SHARE
vers_kind_t versioned;
period_info_t vers;
period_info_t period;
+ /*
+ Protect multiple threads from repeating partition auto-create over
+ single share.
+
+ TODO: remove it when partitioning metadata will be in TABLE_SHARE.
+ */
+ bool vers_skip_auto_create;
bool init_period_from_extra2(period_info_t *period, const uchar *data,
const uchar *end);
@@ -1766,6 +1774,10 @@ public:
ulonglong vers_start_id() const;
ulonglong vers_end_id() const;
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ bool vers_switch_partition(THD *thd, TABLE_LIST *table_list,
+ Open_table_context *ot_ctx);
+#endif
int update_generated_fields();
int period_make_insert(Item *src, Field *dst);
@@ -2558,6 +2570,13 @@ struct TABLE_LIST
bool merged;
bool merged_for_insert;
bool sequence; /* Part of NEXTVAL/CURVAL/LASTVAL */
+ /*
+ Protect single thread from repeating partition auto-create over
+ multiple share instances (as the share is closed on backoff action).
+
+ Skips auto-create only for one given query id.
+ */
+ query_id_t vers_skip_create;
/*
Items created by create_view_field and collected to change them in case
diff --git a/sql/transaction.cc b/sql/transaction.cc
index 958abebfc47..b1e98be56bc 100644
--- a/sql/transaction.cc
+++ b/sql/transaction.cc
@@ -463,7 +463,7 @@ bool trans_commit_stmt(THD *thd)
a savepoint for each nested statement, and release the
savepoint when statement has succeeded.
*/
- DBUG_ASSERT(! thd->in_sub_stmt);
+ DBUG_ASSERT(!(thd->in_sub_stmt));
thd->merge_unsafe_rollback_flags();