From 7073199a719a5887afdf16cd352da093e926b4ba Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Fri, 29 May 2026 13:19:50 +1000 Subject: [PATCH 1/3] MDEV-39789 Fix compiling without perfschema --- extra/mariadb_migrate_config_file.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extra/mariadb_migrate_config_file.c b/extra/mariadb_migrate_config_file.c index a69e8fdfa4196..f24c1e5ee859b 100644 --- a/extra/mariadb_migrate_config_file.c +++ b/extra/mariadb_migrate_config_file.c @@ -135,7 +135,9 @@ static size_t global_copied_lines=0, global_unsupported_lines= 0; static size_t global_mariadbd_additions= 0; static PSI_memory_key key_memory_upgrade_config; +#ifdef HAVE_PSI_FILE_INTERFACE static PSI_file_key key_file_cnf; +#endif static size_t global_update_count= 0; static my_bool give_error_for_missing_files= 0; static my_bool opt_mariadbd_testing; From 858b2b80dad303070a2b14041d2b293fd3a7f127 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Wed, 3 Jun 2026 14:35:17 +1000 Subject: [PATCH 2/3] MDEV-15621 [refactor] Partitioning cleanup change p_column_list_val::fixed to a bool remove redundant end label in partition_info::fix_column_value_functions --- sql/partition_element.h | 8 ++------ sql/partition_info.cc | 19 +++++++------------ 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/sql/partition_element.h b/sql/partition_element.h index 795a7a1d56fb2..fcef687a89407 100644 --- a/sql/partition_element.h +++ b/sql/partition_element.h @@ -54,11 +54,7 @@ enum partition_state { The data in this fixed in two steps. The parser will only fill in whether it is a max_value or provide an expression. Filling in column_value, part_info, partition_id, null_value is done by the - function fix_column_value_function. However the item tree needs - fixed also before writing it into the frm file (in add_column_list_values). - To distinguish between those two variants, fixed= 1 after the - fixing in add_column_list_values and fixed= 2 otherwise. This is - since the fixing in add_column_list_values isn't a complete fixing. + function fix_column_value_function. */ typedef struct p_column_list_val @@ -69,7 +65,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..a6320dc489dd9 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -2166,7 +2166,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 +2219,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 +2246,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 +2255,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); } From d59a6a1502798fd881284cd61b86c057b8e6d69b Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Fri, 5 Jun 2026 16:34:46 +1000 Subject: [PATCH 3/3] MDEV-15621 Auto add RANGE COLUMNS partitions by interval Allow auto partitioning by interval in PARTITION BY RANGE COLUMNS PARTITION BY RANGE COLUMNS (col_name) INTERVAL interval [AUTO] ( PARTITION partition_name VALUES LESS THAN (value) [, PARTITION partition_name VALUES LESS THAN (value) ... ] ) where - col_name is the name of one column of type DATE or DATETIME or TIMESTAMP - at least one partition is supplied, and the highest partition cannot have MAXVALUE range - INTERVAL interval is a positive time interval. it can be mariadb format or oracle NUMTODSINTERVAL/NUMTOYMINTERVAL format. Like versioning, the smallest unit is second, i.e. no subsecond like microsecond. - DATE column cannot have interval with values less than a day - Subpartitions are allowed, but restricted to existing subpartition types, i.e. [LINEAR] (KEY|HASH) When performing one of the following DML statements on such a table, it will first add partitions by the specified interval until the partition covers the current time: - INSERT - INSERT ... SELECT - LOAD - UPDATE - REPLACE - REPLACE ... SELECT Partition addition will not cause an implicit commit like DDL normally does. The partitions are named pN. Otherwise the table behaves exactly the same as a normal RANGE COLUMNS partitioned table. Note that TIMESTAMP is not allowed as a type for PARTITION BY RANGE COLUMNS otherwise. --- .../main/partition_range_interval.result | 2010 +++++++++++++++++ mysql-test/main/partition_range_interval.test | 733 ++++++ .../partition_range_interval_binlog.result | 54 + .../main/partition_range_interval_binlog.test | 49 + .../partition_range_interval_debug.result | 98 + .../main/partition_range_interval_debug.test | 74 + .../suite/perfschema/r/digest_view.result | 50 +- .../start_server_low_digest_sql_length.result | 4 +- sql/lex.h | 2 + sql/partition_element.h | 4 +- sql/partition_info.cc | 245 +- sql/partition_info.h | 67 +- sql/share/errmsg-utf8.txt | 6 + sql/sql_base.cc | 84 +- sql/sql_base.h | 4 +- sql/sql_partition.cc | 180 +- sql/sql_yacc.yy | 60 +- sql/table.h | 2 + 18 files changed, 3681 insertions(+), 45 deletions(-) create mode 100644 mysql-test/main/partition_range_interval.result create mode 100644 mysql-test/main/partition_range_interval.test create mode 100644 mysql-test/main/partition_range_interval_binlog.result create mode 100644 mysql-test/main/partition_range_interval_binlog.test create mode 100644 mysql-test/main/partition_range_interval_debug.result create mode 100644 mysql-test/main/partition_range_interval_debug.test diff --git a/mysql-test/main/partition_range_interval.result b/mysql-test/main/partition_range_interval.result new file mode 100644 index 0000000000000..8bee74c206d89 --- /dev/null +++ b/mysql-test/main/partition_range_interval.result @@ -0,0 +1,2010 @@ +# simple case with DATETIME column 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; +# simple case with DATE column +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; +# oracle interval syntax +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL (NUMTODSINTERVAL(1, 'DAY')) +( +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; +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL (NUMTOYMINTERVAL(1, 'MONTH')) +( +PARTITION p0 VALUES LESS THAN ('2025-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 MONTH +(PARTITION `p0` VALUES LESS THAN ('2025-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 MONTH +(PARTITION `p0` VALUES LESS THAN ('2025-04-30') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2025-05-30') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2025-06-30') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2025-07-30') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2025-08-30') ENGINE = InnoDB, + PARTITION `p5` VALUES LESS THAN ('2025-09-30') ENGINE = InnoDB, + PARTITION `p6` VALUES LESS THAN ('2025-10-30') ENGINE = InnoDB, + PARTITION `p7` VALUES LESS THAN ('2025-11-30') ENGINE = InnoDB, + PARTITION `p8` VALUES LESS THAN ('2025-12-30') ENGINE = InnoDB, + PARTITION `p9` VALUES LESS THAN ('2026-01-30') ENGINE = InnoDB, + PARTITION `p10` VALUES LESS THAN ('2026-02-28') ENGINE = InnoDB, + PARTITION `p11` VALUES LESS THAN ('2026-03-28') ENGINE = InnoDB, + PARTITION `p12` VALUES LESS THAN ('2026-04-28') ENGINE = InnoDB, + PARTITION `p13` VALUES LESS THAN ('2026-05-28') 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` '2025-04-30' 0 +p1 RANGE COLUMNS `c` '2025-05-30' 0 +p2 RANGE COLUMNS `c` '2025-06-30' 0 +p3 RANGE COLUMNS `c` '2025-07-30' 0 +p4 RANGE COLUMNS `c` '2025-08-30' 0 +p5 RANGE COLUMNS `c` '2025-09-30' 0 +p6 RANGE COLUMNS `c` '2025-10-30' 0 +p7 RANGE COLUMNS `c` '2025-11-30' 0 +p8 RANGE COLUMNS `c` '2025-12-30' 0 +p9 RANGE COLUMNS `c` '2026-01-30' 0 +p10 RANGE COLUMNS `c` '2026-02-28' 0 +p11 RANGE COLUMNS `c` '2026-03-28' 0 +p12 RANGE COLUMNS `c` '2026-04-28' 0 +p13 RANGE COLUMNS `c` '2026-05-28' 1 +drop table t1; +## NUMTODSINTERVAL takes only DAY, HOUR, MINUTE or SECOND +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL (NUMTODSINTERVAL(1, 'YEAR')) +( +PARTITION p0 VALUES LESS THAN ('2024-04-30') +); +ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for 'INTERVAL' +## NUMTOYMINTERVAL takes only YEAR or MONTH +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL (NUMTOYMINTERVAL(1, 'HOUR')) +( +PARTITION p0 VALUES LESS THAN ('2026-04-30') +); +ERROR HY000: Wrong parameters for partitioned `t1`: wrong value for 'INTERVAL' +# 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; +# DATE column with 1 week interval +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; +# DATETIME column with 1 hour interval +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; +# DATETIME column with some decimal points in partition range value +create table t1 (c datetime) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 hour +( +PARTITION p0 VALUES LESS THAN ('2026-05-05 01:23:45.6789') +); +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 01:23:45.6789') 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 01:23:45.6789') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-05-05 02:23:45.6789') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-05-05 03:23:45.6789') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-05-05 04:23:45.6789') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2026-05-05 05:23:45.6789') ENGINE = InnoDB, + PARTITION `p5` VALUES LESS THAN ('2026-05-05 06:23:45.6789') ENGINE = InnoDB, + PARTITION `p6` VALUES LESS THAN ('2026-05-05 07:23:45.6789') ENGINE = InnoDB, + PARTITION `p7` VALUES LESS THAN ('2026-05-05 08:23:45.6789') ENGINE = InnoDB, + PARTITION `p8` VALUES LESS THAN ('2026-05-05 09:23:45.6789') ENGINE = InnoDB, + PARTITION `p9` VALUES LESS THAN ('2026-05-05 10:23:45.6789') ENGINE = InnoDB, + PARTITION `p10` VALUES LESS THAN ('2026-05-05 11:23:45.6789') ENGINE = InnoDB, + PARTITION `p11` VALUES LESS THAN ('2026-05-05 12:23:45.6789') ENGINE = InnoDB, + PARTITION `p12` VALUES LESS THAN ('2026-05-05 13:23:45.6789') ENGINE = InnoDB, + PARTITION `p13` VALUES LESS THAN ('2026-05-05 14:23:45.6789') ENGINE = InnoDB, + PARTITION `p14` VALUES LESS THAN ('2026-05-05 15:23:45.6789') ENGINE = InnoDB, + PARTITION `p15` VALUES LESS THAN ('2026-05-05 16:23:45.6789') ENGINE = InnoDB, + PARTITION `p16` VALUES LESS THAN ('2026-05-05 17:23:45.6789') ENGINE = InnoDB, + PARTITION `p17` VALUES LESS THAN ('2026-05-05 18:23:45.6789') ENGINE = InnoDB, + PARTITION `p18` VALUES LESS THAN ('2026-05-05 19:23:45.6789') ENGINE = InnoDB, + PARTITION `p19` VALUES LESS THAN ('2026-05-05 20:23:45.6789') ENGINE = InnoDB, + PARTITION `p20` VALUES LESS THAN ('2026-05-05 21:23:45.6789') ENGINE = InnoDB, + PARTITION `p21` VALUES LESS THAN ('2026-05-05 22:23:45.6789') ENGINE = InnoDB, + PARTITION `p22` VALUES LESS THAN ('2026-05-05 23:23:45.6789') ENGINE = InnoDB, + PARTITION `p23` VALUES LESS THAN ('2026-05-06 00:23:45.6789') 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 01:23:45.6789' 0 +p1 RANGE COLUMNS `c` '2026-05-05 02:23:45.6789' 0 +p2 RANGE COLUMNS `c` '2026-05-05 03:23:45.6789' 1 +p3 RANGE COLUMNS `c` '2026-05-05 04:23:45.6789' 0 +p4 RANGE COLUMNS `c` '2026-05-05 05:23:45.6789' 0 +p5 RANGE COLUMNS `c` '2026-05-05 06:23:45.6789' 0 +p6 RANGE COLUMNS `c` '2026-05-05 07:23:45.6789' 0 +p7 RANGE COLUMNS `c` '2026-05-05 08:23:45.6789' 0 +p8 RANGE COLUMNS `c` '2026-05-05 09:23:45.6789' 0 +p9 RANGE COLUMNS `c` '2026-05-05 10:23:45.6789' 0 +p10 RANGE COLUMNS `c` '2026-05-05 11:23:45.6789' 0 +p11 RANGE COLUMNS `c` '2026-05-05 12:23:45.6789' 0 +p12 RANGE COLUMNS `c` '2026-05-05 13:23:45.6789' 0 +p13 RANGE COLUMNS `c` '2026-05-05 14:23:45.6789' 0 +p14 RANGE COLUMNS `c` '2026-05-05 15:23:45.6789' 0 +p15 RANGE COLUMNS `c` '2026-05-05 16:23:45.6789' 0 +p16 RANGE COLUMNS `c` '2026-05-05 17:23:45.6789' 0 +p17 RANGE COLUMNS `c` '2026-05-05 18:23:45.6789' 0 +p18 RANGE COLUMNS `c` '2026-05-05 19:23:45.6789' 0 +p19 RANGE COLUMNS `c` '2026-05-05 20:23:45.6789' 0 +p20 RANGE COLUMNS `c` '2026-05-05 21:23:45.6789' 0 +p21 RANGE COLUMNS `c` '2026-05-05 22:23:45.6789' 0 +p22 RANGE COLUMNS `c` '2026-05-05 23:23:45.6789' 0 +p23 RANGE COLUMNS `c` '2026-05-06 00:23:45.6789' 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 `p1` VALUES LESS THAN ('2026-04-28') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-04-29') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-04-30') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2026-05-01') ENGINE = InnoDB, + PARTITION `p5` VALUES LESS THAN ('2026-05-02') ENGINE = InnoDB, + PARTITION `p6` VALUES LESS THAN ('2026-05-03') ENGINE = InnoDB, + PARTITION `p7` VALUES LESS THAN ('2026-05-04') ENGINE = InnoDB, + PARTITION `p8` VALUES LESS THAN ('2026-05-05') ENGINE = InnoDB, + PARTITION `p9` VALUES LESS THAN ('2026-05-06') ENGINE = InnoDB, + PARTITION `p10` 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' 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 failure for future dates +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' into table t1; +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-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 +drop table t1; +# LOAD DATA INFILE IGNORE for future dates +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, no interval => have interval +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; +# ALTER TABLE, have interval => no interval +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 DAY +( +PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +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) +alter table t1 +PARTITION BY RANGE COLUMNS (c) +( +PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +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`) +(PARTITION `p0` VALUES LESS THAN ('2026-04-25') ENGINE = InnoDB) +insert into t1 values ('2026-05-01'); +ERROR HY000: Table has no partition for value from column_list +drop table t1; +# ALTER TABLE, adding a partition to a RANGE COLUMNS INTERVAL +# partitioned table +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 3 DAY +( +PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +ALTER TABLE t1 ADD PARTITION (PARTITION p1 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 3 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-25') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-04-27') ENGINE = InnoDB) +insert into t1 values ('2026-05-01'); +ALTER TABLE t1 ADD PARTITION (PARTITION p6 VALUES LESS THAN ('2026-05-02')); +ERROR HY000: VALUES LESS THAN value must be strictly increasing for each partition +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 3 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-25') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-04-27') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-04-30') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-05-03') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2026-05-06') ENGINE = InnoDB, + PARTITION `p5` VALUES LESS THAN ('2026-05-09') ENGINE = InnoDB) +ALTER TABLE t1 ADD PARTITION (PARTITION p7 VALUES LESS THAN ('2026-05-10')); +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 3 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-25') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-04-27') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-04-30') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-05-03') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2026-05-06') ENGINE = InnoDB, + PARTITION `p5` VALUES LESS THAN ('2026-05-09') ENGINE = InnoDB, + PARTITION `p7` VALUES LESS THAN ('2026-05-10') ENGINE = InnoDB) +ALTER TABLE t1 ADD PARTITION (PARTITION p8 VALUES LESS THAN MAXVALUE); +ERROR HY000: MAXVALUE is not allowed in range partitioning with interval +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 3 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-25') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-04-27') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-04-30') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-05-03') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2026-05-06') ENGINE = InnoDB, + PARTITION `p5` VALUES LESS THAN ('2026-05-09') ENGINE = InnoDB, + PARTITION `p7` VALUES LESS THAN ('2026-05-10') ENGINE = InnoDB) +drop table t1; +# with subpartitions. +# note that only [LINEAR] KEY and [LINEAR] HASH are allowed +# subpartitioning methods +select to_days('2026-04-20') = 740091; +to_days('2026-04-20') = 740091 +1 +select to_days('2026-05-01') = 740102; +to_days('2026-05-01') = 740102 +1 +create table t1 (c date, d int) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 3 DAY +SUBPARTITION BY KEY ALGORITHM=XXH3 (d) SUBPARTITIONS 2 +( +PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +insert into t1 select from_days(seq), seq from seq_740091_to_740102; +select * from t1; +c d +2026-04-21 740092 +2026-04-23 740094 +2026-04-24 740095 +2026-04-20 740091 +2026-04-22 740093 +2026-04-25 740096 +2026-04-27 740098 +2026-04-26 740097 +2026-04-30 740101 +2026-04-28 740099 +2026-04-29 740100 +2026-05-01 740102 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` date DEFAULT NULL, + `d` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`) INTERVAL 3 DAY +SUBPARTITION BY KEY ALGORITHM = XXH3 (`d`) +SUBPARTITIONS 2 +(PARTITION `p0` VALUES LESS THAN ('2026-04-25') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-04-28') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-05-01') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-05-04') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2026-05-07') ENGINE = InnoDB) +select partition_name, subpartition_name, partition_method, partition_description, table_rows from information_schema.partitions where table_name='t1' and table_rows > 0; +partition_name subpartition_name partition_method partition_description table_rows +p0 p0sp0 RANGE COLUMNS '2026-04-25' 3 +p0 p0sp1 RANGE COLUMNS '2026-04-25' 2 +p1 p1sp0 RANGE COLUMNS '2026-04-28' 2 +p1 p1sp1 RANGE COLUMNS '2026-04-28' 1 +p2 p2sp0 RANGE COLUMNS '2026-05-01' 1 +p2 p2sp1 RANGE COLUMNS '2026-05-01' 2 +p3 p3sp0 RANGE COLUMNS '2026-05-04' 1 +drop table t1; +# with an index +select to_days('2026-04-20') = 740091; +to_days('2026-04-20') = 740091 +1 +select to_days('2026-05-01') = 740102; +to_days('2026-05-01') = 740102 +1 +create table t1 (c date key, d int) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 3 DAY +( +PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +insert into t1 select from_days(seq), seq from seq_740091_to_740102; +select * from t1; +c d +2026-04-20 740091 +2026-04-21 740092 +2026-04-22 740093 +2026-04-23 740094 +2026-04-24 740095 +2026-04-25 740096 +2026-04-26 740097 +2026-04-27 740098 +2026-04-28 740099 +2026-04-29 740100 +2026-04-30 740101 +2026-05-01 740102 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` date NOT NULL, + `d` int(11) DEFAULT NULL, + PRIMARY KEY (`c`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`) INTERVAL 3 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-25') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-04-28') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-05-01') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-05-04') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2026-05-07') ENGINE = InnoDB) +drop table t1; +# REPLACE +select to_days('2026-04-15') = 740086; +to_days('2026-04-15') = 740086 +1 +select to_days('2026-04-24') = 740095; +to_days('2026-04-24') = 740095 +1 +create table t1 (c date key, d int) engine=innodb +PARTITION BY RANGE COLUMNS (c) +( +PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +insert into t1 select from_days(seq), seq from seq_740086_to_740095; +select * from t1; +c d +2026-04-15 740086 +2026-04-16 740087 +2026-04-17 740088 +2026-04-18 740089 +2026-04-19 740090 +2026-04-20 740091 +2026-04-21 740092 +2026-04-22 740093 +2026-04-23 740094 +2026-04-24 740095 +alter table t1 +PARTITION BY RANGE COLUMNS (c) +INTERVAL 3 DAY +( +PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +replace into t1 values ('2026-05-01', 123), ('2026-04-15', 456), ('2026-04-29', 789); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` date NOT NULL, + `d` int(11) DEFAULT NULL, + PRIMARY KEY (`c`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`) INTERVAL 3 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-25') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-04-28') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-05-01') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-05-04') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2026-05-07') ENGINE = InnoDB) +select * from t1; +c d +2026-04-15 456 +2026-04-16 740087 +2026-04-17 740088 +2026-04-18 740089 +2026-04-19 740090 +2026-04-20 740091 +2026-04-21 740092 +2026-04-22 740093 +2026-04-23 740094 +2026-04-24 740095 +2026-04-29 789 +2026-05-01 123 +drop table t1; +# REPLACE ... SELECT +select to_days('2026-04-15') = 740086; +to_days('2026-04-15') = 740086 +1 +select to_days('2026-04-24') = 740095; +to_days('2026-04-24') = 740095 +1 +create table t1 (c date key, d int) engine=innodb +PARTITION BY RANGE COLUMNS (c) +( +PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +insert into t1 select from_days(seq), seq from seq_740086_to_740095; +select * from t1; +c d +2026-04-15 740086 +2026-04-16 740087 +2026-04-17 740088 +2026-04-18 740089 +2026-04-19 740090 +2026-04-20 740091 +2026-04-21 740092 +2026-04-22 740093 +2026-04-23 740094 +2026-04-24 740095 +alter table t1 +PARTITION BY RANGE COLUMNS (c) +INTERVAL 3 DAY +( +PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +replace into t1 select date_add(c, interval 5 day), d from t1; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` date NOT NULL, + `d` int(11) DEFAULT NULL, + PRIMARY KEY (`c`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`) INTERVAL 3 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-25') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-04-28') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-05-01') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-05-04') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2026-05-07') ENGINE = InnoDB) +select * from t1; +c d +2026-04-15 740086 +2026-04-16 740087 +2026-04-17 740088 +2026-04-18 740089 +2026-04-19 740090 +2026-04-20 740086 +2026-04-21 740087 +2026-04-22 740088 +2026-04-23 740089 +2026-04-24 740090 +2026-04-25 740091 +2026-04-26 740092 +2026-04-27 740093 +2026-04-28 740094 +2026-04-29 740095 +drop table t1; +# multi-table update +select to_days('2026-04-10') = 740081; +to_days('2026-04-10') = 740081 +1 +select to_days('2026-04-15') = 740086; +to_days('2026-04-15') = 740086 +1 +select to_days('2026-04-20') = 740091; +to_days('2026-04-20') = 740091 +1 +select to_days('2026-04-24') = 740095; +to_days('2026-04-24') = 740095 +1 +create table t1 (c date, d int) engine=innodb +PARTITION BY RANGE COLUMNS (c) +( +PARTITION p0 VALUES LESS THAN ('2026-04-21') +); +create table t2 (c date, d int) engine=innodb +PARTITION BY RANGE COLUMNS (c) +( +PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +insert into t1 select from_days(seq), seq from seq_740081_to_740091; +insert into t2 select from_days(seq), seq from seq_740086_to_740095; +alter table t1 +PARTITION BY RANGE COLUMNS (c) +INTERVAL 3 DAY +( +PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +alter table t2 +PARTITION BY RANGE COLUMNS (c) +INTERVAL 3 DAY +( +PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +update t1, t2 set t1.c = date_add(t1.c, interval 10 day) where t1.c = t2.c; +select * from t1; +c d +2026-04-10 740081 +2026-04-11 740082 +2026-04-12 740083 +2026-04-13 740084 +2026-04-14 740085 +2026-04-25 740086 +2026-04-26 740087 +2026-04-27 740088 +2026-04-28 740089 +2026-04-29 740090 +2026-04-30 740091 +select * from t2; +c d +2026-04-15 740086 +2026-04-16 740087 +2026-04-17 740088 +2026-04-18 740089 +2026-04-19 740090 +2026-04-20 740091 +2026-04-21 740092 +2026-04-22 740093 +2026-04-23 740094 +2026-04-24 740095 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` date DEFAULT NULL, + `d` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`) INTERVAL 3 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-25') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-04-28') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-05-01') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-05-04') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2026-05-07') ENGINE = InnoDB) +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `c` date DEFAULT NULL, + `d` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci + PARTITION BY RANGE COLUMNS(`c`) INTERVAL 3 DAY +(PARTITION `p0` VALUES LESS THAN ('2026-04-25') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-04-28') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-05-01') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-05-04') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2026-05-07') ENGINE = InnoDB) +drop table t1, t2; +# cannot alter to a partition with a lower date even with interval if +# date does not fit. this is because auto partition creation only +# happens in DML +create table t1 (c date) +PARTITION BY RANGE COLUMNS (c) +( +PARTITION p0 VALUES LESS THAN ('2026-04-30') +); +insert into t1 values ('2026-04-29'); +alter table t1 +PARTITION BY RANGE COLUMNS (c) +interval 3 day +( +PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +ERROR HY000: Table has no partition for value from column_list +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; +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') +); +begin; +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 +rollback; +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) +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 +create table t1 (c timestamp) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 hour +( +PARTITION p0 VALUES LESS THAN ('2026-05-04 12:34:56.789') +); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` timestamp NULL 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-04 12:34:56.789') ENGINE = InnoDB) +insert into t1 values ('2026-05-05 10:00:00.123456'); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` timestamp NULL 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-04 12:34:56.789') ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN ('2026-05-04 13:34:56.789') ENGINE = InnoDB, + PARTITION `p2` VALUES LESS THAN ('2026-05-04 14:34:56.789') ENGINE = InnoDB, + PARTITION `p3` VALUES LESS THAN ('2026-05-04 15:34:56.789') ENGINE = InnoDB, + PARTITION `p4` VALUES LESS THAN ('2026-05-04 16:34:56.789') ENGINE = InnoDB, + PARTITION `p5` VALUES LESS THAN ('2026-05-04 17:34:56.789') ENGINE = InnoDB, + PARTITION `p6` VALUES LESS THAN ('2026-05-04 18:34:56.789') ENGINE = InnoDB, + PARTITION `p7` VALUES LESS THAN ('2026-05-04 19:34:56.789') ENGINE = InnoDB, + PARTITION `p8` VALUES LESS THAN ('2026-05-04 20:34:56.789') ENGINE = InnoDB, + PARTITION `p9` VALUES LESS THAN ('2026-05-04 21:34:56.789') ENGINE = InnoDB, + PARTITION `p10` VALUES LESS THAN ('2026-05-04 22:34:56.789') ENGINE = InnoDB, + PARTITION `p11` VALUES LESS THAN ('2026-05-04 23:34:56.789') ENGINE = InnoDB, + PARTITION `p12` VALUES LESS THAN ('2026-05-05 00:34:56.789') ENGINE = InnoDB, + PARTITION `p13` VALUES LESS THAN ('2026-05-05 01:34:56.789') ENGINE = InnoDB, + PARTITION `p14` VALUES LESS THAN ('2026-05-05 02:34:56.789') ENGINE = InnoDB, + PARTITION `p15` VALUES LESS THAN ('2026-05-05 03:34:56.789') ENGINE = InnoDB, + PARTITION `p16` VALUES LESS THAN ('2026-05-05 04:34:56.789') ENGINE = InnoDB, + PARTITION `p17` VALUES LESS THAN ('2026-05-05 05:34:56.789') ENGINE = InnoDB, + PARTITION `p18` VALUES LESS THAN ('2026-05-05 06:34:56.789') ENGINE = InnoDB, + PARTITION `p19` VALUES LESS THAN ('2026-05-05 07:34:56.789') ENGINE = InnoDB, + PARTITION `p20` VALUES LESS THAN ('2026-05-05 08:34:56.789') ENGINE = InnoDB, + PARTITION `p21` VALUES LESS THAN ('2026-05-05 09:34:56.789') ENGINE = InnoDB, + PARTITION `p22` VALUES LESS THAN ('2026-05-05 10:34:56.789') ENGINE = InnoDB, + PARTITION `p23` VALUES LESS THAN ('2026-05-05 11:34:56.789') ENGINE = InnoDB, + PARTITION `p24` VALUES LESS THAN ('2026-05-05 12:34:56.789') ENGINE = InnoDB, + PARTITION `p25` VALUES LESS THAN ('2026-05-05 13:34:56.789') ENGINE = InnoDB, + PARTITION `p26` VALUES LESS THAN ('2026-05-05 14:34:56.789') ENGINE = InnoDB, + PARTITION `p27` VALUES LESS THAN ('2026-05-05 15:34:56.789') ENGINE = InnoDB, + PARTITION `p28` VALUES LESS THAN ('2026-05-05 16:34:56.789') ENGINE = InnoDB, + PARTITION `p29` VALUES LESS THAN ('2026-05-05 17:34:56.789') ENGINE = InnoDB, + PARTITION `p30` VALUES LESS THAN ('2026-05-05 18:34:56.789') ENGINE = InnoDB, + PARTITION `p31` VALUES LESS THAN ('2026-05-05 19:34:56.789') ENGINE = InnoDB, + PARTITION `p32` VALUES LESS THAN ('2026-05-05 20:34:56.789') ENGINE = InnoDB, + PARTITION `p33` VALUES LESS THAN ('2026-05-05 21:34:56.789') ENGINE = InnoDB, + PARTITION `p34` VALUES LESS THAN ('2026-05-05 22:34:56.789') ENGINE = InnoDB, + PARTITION `p35` VALUES LESS THAN ('2026-05-05 23:34:56.789') ENGINE = InnoDB, + PARTITION `p36` VALUES LESS THAN ('2026-05-06 00:34:56.789') 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-04 12:34:56.789' 0 +p1 RANGE COLUMNS `c` '2026-05-04 13:34:56.789' 0 +p2 RANGE COLUMNS `c` '2026-05-04 14:34:56.789' 0 +p3 RANGE COLUMNS `c` '2026-05-04 15:34:56.789' 0 +p4 RANGE COLUMNS `c` '2026-05-04 16:34:56.789' 0 +p5 RANGE COLUMNS `c` '2026-05-04 17:34:56.789' 0 +p6 RANGE COLUMNS `c` '2026-05-04 18:34:56.789' 0 +p7 RANGE COLUMNS `c` '2026-05-04 19:34:56.789' 0 +p8 RANGE COLUMNS `c` '2026-05-04 20:34:56.789' 0 +p9 RANGE COLUMNS `c` '2026-05-04 21:34:56.789' 0 +p10 RANGE COLUMNS `c` '2026-05-04 22:34:56.789' 0 +p11 RANGE COLUMNS `c` '2026-05-04 23:34:56.789' 0 +p12 RANGE COLUMNS `c` '2026-05-05 00:34:56.789' 0 +p13 RANGE COLUMNS `c` '2026-05-05 01:34:56.789' 0 +p14 RANGE COLUMNS `c` '2026-05-05 02:34:56.789' 0 +p15 RANGE COLUMNS `c` '2026-05-05 03:34:56.789' 0 +p16 RANGE COLUMNS `c` '2026-05-05 04:34:56.789' 0 +p17 RANGE COLUMNS `c` '2026-05-05 05:34:56.789' 0 +p18 RANGE COLUMNS `c` '2026-05-05 06:34:56.789' 0 +p19 RANGE COLUMNS `c` '2026-05-05 07:34:56.789' 0 +p20 RANGE COLUMNS `c` '2026-05-05 08:34:56.789' 0 +p21 RANGE COLUMNS `c` '2026-05-05 09:34:56.789' 0 +p22 RANGE COLUMNS `c` '2026-05-05 10:34:56.789' 1 +p23 RANGE COLUMNS `c` '2026-05-05 11:34:56.789' 0 +p24 RANGE COLUMNS `c` '2026-05-05 12:34:56.789' 0 +p25 RANGE COLUMNS `c` '2026-05-05 13:34:56.789' 0 +p26 RANGE COLUMNS `c` '2026-05-05 14:34:56.789' 0 +p27 RANGE COLUMNS `c` '2026-05-05 15:34:56.789' 0 +p28 RANGE COLUMNS `c` '2026-05-05 16:34:56.789' 0 +p29 RANGE COLUMNS `c` '2026-05-05 17:34:56.789' 0 +p30 RANGE COLUMNS `c` '2026-05-05 18:34:56.789' 0 +p31 RANGE COLUMNS `c` '2026-05-05 19:34:56.789' 0 +p32 RANGE COLUMNS `c` '2026-05-05 20:34:56.789' 0 +p33 RANGE COLUMNS `c` '2026-05-05 21:34:56.789' 0 +p34 RANGE COLUMNS `c` '2026-05-05 22:34:56.789' 0 +p35 RANGE COLUMNS `c` '2026-05-05 23:34:56.789' 0 +p36 RANGE COLUMNS `c` '2026-05-06 00:34:56.789' 0 +drop table t1; +# 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.59' HOUR_SECOND +( +PARTITION p0 VALUES LESS THAN ('2026-04-20') +); +ERROR HY000: RANGE COLUMN partition by a DATE with INTERVAL smaller than date +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL '23.59.60' HOUR_SECOND +( +PARTITION p0 VALUES LESS THAN ('2026-04-20') +); +drop table t1; +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL '24.00.00' HOUR_SECOND +( +PARTITION p0 VALUES LESS THAN ('2026-04-20') +); +drop table t1; +# 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 date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day; +ERROR HY000: For RANGE partitions each partition must be defined +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; +# MDEV-39807 Auto creating partition out of range +SET timestamp=UNIX_TIMESTAMP('2026-05-02 00:00:00'); +CREATE TABLE t1 (c DATETIME) ENGINE=InnoDB +PARTITION BY RANGE COLUMNS (c) +INTERVAL 999999999 DAY +( +PARTITION p0 VALUES LESS THAN ('2026-04-20') +); +INSERT INTO t1 VALUES ('2026-05-01'); +ERROR 22003: partition range value is out of range in 'INTERVAL' +DROP TABLE t1; +## DATE has an extra check for finer time, make sure no +## overflow happens there +create table t1 (c date) +PARTITION BY RANGE COLUMNS (c) +INTERVAL 18446744073709551615 HOUR +( +PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +INSERT INTO t1 VALUES ('2026-05-01'); +ERROR 22003: partition range value is out of range in 'INTERVAL' +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..7d62761fad136 --- /dev/null +++ b/mysql-test/main/partition_range_interval.test @@ -0,0 +1,733 @@ +--source include/have_partition.inc +--source include/have_innodb.inc +--source include/have_sequence.inc + +--echo # simple case with DATETIME column 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; + +--echo # simple case with DATE column +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 # oracle interval syntax +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL (NUMTODSINTERVAL(1, 'DAY')) +( + 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 (NUMTOYMINTERVAL(1, 'MONTH')) +( + PARTITION p0 VALUES LESS THAN ('2025-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 ## NUMTODSINTERVAL takes only DAY, HOUR, MINUTE or SECOND +--error ER_PART_WRONG_VALUE +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL (NUMTODSINTERVAL(1, 'YEAR')) +( + PARTITION p0 VALUES LESS THAN ('2024-04-30') +); + +--echo ## NUMTOYMINTERVAL takes only YEAR or MONTH +--error ER_PART_WRONG_VALUE +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL (NUMTOYMINTERVAL(1, 'HOUR')) +( + PARTITION p0 VALUES LESS THAN ('2026-04-30') +); + +--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; + +--echo # DATE column with 1 week interval +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; + +--echo # DATETIME column with 1 hour interval +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 # DATETIME column with some decimal points in partition range value +create table t1 (c datetime) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 hour +( + PARTITION p0 VALUES LESS THAN ('2026-05-05 01:23:45.6789') +); +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' 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 failure for future dates +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 +--error ER_NO_PARTITION_FOR_GIVEN_VALUE +load data infile 'load.data' 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 # LOAD DATA INFILE IGNORE for future dates +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, no interval => have interval +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 # ALTER TABLE, have interval => no interval +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 DAY +( + PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +show create table t1; +alter table t1 +PARTITION BY RANGE COLUMNS (c) +( + PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +show create table t1; +--error ER_NO_PARTITION_FOR_GIVEN_VALUE +insert into t1 values ('2026-05-01'); +drop table t1; + +--echo # ALTER TABLE, adding a partition to a RANGE COLUMNS INTERVAL +--echo # partitioned table +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 3 DAY +( + PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +ALTER TABLE t1 ADD PARTITION (PARTITION p1 VALUES LESS THAN ('2026-04-27')); +show create table t1; +insert into t1 values ('2026-05-01'); +--error ER_RANGE_NOT_INCREASING_ERROR +ALTER TABLE t1 ADD PARTITION (PARTITION p6 VALUES LESS THAN ('2026-05-02')); +show create table t1; +ALTER TABLE t1 ADD PARTITION (PARTITION p7 VALUES LESS THAN ('2026-05-10')); +show create table t1; +--error ER_PARTITION_INTERVAL_MAXVALUE +ALTER TABLE t1 ADD PARTITION (PARTITION p8 VALUES LESS THAN MAXVALUE); +show create table t1; +drop table t1; + +--echo # with subpartitions. +--echo # note that only [LINEAR] KEY and [LINEAR] HASH are allowed +--echo # subpartitioning methods +select to_days('2026-04-20') = 740091; +select to_days('2026-05-01') = 740102; + +create table t1 (c date, d int) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 3 DAY + SUBPARTITION BY KEY ALGORITHM=XXH3 (d) SUBPARTITIONS 2 +( + PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +insert into t1 select from_days(seq), seq from seq_740091_to_740102; +select * from t1; +show create table t1; +select partition_name, subpartition_name, partition_method, partition_description, table_rows from information_schema.partitions where table_name='t1' and table_rows > 0; +drop table t1; + +--echo # with an index +select to_days('2026-04-20') = 740091; +select to_days('2026-05-01') = 740102; + +create table t1 (c date key, d int) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 3 DAY +( + PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +insert into t1 select from_days(seq), seq from seq_740091_to_740102; +select * from t1; +show create table t1; +drop table t1; + +--echo # REPLACE +select to_days('2026-04-15') = 740086; +select to_days('2026-04-24') = 740095; + +create table t1 (c date key, d int) engine=innodb +PARTITION BY RANGE COLUMNS (c) +( + PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +insert into t1 select from_days(seq), seq from seq_740086_to_740095; +select * from t1; +alter table t1 +PARTITION BY RANGE COLUMNS (c) +INTERVAL 3 DAY +( + PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +replace into t1 values ('2026-05-01', 123), ('2026-04-15', 456), ('2026-04-29', 789); +show create table t1; +select * from t1; +drop table t1; + +--echo # REPLACE ... SELECT +select to_days('2026-04-15') = 740086; +select to_days('2026-04-24') = 740095; + +create table t1 (c date key, d int) engine=innodb +PARTITION BY RANGE COLUMNS (c) +( + PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +insert into t1 select from_days(seq), seq from seq_740086_to_740095; +select * from t1; +alter table t1 +PARTITION BY RANGE COLUMNS (c) +INTERVAL 3 DAY +( + PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +replace into t1 select date_add(c, interval 5 day), d from t1; +show create table t1; +select * from t1; +drop table t1; + +--echo # multi-table update +select to_days('2026-04-10') = 740081; +select to_days('2026-04-15') = 740086; +select to_days('2026-04-20') = 740091; +select to_days('2026-04-24') = 740095; + +create table t1 (c date, d int) engine=innodb +PARTITION BY RANGE COLUMNS (c) +( + PARTITION p0 VALUES LESS THAN ('2026-04-21') +); +create table t2 (c date, d int) engine=innodb +PARTITION BY RANGE COLUMNS (c) +( + PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +insert into t1 select from_days(seq), seq from seq_740081_to_740091; +insert into t2 select from_days(seq), seq from seq_740086_to_740095; +alter table t1 +PARTITION BY RANGE COLUMNS (c) +INTERVAL 3 DAY +( + PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +alter table t2 +PARTITION BY RANGE COLUMNS (c) +INTERVAL 3 DAY +( + PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +update t1, t2 set t1.c = date_add(t1.c, interval 10 day) where t1.c = t2.c; +select * from t1; +select * from t2; +show create table t1; +show create table t2; +drop table t1, t2; + +--echo # cannot alter to a partition with a lower date even with interval if +--echo # date does not fit. this is because auto partition creation only +--echo # happens in DML +create table t1 (c date) +PARTITION BY RANGE COLUMNS (c) +( + PARTITION p0 VALUES LESS THAN ('2026-04-30') +); +insert into t1 values ('2026-04-29'); +--error ER_NO_PARTITION_FOR_GIVEN_VALUE +alter table t1 +PARTITION BY RANGE COLUMNS (c) +interval 3 day +( + PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +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; + +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') +); +begin; +insert into t1 select from_days(seq) from seq_740073_to_740102; +select * from t1; +rollback; +select * from t1; +show create table 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 +create table t1 (c timestamp) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 hour +( + PARTITION p0 VALUES LESS THAN ('2026-05-04 12:34:56.789') +); +show create table t1; +insert into t1 values ('2026-05-05 10:00:00.123456'); +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 # 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') +); + +--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.59' HOUR_SECOND +( + PARTITION p0 VALUES LESS THAN ('2026-04-20') +); + +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL '23.59.60' HOUR_SECOND +( + PARTITION p0 VALUES LESS THAN ('2026-04-20') +); +drop table t1; + +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL '24.00.00' HOUR_SECOND +( + PARTITION p0 VALUES LESS THAN ('2026-04-20') +); +drop table t1; + +--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 +); + +--error ER_PARTITIONS_MUST_BE_DEFINED_ERROR +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day; + +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; + +--echo # MDEV-39807 Auto creating partition out of range +SET timestamp=UNIX_TIMESTAMP('2026-05-02 00:00:00'); +CREATE TABLE t1 (c DATETIME) ENGINE=InnoDB +PARTITION BY RANGE COLUMNS (c) +INTERVAL 999999999 DAY +( + PARTITION p0 VALUES LESS THAN ('2026-04-20') +); +--error ER_DATA_OUT_OF_RANGE +INSERT INTO t1 VALUES ('2026-05-01'); +DROP TABLE t1; + +--echo ## DATE has an extra check for finer time, make sure no +--echo ## overflow happens there +create table t1 (c date) +PARTITION BY RANGE COLUMNS (c) +INTERVAL 18446744073709551615 HOUR +( + PARTITION p0 VALUES LESS THAN ('2026-04-25') +); +--error ER_DATA_OUT_OF_RANGE +INSERT INTO t1 VALUES ('2026-05-01'); +DROP TABLE t1; diff --git a/mysql-test/main/partition_range_interval_binlog.result b/mysql-test/main/partition_range_interval_binlog.result new file mode 100644 index 0000000000000..ea6ec9452e310 --- /dev/null +++ b/mysql-test/main/partition_range_interval_binlog.result @@ -0,0 +1,54 @@ +# +# MDEV-39808 MDEV-15621: ROW-binlog + INSERT: auto-creates an interval partition & logs the row, but not the implicit ADD PARTITION +# +# same server +SET timestamp= UNIX_TIMESTAMP('2026-05-10 00:00:00'); +CREATE TABLE t1 (c DATE) ENGINE=InnoDB +PARTITION BY RANGE COLUMNS (c) INTERVAL 1 DAY +(PARTITION p0 VALUES LESS THAN ('2026-05-05')); +RESET MASTER; +INSERT INTO t1 VALUES ('2026-05-08'); +set statement sql_log_bin=0 for +DROP TABLE t1; +set statement sql_log_bin=0 for +CREATE TABLE t1 (c DATE) ENGINE=InnoDB +PARTITION BY RANGE COLUMNS (c) INTERVAL 1 DAY +(PARTITION p0 VALUES LESS THAN ('2026-05-05')); +SELECT * FROM t1; +c +2026-05-08 +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-06' 0 +p2 RANGE COLUMNS `c` '2026-05-07' 0 +p3 RANGE COLUMNS `c` '2026-05-08' 0 +p4 RANGE COLUMNS `c` '2026-05-09' 1 +p5 RANGE COLUMNS `c` '2026-05-10' 0 +p6 RANGE COLUMNS `c` '2026-05-11' 0 +DROP TABLE t1; +# master-slave +include/master-slave.inc +[connection master] +SET timestamp= UNIX_TIMESTAMP('2026-05-10 00:00:00'); +CREATE TABLE t1 (c DATE) ENGINE=InnoDB +PARTITION BY RANGE COLUMNS (c) INTERVAL 1 DAY +(PARTITION p0 VALUES LESS THAN ('2026-05-05')); +INSERT INTO t1 VALUES ('2026-05-08'); +connection slave; +SELECT * FROM t1; +c +2026-05-08 +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-06' 0 +p2 RANGE COLUMNS `c` '2026-05-07' 0 +p3 RANGE COLUMNS `c` '2026-05-08' 0 +p4 RANGE COLUMNS `c` '2026-05-09' 1 +p5 RANGE COLUMNS `c` '2026-05-10' 0 +p6 RANGE COLUMNS `c` '2026-05-11' 0 +drop table t1; +connection master; +drop table t1; +include/rpl_end.inc diff --git a/mysql-test/main/partition_range_interval_binlog.test b/mysql-test/main/partition_range_interval_binlog.test new file mode 100644 index 0000000000000..3b934da739d63 --- /dev/null +++ b/mysql-test/main/partition_range_interval_binlog.test @@ -0,0 +1,49 @@ +--source include/have_partition.inc +--source include/have_innodb.inc +--source include/have_binlog_format_row.inc + +--echo # +--echo # MDEV-39808 MDEV-15621: ROW-binlog + INSERT: auto-creates an interval partition & logs the row, but not the implicit ADD PARTITION +--echo # + +--echo # same server + +SET timestamp= UNIX_TIMESTAMP('2026-05-10 00:00:00'); +CREATE TABLE t1 (c DATE) ENGINE=InnoDB +PARTITION BY RANGE COLUMNS (c) INTERVAL 1 DAY +(PARTITION p0 VALUES LESS THAN ('2026-05-05')); +RESET MASTER; # Clear the binlog so only the INSERT is captured +INSERT INTO t1 VALUES ('2026-05-08'); +--let $binlog=query_get_value(SHOW MASTER STATUS, File, 1) + +set statement sql_log_bin=0 for +DROP TABLE t1; +set statement sql_log_bin=0 for +CREATE TABLE t1 (c DATE) ENGINE=InnoDB +PARTITION BY RANGE COLUMNS (c) INTERVAL 1 DAY +(PARTITION p0 VALUES LESS THAN ('2026-05-05')); +--let $datadir= `SELECT @@datadir` +--exec $MYSQL_BINLOG $datadir/$binlog 2>&1 | $MYSQL test + +SELECT * FROM t1; +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1'; +DROP TABLE t1; + +--echo # master-slave + +--source include/master-slave.inc + +SET timestamp= UNIX_TIMESTAMP('2026-05-10 00:00:00'); +CREATE TABLE t1 (c DATE) ENGINE=InnoDB +PARTITION BY RANGE COLUMNS (c) INTERVAL 1 DAY +(PARTITION p0 VALUES LESS THAN ('2026-05-05')); +INSERT INTO t1 VALUES ('2026-05-08'); + +--sync_slave_with_master +SELECT * FROM t1; +select partition_name, partition_method, partition_expression, partition_description, table_rows from information_schema.partitions where table_name='t1'; +drop table t1; + +--connection master +drop table t1; +--source include/rpl_end.inc diff --git a/mysql-test/main/partition_range_interval_debug.result b/mysql-test/main/partition_range_interval_debug.result new file mode 100644 index 0000000000000..07b7c00d8cdcb --- /dev/null +++ b/mysql-test/main/partition_range_interval_debug.result @@ -0,0 +1,98 @@ +# Concurrency test: if two threads T1 and T2 both try to insert +# into the same table, where T1 acquires the lock to +# auto-create the new partitions first, T2 has to wait until +# the creation to complete before it can determine how many new +# partitions to auto-create +## T2 cannot acquire lock while T1 has started partition auto-creation +set lock_wait_timeout=1; +set timestamp= unix_timestamp('2026-05-02 00:00:00'); +connect con1,localhost,root,,; +set lock_wait_timeout=1; +set timestamp= unix_timestamp('2026-05-02 00:00:00'); +connection default; +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( +PARTITION p0 VALUES LESS THAN ('2026-04-20') +); +SET DEBUG_SYNC = 'range_interval_create_partitions_lock_acquired SIGNAL con1_will_wait WAIT_FOR default_can_go'; +insert into t1 values ('2026-04-25'); +connection con1; +SET DEBUG_SYNC = 'now WAIT_FOR con1_will_wait'; +SET DEBUG_SYNC = 'before_open_table_wait_refresh SIGNAL default_can_go'; +insert into t1 values ('2026-04-26'); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +connection default; +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) +select * from t1; +c +2026-04-25 +drop table t1; +## T2 auto-creates the correct number of partitions after +## waiting for T1 to finish its auto-creation. +## A slight exaggeration: T1 not finished after two days. +connection default; +set timestamp= unix_timestamp('2026-05-02 00:00:00'); +connection con1; +set timestamp= unix_timestamp('2026-05-04 00:00:00'); +connection default; +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( +PARTITION p0 VALUES LESS THAN ('2026-04-20') +); +SET DEBUG_SYNC = 'range_interval_create_partitions_lock_acquired SIGNAL con1_will_wait WAIT_FOR default_can_go'; +insert into t1 values ('2026-04-25'); +connection con1; +SET DEBUG_SYNC = 'now WAIT_FOR con1_will_wait'; +SET DEBUG_SYNC = 'before_open_table_get_mdl_lock SIGNAL default_can_go'; +insert into t1 values ('2026-04-26'); +connection default; +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) +select * from t1; +c +2026-04-25 +2026-04-26 +drop table t1; diff --git a/mysql-test/main/partition_range_interval_debug.test b/mysql-test/main/partition_range_interval_debug.test new file mode 100644 index 0000000000000..9350c668ad7b0 --- /dev/null +++ b/mysql-test/main/partition_range_interval_debug.test @@ -0,0 +1,74 @@ +--source include/have_partition.inc +--source include/have_innodb.inc +--source include/have_debug_sync.inc + +--echo # Concurrency test: if two threads T1 and T2 both try to insert +--echo # into the same table, where T1 acquires the lock to +--echo # auto-create the new partitions first, T2 has to wait until +--echo # the creation to complete before it can determine how many new +--echo # partitions to auto-create + +--echo ## T2 cannot acquire lock while T1 has started partition auto-creation +set lock_wait_timeout=1; +set timestamp= unix_timestamp('2026-05-02 00:00:00'); + +--connect (con1,localhost,root,,) +set lock_wait_timeout=1; +set timestamp= unix_timestamp('2026-05-02 00:00:00'); + +--connection default +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( + PARTITION p0 VALUES LESS THAN ('2026-04-20') +); + +SET DEBUG_SYNC = 'range_interval_create_partitions_lock_acquired SIGNAL con1_will_wait WAIT_FOR default_can_go'; +--send insert into t1 values ('2026-04-25') + +--connection con1 +SET DEBUG_SYNC = 'now WAIT_FOR con1_will_wait'; +SET DEBUG_SYNC = 'before_open_table_wait_refresh SIGNAL default_can_go'; +--error ER_LOCK_WAIT_TIMEOUT +insert into t1 values ('2026-04-26'); + +--connection default +--reap +show create table t1; +select * from t1; + +drop table t1; + +--echo ## T2 auto-creates the correct number of partitions after +--echo ## waiting for T1 to finish its auto-creation. +--echo ## A slight exaggeration: T1 not finished after two days. + +--connection default +set timestamp= unix_timestamp('2026-05-02 00:00:00'); + +--connection con1 +set timestamp= unix_timestamp('2026-05-04 00:00:00'); + +--connection default +create table t1 (c date) engine=innodb +PARTITION BY RANGE COLUMNS (c) +INTERVAL 1 Day +( + PARTITION p0 VALUES LESS THAN ('2026-04-20') +); + +SET DEBUG_SYNC = 'range_interval_create_partitions_lock_acquired SIGNAL con1_will_wait WAIT_FOR default_can_go'; +--send insert into t1 values ('2026-04-25') + +--connection con1 +SET DEBUG_SYNC = 'now WAIT_FOR con1_will_wait'; +SET DEBUG_SYNC = 'before_open_table_get_mdl_lock SIGNAL default_can_go'; +insert into t1 values ('2026-04-26'); + +--connection default +--reap +show create table t1; +select * from t1; + +drop table t1; diff --git a/mysql-test/suite/perfschema/r/digest_view.result b/mysql-test/suite/perfschema/r/digest_view.result index 23663e90e7232..c471f64012052 100644 --- a/mysql-test/suite/perfschema/r/digest_view.result +++ b/mysql-test/suite/perfschema/r/digest_view.result @@ -191,17 +191,17 @@ SELECT SCHEMA_NAME, DIGEST, DIGEST_TEXT, COUNT_STAR FROM performance_schema.events_statements_summary_by_digest ORDER BY DIGEST_TEXT; SCHEMA_NAME DIGEST DIGEST_TEXT COUNT_STAR -test 1fc4762d236e45317b7a93325cf38ccf EXPLAIN SELECT * FROM `test` . `v1` 1 -test ee977559588e6c4fb3c13107a798d677 EXPLAIN SELECT * FROM `test` . `v1` WHERE `a` = ? 1 -test 37823d0fd1d4fcd052ebbce1c70630be EXPLAIN SELECT * FROM `test` . `v1` WHERE `b` > ? 1 -test 9c9017b1a14d361eef46ba95a30c01ef EXPLAIN SELECT `a` , `b` FROM `test` . `v1` 1 -test 7d5d45adf1446838acc51102b9612956 EXPLAIN SELECT `b` , `a` FROM `test` . `v1` 1 -test 7bd68be1d28c86a38472263247d7cc76 SELECT * FROM `test` . `v1` 1 -test a23c9343657a8bf153039feb07ab52ef SELECT * FROM `test` . `v1` WHERE `a` = ? 1 -test bc6c16c8c39fce4b2120bf5dd9bdcfb2 SELECT * FROM `test` . `v1` WHERE `b` > ? 1 -test 31b28012bff50c13daa9c9028d828d52 SELECT `a` , `b` FROM `test` . `v1` 1 -test cc17deeffae0d3dd3fdbc2429bb944e5 SELECT `b` , `a` FROM `test` . `v1` 1 -test 1953b9861c056191bda4792ddc72d0bd TRUNCATE TABLE `performance_schema` . `events_statements_summary_by_digest` 1 +test 96e2132821b07beb60ca19c4d6d0ec90 EXPLAIN SELECT * FROM `test` . `v1` 1 +test 7d4112e02b139531a03ec2d586123b40 EXPLAIN SELECT * FROM `test` . `v1` WHERE `a` = ? 1 +test 417fb1e0920d9680b200b5c5d2becd8c EXPLAIN SELECT * FROM `test` . `v1` WHERE `b` > ? 1 +test 53e97a6a9fad7bd759800107ac97f132 EXPLAIN SELECT `a` , `b` FROM `test` . `v1` 1 +test 6ea6e3eda2f49175e7970f824dde3096 EXPLAIN SELECT `b` , `a` FROM `test` . `v1` 1 +test 317571224a1fb417dedbe372465dfe56 SELECT * FROM `test` . `v1` 1 +test a6a7ed6725fd7a4c204b70012c1dadda SELECT * FROM `test` . `v1` WHERE `a` = ? 1 +test 2c4d5ac30dccd9735363a5e9ed9f33f4 SELECT * FROM `test` . `v1` WHERE `b` > ? 1 +test 3c0151fd19cb4a1f076e04c16839b3a3 SELECT `a` , `b` FROM `test` . `v1` 1 +test 580517d958d3686d2d5c592f79bfa1b6 SELECT `b` , `a` FROM `test` . `v1` 1 +test c043d020f59ed237fb8d263b98147823 TRUNCATE TABLE `performance_schema` . `events_statements_summary_by_digest` 1 DROP TABLE test.v1; CREATE VIEW test.v1 AS SELECT * FROM test.t1; EXPLAIN SELECT * from test.v1; @@ -248,19 +248,19 @@ SELECT SCHEMA_NAME, DIGEST, DIGEST_TEXT, COUNT_STAR FROM performance_schema.events_statements_summary_by_digest ORDER BY DIGEST_TEXT; SCHEMA_NAME DIGEST DIGEST_TEXT COUNT_STAR -test 59ca08ad599dbad78aa6ba63da12d43c CREATE VIEW `test` . `v1` AS SELECT * FROM `test` . `t1` 1 -test e67d37b92965990c16ba950107bd8bd2 DROP TABLE `test` . `v1` 1 -test 1fc4762d236e45317b7a93325cf38ccf EXPLAIN SELECT * FROM `test` . `v1` 2 -test ee977559588e6c4fb3c13107a798d677 EXPLAIN SELECT * FROM `test` . `v1` WHERE `a` = ? 2 -test 37823d0fd1d4fcd052ebbce1c70630be EXPLAIN SELECT * FROM `test` . `v1` WHERE `b` > ? 2 -test 9c9017b1a14d361eef46ba95a30c01ef EXPLAIN SELECT `a` , `b` FROM `test` . `v1` 2 -test 7d5d45adf1446838acc51102b9612956 EXPLAIN SELECT `b` , `a` FROM `test` . `v1` 2 -test 7bd68be1d28c86a38472263247d7cc76 SELECT * FROM `test` . `v1` 2 -test a23c9343657a8bf153039feb07ab52ef SELECT * FROM `test` . `v1` WHERE `a` = ? 2 -test bc6c16c8c39fce4b2120bf5dd9bdcfb2 SELECT * FROM `test` . `v1` WHERE `b` > ? 2 -test 2780db8ebc63088a83662378fe2c96e4 SELECT SCHEMA_NAME , `DIGEST` , `DIGEST_TEXT` , `COUNT_STAR` FROM `performance_schema` . `events_statements_summary_by_digest` ORDER BY `DIGEST_TEXT` 1 -test 31b28012bff50c13daa9c9028d828d52 SELECT `a` , `b` FROM `test` . `v1` 2 -test cc17deeffae0d3dd3fdbc2429bb944e5 SELECT `b` , `a` FROM `test` . `v1` 2 -test 1953b9861c056191bda4792ddc72d0bd TRUNCATE TABLE `performance_schema` . `events_statements_summary_by_digest` 1 +test e583d29673df9f8c0bfddabc41e6e284 CREATE VIEW `test` . `v1` AS SELECT * FROM `test` . `t1` 1 +test cff107812afc859190748e8d0f0ba1dc DROP TABLE `test` . `v1` 1 +test 96e2132821b07beb60ca19c4d6d0ec90 EXPLAIN SELECT * FROM `test` . `v1` 2 +test 7d4112e02b139531a03ec2d586123b40 EXPLAIN SELECT * FROM `test` . `v1` WHERE `a` = ? 2 +test 417fb1e0920d9680b200b5c5d2becd8c EXPLAIN SELECT * FROM `test` . `v1` WHERE `b` > ? 2 +test 53e97a6a9fad7bd759800107ac97f132 EXPLAIN SELECT `a` , `b` FROM `test` . `v1` 2 +test 6ea6e3eda2f49175e7970f824dde3096 EXPLAIN SELECT `b` , `a` FROM `test` . `v1` 2 +test 317571224a1fb417dedbe372465dfe56 SELECT * FROM `test` . `v1` 2 +test a6a7ed6725fd7a4c204b70012c1dadda SELECT * FROM `test` . `v1` WHERE `a` = ? 2 +test 2c4d5ac30dccd9735363a5e9ed9f33f4 SELECT * FROM `test` . `v1` WHERE `b` > ? 2 +test 91bddaba422973adf9526d46f1ba4011 SELECT SCHEMA_NAME , `DIGEST` , `DIGEST_TEXT` , `COUNT_STAR` FROM `performance_schema` . `events_statements_summary_by_digest` ORDER BY `DIGEST_TEXT` 1 +test 3c0151fd19cb4a1f076e04c16839b3a3 SELECT `a` , `b` FROM `test` . `v1` 2 +test 580517d958d3686d2d5c592f79bfa1b6 SELECT `b` , `a` FROM `test` . `v1` 2 +test c043d020f59ed237fb8d263b98147823 TRUNCATE TABLE `performance_schema` . `events_statements_summary_by_digest` 1 DROP VIEW test.v1; DROP TABLE test.t1; diff --git a/mysql-test/suite/perfschema/r/start_server_low_digest_sql_length.result b/mysql-test/suite/perfschema/r/start_server_low_digest_sql_length.result index 0bd23e42fe833..b0b1777258411 100644 --- a/mysql-test/suite/perfschema/r/start_server_low_digest_sql_length.result +++ b/mysql-test/suite/perfschema/r/start_server_low_digest_sql_length.result @@ -8,5 +8,5 @@ SELECT 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1 #################################### SELECT event_name, digest, digest_text, sql_text FROM events_statements_history_long; event_name digest digest_text sql_text -statement/sql/select 763b65e0dd4673926a2ce8ecdd9b1a90 SELECT ? + ? + SELECT ... -statement/sql/truncate ef3ac63f482c5603fa1cf9d559794435 TRUNCATE TABLE truncat... +statement/sql/select 64a860e46458eda85fcb954b32e5484d SELECT ? + ? + SELECT ... +statement/sql/truncate 173263ae18fec210ba86c1db25a53d6a TRUNCATE TABLE truncat... diff --git a/sql/lex.h b/sql/lex.h index 079633536c0fc..15bc1d2cf693c 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -778,6 +778,8 @@ SYMBOL sql_functions[] = { { "NOW", SYM(NOW_SYM)}, { "NTH_VALUE", SYM(NTH_VALUE_SYM)}, { "NTILE", SYM(NTILE_SYM)}, + { "NUMTODSINTERVAL", SYM(NUMTODSINTERVAL_SYM)}, + { "NUMTOYMINTERVAL", SYM(NUMTOYMINTERVAL_SYM)}, { "POSITION", SYM(POSITION_SYM)}, { "PERCENT_RANK", SYM(PERCENT_RANK_SYM)}, { "PERCENTILE_CONT", SYM(PERCENTILE_CONT_SYM)}, diff --git a/sql/partition_element.h b/sql/partition_element.h index fcef687a89407..82cac70f55315 100644 --- a/sql/partition_element.h +++ b/sql/partition_element.h @@ -54,7 +54,9 @@ enum partition_state { The data in this fixed in two steps. The parser will only fill in whether it is a max_value or provide an expression. Filling in column_value, part_info, partition_id, null_value is done by the - function fix_column_value_function. + function fix_column_value_function, and in the case of range + interval partitioning for auto-created partitions, + check_range_interval_constants. */ typedef struct p_column_list_val diff --git a/sql/partition_info.cc b/sql/partition_info.cc index a6320dc489dd9..243f4b4688001 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,49 @@ 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; + /* At least one range partition is defined */ + if (!el || !(item= el->get_col_val(0).item_expression)) + { + DBUG_ASSERT(0); + my_error(ER_INTERNAL_ERROR, MYF(0), "no range partition specified or invalid partition range expression"); + return true; + } + /* + Compute the transition partition range time and the query time. + They serve as the starting and the end points for new partitions + */ + MYSQL_TIME cur_time, end_time; + longlong cur, end; + cur= item->val_datetime_packed(thd); + unpack_time(cur, &cur_time, MYSQL_TIMESTAMP_DATETIME); + thd->variables.time_zone->gmt_sec_to_TIME(&end_time, thd->query_start()); + end= pack_time(&end_time); + *create_count= 0; + while (cur <= end) + { + if (date_add_interval(thd, &cur_time, int_type, interval)) + { + my_error(ER_DATA_OUT_OF_RANGE, MYF(0), "partition range", "INTERVAL"); + return true; + } + cur= pack_time(&cur_time); + ++*create_count; + if (partitions.elements + *create_count > MAX_PARTITIONS) + { + 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 +1057,113 @@ 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; + partition_info *save_part_info= thd->work_part_info; + Query_tables_list save_query_tables; + Reprepare_observer *save_reprepare_observer= thd->m_reprepare_observer; + bool save_no_write_to_binlog= thd->lex->no_write_to_binlog; + thd->m_reprepare_observer= NULL; + thd->lex->reset_n_backup_query_tables_list(&save_query_tables); + /* + Do not write the partition creation triggered by a DML into the + 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; + DEBUG_SYNC(thd, "range_interval_create_partitions_lock_acquired"); + 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->work_part_info= save_part_info; + thd->m_reprepare_observer= save_reprepare_observer; + thd->lex->restore_backup_query_tables_list(&save_query_tables); + thd->lex->no_write_to_binlog= save_no_write_to_binlog; + return result; +} /** Warn at the end of DML command if the last history partition is out of LIMIT. @@ -2320,6 +2470,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 || @@ -2334,13 +2485,23 @@ 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); } + /* + 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. + */ + 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! */ @@ -2785,6 +2946,84 @@ bool partition_info::vers_init_info(THD * thd) return false; } +/* Check and set interval value for auto interval partitioning */ +bool partition_info::set_range_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; +} + +/* + Check and set interval value for auto interval partitioning, from + the ORACLE NUMTODSINTERVAL (is_ds == true) or NUMTOYMINTERVAL (is_ds + == false) format. +*/ +bool partition_info::set_range_interval(int num, LEX_CSTRING &type, + bool is_ds, + const char *table_name) +{ + if (num < 0) + goto end; + if (is_ds) + { + if (type.length == 3 && !strncasecmp(type.str, "DAY", 3)) + { + interval.day= num; + int_type= INTERVAL_DAY; + return false; + } + else if (type.length == 4 && !strncasecmp(type.str, "HOUR", 4)) + { + interval.hour= num; + int_type= INTERVAL_HOUR; + return false; + } + else if (type.length == 6) + { + if (!strncasecmp(type.str, "MINUTE", 6)) + { + interval.minute= num; + int_type= INTERVAL_MINUTE; + return false; + } + else if (!strncasecmp(type.str, "SECOND", 6)) + { + interval.second= num; + int_type= INTERVAL_SECOND; + return false; + } + } + } + else + { + if (type.length == 4 && !strncasecmp(type.str, "YEAR", 4)) + { + interval.year= num; + int_type= INTERVAL_YEAR; + return false; + } + else if (type.length == 5 && !strncasecmp(type.str, "MONTH", 5)) + { + interval.month= num; + int_type= INTERVAL_MONTH; + return false; + } + } +end: + my_error(ER_PART_WRONG_VALUE, MYF(0), table_name, "INTERVAL"); + return true; +} /** Assign INTERVAL and STARTS for SYSTEM_TIME partitions. diff --git a/sql/partition_info.h b/sql/partition_info.h index e25e27860c966..6885060ffec4a 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), @@ -348,6 +352,9 @@ class partition_info : public DDL_LOG_STATE, public Sql_alloc temp_partitions.empty(); part_field_list.empty(); subpart_field_list.empty(); + interval.second_part= interval.second= interval.minute= + interval.hour= interval.day= interval.month= interval.year= 0; + interval.neg= FALSE; } ~partition_info() = default; @@ -417,11 +424,16 @@ 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_range_interval(THD* thd, Item* ival, interval_type type, + const char *table_name); + bool set_range_interval(int num, LEX_CSTRING& type, bool is_ds, + 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 +442,8 @@ 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(); + 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 +466,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 */ @@ -546,9 +561,59 @@ Lex_ident_partition make_partition_name(char *move_ptr, uint i) #ifdef WITH_PARTITION_STORAGE_ENGINE +static int compare_int(const void *a, const void *b) +{ + if (*(int *) a < *(int *) b) + return -1; + if (*(int *) b < *(int *) a) + return 1; + return 0; +} + +/* + Find the first index for naming range interval auto created + partitions. Find the first gap large enough to fit in all the new + partitions. +*/ +static inline uint range_interval_next_part_no( + uint new_parts, List& partitions) +{ + int *cur, *start, *end; + List_iterator_fast it(partitions); + partition_element *el; + const char *name; + uint right= new_parts; + if(!(start= (int *) my_alloca(sizeof(int) * partitions.elements))) + { + /* Out of memory */ + return 0; + } + cur= start; + while ((el= it++)) + { + name= el->partition_name.str; + if (name[0] == 'p') + { + *cur= atoi(name + 1); + /* Ignore 0 which could be a failed conversion */ + if (*cur > 0) + cur++; + } + } + end= cur; + my_qsort(start, end - start, sizeof(int), compare_int); + for (cur= start; cur < end && right >= (uint) *cur; cur++) + right= (uint) *cur + new_parts; + my_afree(start); + return right - new_parts + 1; +} + inline uint partition_info::next_part_no(uint new_parts) const { + if (is_range_interval()) + return range_interval_next_part_no(new_parts, + table->part_info->partitions); if (part_type != VERSIONING_PARTITION) return num_parts; DBUG_ASSERT(new_parts > 0); diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index ef4fd75fc205b..c75a687bf3198 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -12406,3 +12406,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 d1d876985f81a..f8296f802b6f6 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1922,6 +1922,59 @@ bool TABLE::vers_switch_partition(THD *thd, TABLE_LIST *table_list, return false; } + +/* + 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) +{ + rpl_group_info *rgi= thd->rgi_slave ? thd->rgi_slave : thd->rgi_fake; + if (!part_info || !part_info->is_range_interval() || + table_list->mdl_request.type == MDL_EXCLUSIVE || + ot_ctx->range_interval_create_count > 0) + 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; + case SQLCOM_END: + if (!rgi || !rgi->current_event) + return false; + else + { + switch (rgi->current_event->get_type_code()) + { + case UPDATE_ROWS_EVENT: + case UPDATE_ROWS_EVENT_V1: + case WRITE_ROWS_EVENT: + case WRITE_ROWS_EVENT_V1: + break; + default: + return false; + } + } + 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 */ @@ -2124,6 +2177,7 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx) if (! (flags & MYSQL_OPEN_HAS_MDL_LOCK)) { + DEBUG_SYNC(thd, "before_open_table_get_mdl_lock"); if (open_table_get_mdl_lock(thd, ot_ctx, &table_list->mdl_request, flags, &mdl_ticket) || mdl_ticket == NULL) @@ -2348,7 +2402,8 @@ 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); @@ -3421,7 +3476,7 @@ Open_table_context::Open_table_context(THD *thd, uint flags) m_action(OT_NO_ACTION), m_has_locks(thd->mdl_context.has_locks()), m_has_protection_against_grl(0), - vers_create_count(0) + vers_create_count(0), range_interval_create_count(0) {} @@ -3502,7 +3557,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; @@ -3570,6 +3626,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) @@ -3611,7 +3668,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); @@ -3642,6 +3700,7 @@ Open_table_context::recover_from_failed_open() result= auto_repair_table(m_thd, m_failed_table); break; case OT_ADD_HISTORY_PARTITION: + case OT_ADD_RANGE_INTERVAL_PARTITION: #ifdef WITH_PARTITION_STORAGE_ENGINE { result= false; @@ -3653,9 +3712,20 @@ Open_table_context::recover_from_failed_open() break; } - DBUG_ASSERT(vers_create_count); - result= vers_create_partitions(m_thd, m_failed_table, vers_create_count); - vers_create_count= 0; + if (m_action == OT_ADD_HISTORY_PARTITION) + { + DBUG_ASSERT(vers_create_count); + result= vers_create_partitions(m_thd, m_failed_table, + vers_create_count); + vers_create_count= 0; + } + else + { + 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 || diff --git a/sql/sql_base.h b/sql/sql_base.h index 77d2b17a1fe5d..d428e2bec9e8d 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 85a64936e1f95..8d91ba2d5b9d8 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1248,6 +1248,121 @@ int partition_info_compare_column_values(const void *first_arg, return 0; } +/* Determine the range of the new RANGE COLUMNS partitions by interval */ +static bool check_range_interval_constants(THD *thd, partition_info *part_info) +{ + List_iterator part_it(part_info->partitions); + partition_element *el, *transition_el; + Item *last_el_item; + uint error, part_id= 0; + int warn; + /* No partition auto-creation in DDL. */ + if (thd_sql_command(thd) == SQLCOM_CREATE_TABLE || + thd_sql_command(thd) == SQLCOM_ALTER_TABLE) + return FALSE; + /* 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); + /* Find the first partition to auto-add */ + while ((el= part_it++) && el->part_state == PART_NORMAL) + part_id++; + /* No partition to auto-add */ + if (!el) + return FALSE; + /* + We are in a DML where partitions need to be created. There + should already be some existing partitions + */ + transition_el= part_info->partitions.elem(part_id - 1); + if (!transition_el || + !(last_el_item = transition_el->get_col_val(0).item_expression)) + { + DBUG_ASSERT(0); + my_error(ER_INTERNAL_ERROR, MYF(0), + "no existing range partition, or that the transition partition has an invalid range"); + return true; + } + longlong packed= last_el_item->val_datetime_packed(thd); + MYSQL_TIME ltime; + unpack_time(packed, <ime, MYSQL_TIMESTAMP_DATETIME); + enum_field_types ftype= part_info->part_field_array[0]->type(); + decimal_digits_t dec= last_el_item->datetime_precision(thd); + do + { + if (date_add_interval(thd, <ime, + part_info->int_type, part_info->interval)) + { + /* Same error as in check_vers_constants */ + my_error(ER_DATA_OUT_OF_RANGE, MYF(0), + part_info->part_field_array[0]->type_handler()->name().ptr(), + "INTERVAL"); + return TRUE; + } + Datetime dt(thd, &warn, <ime, Datetime::Options(thd), dec); + Date d(static_cast(&dt)); + Timestamp_or_zero_datetime ts(thd, <ime, &error); + Item *column_item; + switch (ftype) + { + 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, dec); + break; + case MYSQL_TYPE_TIMESTAMP: + column_item= new (thd->mem_root) Item_timestamp_literal(thd, ts, dec); + break; + default: + /* Only DATE, DATETIME and TIMESTAMP are allowed */ + DBUG_ASSERT(0); + return TRUE; + } + part_elem_value *range_val= thd->calloc(1); + part_column_list_val *col_val= thd->calloc(1); + if (!range_val || !col_val || el->list_val_list.push_back(range_val)) + return TRUE; /* OOM */ + 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) + { + field->table->write_set= save_write_set; + 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 +1396,8 @@ 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() && check_range_interval_constants(thd, part_info)) + goto end; if (part_info->column_list) { part_column_list_val *loc_range_col_array; @@ -2292,7 +2409,15 @@ static int add_column_list_values(String *str, partition_info *part_info, part_column_list_val *col_val= &list_value->col_val_array[i]; const char *field_name= it++; if (col_val->max_value) + { + /* MAXVALUE is not allowed for range interval auto-partitioning */ + if (part_info->is_range_interval()) + { + my_error(ER_PARTITION_INTERVAL_MAXVALUE, MYF(0)); + return 1; + } err+= str->append(STRING_WITH_LEN("MAXVALUE")); + } else if (col_val->null_value) err+= str->append(NULL_clex_str); else @@ -2324,7 +2449,41 @@ static int add_column_list_values(String *str, partition_info *part_info, return 1; } th= sql_field->type_handler(); - if (th->partition_field_check(sql_field->field_name, item_expr)) + enum_field_types ftype= th->field_type(); + /* + Only allow DATETIME and DATE, and TIMESTAMP for range + interval auto-partitioning. YEAR is already not allowed in + range column partitioning and not very useful for interval + partitioning. + */ + if (part_info->is_range_interval()) + { + if (ftype != MYSQL_TYPE_DATETIME && ftype != MYSQL_TYPE_DATE && + ftype != MYSQL_TYPE_TIMESTAMP) + { + th->partition_field_type_not_allowed(sql_field->field_name); + return 1; + } + /* + Check that the interval is at least one day long when + partitioned by a DATE column + */ + if (ftype == MYSQL_TYPE_DATE) + { + INTERVAL *interval= &part_info->interval; + if (!interval->year && !interval->month && !interval->day && + interval->hour < 24 && interval->minute < 1440 && + interval->second < 86400 && + interval->hour * 3600 + interval->minute * 60 + + interval->second < 86400) + { + my_error(ER_PARTITION_INTERVAL_FINER_THAN_DATE, MYF(0)); + return 1; + } + } + } + else if (th->partition_field_check(sql_field->field_name, + item_expr)) return 1; field_cs= sql_field->explicit_or_derived_charset(&derived_attr); } @@ -2332,7 +2491,14 @@ static int add_column_list_values(String *str, partition_info *part_info, { Field *field= part_info->part_field_array[i]; th= field->type_handler(); - if (th->partition_field_check(field->field_name, item_expr)) + /* + th->partition_field_check(...) has the side effect of + reporting error so we have to rule out TIMESTAMP with + range interval partitioning first + */ + if (likely(!part_info->is_range_interval() || + th->field_type() != MYSQL_TYPE_TIMESTAMP) && + th->partition_field_check(field->field_name, item_expr)) return 1; field_cs= field->charset(); } @@ -2673,6 +2839,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 +5424,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 df4395395dcde..88eb290f5377c 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1024,6 +1024,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %token NOWAIT_SYM %token NUMBER_MARIADB_SYM /* SQL-2003-N */ %token NUMBER_ORACLE_SYM /* Oracle-R, PLSQL-R */ +%token NUMTODSINTERVAL_SYM +%token NUMTOYMINTERVAL_SYM %token NVARCHAR_SYM %token OBJECT_SYM %token OF_SYM /* SQL-1992-R, Oracle-R */ @@ -5111,7 +5113,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 +5185,53 @@ 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 ? + Lex->create_last_non_select_table->table_name.str : ""; + if (unlikely(part_info->set_range_interval(thd, $2, $3, + table_name))) + MYSQL_YYABORT; + } + | INTERVAL_SYM '(' NUMTODSINTERVAL_SYM + '(' NUM ',' TEXT_STRING_sys ')' ')' + { + partition_info *part_info= Lex->part_info; + const char *table_name= + Lex->create_last_non_select_table ? + Lex->create_last_non_select_table->table_name.str : ""; + if (unlikely(part_info->set_range_interval(atoi($5.str), $7, + true, table_name))) + MYSQL_YYABORT; + } + | INTERVAL_SYM '(' NUMTOYMINTERVAL_SYM + '(' NUM ',' TEXT_STRING_sys ')' ')' + { + partition_info *part_info= Lex->part_info; + const char *table_name= + Lex->create_last_non_select_table ? + Lex->create_last_non_select_table->table_name.str : ""; + if (unlikely(part_info->set_range_interval(atoi($5.str), $7, + false, table_name))) + MYSQL_YYABORT; + } + ; part_func: '(' part_func_expr ')' @@ -5448,6 +5493,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 +5807,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 ba15cf45a1257..6a65d7dfadbba 100644 --- a/sql/table.h +++ b/sql/table.h @@ -2024,6 +2024,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;