1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

MDEV-16546 System versioning setting to allow history modification

1. system_versioning_insert_history session variable allows
pseudocolumns ROW_START and ROW_END be specified in INSERT,
INSERT..SELECT and LOAD DATA.

2. Cleaned up select_insert::send_data() from setting vers_write as
this parameter is now set on TABLE initialization.

4. Replication of system_versioning_insert_history via option_bits in
OPTIONS_WRITTEN_TO_BIN_LOG.
This commit is contained in:
Aleksey Midenkov
2022-08-28 22:44:56 +03:00
committed by Sergei Golubchik
parent d9b0c9ad2b
commit a2cda88631
23 changed files with 581 additions and 23 deletions

View File

@@ -81,4 +81,161 @@ select x, y from t2;
drop table t1;
drop table t2;
--echo #
--echo # MDEV-16546 System versioning setting to allow history modification
--echo #
set @@session.time_zone='+00:00';
let $MAX_TIMESTAMP= TIMESTAMP'2038-01-19 03:14:07.999999';
create table t1(x int primary key) with system versioning;
create table t2(y int primary key,
row_start timestamp(6) as row start invisible,
row_end timestamp(6) as row end invisible,
period for system_time (row_start, row_end))
with system versioning;
create table t3(z int primary key,
row_start timestamp(6) as row start,
row_end timestamp(6) as row end,
period for system_time (row_start, row_end))
with system versioning;
--error ER_BAD_FIELD_ERROR
insert into t1(x, row_start, row_end) values (2, '1980-01-01 00:00:00', '1980-01-01 00:00:01');
--error ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN
insert into t2(y, row_start, row_end) values (2, '1980-01-01 00:00:00', '1980-01-01 00:00:01');
set @@system_versioning_insert_history= 1;
--replace_result $default_engine DEFAULT_ENGINE
show create table t1;
insert into t1(x, row_start, row_end) values (3, '1980-01-01 00:00:00', '1980-01-01 00:00:01');
insert into t2(y, row_start, row_end) values (4, '1980-01-01 00:00:00', '1980-01-01 00:00:01');
insert into t3 values (5, '1980-01-01 00:00:00', '1980-01-01 00:00:01');
select x, row_start, row_end from t1 for system_time all;
select y, row_start, row_end from t2 for system_time all;
select z, row_start, row_end from t3 for system_time all;
insert into t1(x) values (1);
insert into t2(y) values (1);
update t1 set x= x + 1;
--error ER_BAD_FIELD_ERROR
update t1 set row_start= '1971-01-01 00:00:00';
--error ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN
update t2 set row_start= '1971-01-01 00:00:00';
--error ER_BAD_FIELD_ERROR
insert t1 (x) values (2) on duplicate key update x= 3, row_end= '1970-01-01 00:00:00';
--error ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN
insert t2 (y) values (1) on duplicate key update y= 3, row_end= '1970-01-01 00:00:00';
# this should work, row_start/row_end must be mentioned explicitly:
insert into t1 values (4);
insert into t1 set x= 5, row_start= '1980-01-01 00:00:00', row_end= '1980-01-01 00:00:01';
--error ER_WRONG_VALUE
insert into t1(x, row_start, row_end) values (6, '1980-01-01 00:00:01', '1980-01-01 00:00:00');
--error ER_WRONG_VALUE
insert into t1(x, row_start, row_end) values (7, '1980-01-01 00:00:11', '1980-01-01 00:00:11');
--error ER_WRONG_VALUE
insert into t1(x, row_start) values (8, '1980-01-01 00:00:22');
# NOTE: having row_start=0 might be useful and can mean
# "there is no information on when history was started" (an opposite to row_end=MAX_TIMESTAMP)
--error ER_WRONG_VALUE
insert into t1(x, row_end) values (9, '1980-01-01 00:00:33');
--error ER_WRONG_VALUE
eval insert into t1(x, row_end) values (10, $MAX_TIMESTAMP);
select x, check_row_ts(row_start, row_end) from t1 for system_time all order by x;
eval select x, row_start, row_end from t1 for system_time all
where x > 1 and row_end < $MAX_TIMESTAMP order by x, row_start, row_end;
--echo # Direct insert is not possible for TRX_ID versioning
create or replace table t2(y int primary key,
row_start bigint unsigned as row start,
row_end bigint unsigned as row end,
period for system_time (row_start, row_end))
with system versioning engine innodb;
--error ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN
insert into t2(y, row_start, row_end) values (0, 1, 2);
set @@system_versioning_insert_history= 0;
--echo ## INSERT..SELECT
create or replace table t2 like t1;
set @@system_versioning_insert_history= 1;
insert into t2 (x, row_start, row_end) select x, row_start, row_end from t1 for system_time all;
select x, check_row_ts(row_start, row_end) from t2 for system_time all order by x;
eval select x, row_start, row_end from t2 for system_time all
where x > 1 and row_end < $MAX_TIMESTAMP order by x, row_start, row_end;
set @@system_versioning_insert_history= 0;
--echo # REPLACE / REPLACE .. SELECT
create or replace table t2(a int primary key,
row_start timestamp(6) as row start invisible,
row_end timestamp(6) as row end invisible,
period for system_time (row_start, row_end))
with system versioning;
--error ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN
replace into t2 (a, row_start, row_end) values (1, '1980-01-01 00:00:00', '1980-01-01 00:00:01');
--error ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN
replace into t2 (a, row_start, row_end) select x, row_start, row_end from t1;
create or replace table t2 (a int primary key) with system versioning;
--error ER_BAD_FIELD_ERROR
replace into t2 (a, row_start, row_end) values (1, '1980-01-01 00:00:00', '1980-01-01 00:00:01');
--error ER_BAD_FIELD_ERROR
replace into t2 (a, row_start, row_end) select x, row_start, row_end from t1;
set @@system_versioning_insert_history= 1;
--error ER_WRONG_VALUE
replace into t2 (a, row_start) values (1, '1980-01-01 00:00:00');
--error ER_WRONG_VALUE
replace into t2 (a, row_end) values (0, '1980-01-01 00:00:00');
replace into t2 (a, row_start, row_end) values (1, '1980-01-01 00:00:00', '1980-01-01 00:00:01');
select a, row_start, row_end from t2 for system_time all order by a, row_start, row_end;
--echo # Changing row_end via REPLACE is NOT possible, we just insert new row:
# NOTE: because multiple versions of history row with a=1 may exist, so what REPLACE should change?
replace into t2 (a, row_start, row_end) values (1, '1980-01-01 00:00:00', '1990-01-01 00:00:01');
select a, row_start, row_end from t2 for system_time all order by a, row_start, row_end;
--echo # But changing row_start via REPLACE is possible:
replace into t2 (a, row_start, row_end) values (1, '1971-01-01 00:00:00', '1980-01-01 00:00:01');
select a, row_start, row_end from t2 for system_time all order by a, row_start, row_end;
eval replace into t2 (a, row_start, row_end) select x, row_start, row_end from t1 for system_time all
where x > 1 and row_end < $MAX_TIMESTAMP;
select a, row_start, row_end from t2 for system_time all order by a, row_start, row_end;
--echo # LOAD DATA
--let DATAFILE= $MYSQLTEST_VARDIR/tmp/test_versioning_t3.data
--replace_result $DATAFILE DATAFILE
eval select x, row_start, row_end into outfile '$DATAFILE' from t1 for system_time all;
create or replace table t3 like t1;
--replace_result $default_engine DEFAULT_ENGINE
show create table t3;
set @@system_versioning_insert_history= 1;
--replace_result $default_engine DEFAULT_ENGINE
show create table t3;
--replace_result $DATAFILE DATAFILE
eval load data infile '$DATAFILE' into table t3 (x, row_start, row_end);
select x, check_row_ts(row_start, row_end) from t3 for system_time all order by x;
select row_start = '1980-01-01 00:00:00', row_end = '1980-01-01 00:00:01' from t3 for system_time all where x = 3;
--remove_file $DATAFILE
--echo # Honor secure_timestamp option
--let $restart_parameters= --secure-timestamp=YES
--source include/restart_mysqld.inc
set @@system_versioning_insert_history= 1;
--error ER_BAD_FIELD_ERROR
insert into t1(x, row_start, row_end) values (8, '1980-01-01 00:00:00', '1980-01-01 00:00:01');
--let $restart_parameters= --secure-timestamp=REPLICATION
--source include/restart_mysqld.inc
set @@system_versioning_insert_history= 1;
--error ER_BAD_FIELD_ERROR
insert into t1(x, row_start, row_end) values (9, '1980-01-01 00:00:00', '1980-01-01 00:00:01');
--let $restart_parameters= --secure-timestamp=SUPER
--source include/restart_mysqld.inc
set @@system_versioning_insert_history= 1;
insert into t1(x, row_start, row_end) values (10, '1980-01-01 00:00:00', '1980-01-01 00:00:01');
create user nobody;
change_user nobody;
use test;
--error ER_BAD_FIELD_ERROR
insert into t1(x, row_start, row_end) values (7, '1980-01-01 00:00:00', '1980-01-01 00:00:01');
change_user root;
use test;
--let $restart_parameters= --secure-timestamp=NO
--source include/restart_mysqld.inc
drop tables t1, t2, t3;
-- source suite/versioning/common_finish.inc