Skip to content

Commit 9c46f05

Browse files
committed
vers_calc_hist_parts()
1 parent efdb713 commit 9c46f05

File tree

3 files changed

+180
-15
lines changed

3 files changed

+180
-15
lines changed

mysql-test/suite/versioning/r/partition2.result

Lines changed: 86 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
set @@session.time_zone='+00:00';
12
#
23
# MDEV-25529 Auto-create: Pre-existing historical data is not partitioned as specified by ALTER
34
#
@@ -57,7 +58,7 @@ select *, row_start, row_end from t1 partition (p4);
5758
x row_start row_end
5859
select *, row_start, row_end from t1 partition (pn);
5960
x row_start row_end
60-
4 2000-01-01 02:00:00.000000 2038-01-19 06:14:07.999999
61+
4 2000-01-01 02:00:00.000000 2038-01-19 03:14:07.999999
6162
set timestamp= default;
6263
ALTER table t1 partition by system_time
6364
interval 1 hour starts '2000-01-01 00:00:00';
@@ -77,7 +78,7 @@ select *, row_start, row_end from t1 partition (p4);
7778
x row_start row_end
7879
select *, row_start, row_end from t1 partition (pn);
7980
x row_start row_end
80-
4 2000-01-01 02:00:00.000000 2038-01-19 06:14:07.999999
81+
4 2000-01-01 02:00:00.000000 2038-01-19 03:14:07.999999
8182
alter TABLE t1 partition by system_time
8283
interval 1 hour;
8384
select *, row_start, row_end from t1 partition (p0);
@@ -96,7 +97,7 @@ select *, row_start, row_end from t1 partition (p4);
9697
x row_start row_end
9798
select *, row_start, row_end from t1 partition (pn);
9899
x row_start row_end
99-
4 2000-01-01 02:00:00.000000 2038-01-19 06:14:07.999999
100+
4 2000-01-01 02:00:00.000000 2038-01-19 03:14:07.999999
100101
set @@system_versioning_alter_history= keep;
101102
alter table t1 remove partitioning;
102103
select *, row_start, row_end from t1 for system_time all;
@@ -105,7 +106,7 @@ x row_start row_end
105106
1 2000-01-01 00:10:00.220000 2000-01-01 01:00:00.000000
106107
2 2000-01-01 01:00:00.000000 2000-01-01 01:30:00.000000
107108
3 2000-01-01 01:30:00.000000 2000-01-01 02:00:00.000000
108-
4 2000-01-01 02:00:00.000000 2038-01-19 06:14:07.999999
109+
4 2000-01-01 02:00:00.000000 2038-01-19 03:14:07.999999
109110
alter table t1 PARTITION by system_time interval 1 hour auto;
110111
show create table t1;
111112
Table Create Table
@@ -132,7 +133,7 @@ x row_start row_end
132133
3 2000-01-01 01:30:00.000000 2000-01-01 02:00:00.000000
133134
select *, row_start, row_end from t1 partition (pn);
134135
x row_start row_end
135-
4 2000-01-01 02:00:00.000000 2038-01-19 06:14:07.999999
136+
4 2000-01-01 02:00:00.000000 2038-01-19 03:14:07.999999
136137
alter table t1 remove partitioning;
137138
alter table t1 partition by SYSTEM_TIME interval 1 hour starts '2000-01-01 00:00:00' auto;
138139
show create table t1;
@@ -160,7 +161,7 @@ x row_start row_end
160161
3 2000-01-01 01:30:00.000000 2000-01-01 02:00:00.000000
161162
select *, row_start, row_end from t1 partition (pn);
162163
x row_start row_end
163-
4 2000-01-01 02:00:00.000000 2038-01-19 06:14:07.999999
164+
4 2000-01-01 02:00:00.000000 2038-01-19 03:14:07.999999
164165
set timestamp= unix_timestamp('2000-01-02 03:01:23.456');
165166
delete from t1;
166167
alter table t1 remove partitioning;
@@ -394,6 +395,85 @@ t1 CREATE TABLE `t1` (
394395
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci WITH SYSTEM VERSIONING
395396
PARTITION BY SYSTEM_TIME INTERVAL 9 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
396397
PARTITIONS 7
398+
# Year/month interval
399+
delete history from t1;
400+
alter table t1 remove partitioning;
401+
set timestamp= unix_timestamp('2000-01-01 00:00:00');
402+
insert t1 values (77);
403+
delete from t1;
404+
set timestamp= unix_timestamp('2003-10-01 00:00:00');
405+
insert t1 values (88);
406+
delete from t1;
407+
alter table t1 partition by system_time interval 11 month auto force;
408+
show create table t1;
409+
Table Create Table
410+
t1 CREATE TABLE `t1` (
411+
`x` int(11) DEFAULT NULL,
412+
`row_start` timestamp(6) GENERATED ALWAYS AS ROW START INVISIBLE,
413+
`row_end` timestamp(6) GENERATED ALWAYS AS ROW END INVISIBLE,
414+
KEY `row_end` (`row_end`,`row_start`),
415+
KEY `row_start` (`row_start`),
416+
KEY `row_end_2` (`row_end`,`x`),
417+
KEY `x` (`x`,`row_end`),
418+
KEY `row_end_3` (`row_end`),
419+
PERIOD FOR SYSTEM_TIME (`row_start`, `row_end`)
420+
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci WITH SYSTEM VERSIONING
421+
PARTITION BY SYSTEM_TIME INTERVAL 11 MONTH STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
422+
PARTITIONS 6
423+
alter table t1 partition by system_time interval 1 year auto force;
424+
Warnings:
425+
Warning 4193 `t1`: STARTS timestamp 2003-10-01 00:00:00 is above earliest history date 2000-01-01 00:00:00 and was set to 2000-01-01 00:00:00
426+
show create table t1;
427+
Table Create Table
428+
t1 CREATE TABLE `t1` (
429+
`x` int(11) DEFAULT NULL,
430+
`row_start` timestamp(6) GENERATED ALWAYS AS ROW START INVISIBLE,
431+
`row_end` timestamp(6) GENERATED ALWAYS AS ROW END INVISIBLE,
432+
KEY `row_end` (`row_end`,`row_start`),
433+
KEY `row_start` (`row_start`),
434+
KEY `row_end_2` (`row_end`,`x`),
435+
KEY `x` (`x`,`row_end`),
436+
KEY `row_end_3` (`row_end`),
437+
PERIOD FOR SYSTEM_TIME (`row_start`, `row_end`)
438+
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci WITH SYSTEM VERSIONING
439+
PARTITION BY SYSTEM_TIME INTERVAL 1 YEAR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
440+
PARTITIONS 5
441+
# No history
442+
delete history from t1;
443+
set timestamp= unix_timestamp('2000-01-01 00:00:00');
444+
alter table t1 partition by system_time interval 1 hour auto force;
445+
show create table t1;
446+
Table Create Table
447+
t1 CREATE TABLE `t1` (
448+
`x` int(11) DEFAULT NULL,
449+
`row_start` timestamp(6) GENERATED ALWAYS AS ROW START INVISIBLE,
450+
`row_end` timestamp(6) GENERATED ALWAYS AS ROW END INVISIBLE,
451+
KEY `row_end` (`row_end`,`row_start`),
452+
KEY `row_start` (`row_start`),
453+
KEY `row_end_2` (`row_end`,`x`),
454+
KEY `x` (`x`,`row_end`),
455+
KEY `row_end_3` (`row_end`),
456+
PERIOD FOR SYSTEM_TIME (`row_start`, `row_end`)
457+
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci WITH SYSTEM VERSIONING
458+
PARTITION BY SYSTEM_TIME INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
459+
PARTITIONS 5
460+
insert t1 values (99);
461+
alter table t1 partition by system_time interval 1 hour auto force;
462+
show create table t1;
463+
Table Create Table
464+
t1 CREATE TABLE `t1` (
465+
`x` int(11) DEFAULT NULL,
466+
`row_start` timestamp(6) GENERATED ALWAYS AS ROW START INVISIBLE,
467+
`row_end` timestamp(6) GENERATED ALWAYS AS ROW END INVISIBLE,
468+
KEY `row_end` (`row_end`,`row_start`),
469+
KEY `row_start` (`row_start`),
470+
KEY `row_end_2` (`row_end`,`x`),
471+
KEY `x` (`x`,`row_end`),
472+
KEY `row_end_3` (`row_end`),
473+
PERIOD FOR SYSTEM_TIME (`row_start`, `row_end`)
474+
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci WITH SYSTEM VERSIONING
475+
PARTITION BY SYSTEM_TIME INTERVAL 1 HOUR STARTS TIMESTAMP'2000-01-01 00:00:00' AUTO
476+
PARTITIONS 5
397477
# Slow scan warning
398478
create or replace table t1 (x int,
399479
row_start timestamp(6) as row start invisible,

mysql-test/suite/versioning/t/partition2.test

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
--source include/have_innodb.inc
33
--source include/maybe_debug.inc
44

5+
set @@session.time_zone='+00:00';
6+
57
--echo #
68
--echo # MDEV-25529 Auto-create: Pre-existing historical data is not partitioned as specified by ALTER
79
--echo #
@@ -155,6 +157,29 @@ alter table t1 partition by system_time interval 9 hour
155157
starts '2001-01-01 00:00:00' auto force;
156158
show create table t1;
157159

160+
--echo # Year/month interval
161+
delete history from t1;
162+
alter table t1 remove partitioning;
163+
set timestamp= unix_timestamp('2000-01-01 00:00:00');
164+
insert t1 values (77);
165+
delete from t1;
166+
set timestamp= unix_timestamp('2003-10-01 00:00:00');
167+
insert t1 values (88);
168+
delete from t1;
169+
alter table t1 partition by system_time interval 11 month auto force;
170+
show create table t1;
171+
alter table t1 partition by system_time interval 1 year auto force;
172+
show create table t1;
173+
174+
--echo # No history
175+
delete history from t1;
176+
set timestamp= unix_timestamp('2000-01-01 00:00:00');
177+
alter table t1 partition by system_time interval 1 hour auto force;
178+
show create table t1;
179+
insert t1 values (99);
180+
alter table t1 partition by system_time interval 1 hour auto force;
181+
show create table t1;
182+
158183
--echo # Slow scan warning
159184
create or replace table t1 (x int,
160185
row_start timestamp(6) as row start invisible,

sql/sql_partition.cc

Lines changed: 69 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ static int get_partition_id_linear_key_sub(partition_info *part_info, uint32 *pa
100100
static uint32 get_next_partition_via_walking(PARTITION_ITERATOR*);
101101
static void set_up_range_analysis_info(partition_info *part_info);
102102
static uint32 get_next_subpartition_via_walking(PARTITION_ITERATOR*);
103+
static bool vers_calc_hist_parts(THD *thd, my_time_t end,
104+
const Vers_part_info::interval_t &interval,
105+
uint *hist_parts);
103106
#endif
104107

105108
uint32 get_next_partition_id_range(PARTITION_ITERATOR* part_iter);
@@ -6187,15 +6190,9 @@ the generated partition syntax in a correct manner.
61876190
part_info->default_partitions_setup= false;
61886191
part_info->partitions.empty();
61896192

6190-
my_time_t range= max_ts.sec - interval.start;
6191-
DBUG_ASSERT(range >= 0);
6192-
if (!range)
6193-
range++;
6194-
const longlong i_sec= interval2sec(&interval.step);
6195-
DBUG_ASSERT(i_sec > 0);
6196-
uint hist_parts= range / i_sec;
6197-
if (hist_parts * i_sec != range)
6198-
hist_parts++;
6193+
uint hist_parts= 0;
6194+
if (vers_calc_hist_parts(thd, max_ts.sec, interval, &hist_parts))
6195+
DBUG_RETURN(true);
61996196
part_info->num_parts= hist_parts + 1;
62006197
} /* if (max_ts.sec > MY_TIME_T_MIN) */
62016198
else
@@ -6238,6 +6235,69 @@ the generated partition syntax in a correct manner.
62386235
}
62396236

62406237

6238+
static bool vers_calc_hist_parts(THD *thd, my_time_t end,
6239+
const Vers_part_info::interval_t &interval,
6240+
uint *hist_parts)
6241+
{
6242+
uint error= 0;
6243+
my_time_t start= interval.start;
6244+
DBUG_ASSERT(hist_parts != NULL);
6245+
*hist_parts= 0;
6246+
6247+
if (end < start)
6248+
return false;
6249+
6250+
if (!(interval.step.year || interval.step.month))
6251+
{
6252+
my_time_t range= end - start;
6253+
if (!range)
6254+
range++;
6255+
6256+
const longlong i_sec= interval2sec(&interval.step);
6257+
DBUG_ASSERT(i_sec > 0);
6258+
6259+
*hist_parts= static_cast<uint>(range / i_sec);
6260+
if ((*hist_parts) * i_sec != range)
6261+
(*hist_parts)++;
6262+
if (*hist_parts >= MAX_PARTITIONS)
6263+
{
6264+
my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
6265+
return true;
6266+
}
6267+
return false;
6268+
}
6269+
6270+
MYSQL_TIME boundary;
6271+
thd->variables.time_zone->gmt_sec_to_TIME(&boundary, start);
6272+
6273+
while (start < end)
6274+
{
6275+
if (*hist_parts >= MAX_PARTITIONS)
6276+
{
6277+
my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
6278+
return true;
6279+
}
6280+
6281+
if (date_add_interval(thd, &boundary, interval.type, interval.step))
6282+
{
6283+
my_error(ER_DATA_OUT_OF_RANGE, MYF(0), "TIMESTAMP", "INTERVAL");
6284+
return true;
6285+
}
6286+
6287+
start= thd->variables.time_zone->TIME_to_gmt_sec(&boundary, &error);
6288+
if (start <= 0 || error)
6289+
{
6290+
my_error(ER_DATA_OUT_OF_RANGE, MYF(0), "TIMESTAMP", "INTERVAL");
6291+
return true;
6292+
}
6293+
6294+
(*hist_parts)++;
6295+
}
6296+
6297+
return false;
6298+
}
6299+
6300+
62416301
/*
62426302
Change partitions, used to implement ALTER TABLE ADD/REORGANIZE/COALESCE
62436303
partitions. This method is used to implement both single-phase and multi-

0 commit comments

Comments
 (0)