1
0
mirror of https://github.com/MariaDB/server.git synced 2025-11-09 11:41:36 +03:00

MDEV-34046 Parameterized PS converts error to warning, causes

replication problems

DELETE HISTORY did not process parameterized PS properly as the
history expression was checked on prepare stage when the parameters
was not yet substituted. In that case check_units() succeeded as there
is no invalid type: Item_param has type_handler_null which is
inherited from string type and this is valid type for history
expression. The warning was thrown when the expression was evaluated
for comparison on delete execution (when the parameter was already
substituted).

The fix postpones check_units() until the first PS execution. We have
to postpone where conditions processing until the first execution and
update select_lex.where on every execution as it is reset to the state
after prepare.
This commit is contained in:
Aleksey Midenkov
2025-06-11 16:38:10 +03:00
parent bff9b1e472
commit f1f9284181
6 changed files with 357 additions and 5 deletions

View File

@@ -251,3 +251,216 @@ t CREATE TABLE `t` (
PARTITIONS 2
drop table t;
# End of 10.9 tests
#
# MDEV-34046 Parameterized PS converts error to warning, causes replication problems
#
create table t (a int) with system versioning;
set timestamp= unix_timestamp('2000-01-01 00:00:00');
insert into t values (1), (100);
delete history from t before system_time @@timestamp;
ERROR HY000: Illegal parameter data type double for operation 'FOR SYSTEM_TIME'
execute immediate "delete history from t before system_time @@timestamp";
ERROR HY000: Illegal parameter data type double for operation 'FOR SYSTEM_TIME'
execute immediate "delete history from t before system_time ?" using @@timestamp;
ERROR HY000: Illegal parameter data type double for operation 'FOR SYSTEM_TIME'
set @ts1= '2000-01-01 00:00:01';
set timestamp= unix_timestamp(@ts1);
update t set a= a + 1 where a < 100;
set @ts2= '2000-01-01 00:00:02';
set timestamp= unix_timestamp(@ts2);
update t set a= a + 1 where a < 100;
set @ts3= '2000-01-01 00:00:03';
set timestamp= unix_timestamp(@ts3);
select *, row_start, row_end from t for system_time all order by a;
a row_start row_end
1 2000-01-01 00:00:00.000000 2000-01-01 00:00:01.000000
2 2000-01-01 00:00:01.000000 2000-01-01 00:00:02.000000
3 2000-01-01 00:00:02.000000 2038-01-19 03:14:07.999999
100 2000-01-01 00:00:00.000000 2038-01-19 03:14:07.999999
execute immediate "delete history from t before system_time @ts1";
select *, row_start, row_end from t for system_time all order by a;
a row_start row_end
1 2000-01-01 00:00:00.000000 2000-01-01 00:00:01.000000
2 2000-01-01 00:00:01.000000 2000-01-01 00:00:02.000000
3 2000-01-01 00:00:02.000000 2038-01-19 03:14:07.999999
100 2000-01-01 00:00:00.000000 2038-01-19 03:14:07.999999
execute immediate "delete history from t before system_time @ts2";
select *, row_start, row_end from t for system_time all order by a;
a row_start row_end
2 2000-01-01 00:00:01.000000 2000-01-01 00:00:02.000000
3 2000-01-01 00:00:02.000000 2038-01-19 03:14:07.999999
100 2000-01-01 00:00:00.000000 2038-01-19 03:14:07.999999
execute immediate "delete history from t before system_time ?" using @ts3;
select *, row_start, row_end from t for system_time all order by a;
a row_start row_end
3 2000-01-01 00:00:02.000000 2038-01-19 03:14:07.999999
100 2000-01-01 00:00:00.000000 2038-01-19 03:14:07.999999
execute immediate "delete history from t before system_time ?" using @ts3;
select *, row_start, row_end from t for system_time all order by a;
a row_start row_end
3 2000-01-01 00:00:02.000000 2038-01-19 03:14:07.999999
100 2000-01-01 00:00:00.000000 2038-01-19 03:14:07.999999
update t set a= a + 1 where a < 100;
set @ts4= '2000-01-01 00:00:04';
set timestamp= unix_timestamp(@ts4);
update t set a= a + 1 where a < 100;
select *, row_start, row_end from t for system_time all order by a;
a row_start row_end
3 2000-01-01 00:00:02.000000 2000-01-01 00:00:03.000000
4 2000-01-01 00:00:03.000000 2000-01-01 00:00:04.000000
5 2000-01-01 00:00:04.000000 2038-01-19 03:14:07.999999
100 2000-01-01 00:00:00.000000 2038-01-19 03:14:07.999999
execute immediate "delete history from t before system_time ?" using '2000-01-01 00:00:04';
select *, row_start, row_end from t for system_time all order by a;
a row_start row_end
4 2000-01-01 00:00:03.000000 2000-01-01 00:00:04.000000
5 2000-01-01 00:00:04.000000 2038-01-19 03:14:07.999999
100 2000-01-01 00:00:00.000000 2038-01-19 03:14:07.999999
set @ts5= '2000-01-01 00:00:05';
set timestamp= unix_timestamp(@ts5);
update t set a= a + 1 where a < 100;
set @ts6= '2000-01-01 00:00:06';
set timestamp= unix_timestamp(@ts6);
update t set a= a + 1 where a < 100;
set @ts7= '2000-01-01 00:00:07';
set timestamp= unix_timestamp(@ts7);
update t set a= a + 1 where a < 100;
select *, row_start, row_end from t for system_time all order by a;
a row_start row_end
4 2000-01-01 00:00:03.000000 2000-01-01 00:00:04.000000
5 2000-01-01 00:00:04.000000 2000-01-01 00:00:05.000000
6 2000-01-01 00:00:05.000000 2000-01-01 00:00:06.000000
7 2000-01-01 00:00:06.000000 2000-01-01 00:00:07.000000
8 2000-01-01 00:00:07.000000 2038-01-19 03:14:07.999999
100 2000-01-01 00:00:00.000000 2038-01-19 03:14:07.999999
prepare stmt from 'delete history from t before system_time ?';
execute stmt using @ts4;
select *, row_start, row_end from t for system_time all order by a;
a row_start row_end
4 2000-01-01 00:00:03.000000 2000-01-01 00:00:04.000000
5 2000-01-01 00:00:04.000000 2000-01-01 00:00:05.000000
6 2000-01-01 00:00:05.000000 2000-01-01 00:00:06.000000
7 2000-01-01 00:00:06.000000 2000-01-01 00:00:07.000000
8 2000-01-01 00:00:07.000000 2038-01-19 03:14:07.999999
100 2000-01-01 00:00:00.000000 2038-01-19 03:14:07.999999
execute stmt using @ts5;
select *, row_start, row_end from t for system_time all order by a;
a row_start row_end
5 2000-01-01 00:00:04.000000 2000-01-01 00:00:05.000000
6 2000-01-01 00:00:05.000000 2000-01-01 00:00:06.000000
7 2000-01-01 00:00:06.000000 2000-01-01 00:00:07.000000
8 2000-01-01 00:00:07.000000 2038-01-19 03:14:07.999999
100 2000-01-01 00:00:00.000000 2038-01-19 03:14:07.999999
execute stmt using @ts6;
select *, row_start, row_end from t for system_time all order by a;
a row_start row_end
6 2000-01-01 00:00:05.000000 2000-01-01 00:00:06.000000
7 2000-01-01 00:00:06.000000 2000-01-01 00:00:07.000000
8 2000-01-01 00:00:07.000000 2038-01-19 03:14:07.999999
100 2000-01-01 00:00:00.000000 2038-01-19 03:14:07.999999
execute stmt using '2000-01-01 00:00:06';
select *, row_start, row_end from t for system_time all order by a;
a row_start row_end
6 2000-01-01 00:00:05.000000 2000-01-01 00:00:06.000000
7 2000-01-01 00:00:06.000000 2000-01-01 00:00:07.000000
8 2000-01-01 00:00:07.000000 2038-01-19 03:14:07.999999
100 2000-01-01 00:00:00.000000 2038-01-19 03:14:07.999999
execute stmt using '2000-01-01 00:00:06.000001';
select *, row_start, row_end from t for system_time all order by a;
a row_start row_end
7 2000-01-01 00:00:06.000000 2000-01-01 00:00:07.000000
8 2000-01-01 00:00:07.000000 2038-01-19 03:14:07.999999
100 2000-01-01 00:00:00.000000 2038-01-19 03:14:07.999999
set @ts8= '2000-01-01 00:00:08';
set timestamp= unix_timestamp(@ts8);
delete from t;
select *, row_start, row_end from t for system_time all order by a;
a row_start row_end
7 2000-01-01 00:00:06.000000 2000-01-01 00:00:07.000000
8 2000-01-01 00:00:07.000000 2000-01-01 00:00:08.000000
100 2000-01-01 00:00:00.000000 2000-01-01 00:00:08.000000
execute immediate "delete history from t before system_time from_unixtime(?)" using @@timestamp;
select *, row_start, row_end from t for system_time all order by a;
a row_start row_end
8 2000-01-01 00:00:07.000000 2000-01-01 00:00:08.000000
100 2000-01-01 00:00:00.000000 2000-01-01 00:00:08.000000
execute stmt using '2020-01-01';
select *, row_start, row_end from t for system_time all order by a;
a row_start row_end
drop prepare stmt;
set timestamp= unix_timestamp('2000-01-01 00:00:00');
insert into t values (1), (100);
set @ts1= '2000-01-01 00:00:01';
set timestamp= unix_timestamp(@ts1);
update t set a= a + 1 where a < 100;
set timestamp= @@timestamp + 1;
set @ts2= @@timestamp;
update t set a= a + 1 where a < 100;
set timestamp= @@timestamp + 1;
update t set a= a + 1 where a < 100;
prepare stmt from 'delete history from t before system_time from_unixtime(? + ?)';
select *, row_start, row_end from t for system_time all order by a;
a row_start row_end
1 2000-01-01 00:00:00.000000 2000-01-01 00:00:01.000000
2 2000-01-01 00:00:01.000000 2000-01-01 00:00:02.000000
3 2000-01-01 00:00:02.000000 2000-01-01 00:00:03.000000
4 2000-01-01 00:00:03.000000 2038-01-19 03:14:07.999999
100 2000-01-01 00:00:00.000000 2038-01-19 03:14:07.999999
execute stmt using @ts1, 0;
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: '2000-01-01 00:00:01'
Warning 1292 Truncated incorrect DOUBLE value: '2000-01-01 00:00:01'
Warning 1292 Truncated incorrect DOUBLE value: '2000-01-01 00:00:01'
Warning 1292 Truncated incorrect DOUBLE value: '2000-01-01 00:00:01'
Warning 1292 Truncated incorrect DOUBLE value: '2000-01-01 00:00:01'
select *, row_start, row_end from t for system_time all order by a;
a row_start row_end
1 2000-01-01 00:00:00.000000 2000-01-01 00:00:01.000000
2 2000-01-01 00:00:01.000000 2000-01-01 00:00:02.000000
3 2000-01-01 00:00:02.000000 2000-01-01 00:00:03.000000
4 2000-01-01 00:00:03.000000 2038-01-19 03:14:07.999999
100 2000-01-01 00:00:00.000000 2038-01-19 03:14:07.999999
execute stmt using @ts2, 0;
select *, row_start, row_end from t for system_time all order by a;
a row_start row_end
2 2000-01-01 00:00:01.000000 2000-01-01 00:00:02.000000
3 2000-01-01 00:00:02.000000 2000-01-01 00:00:03.000000
4 2000-01-01 00:00:03.000000 2038-01-19 03:14:07.999999
100 2000-01-01 00:00:00.000000 2038-01-19 03:14:07.999999
execute stmt using @@timestamp, NULL;
select *, row_start, row_end from t for system_time all order by a;
a row_start row_end
2 2000-01-01 00:00:01.000000 2000-01-01 00:00:02.000000
3 2000-01-01 00:00:02.000000 2000-01-01 00:00:03.000000
4 2000-01-01 00:00:03.000000 2038-01-19 03:14:07.999999
100 2000-01-01 00:00:00.000000 2038-01-19 03:14:07.999999
execute stmt using NULL, NULL;
select *, row_start, row_end from t for system_time all order by a;
a row_start row_end
2 2000-01-01 00:00:01.000000 2000-01-01 00:00:02.000000
3 2000-01-01 00:00:02.000000 2000-01-01 00:00:03.000000
4 2000-01-01 00:00:03.000000 2038-01-19 03:14:07.999999
100 2000-01-01 00:00:00.000000 2038-01-19 03:14:07.999999
execute stmt using @ts2, 1;
select *, row_start, row_end from t for system_time all order by a;
a row_start row_end
3 2000-01-01 00:00:02.000000 2000-01-01 00:00:03.000000
4 2000-01-01 00:00:03.000000 2038-01-19 03:14:07.999999
100 2000-01-01 00:00:00.000000 2038-01-19 03:14:07.999999
execute stmt using @ts2, @ts2;
select *, row_start, row_end from t for system_time all order by a;
a row_start row_end
4 2000-01-01 00:00:03.000000 2038-01-19 03:14:07.999999
100 2000-01-01 00:00:00.000000 2038-01-19 03:14:07.999999
delete from t;
select *, row_start, row_end from t for system_time all order by a;
a row_start row_end
4 2000-01-01 00:00:03.000000 2000-01-01 00:00:03.000000
100 2000-01-01 00:00:00.000000 2000-01-01 00:00:03.000000
execute stmt using @ts2, @ts2;
select *, row_start, row_end from t for system_time all order by a;
a row_start row_end
drop prepare stmt;
drop table t;
set timestamp= default;
# End of 10.11 tests