Hey all, I took a stab at a quick and dirty TAP test (my first ever). So it can probably be improved a lot. Please take a look.
On Thu, Mar 04, 2021 at 10:28:31AM +0900, Kyotaro Horiguchi wrote: > 2. Restore ThisTimeLineID after calling XLogReadRecord() in the > *caller* side. This is what came up to me first but I don't like > this, too, but I don't find better fix. way. +1 to this patch [1]. The above TAP test passes with this patch applied. [1] https://www.postgresql.org/message-id/attachment/119972/dont_change_thistimelineid.patch Regards, Soumyadeep Regards, Soumyadeep
diff --git a/src/test/recovery/t/022_pitr_prepared_xact.pl b/src/test/recovery/t/022_pitr_prepared_xact.pl new file mode 100644 index 00000000000..b8d5146bb9d --- /dev/null +++ b/src/test/recovery/t/022_pitr_prepared_xact.pl @@ -0,0 +1,69 @@ +# Test for timeline switch +use strict; +use warnings; +use File::Path qw(rmtree); +use PostgresNode; +use TestLib; +use Test::More tests => 2; +use File::Compare; +use Time::HiRes qw(usleep); + +$ENV{PGDATABASE} = 'postgres'; + +# Initialize primary node +my $node_primary = get_new_node('primary'); +$node_primary->init(has_archiving => 1); +$node_primary->append_conf('postgresql.conf', "max_prepared_transactions = 10"); +$node_primary->append_conf('postgresql.conf', "max_wal_senders = 10"); +$node_primary->append_conf('postgresql.conf', "wal_level = 'replica'"); +$node_primary->start; + +# Take backup +my $backup_name = 'my_backup'; +$node_primary->backup($backup_name); + +my $node_pitr = get_new_node('node_pitr'); +$node_pitr->init_from_backup($node_primary, $backup_name, + standby => 0, has_restoring => 1); +$node_pitr->append_conf('postgresql.conf', "max_prepared_transactions = 10"); +$node_pitr->append_conf('postgresql.conf', "recovery_target_name = 'rp'"); +$node_pitr->append_conf('postgresql.conf', "recovery_target_action = 'promote'"); + +# Workload with prepared transaction +$node_primary->psql( + 'postgres', qq{ +CREATE TABLE foo(i int); +BEGIN; +INSERT INTO foo VALUES(1); +PREPARE TRANSACTION 'fooinsert'; +SELECT pg_create_restore_point('rp'); +INSERT INTO foo VALUES(2); +SELECT pg_switch_wal(); +}); + +# Sleep 5s to ensure that the WAL has been archived. +# probably can be replaced by a wait +usleep(5000000); + +$node_pitr->start; + +my $last_archived_wal_file_name = $node_primary->safe_psql('postgres', + "SELECT last_archived_wal FROM pg_stat_archiver;"); + +# Ensure that we don't write to the older timeline during PITR promotion by +# ensuring that the last archived WAL file was not overwritten during recovery. +my $archive_dir = $node_primary->archive_dir; +my $archive_wal_file_path = "${archive_dir}/${last_archived_wal_file_name}"; +my $node_pitr_data = $node_pitr->data_dir; +my $local_wal_file_path = "${node_pitr_data}/pg_wal/${last_archived_wal_file_name}"; +is(compare($archive_wal_file_path, $local_wal_file_path), qq(0), "Check if the last archived WAL file was overwritten"); + +$node_pitr->psql( + 'postgres', qq{ +COMMIT PREPARED 'fooinsert'; +}); + +my $foo_select_result = $node_pitr->safe_psql('postgres', + "SELECT * FROM foo;"); + +is($foo_select_result, qq(1), "Check foo select result");