mirror of
https://github.com/MariaDB/server.git
synced 2026-05-13 18:40:48 +02:00
MDEV-29114 Pruning depends on current timestamp for partition by SYSTEM_TIME
Wrong "fastpath" boundary conditions. The right boundary is open, the
left boundary is closed. The condition range_value[loc_hist_id - 1] as
left boundary must be checked with <= operator. The same with the
right boundary range_value[loc_hist_id] as the correct way is to check
it with > operator, the right boundary check was rewritten for clear
understanding:
ts < range_value[loc_hist_id]
The below code confirms closed endpoint type for left boundary:
if (range_value[loc_hist_id] <= ts)
min_hist_id= loc_hist_id + 1;
Also the endpoint type (closed for left, open for right) is confirmed
by vers_set_hist_part() for DML:
else if (vers_info->interval.is_set() &&
vers_info->hist_part->range_value <= thd->query_start())
and here (right boundary, rewritten for clarity):
if (thd->query_start() < next->range_value)
{
error= false;
break;
}
This commit is contained in:
parent
3c8a5ea128
commit
dfd28e5324
4 changed files with 115 additions and 3 deletions
|
|
@ -3524,6 +3524,69 @@ alter table `t1` partition by system_time interval 7 year ;
|
|||
ERROR 22003: TIMESTAMP value is out of range in 'INTERVAL'
|
||||
drop table t1;
|
||||
#
|
||||
# MDEV-29114 ALTER puts row into different partition for system_time
|
||||
# interval partitioning
|
||||
#
|
||||
# CREATE case
|
||||
set timestamp= unix_timestamp('2000-01-01 00:00:00');
|
||||
create or replace table t1 (x int) with system versioning
|
||||
partition by system_time interval 1 hour (
|
||||
partition p0 history, partition p1 history, partition pn current);
|
||||
set timestamp= unix_timestamp('2000-01-01 00:00:00');
|
||||
insert t1 values (0);
|
||||
set timestamp= unix_timestamp('2000-01-01 00:10:00');
|
||||
update t1 set x= 1;
|
||||
set timestamp= unix_timestamp('2000-01-01 01:00:00');
|
||||
update t1 set x= 2;
|
||||
set timestamp= unix_timestamp('2000-01-01 01:30:00');
|
||||
update t1 set x= 3;
|
||||
# CREATE result: row 1 got into p1
|
||||
select *, row_start, row_end from t1 partition (p0);
|
||||
x row_start row_end
|
||||
0 2000-01-01 00:00:00.000000 2000-01-01 00:10:00.000000
|
||||
select *, row_start, row_end from t1 partition (p1);
|
||||
x row_start row_end
|
||||
1 2000-01-01 00:10:00.000000 2000-01-01 01:00:00.000000
|
||||
2 2000-01-01 01:00:00.000000 2000-01-01 01:30:00.000000
|
||||
flush tables;
|
||||
# For CREATE pruning is affected by current timestamp, but SELECT works
|
||||
# in any case since row 1 got into p1
|
||||
set timestamp= unix_timestamp('2000-01-01 00:00:00');
|
||||
explain partitions select * from t1 for system_time as of '2000-01-01 00:59:59';
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 p0,p1,pn ALL NULL NULL NULL NULL 4 Using where
|
||||
select * from t1 for system_time as of '2000-01-01 00:59:59';
|
||||
x
|
||||
1
|
||||
set timestamp= unix_timestamp('2020-01-01 00:00:00');
|
||||
explain partitions select * from t1 for system_time as of '2000-01-01 00:59:59';
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 p0,p1,pn ALL NULL NULL NULL NULL 4 Using where
|
||||
select * from t1 for system_time as of '2000-01-01 00:59:59';
|
||||
x
|
||||
1
|
||||
# ALTER case
|
||||
set timestamp= unix_timestamp('2000-01-01 00:00:00');
|
||||
alter table t1
|
||||
partition by system_time interval 1 hour (
|
||||
partition p0 history, partition p1 history, partition pn current);
|
||||
# ALTER result: row 1 got into p1
|
||||
Select *, row_start, row_end from t1 partition (p0);
|
||||
x row_start row_end
|
||||
0 2000-01-01 00:00:00.000000 2000-01-01 00:10:00.000000
|
||||
Select *, row_start, row_end from t1 partition (p1);
|
||||
x row_start row_end
|
||||
1 2000-01-01 00:10:00.000000 2000-01-01 01:00:00.000000
|
||||
2 2000-01-01 01:00:00.000000 2000-01-01 01:30:00.000000
|
||||
flush tables;
|
||||
Explain partitions select * from t1 for system_time as of '2000-01-01 00:59:59';
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 p0,p1,pn ALL NULL NULL NULL NULL 4 Using where
|
||||
Select * from t1 for system_time as of '2000-01-01 00:59:59';
|
||||
x
|
||||
1
|
||||
drop table t1;
|
||||
#
|
||||
# End of 10.11 tests
|
||||
#
|
||||
set global innodb_stats_persistent= @save_persistent;
|
||||
|
|
|
|||
|
|
@ -2768,6 +2768,52 @@ partition by system_time interval 1 month (
|
|||
alter table `t1` partition by system_time interval 7 year ;
|
||||
drop table t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-29114 ALTER puts row into different partition for system_time
|
||||
--echo # interval partitioning
|
||||
--echo #
|
||||
--echo # CREATE case
|
||||
set timestamp= unix_timestamp('2000-01-01 00:00:00');
|
||||
create or replace table t1 (x int) with system versioning
|
||||
partition by system_time interval 1 hour (
|
||||
partition p0 history, partition p1 history, partition pn current);
|
||||
set timestamp= unix_timestamp('2000-01-01 00:00:00');
|
||||
insert t1 values (0);
|
||||
set timestamp= unix_timestamp('2000-01-01 00:10:00');
|
||||
update t1 set x= 1;
|
||||
set timestamp= unix_timestamp('2000-01-01 01:00:00');
|
||||
update t1 set x= 2;
|
||||
set timestamp= unix_timestamp('2000-01-01 01:30:00');
|
||||
update t1 set x= 3;
|
||||
|
||||
--echo # CREATE result: row 1 got into p1
|
||||
select *, row_start, row_end from t1 partition (p0);
|
||||
select *, row_start, row_end from t1 partition (p1);
|
||||
flush tables;
|
||||
--echo # For CREATE pruning is affected by current timestamp, but SELECT works
|
||||
--echo # in any case since row 1 got into p1
|
||||
set timestamp= unix_timestamp('2000-01-01 00:00:00');
|
||||
explain partitions select * from t1 for system_time as of '2000-01-01 00:59:59';
|
||||
select * from t1 for system_time as of '2000-01-01 00:59:59';
|
||||
set timestamp= unix_timestamp('2020-01-01 00:00:00');
|
||||
explain partitions select * from t1 for system_time as of '2000-01-01 00:59:59';
|
||||
select * from t1 for system_time as of '2000-01-01 00:59:59';
|
||||
|
||||
--echo # ALTER case
|
||||
set timestamp= unix_timestamp('2000-01-01 00:00:00');
|
||||
alter table t1
|
||||
partition by system_time interval 1 hour (
|
||||
partition p0 history, partition p1 history, partition pn current);
|
||||
|
||||
--echo # ALTER result: row 1 got into p1
|
||||
Select *, row_start, row_end from t1 partition (p0);
|
||||
Select *, row_start, row_end from t1 partition (p1);
|
||||
flush tables;
|
||||
Explain partitions select * from t1 for system_time as of '2000-01-01 00:59:59';
|
||||
Select * from t1 for system_time as of '2000-01-01 00:59:59';
|
||||
|
||||
drop table t1;
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.11 tests
|
||||
--echo #
|
||||
|
|
|
|||
|
|
@ -831,6 +831,7 @@ bool partition_info::vers_set_hist_part(THD *thd, uint *create_count)
|
|||
return 0;
|
||||
}
|
||||
else if (vers_info->interval.is_set() &&
|
||||
/* Left boundary is closed */
|
||||
vers_info->hist_part->range_value <= thd->query_start())
|
||||
{
|
||||
partition_element *next= NULL;
|
||||
|
|
@ -842,7 +843,8 @@ bool partition_info::vers_set_hist_part(THD *thd, uint *create_count)
|
|||
while ((next= it++) != vers_info->now_part)
|
||||
{
|
||||
vers_info->hist_part= next;
|
||||
if (next->range_value > thd->query_start())
|
||||
/* Right boundary is open */
|
||||
if (thd->query_start() < next->range_value)
|
||||
{
|
||||
error= false;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -3511,13 +3511,14 @@ int vers_get_partition_id(partition_info *part_info, uint32 *part_id,
|
|||
goto done; // fastpath
|
||||
|
||||
ts= row_end->get_timestamp(&unused);
|
||||
if ((loc_hist_id == 0 || range_value[loc_hist_id - 1] < ts) &&
|
||||
(loc_hist_id == max_hist_id || range_value[loc_hist_id] >= ts))
|
||||
if ((loc_hist_id == 0 || range_value[loc_hist_id - 1] <= ts) &&
|
||||
(loc_hist_id == max_hist_id || ts < range_value[loc_hist_id]))
|
||||
goto done; // fastpath
|
||||
|
||||
while (max_hist_id > min_hist_id)
|
||||
{
|
||||
loc_hist_id= (max_hist_id + min_hist_id) / 2;
|
||||
/* Left boundary is closed */
|
||||
if (range_value[loc_hist_id] <= ts)
|
||||
min_hist_id= loc_hist_id + 1;
|
||||
else
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue