Hi, Aleksey!
On Apr 07, Aleksey Midenkov wrote:
> revision-id: 9941c6a3179 (mariadb-10.5.2-164-g9941c6a3179)
> parent(s): 920c3c6b237
> author: Aleksey Midenkov <midenok(a)gmail.com>
> committer: Aleksey Midenkov <midenok(a)gmail.com>
> timestamp: 2020-04-06 08:05:43 +0300
> message:
>
> MDEV-17554 Auto-create new partition for system versioned tables with history partitioned by INTERVAL/LIMIT
See some comment below, please
> diff --git a/mysql-test/suite/versioning/common.inc b/mysql-test/suite/versioning/common.inc
> index 355b571e5a0..b35a5138015 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';
Why is that? I understand you might've needed it when a partition was added
in a separate thread, but why now?
> 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/r/delete_history.result b/mysql-test/suite/versioning/r/delete_history.result
> index cb865a835b3..2e4a2bf9974 100644
> --- a/mysql-test/suite/versioning/r/delete_history.result
> +++ b/mysql-test/suite/versioning/r/delete_history.result
> @@ -154,3 +154,18 @@ select * from t1;
> a
> 1
> 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:
> +create or replace table t (a int) with system versioning
> +partition by system_time limit 1000 auto_increment;
this looks like a hack, I think we need a dedicated syntax for that.
but I couldn't think of anything good now.
ok, I see that you allow both AUTO_INCREMENT and AUTO.
May be better just to use AUTO?
> +delete history from t;
> +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 LIMIT 1000 AUTO_INCREMENT
> +PARTITIONS 2
> +drop table t;
> diff --git a/mysql-test/suite/versioning/r/partition.result b/mysql-test/suite/versioning/r/partition.result
> index a7047cbd11b..660d2c81961 100644
> --- a/mysql-test/suite/versioning/r/partition.result
> +++ b/mysql-test/suite/versioning/r/partition.result
> @@ -289,11 +291,27 @@ x
> 6
> 7
> 8
> -## rotation by INTERVAL
> +# Auto-create history partitions
> +create or replace table t1 (x int) with system versioning
> +partition by system_time limit 1000 auto_increment;
> +lock tables t1 write;
> +insert into t1 values (1);
> +update t1 set x= x + 1;
> +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 LIMIT 1000 AUTO_INCREMENT
> +PARTITIONS 3
this test needs a comment, I don't understand what's happening here.
why lock tables?
> +#
> +# 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
> @@ -302,7 +320,7 @@ partition by system_time interval 10 year partitions 3;
> ERROR 22003: TIMESTAMP value is out of range in 'INTERVAL'
> # INTERVAL and ALTER TABLE
> create or replace table t1 (i int) with system versioning
> -partition by system_time interval 1 hour;
> +partition by system_time interval 59 minute;
why?
> set @ts=(select partition_description from information_schema.partitions
> where table_schema='test' and table_name='t1' and partition_name='p0');
> alter table t1 add column b int;
> @@ -353,28 +371,51 @@ Warning 4114 Versioned table `test`.`t1`: last HISTORY partition (`p1`) is out o
> delete from 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';
> +select subpartition_name,partition_description from information_schema.partitions where table_schema='test' and table_name='t1';
why?
> -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
> +subpartition_name partition_description
> +p1sp0 2001-02-04 00:00:00
> +p1sp1 2001-02-04 00:00:00
> +pnsp0 CURRENT
> +pnsp1 CURRENT
> +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';
> -subpartition_name partition_description table_rows
> -p1sp0 2001-02-04 00:00:00 1
> -p1sp1 2001-02-04 00:00:00 0
> -p0sp0 2001-02-05 00:00:00 1
> -p0sp1 2001-02-05 00:00:00 1
> -p2sp0 2001-02-06 00:00:00 0
> -p2sp1 2001-02-06 00:00:00 0
> -pnsp0 CURRENT 0
> -pnsp1 CURRENT 2
> +select subpartition_name, partition_description from information_schema.partitions where table_schema='test' and table_name='t1';
> +subpartition_name partition_description
> +p1sp0 2001-02-04 00:00:00
> +p1sp1 2001-02-04 00:00:00
> +p0sp0 2001-02-05 00:00:00
> +p0sp1 2001-02-05 00:00:00
> +p2sp0 2001-02-06 00:00:00
> +p2sp1 2001-02-06 00:00:00
> +pnsp0 CURRENT
> +pnsp1 CURRENT
> +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);
> @@ -1044,3 +1085,568 @@ t1 CREATE TABLE `t1` (
> PARTITION BY SYSTEM_TIME
> PARTITIONS 8
> drop tables t1;
> +#
> +# 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 999 auto_increment;
> +ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for LIMIT (< 1000)
> +create or replace table t1 (x int) with system versioning
> +partition by system_time interval 3599 second auto_increment;
> +ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for INTERVAL (< 1 HOUR)
no arbitrary limitations, please
> +create or replace table t1 (x int) with system versioning
> +partition by system_time limit 1000 auto_increment;
> +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 1000 AUTO_INCREMENT
> +PARTITIONS 2
> +affected rows: 1
> +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 LIMIT 1000 AUTO_INCREMENT
> +PARTITIONS 3
> +affected rows: 1
> +# Increment from 2 to 5
> +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_increment;
> +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 INTERVAL 3600 SECOND STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO_INCREMENT
> +PARTITIONS 2
> +affected rows: 1
> +set timestamp= unix_timestamp('2000-01-01 00:00:00');
> +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_INCREMENT
> +PARTITIONS 3
> +affected rows: 1
> +set timestamp= unix_timestamp('2000-01-01 01: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_INCREMENT
> +PARTITIONS 4
> +affected rows: 1
> +set timestamp= unix_timestamp('2000-01-01 02: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_INCREMENT
> +PARTITIONS 5
> +affected rows: 1
> +# Increment from 3 to 6, manual names, LOCK TABLES
again, I think this is overcomplication and overengineering.
I don't see any need for mixing automatic and manual partition names.
> +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_increment (
> +partition p1 history,
> +partition p3 history,
> +partition pn current);
> +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 INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO_INCREMENT
> +(PARTITION `p1` HISTORY ENGINE = DEFAULT_ENGINE,
> + PARTITION `p3` HISTORY ENGINE = DEFAULT_ENGINE,
> + PARTITION `pn` CURRENT ENGINE = DEFAULT_ENGINE)
> +affected rows: 1
> +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_INCREMENT
> +(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 01: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_INCREMENT
> +(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 02: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_INCREMENT
> +(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
> +lock tables t1 write;
> +affected rows: 0
> +set timestamp= unix_timestamp('2000-01-01 03:00:00');
> +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_INCREMENT
> +(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
> +# 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_increment;
> +affected rows: 0
> +create or replace view v1 as select * from t1;
> +affected rows: 0
> +insert into v1 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_INCREMENT
> +PARTITIONS 3
> +affected rows: 1
> +lock tables t1 write;
> +affected rows: 0
> +set timestamp= unix_timestamp('2000-01-01 01: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_INCREMENT
> +PARTITIONS 4
> +affected rows: 1
> +unlock tables;
> +affected rows: 0
> +drop view v1;
> +affected rows: 0
> +drop tables t1;
> +affected rows: 0
> +# Multiple increments in single command
> +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_increment partitions 3;
> +affected rows: 0
> +create or replace table t2 (y int) with system versioning
> +partition by system_time interval 1 hour auto_increment partitions 4;
> +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_INCREMENT
> +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_INCREMENT
> +PARTITIONS 4
> +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_INCREMENT
> +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_INCREMENT
> +PARTITIONS 5
> +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_increment;
> +affected rows: 0
> +execute immediate '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_INCREMENT
> +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 01: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_INCREMENT
> +PARTITIONS 4
> +affected rows: 1
> +lock tables t1 write;
> +affected rows: 0
> +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_INCREMENT
> +PARTITIONS 5
add a test where timestamp is incremented by, say, 24 hours, please
> +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 03: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_INCREMENT
> +PARTITIONS 6
> +affected rows: 1
> +lock tables t1 write;
> +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_INCREMENT
> +PARTITIONS 7
> +affected rows: 1
> +unlock tables;
> +affected rows: 0
> +drop procedure sp;
> +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_increment (
> +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 utf8 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,
> + PRIMARY KEY (`x`,`e`),
> + UNIQUE KEY `u` (`u`,`e`),
> + KEY `three` (`i1`,`i2`,`i3`),
> + PERIOD FOR SYSTEM_TIME (`s`, `e`),
> + PERIOD FOR `app_time` (`ps`, `pe`),
> + 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_INCREMENT
> +(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
> +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 utf8 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,
> + PRIMARY KEY (`x`,`e`),
> + UNIQUE KEY `u` (`u`,`e`),
> + KEY `three` (`i1`,`i2`,`i3`),
> + PERIOD FOR SYSTEM_TIME (`s`, `e`),
> + PERIOD FOR `app_time` (`ps`, `pe`),
> + CONSTRAINT `check_constr` CHECK (`u` > -1)
> +) ENGINE=DEFAULT_ENGINE AUTO_INCREMENT=2 DEFAULT CHARSET=ucs2 WITH SYSTEM VERSIONING
> + PARTITION BY SYSTEM_TIME INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO_INCREMENT
> +(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 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 utf8 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,
> + PRIMARY KEY (`x`,`e`),
> + UNIQUE KEY `u` (`u`,`e`),
> + KEY `three` (`i1`,`i2`,`i3`),
> + PERIOD FOR SYSTEM_TIME (`s`, `e`),
> + PERIOD FOR `app_time` (`ps`, `pe`),
> + 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_INCREMENT
> +(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
> +# 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_increment;
> +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_INCREMENT
> +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 01:00:00');
> +update t1 set x= x + 10;
> +connection con2;
> +set timestamp= unix_timestamp('2000-01-01 01:00:00');
> +update t1 set x= x + 20;
> +connection con3;
> +set timestamp= unix_timestamp('2000-01-01 01:00:00');
> +update t1 set x= x + 30;
> +connection con4;
> +set timestamp= unix_timestamp('2000-01-01 01:00:00');
> +update t1 set x= x + 40;
> +connection con5;
> +set timestamp= unix_timestamp('2000-01-01 01:00:00');
> +update t1 set x= x + 50;
> +connection con6;
> +set timestamp= unix_timestamp('2000-01-01 01:00:00');
> +update t1 set x= x + 60;
> +connection con7;
> +set timestamp= unix_timestamp('2000-01-01 01:00:00');
> +update t1 set x= x + 70;
> +connection con8;
> +set timestamp= unix_timestamp('2000-01-01 01: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_INCREMENT
> +PARTITIONS 4
> +drop tables t1;
> +create or replace table t1 (x int) with system versioning engine innodb
> +partition by system_time interval 1 hour auto;
> +start transaction;
> +select * from t1;
> +x
> +connect con1, localhost, root;
> +set lock_wait_timeout= 1;
> +insert into t1 values (1);
> +Warnings:
> +Warning 4114 Versioned table `test`.`t1`: last HISTORY partition (`p0`) is out of INTERVAL, need more HISTORY partitions
> +Error 1205 Lock wait timeout exceeded; try restarting transaction
> +Warning 4171 Auto-increment history partition: alter partition table failed
> +Warning 4171 Versioned table `test`.`t1`: adding HISTORY partition failed with error 0, see error log for details
"error 0" is strange and "see error log for details" isn't very
user-friendly, a user might not have access to the error log at all
> +select * from t1;
> +x
> +1
I don't understand, there was an error above, why did insert succeed?
> +disconnect con1;
> +connection default;
> +drop table t1;
> diff --git a/mysql-test/suite/versioning/r/rpl.result b/mysql-test/suite/versioning/r/rpl.result
> index 627f3991499..68113190889 100644
> --- a/mysql-test/suite/versioning/r/rpl.result
> +++ b/mysql-test/suite/versioning/r/rpl.result
> @@ -164,4 +164,65 @@ 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_increment;
> +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_INCREMENT
> +PARTITIONS 4
> +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_INCREMENT
> +PARTITIONS 4
> +connection master;
> +drop table t1;
> +#
> +# MENT-685 DML events for auto-partitioned tables are written into binary log twice
> +#
the test below doesn't seem to match the description above
> +create table t1 (x int) partition by hash (x);
> +alter table t1 add partition partitions 1 auto_increment;
> +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
> +drop table t1;
> +create table t1 (x int) with system versioning
> +partition by system_time limit 1000 auto
> +(partition p1 history, partition pn current);
> +insert into t1 values (1);
> +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 LIMIT 1000 AUTO_INCREMENT
> +(PARTITION `p1` HISTORY ENGINE = ENGINE,
> + PARTITION `p2` HISTORY ENGINE = ENGINE,
> + PARTITION `pn` CURRENT ENGINE = ENGINE)
> +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 LIMIT 1000 AUTO_INCREMENT
> +(PARTITION `p1` HISTORY ENGINE = ENGINE,
> + PARTITION `p2` HISTORY ENGINE = ENGINE,
> + PARTITION `pn` CURRENT ENGINE = ENGINE)
> +select * from t1;
> +x
> +1
> +connection master;
> +drop table t1;
> include/rpl_end.inc
> diff --git a/sql/handler.cc b/sql/handler.cc
> index c6ecc9566d8..c86f96b9689 100644
> --- a/sql/handler.cc
> +++ b/sql/handler.cc
> @@ -1512,7 +1512,7 @@ int ha_commit_trans(THD *thd, bool all)
> DBUG_ASSERT(thd->transaction.stmt.ha_list == NULL ||
> trans == &thd->transaction.stmt);
>
> - if (thd->in_sub_stmt)
> + if (thd->in_sub_stmt & ~SUB_STMT_AUTO_HIST)
1. why? That is, why do you call ha_commit_trans() when adding a partition?
2. please add a test with insert under start transaction.
what should happen in this case?
> {
> DBUG_ASSERT(0);
> /*
> diff --git a/sql/partition_info.cc b/sql/partition_info.cc
> index f4b7260f8b0..617c839721b 100644
> --- a/sql/partition_info.cc
> +++ b/sql/partition_info.cc
> @@ -848,29 +850,289 @@ void partition_info::vers_set_hist_part(THD *thd)
> else
> vers_info->hist_part= next;
> }
> + }
> + else if (vers_info->interval.is_set())
> + {
> + if (vers_info->hist_part->range_value <= thd->query_start())
> + {
> + partition_element *next= NULL;
> + bool error= true;
> + List_iterator<partition_element> it(partitions);
> + while (next != vers_info->hist_part)
> + next= it++;
> +
> + while ((next= it++) != vers_info->now_part)
> + {
> + vers_info->hist_part= next;
> + if (next->range_value > thd->query_start())
> + {
> + error= false;
> + break;
> + }
> + }
> + if (error)
> + 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");
> + }
> + }
> +
> + if (!vers_info->auto_inc ||
> + vers_info->hist_part->id + VERS_MIN_EMPTY < vers_info->now_part->id)
> return;
> +
> + switch (thd->lex->sql_command)
> + {
> + case SQLCOM_DELETE:
> + if (thd->lex->last_table()->vers_conditions.delete_history)
> + break;
> + /* fallthrough */
> + case SQLCOM_UPDATE:
> + case SQLCOM_INSERT:
> + case SQLCOM_INSERT_SELECT:
> + case SQLCOM_LOAD:
> + case SQLCOM_REPLACE:
> + case SQLCOM_REPLACE_SELECT:
> + case SQLCOM_DELETE_MULTI:
> + case SQLCOM_UPDATE_MULTI:
it's rather fragile to check for specific sql statements.
why not to look at the table lock instead?
(with a special check for delete history)
Ok, it's a bug. Please add a test with multi-update,
where a partitioned table is *not* updated. Like
update t1, tpart set t1.x=5 where t1.y=tpart.z;
here a new partition should clearly not be created.
also, a simpler example (multi-update is difficult):
insert t1 select * from tpart;
add both, please.
> + {
> + TABLE_SHARE *share;
> + List_iterator_fast<TABLE_SHARE> it(thd->vers_auto_part_tables);
> + while ((share= it++))
> + {
> + if (table->s == share)
> + break;
> + }
> + if (share)
> + break;
> + /* Prevent spawning multiple instances of vers_add_auto_parts() */
> + bool altering;
> + mysql_mutex_lock(&table->s->LOCK_share);
> + altering= table->s->vers_auto_part;
> + if (!altering)
> + table->s->vers_auto_part= true;
> + mysql_mutex_unlock(&table->s->LOCK_share);
> + if (altering)
> + break;
what happens if you're altering already?
logically this thread should wait. Where does it do it?
> + if (thd->vers_auto_part_tables.push_back(table->s))
> + {
> + my_error(ER_OUT_OF_RESOURCES, MYF(0));
> + }
> + }
> + default:;
> }
> +}
>
> - if (vers_info->interval.is_set())
> - {
> - if (vers_info->hist_part->range_value > thd->query_start())
> - return;
>
> - partition_element *next= NULL;
> - List_iterator<partition_element> it(partitions);
> - while (next != vers_info->hist_part)
> - next= it++;
> +/**
> + @brief Run fast_alter_partition_table() to add new history partitions
> + for tables requiring them.
> +*/
> +void vers_add_auto_parts(THD *thd)
> +{
> + HA_CREATE_INFO create_info;
> + Alter_info alter_info;
> + String query;
> + TABLE_LIST *table_list= NULL;
> + partition_info *save_part_info= thd->work_part_info;
> + Query_tables_list save_query_tables;
> + Reprepare_observer *save_reprepare_observer= thd->m_reprepare_observer;
> + Diagnostics_area new_stmt_da(thd->query_id, false, true);
> + Diagnostics_area *save_stmt_da= thd->get_stmt_da();
> + bool save_no_write_to_binlog= thd->lex->no_write_to_binlog;
> + const CSET_STRING save_query= thd->query_string;
> + thd->m_reprepare_observer= NULL;
> + thd->lex->reset_n_backup_query_tables_list(&save_query_tables);
> + thd->in_sub_stmt|= SUB_STMT_AUTO_HIST;
> + thd->lex->no_write_to_binlog= !thd->is_current_stmt_binlog_format_row();
> + TABLE_LIST *tl;
> +
> + DBUG_ASSERT(!thd->vers_auto_part_tables.is_empty());
> +
> + for (TABLE_SHARE &share: thd->vers_auto_part_tables)
> + {
> + tl= (TABLE_LIST *) thd->alloc(sizeof(TABLE_LIST));
> + tl->init_one_table(&share.db, &share.table_name, NULL, TL_READ_NO_INSERT);
> + tl->open_type= OT_BASE_ONLY;
> + tl->i_s_requested_object= OPEN_TABLE_ONLY;
> + tl->next_global= table_list;
> + table_list= tl;
> + }
> +
> + /* NB: mysql_execute_command() can be recursive because of PS/SP.
> + Don't duplicate any processing including error messages. */
> + thd->vers_auto_part_tables.empty();
> +
> + DBUG_ASSERT(!thd->is_error());
> + /* NB: we have to preserve m_affected_rows, m_row_count_func, m_last_insert_id, etc */
> + thd->set_stmt_da(&new_stmt_da);
> + new_stmt_da.set_overwrite_status(true);
> +
> + DDL_options_st ddl_opts_none;
> + ddl_opts_none.init();
> + if (open_and_lock_tables(thd, ddl_opts_none, table_list, false, 0))
> + goto open_err;
> +
> + for (tl= table_list; tl; tl= tl->next_global)
> + {
> + TABLE *table= tl->table;
> + DBUG_ASSERT(table);
> + 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);
> +
> + if (thd->mdl_context.upgrade_shared_lock(table->mdl_ticket,
> + MDL_SHARED_NO_WRITE,
> + thd->variables.lock_wait_timeout))
> + goto exit;
> +
> + 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= 1;
> + 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;
> + }
> + /* Choose first non-occupied name suffix */
> + uint32 suffix= table->part_info->num_parts - 1;
> + DBUG_ASSERT(suffix > 0);
> + char part_name[MAX_PART_NAME_SIZE + 1];
> + if (make_partition_name(part_name, suffix))
> + {
> +vers_make_name_err:
> + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
> + WARN_VERS_HIST_PART_ERROR,
> + "Auto-increment history partition: "
> + "name generation failed for suffix %d", suffix);
> + my_error(WARN_VERS_HIST_PART_ERROR, MYF(ME_WARNING),
> + table->s->db.str, table->s->table_name.str, 0);
> + goto exit;
> + }
> + List_iterator_fast<partition_element> it(table->part_info->partitions);
> + partition_element *el;
> + while ((el= it++))
> + {
> + if (0 == my_strcasecmp(&my_charset_latin1, el->partition_name, part_name))
> + {
> + if (make_partition_name(part_name, ++suffix))
> + goto vers_make_name_err;
> + it.rewind();
> + }
> + }
>
> - while ((next= it++) != vers_info->now_part)
> + // NB: set_ok_status() requires DA_EMPTY
> + thd->get_stmt_da()->reset_diagnostics_area();
> +
> + thd->work_part_info= part_info;
> + if (part_info->set_up_defaults_for_partitioning(thd, table->file,
> + NULL, suffix + 1))
> {
> - vers_info->hist_part= next;
> - if (next->range_value > thd->query_start())
> - return;
> + push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
> + WARN_VERS_HIST_PART_ERROR,
> + "Auto-increment history partition: "
> + "setting up defaults failed");
> + 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))
> + {
> + push_warning(thd, Sql_condition::WARN_LEVEL_WARN, WARN_VERS_HIST_PART_ERROR,
> + "Auto-increment history partition: "
> + "alter partitition prepare failed");
> + goto exit;
> + }
> + if (!fast_alter_partition)
> + {
> + push_warning(thd, Sql_condition::WARN_LEVEL_WARN, WARN_VERS_HIST_PART_ERROR,
> + "Auto-increment history partition: "
> + "fast alter partitition is not possible");
> + my_error(WARN_VERS_HIST_PART_ERROR, MYF(ME_WARNING),
> + table->s->db.str, table->s->table_name.str, 0);
> + goto exit;
> + }
> + DBUG_ASSERT(partition_changed);
> + if (mysql_prepare_alter_table(thd, table, &create_info, &alter_info,
> + &alter_ctx))
> + {
> + push_warning(thd, Sql_condition::WARN_LEVEL_WARN, WARN_VERS_HIST_PART_ERROR,
> + "Auto-increment history partition: "
> + "alter prepare failed");
> + goto exit;
> + }
> +
> + // Forge query string for rpl logging
> + if (!thd->lex->no_write_to_binlog)
> + {
> + query.set(STRING_WITH_LEN("ALTER TABLE `"), &my_charset_latin1);
> +
> + if (query.append(table->s->db) ||
> + query.append(STRING_WITH_LEN("`.`")) ||
> + query.append(table->s->table_name) ||
> + query.append("` ADD PARTITION (PARTITION `") ||
> + query.append(part_name) ||
> + query.append("` HISTORY) AUTO_INCREMENT"))
> + {
> + my_error(ER_OUT_OF_RESOURCES, MYF(ME_ERROR_LOG));
> + goto exit;
> + }
> + CSET_STRING qs(query.c_ptr(), query.length(), &my_charset_latin1);
> + thd->set_query(qs);
> + }
> +
> + if (fast_alter_partition_table(thd, table, &alter_info, &create_info,
> + tl, &table->s->db, &table->s->table_name))
> + {
> + push_warning(thd, Sql_condition::WARN_LEVEL_WARN, WARN_VERS_HIST_PART_ERROR,
> + "Auto-increment history partition: "
> + "alter partition table failed");
> + my_error(WARN_VERS_HIST_PART_ERROR, MYF(ME_WARNING),
> + tl->db.str, tl->table_name.str, 0);
> }
> - 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");
> }
> +
> + if (!thd->transaction.stmt.is_empty())
> + trans_commit_stmt(thd);
> +
> +exit:
> + // If we failed with error allow non-processed tables to be processed next time
> + if (tl)
> + while ((tl= tl->next_global))
> + tl->table->s->vers_auto_part= false;
> + close_thread_tables(thd);
> +open_err:
> + 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->in_sub_stmt&= ~SUB_STMT_AUTO_HIST;
> + if (!new_stmt_da.is_warning_info_empty())
> + save_stmt_da->copy_sql_conditions_from_wi(thd, new_stmt_da.get_warning_info());
> + thd->set_stmt_da(save_stmt_da);
> + thd->lex->no_write_to_binlog= save_no_write_to_binlog;
> + thd->set_query(save_query);
> }
>
>
> diff --git a/sql/partition_info.h b/sql/partition_info.h
> index eb8e53a381a..d02eecea073 100644
> --- a/sql/partition_info.h
> +++ b/sql/partition_info.h
> @@ -34,10 +34,19 @@ typedef bool (*check_constants_func)(THD *thd, partition_info *part_info);
>
> struct st_ddl_log_memory_entry;
>
> +
> +/* Auto-create history partition configuration */
> +static const uint VERS_MIN_EMPTY= 1;
No, this doesn't work. One can easily set @@timestamp to do a multi-hour jump and no
fixed value of VERS_MIN_EMPTY will help. You need to add partitions before the statement, as
I wrote in my previous review.
> +static const uint VERS_MIN_INTERVAL= 3600; // seconds
> +static const uint VERS_MIN_LIMIT= 1000;
> +static const uint VERS_ERROR_TIMEOUT= 300; // seconds
> +
> +
> struct Vers_part_info : public Sql_alloc
> {
> Vers_part_info() :
> limit(0),
> + auto_inc(false),
> now_part(NULL),
> hist_part(NULL)
> {
> diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
> index 7cc1faea79b..4be3342e78e 100644
> --- a/sql/sql_yacc.yy
> +++ b/sql/sql_yacc.yy
> @@ -7521,14 +7533,19 @@ add_partition_rule:
>
> add_part_extra:
> /* empty */
> - | '(' part_def_list ')'
> + | '(' part_def_list ')' opt_vers_auto_inc
> {
> LEX *lex= Lex;
> lex->part_info->num_parts= lex->part_info->partitions.elements;
> + if ($4)
> + lex->alter_info.partition_flags|= ALTER_PARTITION_AUTO_HIST;
> }
> - | PARTITIONS_SYM real_ulong_num
> + | PARTITIONS_SYM real_ulong_num opt_vers_auto_inc
> {
> - Lex->part_info->num_parts= $2;
> + LEX *lex= Lex;
^^^ this pattern is obsolete for, like, 10 years.
It does no harm, but adds no value either.
> + lex->part_info->num_parts= $2;
> + if ($3)
> + lex->alter_info.partition_flags|= ALTER_PARTITION_AUTO_HIST;
> }
> ;
>
> diff --git a/storage/mroonga/mrn_table.cpp b/storage/mroonga/mrn_table.cpp
> index b10668cfcce..6458402f572 100644
> --- a/storage/mroonga/mrn_table.cpp
> +++ b/storage/mroonga/mrn_table.cpp
> @@ -932,7 +932,7 @@ MRN_SHARE *mrn_get_share(const char *table_name, TABLE *table, int *error)
> share->wrap_key_info = NULL;
> share->wrap_primary_key = MAX_KEY;
> }
> - memcpy(wrap_table_share, table->s, sizeof(*wrap_table_share));
> + memcpy((void *)wrap_table_share, (void *)table->s, sizeof(*wrap_table_share));
why is that?
> mrn_init_sql_alloc(current_thd, &(wrap_table_share->mem_root));
> wrap_table_share->keys = share->wrap_keys;
> wrap_table_share->key_info = share->wrap_key_info;
Regards,
Sergei
VP of MariaDB Server Engineering
and security(a)mariadb.org