diff --git a/mysql-test/main/partition_range_interval.result b/mysql-test/main/partition_range_interval.result new file mode 100644 index 0000000000000..f3a4e8be222fe --- /dev/null +++ b/mysql-test/main/partition_range_interval.result @@ -0,0 +1,1142 @@ +# simple case showing partitions added in INSERT +set timestamp= unix_timestamp('2026-05-02 00:00:00'); +create table t1 (c datetime) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( +PARTITION p0 VALUES LESS THAN ('2026-04-20') +); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` datetime DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 1 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-20') ENGINE = InnoDB) +insert into t1 values ('2026-05-01'); +select * from t1; +c +2026-05-01 00:00:00 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` datetime DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 1 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-20') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-04-21 00:00:00') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-04-22 00:00:00') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-04-23 00:00:00') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2026-04-24 00:00:00') ENGINE = InnoDB, + PARTITION `p5` VALUES LESS THAN ('2026-04-25 00:00:00') ENGINE = InnoDB, + PARTITION `p6` VALUES LESS THAN ('2026-04-26 00:00:00') ENGINE = InnoDB, + PARTITION `p7` VALUES LESS THAN ('2026-04-27 00:00:00') ENGINE = InnoDB, + PARTITION `p8` VALUES LESS THAN ('2026-04-28 00:00:00') ENGINE = InnoDB, + PARTITION `p9` VALUES LESS THAN ('2026-04-29 00:00:00') ENGINE = InnoDB, + PARTITION `p10` VALUES LESS THAN ('2026-04-30 00:00:00') ENGINE = InnoDB, + PARTITION `p11` VALUES LESS THAN ('2026-05-01 00:00:00') ENGINE = InnoDB, + PARTITION `p12` VALUES LESS THAN ('2026-05-02 00:00:00') ENGINE = InnoDB, + PARTITION `p13` VALUES LESS THAN ('2026-05-03 00:00:00') ENGINE = InnoDB) +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1'; +partition_name partition_method partition_expression partition_description table_rows +p0 RANGE COLUMNS `c` '2026-04-20' 0 +p1 RANGE COLUMNS `c` '2026-04-21 00:00:00' 0 +p2 RANGE COLUMNS `c` '2026-04-22 00:00:00' 0 +p3 RANGE COLUMNS `c` '2026-04-23 00:00:00' 0 +p4 RANGE COLUMNS `c` '2026-04-24 00:00:00' 0 +p5 RANGE COLUMNS `c` '2026-04-25 00:00:00' 0 +p6 RANGE COLUMNS `c` '2026-04-26 00:00:00' 0 +p7 RANGE COLUMNS `c` '2026-04-27 00:00:00' 0 +p8 RANGE COLUMNS `c` '2026-04-28 00:00:00' 0 +p9 RANGE COLUMNS `c` '2026-04-29 00:00:00' 0 +p10 RANGE COLUMNS `c` '2026-04-30 00:00:00' 0 +p11 RANGE COLUMNS `c` '2026-05-01 00:00:00' 0 +p12 RANGE COLUMNS `c` '2026-05-02 00:00:00' 1 +p13 RANGE COLUMNS `c` '2026-05-03 00:00:00' 0 +set timestamp= unix_timestamp('2026-05-06 00:00:00'); +insert into t1 values ('2026-05-04'); +select * from t1; +c +2026-05-01 00:00:00 +2026-05-04 00:00:00 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` datetime DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 1 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-20') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-04-21 00:00:00') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-04-22 00:00:00') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-04-23 00:00:00') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2026-04-24 00:00:00') ENGINE = InnoDB, + PARTITION `p5` VALUES LESS THAN ('2026-04-25 00:00:00') ENGINE = InnoDB, + PARTITION `p6` VALUES LESS THAN ('2026-04-26 00:00:00') ENGINE = InnoDB, + PARTITION `p7` VALUES LESS THAN ('2026-04-27 00:00:00') ENGINE = InnoDB, + PARTITION `p8` VALUES LESS THAN ('2026-04-28 00:00:00') ENGINE = InnoDB, + PARTITION `p9` VALUES LESS THAN ('2026-04-29 00:00:00') ENGINE = InnoDB, + PARTITION `p10` VALUES LESS THAN ('2026-04-30 00:00:00') ENGINE = InnoDB, + PARTITION `p11` VALUES LESS THAN ('2026-05-01 00:00:00') ENGINE = InnoDB, + PARTITION `p12` VALUES LESS THAN ('2026-05-02 00:00:00') ENGINE = InnoDB, + PARTITION `p13` VALUES LESS THAN ('2026-05-03 00:00:00') ENGINE = InnoDB, + PARTITION `p14` VALUES LESS THAN ('2026-05-04 00:00:00') ENGINE = InnoDB, + PARTITION `p15` VALUES LESS THAN ('2026-05-05 00:00:00') ENGINE = InnoDB, + PARTITION `p16` VALUES LESS THAN ('2026-05-06 00:00:00') ENGINE = InnoDB, + PARTITION `p17` VALUES LESS THAN ('2026-05-07 00:00:00') ENGINE = InnoDB) +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1'; +partition_name partition_method partition_expression partition_description table_rows +p0 RANGE COLUMNS `c` '2026-04-20' 0 +p1 RANGE COLUMNS `c` '2026-04-21 00:00:00' 0 +p2 RANGE COLUMNS `c` '2026-04-22 00:00:00' 0 +p3 RANGE COLUMNS `c` '2026-04-23 00:00:00' 0 +p4 RANGE COLUMNS `c` '2026-04-24 00:00:00' 0 +p5 RANGE COLUMNS `c` '2026-04-25 00:00:00' 0 +p6 RANGE COLUMNS `c` '2026-04-26 00:00:00' 0 +p7 RANGE COLUMNS `c` '2026-04-27 00:00:00' 0 +p8 RANGE COLUMNS `c` '2026-04-28 00:00:00' 0 +p9 RANGE COLUMNS `c` '2026-04-29 00:00:00' 0 +p10 RANGE COLUMNS `c` '2026-04-30 00:00:00' 0 +p11 RANGE COLUMNS `c` '2026-05-01 00:00:00' 0 +p12 RANGE COLUMNS `c` '2026-05-02 00:00:00' 1 +p13 RANGE COLUMNS `c` '2026-05-03 00:00:00' 0 +p14 RANGE COLUMNS `c` '2026-05-04 00:00:00' 0 +p15 RANGE COLUMNS `c` '2026-05-05 00:00:00' 1 +p16 RANGE COLUMNS `c` '2026-05-06 00:00:00' 0 +p17 RANGE COLUMNS `c` '2026-05-07 00:00:00' 0 +drop table t1; +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 DAY AUTO +( +PARTITION p0 VALUES LESS THAN ('2026-04-30') +); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` date DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 1 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-30') ENGINE = InnoDB) +insert into t1 values ('2026-05-01'); +select * from t1; +c +2026-05-01 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` date DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 1 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-30') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-05-01') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-05-02') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-05-03') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2026-05-04') ENGINE = InnoDB, + PARTITION `p5` VALUES LESS THAN ('2026-05-05') ENGINE = InnoDB, + PARTITION `p6` VALUES LESS THAN ('2026-05-06') ENGINE = InnoDB, + PARTITION `p7` VALUES LESS THAN ('2026-05-07') ENGINE = InnoDB) +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1'; +partition_name partition_method partition_expression partition_description table_rows +p0 RANGE COLUMNS `c` '2026-04-30' 0 +p1 RANGE COLUMNS `c` '2026-05-01' 0 +p2 RANGE COLUMNS `c` '2026-05-02' 1 +p3 RANGE COLUMNS `c` '2026-05-03' 0 +p4 RANGE COLUMNS `c` '2026-05-04' 0 +p5 RANGE COLUMNS `c` '2026-05-05' 0 +p6 RANGE COLUMNS `c` '2026-05-06' 0 +p7 RANGE COLUMNS `c` '2026-05-07' 0 +drop table t1; +# 1.5 day interval truncated to +1d, +2d, +1d, +2d, ... +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 36 Hour +( +PARTITION p0 VALUES LESS THAN ('2026-04-30') +); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` date DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 36 HOUR +(PARTITION `p0` VALUES LESS THAN ('2026-04-30') ENGINE = InnoDB) +insert into t1 values ('2026-05-01'); +select * from t1; +c +2026-05-01 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` date DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 36 HOUR +(PARTITION `p0` VALUES LESS THAN ('2026-04-30') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-05-01') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-05-03') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-05-04') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2026-05-06') ENGINE = InnoDB, + PARTITION `p5` VALUES LESS THAN ('2026-05-07') ENGINE = InnoDB) +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1'; +partition_name partition_method partition_expression partition_description table_rows +p0 RANGE COLUMNS `c` '2026-04-30' 0 +p1 RANGE COLUMNS `c` '2026-05-01' 0 +p2 RANGE COLUMNS `c` '2026-05-03' 1 +p3 RANGE COLUMNS `c` '2026-05-04' 0 +p4 RANGE COLUMNS `c` '2026-05-06' 0 +p5 RANGE COLUMNS `c` '2026-05-07' 0 +drop table t1; +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Week +( +PARTITION p0 VALUES LESS THAN ('2026-04-20') +); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` date DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 7 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-20') ENGINE = InnoDB) +insert into t1 values ('2026-05-01'); +select * from t1; +c +2026-05-01 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` date DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 7 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-20') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-04-27') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-05-04') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-05-11') ENGINE = InnoDB) +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1'; +partition_name partition_method partition_expression partition_description table_rows +p0 RANGE COLUMNS `c` '2026-04-20' 0 +p1 RANGE COLUMNS `c` '2026-04-27' 0 +p2 RANGE COLUMNS `c` '2026-05-04' 1 +p3 RANGE COLUMNS `c` '2026-05-11' 0 +drop table t1; +create table t1 (c datetime) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 hour +( +PARTITION p0 VALUES LESS THAN ('2026-05-05') +); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` datetime DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 1 HOUR +(PARTITION `p0` VALUES LESS THAN ('2026-05-05') ENGINE = InnoDB) +insert into t1 values ('2026-05-05 03:00:00'); +select * from t1; +c +2026-05-05 03:00:00 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` datetime DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 1 HOUR +(PARTITION `p0` VALUES LESS THAN ('2026-05-05') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-05-05 01:00:00') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-05-05 02:00:00') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-05-05 03:00:00') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2026-05-05 04:00:00') ENGINE = InnoDB, + PARTITION `p5` VALUES LESS THAN ('2026-05-05 05:00:00') ENGINE = InnoDB, + PARTITION `p6` VALUES LESS THAN ('2026-05-05 06:00:00') ENGINE = InnoDB, + PARTITION `p7` VALUES LESS THAN ('2026-05-05 07:00:00') ENGINE = InnoDB, + PARTITION `p8` VALUES LESS THAN ('2026-05-05 08:00:00') ENGINE = InnoDB, + PARTITION `p9` VALUES LESS THAN ('2026-05-05 09:00:00') ENGINE = InnoDB, + PARTITION `p10` VALUES LESS THAN ('2026-05-05 10:00:00') ENGINE = InnoDB, + PARTITION `p11` VALUES LESS THAN ('2026-05-05 11:00:00') ENGINE = InnoDB, + PARTITION `p12` VALUES LESS THAN ('2026-05-05 12:00:00') ENGINE = InnoDB, + PARTITION `p13` VALUES LESS THAN ('2026-05-05 13:00:00') ENGINE = InnoDB, + PARTITION `p14` VALUES LESS THAN ('2026-05-05 14:00:00') ENGINE = InnoDB, + PARTITION `p15` VALUES LESS THAN ('2026-05-05 15:00:00') ENGINE = InnoDB, + PARTITION `p16` VALUES LESS THAN ('2026-05-05 16:00:00') ENGINE = InnoDB, + PARTITION `p17` VALUES LESS THAN ('2026-05-05 17:00:00') ENGINE = InnoDB, + PARTITION `p18` VALUES LESS THAN ('2026-05-05 18:00:00') ENGINE = InnoDB, + PARTITION `p19` VALUES LESS THAN ('2026-05-05 19:00:00') ENGINE = InnoDB, + PARTITION `p20` VALUES LESS THAN ('2026-05-05 20:00:00') ENGINE = InnoDB, + PARTITION `p21` VALUES LESS THAN ('2026-05-05 21:00:00') ENGINE = InnoDB, + PARTITION `p22` VALUES LESS THAN ('2026-05-05 22:00:00') ENGINE = InnoDB, + PARTITION `p23` VALUES LESS THAN ('2026-05-05 23:00:00') ENGINE = InnoDB, + PARTITION `p24` VALUES LESS THAN ('2026-05-06 00:00:00') ENGINE = InnoDB, + PARTITION `p25` VALUES LESS THAN ('2026-05-06 01:00:00') ENGINE = InnoDB) +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1'; +partition_name partition_method partition_expression partition_description table_rows +p0 RANGE COLUMNS `c` '2026-05-05' 0 +p1 RANGE COLUMNS `c` '2026-05-05 01:00:00' 0 +p2 RANGE COLUMNS `c` '2026-05-05 02:00:00' 0 +p3 RANGE COLUMNS `c` '2026-05-05 03:00:00' 0 +p4 RANGE COLUMNS `c` '2026-05-05 04:00:00' 1 +p5 RANGE COLUMNS `c` '2026-05-05 05:00:00' 0 +p6 RANGE COLUMNS `c` '2026-05-05 06:00:00' 0 +p7 RANGE COLUMNS `c` '2026-05-05 07:00:00' 0 +p8 RANGE COLUMNS `c` '2026-05-05 08:00:00' 0 +p9 RANGE COLUMNS `c` '2026-05-05 09:00:00' 0 +p10 RANGE COLUMNS `c` '2026-05-05 10:00:00' 0 +p11 RANGE COLUMNS `c` '2026-05-05 11:00:00' 0 +p12 RANGE COLUMNS `c` '2026-05-05 12:00:00' 0 +p13 RANGE COLUMNS `c` '2026-05-05 13:00:00' 0 +p14 RANGE COLUMNS `c` '2026-05-05 14:00:00' 0 +p15 RANGE COLUMNS `c` '2026-05-05 15:00:00' 0 +p16 RANGE COLUMNS `c` '2026-05-05 16:00:00' 0 +p17 RANGE COLUMNS `c` '2026-05-05 17:00:00' 0 +p18 RANGE COLUMNS `c` '2026-05-05 18:00:00' 0 +p19 RANGE COLUMNS `c` '2026-05-05 19:00:00' 0 +p20 RANGE COLUMNS `c` '2026-05-05 20:00:00' 0 +p21 RANGE COLUMNS `c` '2026-05-05 21:00:00' 0 +p22 RANGE COLUMNS `c` '2026-05-05 22:00:00' 0 +p23 RANGE COLUMNS `c` '2026-05-05 23:00:00' 0 +p24 RANGE COLUMNS `c` '2026-05-06 00:00:00' 0 +p25 RANGE COLUMNS `c` '2026-05-06 01:00:00' 0 +drop table t1; +# more than 1 starting partition +create table t1 (c datetime) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( +PARTITION p0 VALUES LESS THAN ('2026-04-20'), +PARTITION p1 VALUES LESS THAN ('2026-04-25') +); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` datetime DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 1 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-20') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-04-25') ENGINE = InnoDB) +insert into t1 values ('2026-05-01'); +select * from t1; +c +2026-05-01 00:00:00 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` datetime DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 1 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-20') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-04-25') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-04-26 00:00:00') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-04-27 00:00:00') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2026-04-28 00:00:00') ENGINE = InnoDB, + PARTITION `p5` VALUES LESS THAN ('2026-04-29 00:00:00') ENGINE = InnoDB, + PARTITION `p6` VALUES LESS THAN ('2026-04-30 00:00:00') ENGINE = InnoDB, + PARTITION `p7` VALUES LESS THAN ('2026-05-01 00:00:00') ENGINE = InnoDB, + PARTITION `p8` VALUES LESS THAN ('2026-05-02 00:00:00') ENGINE = InnoDB, + PARTITION `p9` VALUES LESS THAN ('2026-05-03 00:00:00') ENGINE = InnoDB, + PARTITION `p10` VALUES LESS THAN ('2026-05-04 00:00:00') ENGINE = InnoDB, + PARTITION `p11` VALUES LESS THAN ('2026-05-05 00:00:00') ENGINE = InnoDB, + PARTITION `p12` VALUES LESS THAN ('2026-05-06 00:00:00') ENGINE = InnoDB, + PARTITION `p13` VALUES LESS THAN ('2026-05-07 00:00:00') ENGINE = InnoDB) +drop table t1; +# no need to create new partition when existing ones are sufficient +create table t1 (c datetime) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( +PARTITION p0 VALUES LESS THAN ('2026-04-01'), +PARTITION p1 VALUES LESS THAN ('2026-05-06') +); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` datetime DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 1 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-01') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-05-06') ENGINE = InnoDB) +insert into t1 values ('2026-05-01'); +select * from t1; +c +2026-05-01 00:00:00 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` datetime DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 1 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-01') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-05-06') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-05-07 00:00:00') ENGINE = InnoDB) +drop table t1; +# find a gap big enough for names of 10 new partition names +create table t1 (c datetime) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( +PARTITION p9 VALUES LESS THAN ('2026-04-01'), +PARTITION p29 VALUES LESS THAN ('2026-04-04'), +PARTITION p19 VALUES LESS THAN ('2026-04-23'), +PARTITION p40 VALUES LESS THAN ('2026-04-27') +); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` datetime DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 1 DAY +(PARTITION `p9` VALUES LESS THAN ('2026-04-01') ENGINE = InnoDB, + PARTITION `p29` VALUES LESS THAN ('2026-04-04') ENGINE = InnoDB, + PARTITION `p19` VALUES LESS THAN ('2026-04-23') ENGINE = InnoDB, + PARTITION `p40` VALUES LESS THAN ('2026-04-27') ENGINE = InnoDB) +insert into t1 values ('2026-05-01'); +select * from t1; +c +2026-05-01 00:00:00 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` datetime DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 1 DAY +(PARTITION `p9` VALUES LESS THAN ('2026-04-01') ENGINE = InnoDB, + PARTITION `p29` VALUES LESS THAN ('2026-04-04') ENGINE = InnoDB, + PARTITION `p19` VALUES LESS THAN ('2026-04-23') ENGINE = InnoDB, + PARTITION `p40` VALUES LESS THAN ('2026-04-27') ENGINE = InnoDB, + PARTITION `p30` VALUES LESS THAN ('2026-04-28 00:00:00') ENGINE = InnoDB, + PARTITION `p31` VALUES LESS THAN ('2026-04-29 00:00:00') ENGINE = InnoDB, + PARTITION `p32` VALUES LESS THAN ('2026-04-30 00:00:00') ENGINE = InnoDB, + PARTITION `p33` VALUES LESS THAN ('2026-05-01 00:00:00') ENGINE = InnoDB, + PARTITION `p34` VALUES LESS THAN ('2026-05-02 00:00:00') ENGINE = InnoDB, + PARTITION `p35` VALUES LESS THAN ('2026-05-03 00:00:00') ENGINE = InnoDB, + PARTITION `p36` VALUES LESS THAN ('2026-05-04 00:00:00') ENGINE = InnoDB, + PARTITION `p37` VALUES LESS THAN ('2026-05-05 00:00:00') ENGINE = InnoDB, + PARTITION `p38` VALUES LESS THAN ('2026-05-06 00:00:00') ENGINE = InnoDB, + PARTITION `p39` VALUES LESS THAN ('2026-05-07 00:00:00') ENGINE = InnoDB) +drop table t1; +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( +PARTITION p40 VALUES LESS THAN ('2026-04-27') +); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` date DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 1 DAY +(PARTITION `p40` VALUES LESS THAN ('2026-04-27') ENGINE = InnoDB) +insert into t1 values ('2026-05-01'); +select * from t1; +c +2026-05-01 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` date DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 1 DAY +(PARTITION `p40` VALUES LESS THAN ('2026-04-27') ENGINE = InnoDB, + PARTITION `p0` VALUES LESS THAN ('2026-04-28') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-04-29') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-04-30') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-05-01') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2026-05-02') ENGINE = InnoDB, + PARTITION `p5` VALUES LESS THAN ('2026-05-03') ENGINE = InnoDB, + PARTITION `p6` VALUES LESS THAN ('2026-05-04') ENGINE = InnoDB, + PARTITION `p7` VALUES LESS THAN ('2026-05-05') ENGINE = InnoDB, + PARTITION `p8` VALUES LESS THAN ('2026-05-06') ENGINE = InnoDB, + PARTITION `p9` VALUES LESS THAN ('2026-05-07') ENGINE = InnoDB) +drop table t1; +# CREATE TABLE ... SELECT +# does not work probably because of MDEV-29769 +select to_days('2026-04-01') = 740072; +to_days('2026-04-01') = 740072 +1 +select to_days('2026-05-01') = 740102; +to_days('2026-05-01') = 740102 +1 +# somehow ps protocol has different results +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( +PARTITION p0 VALUES LESS THAN ('2026-04-01') +) +select from_days(seq) as c from seq_740073_to_740102; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` date DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1'; +partition_name partition_method partition_expression partition_description table_rows +NULL NULL NULL NULL 30 +drop table t1; +# INSERT ... SELECT +select to_days('2026-04-01') = 740072; +to_days('2026-04-01') = 740072 +1 +select to_days('2026-05-01') = 740102; +to_days('2026-05-01') = 740102 +1 +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( +PARTITION p0 VALUES LESS THAN ('2026-04-01') +); +insert into t1 select from_days(seq) from seq_740073_to_740102; +select * from t1; +c +2026-04-02 +2026-04-03 +2026-04-04 +2026-04-05 +2026-04-06 +2026-04-07 +2026-04-08 +2026-04-09 +2026-04-10 +2026-04-11 +2026-04-12 +2026-04-13 +2026-04-14 +2026-04-15 +2026-04-16 +2026-04-17 +2026-04-18 +2026-04-19 +2026-04-20 +2026-04-21 +2026-04-22 +2026-04-23 +2026-04-24 +2026-04-25 +2026-04-26 +2026-04-27 +2026-04-28 +2026-04-29 +2026-04-30 +2026-05-01 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` date DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 1 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-01') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-04-02') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-04-03') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-04-04') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2026-04-05') ENGINE = InnoDB, + PARTITION `p5` VALUES LESS THAN ('2026-04-06') ENGINE = InnoDB, + PARTITION `p6` VALUES LESS THAN ('2026-04-07') ENGINE = InnoDB, + PARTITION `p7` VALUES LESS THAN ('2026-04-08') ENGINE = InnoDB, + PARTITION `p8` VALUES LESS THAN ('2026-04-09') ENGINE = InnoDB, + PARTITION `p9` VALUES LESS THAN ('2026-04-10') ENGINE = InnoDB, + PARTITION `p10` VALUES LESS THAN ('2026-04-11') ENGINE = InnoDB, + PARTITION `p11` VALUES LESS THAN ('2026-04-12') ENGINE = InnoDB, + PARTITION `p12` VALUES LESS THAN ('2026-04-13') ENGINE = InnoDB, + PARTITION `p13` VALUES LESS THAN ('2026-04-14') ENGINE = InnoDB, + PARTITION `p14` VALUES LESS THAN ('2026-04-15') ENGINE = InnoDB, + PARTITION `p15` VALUES LESS THAN ('2026-04-16') ENGINE = InnoDB, + PARTITION `p16` VALUES LESS THAN ('2026-04-17') ENGINE = InnoDB, + PARTITION `p17` VALUES LESS THAN ('2026-04-18') ENGINE = InnoDB, + PARTITION `p18` VALUES LESS THAN ('2026-04-19') ENGINE = InnoDB, + PARTITION `p19` VALUES LESS THAN ('2026-04-20') ENGINE = InnoDB, + PARTITION `p20` VALUES LESS THAN ('2026-04-21') ENGINE = InnoDB, + PARTITION `p21` VALUES LESS THAN ('2026-04-22') ENGINE = InnoDB, + PARTITION `p22` VALUES LESS THAN ('2026-04-23') ENGINE = InnoDB, + PARTITION `p23` VALUES LESS THAN ('2026-04-24') ENGINE = InnoDB, + PARTITION `p24` VALUES LESS THAN ('2026-04-25') ENGINE = InnoDB, + PARTITION `p25` VALUES LESS THAN ('2026-04-26') ENGINE = InnoDB, + PARTITION `p26` VALUES LESS THAN ('2026-04-27') ENGINE = InnoDB, + PARTITION `p27` VALUES LESS THAN ('2026-04-28') ENGINE = InnoDB, + PARTITION `p28` VALUES LESS THAN ('2026-04-29') ENGINE = InnoDB, + PARTITION `p29` VALUES LESS THAN ('2026-04-30') ENGINE = InnoDB, + PARTITION `p30` VALUES LESS THAN ('2026-05-01') ENGINE = InnoDB, + PARTITION `p31` VALUES LESS THAN ('2026-05-02') ENGINE = InnoDB, + PARTITION `p32` VALUES LESS THAN ('2026-05-03') ENGINE = InnoDB, + PARTITION `p33` VALUES LESS THAN ('2026-05-04') ENGINE = InnoDB, + PARTITION `p34` VALUES LESS THAN ('2026-05-05') ENGINE = InnoDB, + PARTITION `p35` VALUES LESS THAN ('2026-05-06') ENGINE = InnoDB, + PARTITION `p36` VALUES LESS THAN ('2026-05-07') ENGINE = InnoDB) +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1'; +partition_name partition_method partition_expression partition_description table_rows +p0 RANGE COLUMNS `c` '2026-04-01' 0 +p1 RANGE COLUMNS `c` '2026-04-02' 0 +p2 RANGE COLUMNS `c` '2026-04-03' 1 +p3 RANGE COLUMNS `c` '2026-04-04' 1 +p4 RANGE COLUMNS `c` '2026-04-05' 1 +p5 RANGE COLUMNS `c` '2026-04-06' 1 +p6 RANGE COLUMNS `c` '2026-04-07' 1 +p7 RANGE COLUMNS `c` '2026-04-08' 1 +p8 RANGE COLUMNS `c` '2026-04-09' 1 +p9 RANGE COLUMNS `c` '2026-04-10' 1 +p10 RANGE COLUMNS `c` '2026-04-11' 1 +p11 RANGE COLUMNS `c` '2026-04-12' 1 +p12 RANGE COLUMNS `c` '2026-04-13' 1 +p13 RANGE COLUMNS `c` '2026-04-14' 1 +p14 RANGE COLUMNS `c` '2026-04-15' 1 +p15 RANGE COLUMNS `c` '2026-04-16' 1 +p16 RANGE COLUMNS `c` '2026-04-17' 1 +p17 RANGE COLUMNS `c` '2026-04-18' 1 +p18 RANGE COLUMNS `c` '2026-04-19' 1 +p19 RANGE COLUMNS `c` '2026-04-20' 1 +p20 RANGE COLUMNS `c` '2026-04-21' 1 +p21 RANGE COLUMNS `c` '2026-04-22' 1 +p22 RANGE COLUMNS `c` '2026-04-23' 1 +p23 RANGE COLUMNS `c` '2026-04-24' 1 +p24 RANGE COLUMNS `c` '2026-04-25' 1 +p25 RANGE COLUMNS `c` '2026-04-26' 1 +p26 RANGE COLUMNS `c` '2026-04-27' 1 +p27 RANGE COLUMNS `c` '2026-04-28' 1 +p28 RANGE COLUMNS `c` '2026-04-29' 1 +p29 RANGE COLUMNS `c` '2026-04-30' 1 +p30 RANGE COLUMNS `c` '2026-05-01' 1 +p31 RANGE COLUMNS `c` '2026-05-02' 1 +p32 RANGE COLUMNS `c` '2026-05-03' 0 +p33 RANGE COLUMNS `c` '2026-05-04' 0 +p34 RANGE COLUMNS `c` '2026-05-05' 0 +p35 RANGE COLUMNS `c` '2026-05-06' 0 +p36 RANGE COLUMNS `c` '2026-05-07' 0 +drop table t1; +select to_days('2026-05-01') = 740102; +to_days('2026-05-01') = 740102 +1 +select to_days('2026-05-08') = 740109; +to_days('2026-05-08') = 740109 +1 +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( +PARTITION p0 VALUES LESS THAN ('2026-04-01') +); +insert into t1 select from_days(seq) from seq_740102_to_740109; +ERROR HY000: Table has no partition for value from column_list +select * from t1; +c +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` date DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 1 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-01') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-04-02') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-04-03') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-04-04') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2026-04-05') ENGINE = InnoDB, + PARTITION `p5` VALUES LESS THAN ('2026-04-06') ENGINE = InnoDB, + PARTITION `p6` VALUES LESS THAN ('2026-04-07') ENGINE = InnoDB, + PARTITION `p7` VALUES LESS THAN ('2026-04-08') ENGINE = InnoDB, + PARTITION `p8` VALUES LESS THAN ('2026-04-09') ENGINE = InnoDB, + PARTITION `p9` VALUES LESS THAN ('2026-04-10') ENGINE = InnoDB, + PARTITION `p10` VALUES LESS THAN ('2026-04-11') ENGINE = InnoDB, + PARTITION `p11` VALUES LESS THAN ('2026-04-12') ENGINE = InnoDB, + PARTITION `p12` VALUES LESS THAN ('2026-04-13') ENGINE = InnoDB, + PARTITION `p13` VALUES LESS THAN ('2026-04-14') ENGINE = InnoDB, + PARTITION `p14` VALUES LESS THAN ('2026-04-15') ENGINE = InnoDB, + PARTITION `p15` VALUES LESS THAN ('2026-04-16') ENGINE = InnoDB, + PARTITION `p16` VALUES LESS THAN ('2026-04-17') ENGINE = InnoDB, + PARTITION `p17` VALUES LESS THAN ('2026-04-18') ENGINE = InnoDB, + PARTITION `p18` VALUES LESS THAN ('2026-04-19') ENGINE = InnoDB, + PARTITION `p19` VALUES LESS THAN ('2026-04-20') ENGINE = InnoDB, + PARTITION `p20` VALUES LESS THAN ('2026-04-21') ENGINE = InnoDB, + PARTITION `p21` VALUES LESS THAN ('2026-04-22') ENGINE = InnoDB, + PARTITION `p22` VALUES LESS THAN ('2026-04-23') ENGINE = InnoDB, + PARTITION `p23` VALUES LESS THAN ('2026-04-24') ENGINE = InnoDB, + PARTITION `p24` VALUES LESS THAN ('2026-04-25') ENGINE = InnoDB, + PARTITION `p25` VALUES LESS THAN ('2026-04-26') ENGINE = InnoDB, + PARTITION `p26` VALUES LESS THAN ('2026-04-27') ENGINE = InnoDB, + PARTITION `p27` VALUES LESS THAN ('2026-04-28') ENGINE = InnoDB, + PARTITION `p28` VALUES LESS THAN ('2026-04-29') ENGINE = InnoDB, + PARTITION `p29` VALUES LESS THAN ('2026-04-30') ENGINE = InnoDB, + PARTITION `p30` VALUES LESS THAN ('2026-05-01') ENGINE = InnoDB, + PARTITION `p31` VALUES LESS THAN ('2026-05-02') ENGINE = InnoDB, + PARTITION `p32` VALUES LESS THAN ('2026-05-03') ENGINE = InnoDB, + PARTITION `p33` VALUES LESS THAN ('2026-05-04') ENGINE = InnoDB, + PARTITION `p34` VALUES LESS THAN ('2026-05-05') ENGINE = InnoDB, + PARTITION `p35` VALUES LESS THAN ('2026-05-06') ENGINE = InnoDB, + PARTITION `p36` VALUES LESS THAN ('2026-05-07') ENGINE = InnoDB) +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1' and table_rows > 0; +partition_name partition_method partition_expression partition_description table_rows +drop table t1; +# LOAD DATA INFILE +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( +PARTITION p0 VALUES LESS THAN ('2026-04-20') +); +load data infile 'load.data' ignore into table t1; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` date DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 1 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-20') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-04-21') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-04-22') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-04-23') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2026-04-24') ENGINE = InnoDB, + PARTITION `p5` VALUES LESS THAN ('2026-04-25') ENGINE = InnoDB, + PARTITION `p6` VALUES LESS THAN ('2026-04-26') ENGINE = InnoDB, + PARTITION `p7` VALUES LESS THAN ('2026-04-27') ENGINE = InnoDB, + PARTITION `p8` VALUES LESS THAN ('2026-04-28') ENGINE = InnoDB, + PARTITION `p9` VALUES LESS THAN ('2026-04-29') ENGINE = InnoDB, + PARTITION `p10` VALUES LESS THAN ('2026-04-30') ENGINE = InnoDB, + PARTITION `p11` VALUES LESS THAN ('2026-05-01') ENGINE = InnoDB, + PARTITION `p12` VALUES LESS THAN ('2026-05-02') ENGINE = InnoDB, + PARTITION `p13` VALUES LESS THAN ('2026-05-03') ENGINE = InnoDB, + PARTITION `p14` VALUES LESS THAN ('2026-05-04') ENGINE = InnoDB, + PARTITION `p15` VALUES LESS THAN ('2026-05-05') ENGINE = InnoDB, + PARTITION `p16` VALUES LESS THAN ('2026-05-06') ENGINE = InnoDB, + PARTITION `p17` VALUES LESS THAN ('2026-05-07') ENGINE = InnoDB) +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1' and table_rows > 0; +partition_name partition_method partition_expression partition_description table_rows +p12 RANGE COLUMNS `c` '2026-05-02' 1 +p13 RANGE COLUMNS `c` '2026-05-03' 1 +p14 RANGE COLUMNS `c` '2026-05-04' 1 +p15 RANGE COLUMNS `c` '2026-05-05' 1 +p16 RANGE COLUMNS `c` '2026-05-06' 1 +drop table t1; +# LOAD DATA INFILE is not atomic +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( +PARTITION p0 VALUES LESS THAN ('2026-04-20') +); +load data infile 'load.data' ignore into table t1; +Warnings: +Warning 1526 Table has no partition for value from column_list +Warning 1526 Table has no partition for value from column_list +select * from t1; +c +2026-05-05 +2026-05-06 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` date DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 1 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-20') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-04-21') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-04-22') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-04-23') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2026-04-24') ENGINE = InnoDB, + PARTITION `p5` VALUES LESS THAN ('2026-04-25') ENGINE = InnoDB, + PARTITION `p6` VALUES LESS THAN ('2026-04-26') ENGINE = InnoDB, + PARTITION `p7` VALUES LESS THAN ('2026-04-27') ENGINE = InnoDB, + PARTITION `p8` VALUES LESS THAN ('2026-04-28') ENGINE = InnoDB, + PARTITION `p9` VALUES LESS THAN ('2026-04-29') ENGINE = InnoDB, + PARTITION `p10` VALUES LESS THAN ('2026-04-30') ENGINE = InnoDB, + PARTITION `p11` VALUES LESS THAN ('2026-05-01') ENGINE = InnoDB, + PARTITION `p12` VALUES LESS THAN ('2026-05-02') ENGINE = InnoDB, + PARTITION `p13` VALUES LESS THAN ('2026-05-03') ENGINE = InnoDB, + PARTITION `p14` VALUES LESS THAN ('2026-05-04') ENGINE = InnoDB, + PARTITION `p15` VALUES LESS THAN ('2026-05-05') ENGINE = InnoDB, + PARTITION `p16` VALUES LESS THAN ('2026-05-06') ENGINE = InnoDB, + PARTITION `p17` VALUES LESS THAN ('2026-05-07') ENGINE = InnoDB) +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1' and table_rows > 0; +partition_name partition_method partition_expression partition_description table_rows +p16 RANGE COLUMNS `c` '2026-05-06' 1 +p17 RANGE COLUMNS `c` '2026-05-07' 1 +drop table t1; +# UPDATE +set timestamp= unix_timestamp('2026-05-02 00:00:00'); +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( +PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +insert into t1 values ('2026-04-28'), ('2026-04-29'), ('2026-04-30'); +select * from t1; +c +2026-04-28 +2026-04-29 +2026-04-30 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` date DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 1 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-25') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-04-26') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-04-27') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-04-28') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2026-04-29') ENGINE = InnoDB, + PARTITION `p5` VALUES LESS THAN ('2026-04-30') ENGINE = InnoDB, + PARTITION `p6` VALUES LESS THAN ('2026-05-01') ENGINE = InnoDB, + PARTITION `p7` VALUES LESS THAN ('2026-05-02') ENGINE = InnoDB, + PARTITION `p8` VALUES LESS THAN ('2026-05-03') ENGINE = InnoDB) +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1' and table_rows > 0; +partition_name partition_method partition_expression partition_description table_rows +p4 RANGE COLUMNS `c` '2026-04-29' 1 +p5 RANGE COLUMNS `c` '2026-04-30' 1 +p6 RANGE COLUMNS `c` '2026-05-01' 1 +set timestamp= unix_timestamp('2026-05-06 00:00:00'); +update t1 set c = date_add(c, interval 6 day); +select * from t1; +c +2026-05-04 +2026-05-05 +2026-05-06 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` date DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 1 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-25') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-04-26') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-04-27') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-04-28') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2026-04-29') ENGINE = InnoDB, + PARTITION `p5` VALUES LESS THAN ('2026-04-30') ENGINE = InnoDB, + PARTITION `p6` VALUES LESS THAN ('2026-05-01') ENGINE = InnoDB, + PARTITION `p7` VALUES LESS THAN ('2026-05-02') ENGINE = InnoDB, + PARTITION `p8` VALUES LESS THAN ('2026-05-03') ENGINE = InnoDB, + PARTITION `p9` VALUES LESS THAN ('2026-05-04') ENGINE = InnoDB, + PARTITION `p10` VALUES LESS THAN ('2026-05-05') ENGINE = InnoDB, + PARTITION `p11` VALUES LESS THAN ('2026-05-06') ENGINE = InnoDB, + PARTITION `p12` VALUES LESS THAN ('2026-05-07') ENGINE = InnoDB) +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1' and table_rows > 0; +partition_name partition_method partition_expression partition_description table_rows +p10 RANGE COLUMNS `c` '2026-05-05' 1 +p11 RANGE COLUMNS `c` '2026-05-06' 1 +p12 RANGE COLUMNS `c` '2026-05-07' 1 +set timestamp= unix_timestamp('2026-05-08 00:00:00'); +update t1 set c = date_add(c, interval 3 day); +ERROR HY000: Table has no partition for value from column_list +select * from t1; +c +2026-05-04 +2026-05-05 +2026-05-06 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` date DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 1 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-25') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-04-26') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-04-27') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-04-28') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2026-04-29') ENGINE = InnoDB, + PARTITION `p5` VALUES LESS THAN ('2026-04-30') ENGINE = InnoDB, + PARTITION `p6` VALUES LESS THAN ('2026-05-01') ENGINE = InnoDB, + PARTITION `p7` VALUES LESS THAN ('2026-05-02') ENGINE = InnoDB, + PARTITION `p8` VALUES LESS THAN ('2026-05-03') ENGINE = InnoDB, + PARTITION `p9` VALUES LESS THAN ('2026-05-04') ENGINE = InnoDB, + PARTITION `p10` VALUES LESS THAN ('2026-05-05') ENGINE = InnoDB, + PARTITION `p11` VALUES LESS THAN ('2026-05-06') ENGINE = InnoDB, + PARTITION `p12` VALUES LESS THAN ('2026-05-07') ENGINE = InnoDB, + PARTITION `p13` VALUES LESS THAN ('2026-05-08') ENGINE = InnoDB, + PARTITION `p14` VALUES LESS THAN ('2026-05-09') ENGINE = InnoDB) +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1' and table_rows > 0; +partition_name partition_method partition_expression partition_description table_rows +p10 RANGE COLUMNS `c` '2026-05-05' 1 +p11 RANGE COLUMNS `c` '2026-05-06' 1 +p12 RANGE COLUMNS `c` '2026-05-07' 1 +set timestamp= unix_timestamp('2026-05-06 00:00:00'); +drop table t1; +# ALTER TABLE +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +( +PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +insert into t1 values ('2026-05-01'); +ERROR HY000: Table has no partition for value from column_list +ALTER TABLE t1 PARTITION BY RANGE COLUMNS (c) INTERVAL 1 DAY +( +PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +insert into t1 values ('2026-05-01'); +SELECT * FROM t1; +c +2026-05-01 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` date DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 1 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-25') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-04-26') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-04-27') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-04-28') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2026-04-29') ENGINE = InnoDB, + PARTITION `p5` VALUES LESS THAN ('2026-04-30') ENGINE = InnoDB, + PARTITION `p6` VALUES LESS THAN ('2026-05-01') ENGINE = InnoDB, + PARTITION `p7` VALUES LESS THAN ('2026-05-02') ENGINE = InnoDB, + PARTITION `p8` VALUES LESS THAN ('2026-05-03') ENGINE = InnoDB, + PARTITION `p9` VALUES LESS THAN ('2026-05-04') ENGINE = InnoDB, + PARTITION `p10` VALUES LESS THAN ('2026-05-05') ENGINE = InnoDB, + PARTITION `p11` VALUES LESS THAN ('2026-05-06') ENGINE = InnoDB, + PARTITION `p12` VALUES LESS THAN ('2026-05-07') ENGINE = InnoDB) +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1' and table_rows > 0; +partition_name partition_method partition_expression partition_description table_rows +p7 RANGE COLUMNS `c` '2026-05-02' 1 +drop table t1; +# failing insertion of dates in the future +create table t1 (c datetime) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( +PARTITION p0 VALUES LESS THAN ('2026-04-01') +); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` datetime DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 1 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-01') ENGINE = InnoDB) +insert into t1 values ('2026-05-07'); +ERROR HY000: Table has no partition for value from column_list +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` datetime DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 1 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-01') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-04-02 00:00:00') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-04-03 00:00:00') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-04-04 00:00:00') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2026-04-05 00:00:00') ENGINE = InnoDB, + PARTITION `p5` VALUES LESS THAN ('2026-04-06 00:00:00') ENGINE = InnoDB, + PARTITION `p6` VALUES LESS THAN ('2026-04-07 00:00:00') ENGINE = InnoDB, + PARTITION `p7` VALUES LESS THAN ('2026-04-08 00:00:00') ENGINE = InnoDB, + PARTITION `p8` VALUES LESS THAN ('2026-04-09 00:00:00') ENGINE = InnoDB, + PARTITION `p9` VALUES LESS THAN ('2026-04-10 00:00:00') ENGINE = InnoDB, + PARTITION `p10` VALUES LESS THAN ('2026-04-11 00:00:00') ENGINE = InnoDB, + PARTITION `p11` VALUES LESS THAN ('2026-04-12 00:00:00') ENGINE = InnoDB, + PARTITION `p12` VALUES LESS THAN ('2026-04-13 00:00:00') ENGINE = InnoDB, + PARTITION `p13` VALUES LESS THAN ('2026-04-14 00:00:00') ENGINE = InnoDB, + PARTITION `p14` VALUES LESS THAN ('2026-04-15 00:00:00') ENGINE = InnoDB, + PARTITION `p15` VALUES LESS THAN ('2026-04-16 00:00:00') ENGINE = InnoDB, + PARTITION `p16` VALUES LESS THAN ('2026-04-17 00:00:00') ENGINE = InnoDB, + PARTITION `p17` VALUES LESS THAN ('2026-04-18 00:00:00') ENGINE = InnoDB, + PARTITION `p18` VALUES LESS THAN ('2026-04-19 00:00:00') ENGINE = InnoDB, + PARTITION `p19` VALUES LESS THAN ('2026-04-20 00:00:00') ENGINE = InnoDB, + PARTITION `p20` VALUES LESS THAN ('2026-04-21 00:00:00') ENGINE = InnoDB, + PARTITION `p21` VALUES LESS THAN ('2026-04-22 00:00:00') ENGINE = InnoDB, + PARTITION `p22` VALUES LESS THAN ('2026-04-23 00:00:00') ENGINE = InnoDB, + PARTITION `p23` VALUES LESS THAN ('2026-04-24 00:00:00') ENGINE = InnoDB, + PARTITION `p24` VALUES LESS THAN ('2026-04-25 00:00:00') ENGINE = InnoDB, + PARTITION `p25` VALUES LESS THAN ('2026-04-26 00:00:00') ENGINE = InnoDB, + PARTITION `p26` VALUES LESS THAN ('2026-04-27 00:00:00') ENGINE = InnoDB, + PARTITION `p27` VALUES LESS THAN ('2026-04-28 00:00:00') ENGINE = InnoDB, + PARTITION `p28` VALUES LESS THAN ('2026-04-29 00:00:00') ENGINE = InnoDB, + PARTITION `p29` VALUES LESS THAN ('2026-04-30 00:00:00') ENGINE = InnoDB, + PARTITION `p30` VALUES LESS THAN ('2026-05-01 00:00:00') ENGINE = InnoDB, + PARTITION `p31` VALUES LESS THAN ('2026-05-02 00:00:00') ENGINE = InnoDB, + PARTITION `p32` VALUES LESS THAN ('2026-05-03 00:00:00') ENGINE = InnoDB, + PARTITION `p33` VALUES LESS THAN ('2026-05-04 00:00:00') ENGINE = InnoDB, + PARTITION `p34` VALUES LESS THAN ('2026-05-05 00:00:00') ENGINE = InnoDB, + PARTITION `p35` VALUES LESS THAN ('2026-05-06 00:00:00') ENGINE = InnoDB, + PARTITION `p36` VALUES LESS THAN ('2026-05-07 00:00:00') ENGINE = InnoDB) +drop table t1; +# passthrough behaviour +create table t1 (c datetime) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( +PARTITION p0 VALUES LESS THAN ('2026-04-01') +); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` datetime DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 1 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-01') ENGINE = InnoDB) +begin; +insert into t1 values ('2026-05-01'); +insert into t1 values ('2026-05-02'); +select * from t1; +c +2026-05-01 00:00:00 +2026-05-02 00:00:00 +rollback; +select * from t1; +c +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` datetime DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`)INTERVAL 1 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-01') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-04-02 00:00:00') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-04-03 00:00:00') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-04-04 00:00:00') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2026-04-05 00:00:00') ENGINE = InnoDB, + PARTITION `p5` VALUES LESS THAN ('2026-04-06 00:00:00') ENGINE = InnoDB, + PARTITION `p6` VALUES LESS THAN ('2026-04-07 00:00:00') ENGINE = InnoDB, + PARTITION `p7` VALUES LESS THAN ('2026-04-08 00:00:00') ENGINE = InnoDB, + PARTITION `p8` VALUES LESS THAN ('2026-04-09 00:00:00') ENGINE = InnoDB, + PARTITION `p9` VALUES LESS THAN ('2026-04-10 00:00:00') ENGINE = InnoDB, + PARTITION `p10` VALUES LESS THAN ('2026-04-11 00:00:00') ENGINE = InnoDB, + PARTITION `p11` VALUES LESS THAN ('2026-04-12 00:00:00') ENGINE = InnoDB, + PARTITION `p12` VALUES LESS THAN ('2026-04-13 00:00:00') ENGINE = InnoDB, + PARTITION `p13` VALUES LESS THAN ('2026-04-14 00:00:00') ENGINE = InnoDB, + PARTITION `p14` VALUES LESS THAN ('2026-04-15 00:00:00') ENGINE = InnoDB, + PARTITION `p15` VALUES LESS THAN ('2026-04-16 00:00:00') ENGINE = InnoDB, + PARTITION `p16` VALUES LESS THAN ('2026-04-17 00:00:00') ENGINE = InnoDB, + PARTITION `p17` VALUES LESS THAN ('2026-04-18 00:00:00') ENGINE = InnoDB, + PARTITION `p18` VALUES LESS THAN ('2026-04-19 00:00:00') ENGINE = InnoDB, + PARTITION `p19` VALUES LESS THAN ('2026-04-20 00:00:00') ENGINE = InnoDB, + PARTITION `p20` VALUES LESS THAN ('2026-04-21 00:00:00') ENGINE = InnoDB, + PARTITION `p21` VALUES LESS THAN ('2026-04-22 00:00:00') ENGINE = InnoDB, + PARTITION `p22` VALUES LESS THAN ('2026-04-23 00:00:00') ENGINE = InnoDB, + PARTITION `p23` VALUES LESS THAN ('2026-04-24 00:00:00') ENGINE = InnoDB, + PARTITION `p24` VALUES LESS THAN ('2026-04-25 00:00:00') ENGINE = InnoDB, + PARTITION `p25` VALUES LESS THAN ('2026-04-26 00:00:00') ENGINE = InnoDB, + PARTITION `p26` VALUES LESS THAN ('2026-04-27 00:00:00') ENGINE = InnoDB, + PARTITION `p27` VALUES LESS THAN ('2026-04-28 00:00:00') ENGINE = InnoDB, + PARTITION `p28` VALUES LESS THAN ('2026-04-29 00:00:00') ENGINE = InnoDB, + PARTITION `p29` VALUES LESS THAN ('2026-04-30 00:00:00') ENGINE = InnoDB, + PARTITION `p30` VALUES LESS THAN ('2026-05-01 00:00:00') ENGINE = InnoDB, + PARTITION `p31` VALUES LESS THAN ('2026-05-02 00:00:00') ENGINE = InnoDB, + PARTITION `p32` VALUES LESS THAN ('2026-05-03 00:00:00') ENGINE = InnoDB, + PARTITION `p33` VALUES LESS THAN ('2026-05-04 00:00:00') ENGINE = InnoDB, + PARTITION `p34` VALUES LESS THAN ('2026-05-05 00:00:00') ENGINE = InnoDB, + PARTITION `p35` VALUES LESS THAN ('2026-05-06 00:00:00') ENGINE = InnoDB, + PARTITION `p36` VALUES LESS THAN ('2026-05-07 00:00:00') ENGINE = InnoDB) +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1'; +partition_name partition_method partition_expression partition_description table_rows +p0 RANGE COLUMNS `c` '2026-04-01' 0 +p1 RANGE COLUMNS `c` '2026-04-02 00:00:00' 0 +p2 RANGE COLUMNS `c` '2026-04-03 00:00:00' 0 +p3 RANGE COLUMNS `c` '2026-04-04 00:00:00' 0 +p4 RANGE COLUMNS `c` '2026-04-05 00:00:00' 0 +p5 RANGE COLUMNS `c` '2026-04-06 00:00:00' 0 +p6 RANGE COLUMNS `c` '2026-04-07 00:00:00' 0 +p7 RANGE COLUMNS `c` '2026-04-08 00:00:00' 0 +p8 RANGE COLUMNS `c` '2026-04-09 00:00:00' 0 +p9 RANGE COLUMNS `c` '2026-04-10 00:00:00' 0 +p10 RANGE COLUMNS `c` '2026-04-11 00:00:00' 0 +p11 RANGE COLUMNS `c` '2026-04-12 00:00:00' 0 +p12 RANGE COLUMNS `c` '2026-04-13 00:00:00' 0 +p13 RANGE COLUMNS `c` '2026-04-14 00:00:00' 0 +p14 RANGE COLUMNS `c` '2026-04-15 00:00:00' 0 +p15 RANGE COLUMNS `c` '2026-04-16 00:00:00' 0 +p16 RANGE COLUMNS `c` '2026-04-17 00:00:00' 0 +p17 RANGE COLUMNS `c` '2026-04-18 00:00:00' 0 +p18 RANGE COLUMNS `c` '2026-04-19 00:00:00' 0 +p19 RANGE COLUMNS `c` '2026-04-20 00:00:00' 0 +p20 RANGE COLUMNS `c` '2026-04-21 00:00:00' 0 +p21 RANGE COLUMNS `c` '2026-04-22 00:00:00' 0 +p22 RANGE COLUMNS `c` '2026-04-23 00:00:00' 0 +p23 RANGE COLUMNS `c` '2026-04-24 00:00:00' 0 +p24 RANGE COLUMNS `c` '2026-04-25 00:00:00' 0 +p25 RANGE COLUMNS `c` '2026-04-26 00:00:00' 0 +p26 RANGE COLUMNS `c` '2026-04-27 00:00:00' 0 +p27 RANGE COLUMNS `c` '2026-04-28 00:00:00' 0 +p28 RANGE COLUMNS `c` '2026-04-29 00:00:00' 0 +p29 RANGE COLUMNS `c` '2026-04-30 00:00:00' 0 +p30 RANGE COLUMNS `c` '2026-05-01 00:00:00' 0 +p31 RANGE COLUMNS `c` '2026-05-02 00:00:00' 0 +p32 RANGE COLUMNS `c` '2026-05-03 00:00:00' 0 +p33 RANGE COLUMNS `c` '2026-05-04 00:00:00' 0 +p34 RANGE COLUMNS `c` '2026-05-05 00:00:00' 0 +p35 RANGE COLUMNS `c` '2026-05-06 00:00:00' 0 +p36 RANGE COLUMNS `c` '2026-05-07 00:00:00' 0 +drop table t1; +# failures +create table t1 (c1 datetime, c2 datetime) +PARTITION BY RANGE COLUMNS (c1, c2) +INTERVAL 1 Day +( +PARTITION p0 VALUES LESS THAN ('2026-04-01', '2026-04-01') +); +ERROR HY000: Too many fields in 'range interval partition fields' +create table t1 (c datetime) +PARTITION BY LIST COLUMNS (c) +INTERVAL 1 Day +( +PARTITION p0 VALUES IN ('2026-04-01') +); +ERROR HY000: LIST partition type does not support INTERVAL +create table t1 (c int) +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( +PARTITION p0 VALUES LESS THAN (740072) +); +ERROR HY000: Field 'c' is of a not allowed type for this type of partitioning +# timestamp is not allowed in range column partitioning +create table t1 (c timestamp) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 minute +( +PARTITION p0 VALUES LESS THAN ('2026-05-05') +); +ERROR HY000: Field 'c' is of a not allowed type for this type of partitioning +# year is not allowed in range column partitioning +create table t1 (c year) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 minute +( +PARTITION p0 VALUES LESS THAN ('2025') +); +ERROR HY000: Field 'c' is of a not allowed type for this type of partitioning +# interval less than a day for date column +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 23.59 HOUR_MINUTE +( +PARTITION p0 VALUES LESS THAN ('2026-04-20') +); +ERROR HY000: RANGE COLUMN partition by a DATE with INTERVAL smaller than date +# bad interval values +create table t1 (c datetime) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL -1 Day +( +PARTITION p0 VALUES LESS THAN ('2026-04-20') +); +ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for 'INTERVAL' +create table t1 (c datetime) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 0 Day +( +PARTITION p0 VALUES LESS THAN ('2026-04-20') +); +ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for 'INTERVAL' +create table t1 (c datetime) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1.1 SECOND_MICROSECOND +( +PARTITION p0 VALUES LESS THAN ('2026-04-20') +); +ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for 'INTERVAL' +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( +PARTITION p1 VALUES LESS THAN ('2026-04-01'), +PARTITION p0 VALUES LESS THAN MAXVALUE +); +ERROR HY000: MAXVALUE is not allowed in range partitioning with interval +create table t1 (c datetime) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Second +( +PARTITION p1 VALUES LESS THAN ('2026-04-01') +); +insert into t1 values ('2026-01-01'); +ERROR HY000: Too many partitions (including subpartitions) were defined +drop table t1; diff --git a/mysql-test/main/partition_range_interval.test b/mysql-test/main/partition_range_interval.test new file mode 100644 index 0000000000000..9100a78ef196e --- /dev/null +++ b/mysql-test/main/partition_range_interval.test @@ -0,0 +1,412 @@ +--source include/have_partition.inc +--source include/have_innodb.inc +--source include/have_sequence.inc + +--echo # simple case showing partitions added in INSERT +set timestamp= unix_timestamp('2026-05-02 00:00:00'); + +create table t1 (c datetime) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( + PARTITION p0 VALUES LESS THAN ('2026-04-20') +); + +show create table t1; +insert into t1 values ('2026-05-01'); +select * from t1; +show create table t1; +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1'; + +set timestamp= unix_timestamp('2026-05-06 00:00:00'); + +insert into t1 values ('2026-05-04'); +select * from t1; +show create table t1; +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1'; + +drop table t1; + +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 DAY AUTO +( + PARTITION p0 VALUES LESS THAN ('2026-04-30') +); +show create table t1; +insert into t1 values ('2026-05-01'); +select * from t1; +show create table t1; +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1'; +drop table t1; + +--echo # 1.5 day interval truncated to +1d, +2d, +1d, +2d, ... +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 36 Hour +( + PARTITION p0 VALUES LESS THAN ('2026-04-30') +); +show create table t1; +insert into t1 values ('2026-05-01'); +select * from t1; +show create table t1; +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1'; +drop table t1; + +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Week +( + PARTITION p0 VALUES LESS THAN ('2026-04-20') +); +show create table t1; +insert into t1 values ('2026-05-01'); +select * from t1; +show create table t1; +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1'; +drop table t1; + +create table t1 (c datetime) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 hour +( + PARTITION p0 VALUES LESS THAN ('2026-05-05') +); +show create table t1; +insert into t1 values ('2026-05-05 03:00:00'); +select * from t1; +show create table t1; +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1'; +drop table t1; + + +--echo # more than 1 starting partition +create table t1 (c datetime) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( + PARTITION p0 VALUES LESS THAN ('2026-04-20'), + PARTITION p1 VALUES LESS THAN ('2026-04-25') +); + +show create table t1; +insert into t1 values ('2026-05-01'); +select * from t1; +show create table t1; +drop table t1; + +--echo # no need to create new partition when existing ones are sufficient +create table t1 (c datetime) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( + PARTITION p0 VALUES LESS THAN ('2026-04-01'), + PARTITION p1 VALUES LESS THAN ('2026-05-06') +); + +show create table t1; +insert into t1 values ('2026-05-01'); +select * from t1; +show create table t1; +drop table t1; + +--echo # find a gap big enough for names of 10 new partition names +create table t1 (c datetime) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( + PARTITION p9 VALUES LESS THAN ('2026-04-01'), + PARTITION p29 VALUES LESS THAN ('2026-04-04'), + PARTITION p19 VALUES LESS THAN ('2026-04-23'), + PARTITION p40 VALUES LESS THAN ('2026-04-27') +); + +show create table t1; +insert into t1 values ('2026-05-01'); +select * from t1; +show create table t1; +drop table t1; + +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( + PARTITION p40 VALUES LESS THAN ('2026-04-27') +); + +show create table t1; +insert into t1 values ('2026-05-01'); +select * from t1; +show create table t1; +drop table t1; + +--echo # CREATE TABLE ... SELECT +--echo # does not work probably because of MDEV-29769 +select to_days('2026-04-01') = 740072; +select to_days('2026-05-01') = 740102; + +--echo # somehow ps protocol has different results +--disable_ps_protocol +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( + PARTITION p0 VALUES LESS THAN ('2026-04-01') +) +select from_days(seq) as c from seq_740073_to_740102; +--enable_ps_protocol +show create table t1; +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1'; +drop table t1; + +--echo # INSERT ... SELECT +select to_days('2026-04-01') = 740072; +select to_days('2026-05-01') = 740102; + +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( + PARTITION p0 VALUES LESS THAN ('2026-04-01') +); +insert into t1 select from_days(seq) from seq_740073_to_740102; +select * from t1; +show create table t1; +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1'; +drop table t1; + +select to_days('2026-05-01') = 740102; +select to_days('2026-05-08') = 740109; + +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( + PARTITION p0 VALUES LESS THAN ('2026-04-01') +); +--error ER_NO_PARTITION_FOR_GIVEN_VALUE +insert into t1 select from_days(seq) from seq_740102_to_740109; +select * from t1; +show create table t1; +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1' and table_rows > 0; +drop table t1; + +--echo # LOAD DATA INFILE +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( + PARTITION p0 VALUES LESS THAN ('2026-04-20') +); + +--let $mysqld_datadir= `select @@datadir` +--write_file $mysqld_datadir/test/load.data +2026-05-01 +2026-05-02 +2026-05-03 +2026-05-04 +2026-05-05 +EOF +load data infile 'load.data' ignore into table t1; +--remove_file $mysqld_datadir/test/load.data +show create table t1; +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1' and table_rows > 0; +drop table t1; + +--echo # LOAD DATA INFILE is not atomic +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( + PARTITION p0 VALUES LESS THAN ('2026-04-20') +); + +--let $mysqld_datadir= `select @@datadir` +--write_file $mysqld_datadir/test/load.data +2026-05-05 +2026-05-06 +2026-05-07 +2026-05-08 +EOF +load data infile 'load.data' ignore into table t1; +--remove_file $mysqld_datadir/test/load.data +select * from t1; +show create table t1; +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1' and table_rows > 0; +drop table t1; + +--echo # UPDATE +set timestamp= unix_timestamp('2026-05-02 00:00:00'); +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( + PARTITION p0 VALUES LESS THAN ('2026-04-25') +); + +insert into t1 values ('2026-04-28'), ('2026-04-29'), ('2026-04-30'); +select * from t1; +show create table t1; +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1' and table_rows > 0; +set timestamp= unix_timestamp('2026-05-06 00:00:00'); +update t1 set c = date_add(c, interval 6 day); +select * from t1; +show create table t1; +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1' and table_rows > 0; +set timestamp= unix_timestamp('2026-05-08 00:00:00'); +--error ER_NO_PARTITION_FOR_GIVEN_VALUE +update t1 set c = date_add(c, interval 3 day); +select * from t1; +show create table t1; +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1' and table_rows > 0; +set timestamp= unix_timestamp('2026-05-06 00:00:00'); +drop table t1; + +--echo # ALTER TABLE +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +( + PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +--error ER_NO_PARTITION_FOR_GIVEN_VALUE +insert into t1 values ('2026-05-01'); +ALTER TABLE t1 PARTITION BY RANGE COLUMNS (c) INTERVAL 1 DAY +( + PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +insert into t1 values ('2026-05-01'); +SELECT * FROM t1; +show create table t1; +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1' and table_rows > 0; +drop table t1; + +--echo # failing insertion of dates in the future +create table t1 (c datetime) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( + PARTITION p0 VALUES LESS THAN ('2026-04-01') +); + +show create table t1; +--error ER_NO_PARTITION_FOR_GIVEN_VALUE +insert into t1 values ('2026-05-07'); +show create table t1; +drop table t1; + +--echo # passthrough behaviour +create table t1 (c datetime) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( + PARTITION p0 VALUES LESS THAN ('2026-04-01') +); +show create table t1; +begin; +insert into t1 values ('2026-05-01'); +insert into t1 values ('2026-05-02'); +select * from t1; +rollback; +select * from t1; +show create table t1; +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1'; +drop table t1; + +--echo # failures + +--error ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR +create table t1 (c1 datetime, c2 datetime) +PARTITION BY RANGE COLUMNS (c1, c2) +INTERVAL 1 Day +( + PARTITION p0 VALUES LESS THAN ('2026-04-01', '2026-04-01') +); + +--error ER_PARTITION_INTERVAL_NOT_LIST +create table t1 (c datetime) +PARTITION BY LIST COLUMNS (c) +INTERVAL 1 Day +( + PARTITION p0 VALUES IN ('2026-04-01') +); + +--error ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD +create table t1 (c int) +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( + PARTITION p0 VALUES LESS THAN (740072) +); + +--echo # timestamp is not allowed in range column partitioning +--error ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD +create table t1 (c timestamp) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 minute +( + PARTITION p0 VALUES LESS THAN ('2026-05-05') +); + +--echo # year is not allowed in range column partitioning +--error ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD +create table t1 (c year) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 minute +( + PARTITION p0 VALUES LESS THAN ('2025') +); + +# TODO: somehow 23.59.59 HOUR_SECOND causes parsing error +--echo # interval less than a day for date column +--error ER_PARTITION_INTERVAL_FINER_THAN_DATE +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 23.59 HOUR_MINUTE +( + PARTITION p0 VALUES LESS THAN ('2026-04-20') +); + +--echo # bad interval values +--error ER_PART_WRONG_VALUE +create table t1 (c datetime) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL -1 Day +( + PARTITION p0 VALUES LESS THAN ('2026-04-20') +); + +--error ER_PART_WRONG_VALUE +create table t1 (c datetime) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 0 Day +( + PARTITION p0 VALUES LESS THAN ('2026-04-20') +); + +--error ER_PART_WRONG_VALUE +create table t1 (c datetime) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1.1 SECOND_MICROSECOND +( + PARTITION p0 VALUES LESS THAN ('2026-04-20') +); + +--error ER_PARTITION_INTERVAL_MAXVALUE +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( + PARTITION p1 VALUES LESS THAN ('2026-04-01'), + PARTITION p0 VALUES LESS THAN MAXVALUE +); + +create table t1 (c datetime) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Second +( + PARTITION p1 VALUES LESS THAN ('2026-04-01') +); +--error ER_TOO_MANY_PARTITIONS_ERROR +insert into t1 values ('2026-01-01'); +drop table t1; diff --git a/sql/partition_element.h b/sql/partition_element.h index 795a7a1d56fb2..205df4344b7bf 100644 --- a/sql/partition_element.h +++ b/sql/partition_element.h @@ -69,7 +69,7 @@ typedef struct p_column_list_val uint partition_id; bool max_value; // MAXVALUE for RANGE type or DEFAULT value for LIST type bool null_value; - char fixed; + bool fixed; } part_column_list_val; diff --git a/sql/partition_info.cc b/sql/partition_info.cc index 7666997dc5eca..a112f93052b6d 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -400,7 +400,7 @@ bool partition_info::set_up_default_partitions(THD *thd, handler *file, num_parts= 2; use_default_num_partitions= false; } - else if (part_type != HASH_PARTITION) + else if (part_type != HASH_PARTITION && !is_range_interval()) { const char *error_string; if (part_type == RANGE_PARTITION) @@ -891,6 +891,34 @@ bool partition_info::vers_set_hist_part(THD *thd, uint *create_count) return false; } +/* + Determine the number of range interval partitions to create, like + partition_info::vers_set_hist_part. +*/ +bool partition_info::range_interval_set_count(THD* thd, uint *create_count) +{ + partition_element *el= partitions.elem(partitions.elements - 1); + Item *item= el->get_col_val(0).item_expression; + MYSQL_TIME cur_time, end_time; + thd->variables.time_zone->gmt_sec_to_TIME(&end_time, thd->query_start()); + longlong cur= item->val_datetime_packed(thd); + unpack_time(cur, &cur_time, MYSQL_TIMESTAMP_DATETIME); + longlong end= pack_time(&end_time); + *create_count= 0; + while (cur <= end) + { + if (date_add_interval(thd, &cur_time, int_type, interval)) + return true; + cur= pack_time(&cur_time); + ++*create_count; + if (*create_count == MAX_PARTITIONS - partitions.elements + 1) + { + my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0)); + return true; + } + } + return false; +} /** @brief Run fast_alter_partition_table() to add new history partitions @@ -1014,6 +1042,101 @@ bool vers_create_partitions(THD *thd, TABLE_LIST* tl, uint num_parts) return result; } +/* + similar to vers_create_partitions, create range interval partitions +*/ +bool range_interval_create_partitions(THD* thd, TABLE_LIST* tl, uint num_parts) +{ + bool result= true; + Table_specification_st create_info; + Alter_info alter_info; + TABLE *table= tl->table; + /* TODO: this may still trigger MSAN unitialised? */ + bool save_no_write_to_binlog= thd->lex->no_write_to_binlog; + thd->lex->no_write_to_binlog= true; + + DBUG_ASSERT(!thd->is_error()); + DBUG_ASSERT(num_parts); + + { + alter_info.reset(); + alter_info.partition_flags= ALTER_PARTITION_ADD; + 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(); + DBUG_ASSERT(create_info.db_type); + + 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; + part_info->num_columns= table->part_info->num_columns; + part_info->part_type= RANGE_PARTITION; + /* for partition_info::fix_parser_data to exit early */ + part_info->int_type= table->part_info->int_type; + + thd->work_part_info= part_info; + 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_INTERNAL_ERROR, MYF(ME_WARNING), + tl->db.str, tl->table_name.str); + goto exit; + } + if (!fast_alter_partition) + { + my_error(ER_INTERNAL_ERROR, 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_INTERNAL_ERROR, MYF(ME_WARNING), + tl->db.str, tl->table_name.str); + goto exit; + } + + alter_info.db= alter_ctx.db; + alter_info.table_name= alter_ctx.table_name; + if (fast_alter_partition_table(thd, table, &alter_info, &alter_ctx, + &create_info, tl)) + { + my_error(ER_INTERNAL_ERROR, 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(); + thd->variables.option_bits|= OPTION_BINLOG_THIS; + +exit: + thd->lex->no_write_to_binlog= save_no_write_to_binlog; + return result; +} /** Warn at the end of DML command if the last history partition is out of LIMIT. @@ -2166,7 +2289,7 @@ int partition_info::fix_partition_values(THD *thd, } part_elem->range_value= val->value; } - col_val->fixed= 2; + col_val->fixed= TRUE; DBUG_RETURN(FALSE); } @@ -2219,12 +2342,11 @@ bool partition_info::fix_column_value_functions(THD *thd, uint part_id) { uint n_columns= part_field_list.elements; - bool result= FALSE; uint i; part_column_list_val *col_val= val->col_val_array; DBUG_ENTER("partition_info::fix_column_value_functions"); - if (col_val->fixed > 1) + if (col_val->fixed) { DBUG_RETURN(FALSE); } @@ -2247,8 +2369,7 @@ bool partition_info::fix_column_value_functions(THD *thd, if (!(column_item= get_column_item(column_item, field))) { - result= TRUE; - goto end; + DBUG_RETURN(TRUE); } Sql_mode_instant_set sms(thd, 0); save_got_warning= thd->got_warning; @@ -2257,22 +2378,19 @@ bool partition_info::fix_column_value_functions(THD *thd, thd->got_warning) { my_error(ER_WRONG_TYPE_COLUMN_VALUE_ERROR, MYF(0)); - result= TRUE; - goto end; + DBUG_RETURN(TRUE); } thd->got_warning= save_got_warning; if (!(val_ptr= (uchar*) thd->memdup(field->ptr, len))) { - result= TRUE; - goto end; + DBUG_RETURN(TRUE); } col_val->column_value= val_ptr; } } - col_val->fixed= 2; + col_val->fixed= TRUE; } -end: - DBUG_RETURN(result); + DBUG_RETURN(FALSE); } @@ -2325,6 +2443,7 @@ bool partition_info::fix_parser_data(THD *thd) partition_element *part_elem; uint num_elements; uint i= 0, j, k; + int sql_command= thd_sql_command(thd); DBUG_ENTER("partition_info::fix_parser_data"); if (!(part_type == RANGE_PARTITION || @@ -2339,13 +2458,25 @@ bool partition_info::fix_parser_data(THD *thd) DBUG_RETURN(true); } /* If not set, use DEFAULT = 2 for CREATE and ALTER! */ - if ((thd_sql_command(thd) == SQLCOM_CREATE_TABLE || - thd_sql_command(thd) == SQLCOM_ALTER_TABLE) && + if ((sql_command == SQLCOM_CREATE_TABLE || + sql_command == SQLCOM_ALTER_TABLE) && key_algorithm == KEY_ALGORITHM_NONE) key_algorithm= KEY_ALGORITHM_55; } DBUG_RETURN(FALSE); } + /* + TODO(MDEV-15621): we exit here for range interval partitions + because if this is called from prep_alter_part_table then + partition data is not calculated (in + check_range_interval_constants) yet. But maybe we shouldn't exit + here in user CREATE/ALTER TABLE statements for other checks. + */ + if (sql_command != SQLCOM_CREATE_TABLE && + sql_command != SQLCOM_ALTER_TABLE && is_range_interval()) + { + DBUG_RETURN(FALSE); + } if (is_sub_partitioned() && list_of_subpart_fields) { /* KEY subpartitioning, check ALGORITHM = N. Should not pass the parser! */ @@ -2790,6 +2921,21 @@ bool partition_info::vers_init_info(THD * thd) return false; } +bool partition_info::set_interval(THD* thd, Item* ival, interval_type type, + const char *table_name) +{ + bool error= get_interval_value(thd, ival, type, &interval) || + interval.neg || interval.second_part || + !(interval.year || interval.month || interval.day || interval.hour || + interval.minute || interval.second); + if (error) + { + my_error(ER_PART_WRONG_VALUE, MYF(0), table_name, "INTERVAL"); + return true; + } + int_type= type; + return false; +} /** Assign INTERVAL and STARTS for SYSTEM_TIME partitions. diff --git a/sql/partition_info.h b/sql/partition_info.h index e25e27860c966..9df273f196407 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -207,6 +207,10 @@ class partition_info : public DDL_LOG_STATE, public Sql_alloc part_column_list_val *list_col_array; }; + /* TODO: change to pointer */ + INTERVAL interval; + enum interval_type int_type; + Vers_part_info *vers_info; /******************************************** @@ -319,7 +323,7 @@ class partition_info : public DDL_LOG_STATE, public Sql_alloc restore_part_field_ptrs(NULL), restore_subpart_field_ptrs(NULL), part_expr(NULL), subpart_expr(NULL), item_free_list(NULL), bitmaps_are_initialized(FALSE), - list_array(NULL), vers_info(NULL), err_value(0), + list_array(NULL), int_type(INTERVAL_LAST), vers_info(NULL), err_value(0), part_info_string(NULL), curr_part_elem(NULL), current_partition(NULL), curr_list_object(0), num_columns(0), table(NULL), @@ -417,11 +421,14 @@ class partition_info : public DDL_LOG_STATE, public Sql_alloc bool field_in_partition_expr(Field *field) const; bool vers_init_info(THD *thd); + bool set_interval(THD* thd, Item* ival, interval_type type, + const char *table_name); bool vers_set_interval(THD *thd, Item *interval, interval_type int_type, Item *starts, 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 range_interval_set_count(THD* thd, uint *create_count); bool vers_require_hist_part(THD *thd) const { return part_type == VERSIONING_PARTITION && @@ -430,6 +437,9 @@ class partition_info : public DDL_LOG_STATE, public Sql_alloc void vers_check_limit(THD *thd); bool vers_fix_field_list(THD *thd); void vers_update_el_ids(); + /* TODO(MDEV-15621): change to a new RANGE_INTERVAL_PARTITION part type */ + bool is_range_interval() const + { return int_type != INTERVAL_LAST && part_type == RANGE_PARTITION; } partition_element *get_partition(uint part_id) { List_iterator it(partitions); @@ -452,6 +462,7 @@ void part_type_error(THD *thd, partition_info *work_part_info, 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); +bool range_interval_create_partitions(THD* thd, TABLE_LIST* tl, uint num_parts); /* Initialize the iterator to return a single partition with given part_id */ @@ -549,12 +560,12 @@ Lex_ident_partition make_partition_name(char *move_ptr, uint i) inline uint partition_info::next_part_no(uint new_parts) const { - if (part_type != VERSIONING_PARTITION) + if (part_type != VERSIONING_PARTITION && !is_range_interval()) return num_parts; DBUG_ASSERT(new_parts > 0); /* Choose first non-occupied name suffix */ - uint32 suffix= num_parts - 1; - DBUG_ASSERT(suffix > 0); + uint32 suffix= part_type == VERSIONING_PARTITION ? num_parts - 1 : 0; + DBUG_ASSERT(suffix > 0 || part_type != VERSIONING_PARTITION); char part_name[MAX_PART_NAME_SIZE + 1]; List_iterator_fast it(table->part_info->partitions); for (uint cur_part= 0; cur_part < new_parts; ++cur_part, ++suffix) diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 884fc75c91379..2b675fd3bd186 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -12404,3 +12404,9 @@ ER_WARN_QB_NAME_PATH_VIEW_NOT_FOUND eng "Hint %s is ignored. `%s` required at element #%u of the path is not found in the target query block." ER_WARN_QB_NAME_PATH_NOT_SUPPORTED_INSIDE_VIEW eng "Hint %s is ignored. QB_NAME hints with path are not supported inside view definitions." +ER_PARTITION_INTERVAL_NOT_LIST + eng "LIST partition type does not support INTERVAL" +ER_PARTITION_INTERVAL_FINER_THAN_DATE + eng "RANGE COLUMN partition by a DATE with INTERVAL smaller than date" +ER_PARTITION_INTERVAL_MAXVALUE + eng "MAXVALUE is not allowed in range partitioning with interval" diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 95abfa798bf65..18b37a2a9ea43 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1929,6 +1929,40 @@ bool TABLE::vers_switch_partition(THD *thd, TABLE_LIST *table_list, return false; } + +/* + TODO(MDEV-15621): similar to vers_switch_partition, find how many + partitions to create and calls oc_ctx->request_backoff_action for + actions to take when failing opening_and_process_table +*/ +bool TABLE::range_interval_check_partition(THD *thd, TABLE_LIST *table_list, + Open_table_context *ot_ctx) +{ + if (!part_info || !part_info->is_range_interval() || + table_list->mdl_request.type == MDL_EXCLUSIVE) + return false; + switch (thd->lex->sql_command) + { + case SQLCOM_INSERT_SELECT: + case SQLCOM_INSERT: + case SQLCOM_LOAD: + case SQLCOM_UPDATE: + case SQLCOM_REPLACE: + case SQLCOM_REPLACE_SELECT: + case SQLCOM_UPDATE_MULTI: + break; + default: + return false; + } + if (part_info->range_interval_set_count( + thd, &ot_ctx->range_interval_create_count)) + return true; + if (ot_ctx->range_interval_create_count == 0) + return false; + ot_ctx->request_backoff_action( + Open_table_context::OT_ADD_RANGE_INTERVAL_PARTITION, table_list); + return true; +} #endif /* WITH_PARTITION_STORAGE_ENGINE */ @@ -2355,7 +2389,9 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx) #ifdef WITH_PARTITION_STORAGE_ENGINE if (!part_names_error && - table->vers_switch_partition(thd, table_list, ot_ctx)) + (table->vers_switch_partition(thd, table_list, ot_ctx) || + table->range_interval_check_partition(thd, table_list, ot_ctx)) + ) { MYSQL_UNBIND_TABLE(table->file); tc_release_table(table); @@ -3479,7 +3515,8 @@ request_backoff_action(enum_open_table_action action_arg, if (table) { DBUG_ASSERT(action_arg == OT_DISCOVER || action_arg == OT_REPAIR || - action_arg == OT_ADD_HISTORY_PARTITION); + action_arg == OT_ADD_HISTORY_PARTITION || + action_arg == OT_ADD_RANGE_INTERVAL_PARTITION); m_failed_table= m_thd->alloc(1); if (m_failed_table == NULL) return TRUE; @@ -3547,6 +3584,7 @@ Open_table_context::recover_from_failed_open() break; case OT_DISCOVER: case OT_REPAIR: + case OT_ADD_RANGE_INTERVAL_PARTITION: case OT_ADD_HISTORY_PARTITION: DEBUG_SYNC(m_thd, "add_history_partition"); if (!m_thd->locked_tables_mode) @@ -3588,7 +3626,8 @@ Open_table_context::recover_from_failed_open() 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) + if (m_action != OT_ADD_HISTORY_PARTITION && + m_action != OT_ADD_RANGE_INTERVAL_PARTITION) tdc_remove_table(m_thd, m_failed_table->db.str, m_failed_table->table_name.str); @@ -3618,6 +3657,77 @@ Open_table_context::recover_from_failed_open() case OT_REPAIR: result= auto_repair_table(m_thd, m_failed_table); break; + case OT_ADD_RANGE_INTERVAL_PARTITION: +#ifdef WITH_PARTITION_STORAGE_ENGINE + { + 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(range_interval_create_count); + result= range_interval_create_partitions( + m_thd, m_failed_table, range_interval_create_count); + range_interval_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; + } + /* + TODO(MDEV-15621): here I just copied code from + OT_ADD_HISTORY_PARTITION + */ + 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; + } +#endif case OT_ADD_HISTORY_PARTITION: #ifdef WITH_PARTITION_STORAGE_ENGINE { diff --git a/sql/sql_base.h b/sql/sql_base.h index 32985f319fa07..12e2579a5e442 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -569,7 +569,8 @@ class Open_table_context OT_REOPEN_TABLES, OT_DISCOVER, OT_REPAIR, - OT_ADD_HISTORY_PARTITION + OT_ADD_HISTORY_PARTITION, + OT_ADD_RANGE_INTERVAL_PARTITION }; Open_table_context(THD *thd, uint flags); @@ -645,6 +646,7 @@ class Open_table_context public: uint vers_create_count; + uint range_interval_create_count; }; diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index d676a022c1274..ec322d19aba09 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1248,6 +1248,97 @@ int partition_info_compare_column_values(const void *first_arg, return 0; } +static bool check_range_interval_constants(THD *thd, partition_info *part_info) +{ + /* Range interval is only supported in RANGE COLUMNS with one column */ + DBUG_ASSERT(part_info->column_list); + DBUG_ASSERT(part_info->part_field_list.elements == 1); + List_iterator part_it(part_info->partitions); + partition_element *el; + uint part_id= 0; + int warn; + /* Find the first partition to auto-add */ + while ((el= part_it++) && el->part_state == PART_NORMAL) + { + part_id++; + } + /* No partition to auto-add. Could be CREATE TABLE */ + if (!el) + return FALSE; + /* + We are in a DML where partitions need to be created. There + should already be some existing partitions + */ + DBUG_ASSERT(part_id != 0); + longlong packed= part_info->partitions.elem(part_id - 1)->get_col_val(0).item_expression->val_datetime_packed(thd); + MYSQL_TIME ltime; + unpack_time(packed, <ime, MYSQL_TIMESTAMP_DATETIME); + do + { + if (date_add_interval(thd, <ime, part_info->int_type, part_info->interval)) + { + my_error(ER_DATA_OUT_OF_RANGE, MYF(0), "DATETIME", "INTERVAL"); + return TRUE; + } + Datetime dt(thd, &warn, <ime, Datetime::Options(thd), 0); + Date d(static_cast(&dt)); + Item *column_item; + switch (part_info->part_field_array[0]->type()) + { + case MYSQL_TYPE_DATE: + column_item= new (thd->mem_root) Item_date_literal(thd, &d); + break; + case MYSQL_TYPE_DATETIME: + column_item= new (thd->mem_root) Item_datetime_literal(thd, &dt, 0); + break; + default: + /* Only DATE and DATETIME are allowed */ + DBUG_ASSERT(0); + return TRUE; + } + p_elem_val *range_val= new p_elem_val; + el->list_val_list.push_back(range_val); + part_column_list_val *col_val= new part_column_list_val; + range_val->col_val_array= col_val; + col_val->item_expression= column_item; + col_val->max_value= false; + col_val->null_value= false; + + /* + Similar to partition_info::fix_column_value_functions, but with a + hack on field->table->write_set to pass the assertion of + marked_for_write_or_computed() in + Field_date_common::store_TIME_with_warning + */ + Field *field= part_info->part_field_array[0]; + col_val->part_info= part_info; + col_val->partition_id= part_id; + uchar *val_ptr; + uint len= field->pack_length(); + + Sql_mode_instant_set sms(thd, 0); + /* Needed to pass assertion on Field::marked_for_write_or_computed() */ + MY_BITMAP *save_write_set= field->table->write_set; + field->table->write_set= &field->table->s->all_set; + bool save_got_warning= thd->got_warning; + thd->got_warning= FALSE; + if (column_item->save_in_field(field, TRUE) || thd->got_warning) + { + my_error(ER_WRONG_TYPE_COLUMN_VALUE_ERROR, MYF(0)); + return TRUE; + } + thd->got_warning= save_got_warning; + field->table->write_set= save_write_set; + if (!(val_ptr= (uchar*) thd->memdup(field->ptr, len))) + { + return TRUE; + } + col_val->column_value= val_ptr; + col_val->fixed= TRUE; + part_id++; + } while ((el= part_it++)); + return FALSE; +} /* This routine allocates an array for all range constants to achieve a fast @@ -1281,6 +1372,9 @@ static bool check_range_constants(THD *thd, partition_info *part_info) DBUG_PRINT("enter", ("RANGE with %d parts, column_list = %u", part_info->num_parts, part_info->column_list)); + if (part_info->is_range_interval()) + if (check_range_interval_constants(thd, part_info)) + goto end; if (part_info->column_list) { part_column_list_val *loc_range_col_array; @@ -2324,6 +2418,32 @@ static int add_column_list_values(String *str, partition_info *part_info, return 1; } th= sql_field->type_handler(); + enum_field_types ftype= th->real_field_type(); + /* + Only allow DATETIME and DATE, since TIMESTAMP and YEAR + are already not allowed in range column partitioning + */ + if (part_info->is_range_interval()) + { + if (ftype != MYSQL_TYPE_DATETIME2 && ftype != MYSQL_TYPE_NEWDATE) + { + th->partition_field_type_not_allowed(sql_field->field_name); + return 1; + } + if (ftype == MYSQL_TYPE_NEWDATE) + { + MYSQL_TIME t1= {1, 1, 1, 0, 0, 0, 0, 0, MYSQL_TIMESTAMP_DATE}, + t2= t1; + t1.day++; + date_add_interval(current_thd, &t2, part_info->int_type, + part_info->interval); + if (pack_time(&t1) > pack_time(&t2)) + { + my_error(ER_PARTITION_INTERVAL_FINER_THAN_DATE, MYF(0)); + return 1; + } + } + } if (th->partition_field_check(sql_field->field_name, item_expr)) return 1; field_cs= sql_field->explicit_or_derived_charset(&derived_attr); @@ -2673,6 +2793,13 @@ char *generate_partition_syntax(THD *thd, partition_info *part_info, part_info->part_expr->print_for_table_def(&str); err+= str.append(')'); } + else if (part_info->is_range_interval()) + { + err+= str.append(STRING_WITH_LEN(" COLUMNS")); + err+= add_part_field_list(thd, &str, part_info->part_field_list); + err+= str.append(STRING_WITH_LEN("INTERVAL ")); + err+= append_interval(&str, part_info->int_type, part_info->interval); + } else if (part_info->column_list) { err+= str.append(STRING_WITH_LEN(" COLUMNS")); @@ -5251,7 +5378,8 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, */ if (thd->lex->no_write_to_binlog && tab_part_info->part_type != HASH_PARTITION && - tab_part_info->part_type != VERSIONING_PARTITION) + tab_part_info->part_type != VERSIONING_PARTITION && + !tab_part_info->is_range_interval()) { my_error(ER_NO_BINLOG_ERROR, MYF(0)); goto err; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 269d497058c2f..c1bd8cd435778 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -5111,7 +5111,11 @@ part_type_def: Select->parsing_place= NO_MATTER; } | LIST_SYM part_column_list - { Lex->part_info->part_type= LIST_PARTITION; } + { + Lex->part_info->part_type= LIST_PARTITION; + if (Lex->part_info->int_type != INTERVAL_LAST) + my_yyabort_error((ER_PARTITION_INTERVAL_NOT_LIST, MYF(0))); + } | SYSTEM_TIME_SYM { if (unlikely(Lex->part_info->vers_init_info(thd))) @@ -5179,14 +5183,29 @@ part_field_item: ; part_column_list: - COLUMNS '(' part_field_list ')' + COLUMNS '(' part_field_list ')' opt_part_interval { partition_info *part_info= Lex->part_info; part_info->column_list= TRUE; part_info->list_of_part_fields= TRUE; + if (part_info->int_type != INTERVAL_LAST && + part_info->num_columns > 1) + my_yyabort_error((ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR, MYF(0), + "range interval partition fields")); } ; +opt_part_interval: + /* empty */ {} + | INTERVAL_SYM expr interval opt_auto + { + partition_info *part_info= Lex->part_info; + const char *table_name= + Lex->create_last_non_select_table->table_name.str; + if (unlikely(part_info->set_interval(thd, $2, $3, table_name))) + MYSQL_YYABORT; + } + ; part_func: '(' part_func_expr ')' @@ -5448,6 +5467,11 @@ part_func_max: thd->parse_error(ER_PARTITION_COLUMN_LIST_ERROR); MYSQL_YYABORT; } + else if (part_info->is_range_interval()) + { + my_error(ER_PARTITION_INTERVAL_MAXVALUE, MYF(0)); + MYSQL_YYABORT; + } else part_info->num_columns= 1U; if (unlikely(part_info->init_column_part(thd))) @@ -5757,6 +5781,12 @@ opt_vers_auto_part: $$= 1; } ; + +opt_auto: + /* empty */ {} + | AUTO_SYM {} + ; + /* End of partition parser part */ diff --git a/sql/table.h b/sql/table.h index 0713341840127..47ee067660051 100644 --- a/sql/table.h +++ b/sql/table.h @@ -2023,6 +2023,8 @@ struct TABLE #ifdef WITH_PARTITION_STORAGE_ENGINE bool vers_switch_partition(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx); + bool range_interval_check_partition(THD *thd, TABLE_LIST *table_list, + Open_table_context *ot_ctx); #endif bool vers_implicit() const;