diff --git a/contrib/test_decoding/t/002_two_databases.pl b/contrib/test_decoding/t/002_two_databases.pl index f04fe48abd3..27d62a269fe 100644 --- a/contrib/test_decoding/t/002_two_databases.pl +++ b/contrib/test_decoding/t/002_two_databases.pl @@ -11,6 +11,20 @@ use PostgreSQL::Test::Cluster; use PostgreSQL::Test::Utils; use Test::More; +sub begin_background_txn +{ + my ($node, $database, $statement) = @_; + my $session = $node->background_psql($database, on_error_stop => 1); + + $session->query_safe( + qq[ + BEGIN; + $statement + ]); + + return $session; +} + my $node = PostgreSQL::Test::Cluster->new('test'); $node->init(allows_streaming => 'logical'); $node->start; @@ -23,9 +37,12 @@ $node->safe_psql('postgres', 'CREATE DATABASE db2'); $node->safe_psql('db1', 'CREATE TABLE t1(a int)'); $node->safe_psql('db1', "SELECT pg_create_logical_replication_slot('slot_db1', 'test_decoding')"); -$node->safe_psql('db2', 'CREATE TABLE t2(a int)'); -$node->safe_psql('db2', 'CREATE ROLE regress_role1'); -$node->safe_psql('db2', 'CREATE PUBLICATION pub0 FOR ALL TABLES'); +$node->safe_psql( + 'db2', qq[ + CREATE TABLE t2(a int); + CREATE ROLE regress_role1; + CREATE PUBLICATION pub0 FOR ALL TABLES; +]); my $get_changes = qq( SET log_min_messages = 'debug1'; @@ -36,30 +53,31 @@ my $get_changes = qq( # db1. The commit touches a shared catalog, so the snapshot and the # invalidations are still distributed; the decoding of db1's transaction # must produce correct results. -my $session1 = $node->background_psql('db1', on_error_stop => 1); -$session1->query_safe('BEGIN'); -$session1->query_safe('INSERT INTO t1 VALUES (1)'); +my $session1 = + begin_background_txn($node, 'db1', 'INSERT INTO t1 VALUES (1);'); my $session_role = $node->background_psql('db2', on_error_stop => 1); -$session_role->query_safe('BEGIN'); -$session_role->query_safe('ALTER ROLE regress_role1 CONNECTION LIMIT 10'); -my $xid_role = $session_role->query_safe('SELECT pg_current_xact_id()'); +my $xid_role = $session_role->query_safe( + qq[ + BEGIN; + ALTER ROLE regress_role1 CONNECTION LIMIT 10; + SELECT pg_current_xact_id(); + COMMIT; +]); chomp($xid_role); -$session_role->query_safe('COMMIT'); $session_role->quit; $session1->query_safe('COMMIT'); $session1->quit; - my $result = $node->safe_psql('db1', $get_changes); -is($result, qq(BEGIN +is( $result, qq(BEGIN table public.t1: INSERT: a[integer]:1 COMMIT), 'shared-catalog DDL in db2 does not disturb decoding of db1'); - my $log = slurp_file($node->logfile); -like($log, - qr/transaction $xid_role committed in database \d+ has catalog changes relevant/, +like( + $log, + qr/transaction $xid_role committed in database \d+ has relevant catalog changes/, 'shared-catalog DDL in db2 classified as relevant'); # A catalog DDL committed in db2, with a shared-catalog DDL rolled back to @@ -69,33 +87,35 @@ like($log, # carries only the surviving messages, which touch no shared catalog, so # the snapshot distribution is skipped; the decoding of db1's transaction # must still produce correct results. -$session1 = $node->background_psql('db1', on_error_stop => 1); -$session1->query_safe('BEGIN'); -$session1->query_safe('INSERT INTO t1 VALUES (2)'); +$session1 = begin_background_txn($node, 'db1', 'INSERT INTO t1 VALUES (2);'); my $session2 = $node->background_psql('db2', on_error_stop => 1); -$session2->query_safe('BEGIN'); -$session2->query_safe('ALTER TABLE t2 RENAME TO t2_new'); -$session2->query_safe('SAVEPOINT s1'); -$session2->query_safe('ALTER ROLE regress_role1 RENAME TO regress_role2'); -$session2->query_safe('ROLLBACK TO SAVEPOINT s1'); -my $xid_savepoint = $session2->query_safe('SELECT pg_current_xact_id()'); +my $xid_savepoint = $session2->query_safe( + qq[ + BEGIN; + ALTER TABLE t2 RENAME TO t2_new; + SAVEPOINT s1; + ALTER ROLE regress_role1 RENAME TO regress_role2; + ROLLBACK TO SAVEPOINT s1; + SELECT pg_current_xact_id(); + COMMIT; +]); chomp($xid_savepoint); -$session2->query_safe('COMMIT'); $session2->quit; $session1->query_safe('COMMIT'); $session1->quit; $result = $node->safe_psql('db1', $get_changes); -is($result, qq(BEGIN +is( $result, qq(BEGIN table public.t1: INSERT: a[integer]:2 COMMIT), 'rolled back shared-catalog DDL in db2 does not disturb decoding of db1'); $log = slurp_file($node->logfile); -like($log, - qr/transaction $xid_savepoint committed in database \d+ does not have catalog changes relevant/, +like( + $log, + qr/transaction $xid_savepoint committed in database \d+ does not have relevant catalog changes/, 'ddl+savepoint+ddl+rollback in db2 classified as irrelevant'); # A publication parameter change on a FOR ALL TABLES publication in db2 @@ -104,40 +124,37 @@ like($log, # conservatively treated as touching a shared catalog, so the snapshot and # the invalidations are still distributed; the decoding of db1's # transaction must produce correct results. -$session1 = $node->background_psql('db1', on_error_stop => 1); -$session1->query_safe('BEGIN'); -$session1->query_safe('INSERT INTO t1 VALUES (3)'); +$session1 = begin_background_txn($node, 'db1', 'INSERT INTO t1 VALUES (3);'); my $session_pub = $node->background_psql('db2', on_error_stop => 1); -$session_pub->query_safe('BEGIN'); -$session_pub->query_safe( - "ALTER PUBLICATION pub0 SET (publish = 'insert, update, delete')"); -my $xid_pub = $session_pub->query_safe('SELECT pg_current_xact_id()'); +my $xid_pub = $session_pub->query_safe( + qq[ + BEGIN; + ALTER PUBLICATION pub0 SET (publish = 'insert, update, delete'); + SELECT pg_current_xact_id(); + COMMIT; +]); chomp($xid_pub); -$session_pub->query_safe('COMMIT'); $session_pub->quit; $session1->query_safe('COMMIT'); $session1->quit; - $result = $node->safe_psql('db1', $get_changes); -is($result, qq(BEGIN +is( $result, qq(BEGIN table public.t1: INSERT: a[integer]:3 COMMIT), 'whole-relcache broadcast in db2 does not disturb decoding of db1'); - $log = slurp_file($node->logfile); -like($log, - qr/transaction $xid_pub committed in database \d+ has catalog changes relevant/, +like( + $log, + qr/transaction $xid_pub committed in database \d+ has relevant catalog changes/, 'whole-relcache broadcast in db2 classified as relevant'); - # Many catalog commits in db2 with the xmin of the historic snapshots pinned # by an in-progress transaction. Each such commit is irrelevant to this slot, # so no snapshot is distributed and the reorder buffer must not spill. -my $session3 = $node->background_psql('db2', on_error_stop => 1); -$session3->query_safe('BEGIN'); -$session3->query_safe('INSERT INTO t2_new VALUES (1)'); +my $session3 = + begin_background_txn($node, 'db2', 'INSERT INTO t2_new VALUES (1);'); my $session4 = $node->background_psql('db2', on_error_stop => 1); for my $i (1 .. 300) @@ -157,8 +174,8 @@ $node->safe_psql( 'include-xids', '0', 'skip-empty-xacts', '1'))); $result = $node->safe_psql('db1', - "SELECT spill_bytes FROM pg_stat_replication_slots WHERE slot_name = 'slot_db1'"); -is($result, '0', - 'catalog commits in db2 do not spill the reorder buffer'); + "SELECT spill_bytes FROM pg_stat_replication_slots WHERE slot_name = 'slot_db1'" +); +is($result, '0', 'catalog commits in db2 do not spill the reorder buffer'); done_testing(); diff --git a/src/backend/replication/logical/decode.c b/src/backend/replication/logical/decode.c index 54e7d64ec0c..c77e65444e5 100644 --- a/src/backend/replication/logical/decode.c +++ b/src/backend/replication/logical/decode.c @@ -715,7 +715,7 @@ DecodeCommit(LogicalDecodingContext *ctx, XLogRecordBuffer *buf, catalog_changes_relevant = false; elog(DEBUG1, - "transaction %u committed in database %u %s catalog changes relevant", + "transaction %u committed in database %u %s relevant catalog changes", xid, parsed->dbId, catalog_changes_relevant ? "has" : "does not have");