Remove assertion for replication origins in PREPARE TRANSACTION
authorMichael Paquier
Tue, 14 Dec 2021 01:58:29 +0000 (10:58 +0900)
committerMichael Paquier
Tue, 14 Dec 2021 01:58:29 +0000 (10:58 +0900)
When using replication origins, pg_replication_origin_xact_setup() is an
optional choice to be able to set a LSN and a timestamp to mark the
origin, which would be additionally added to WAL for transaction commits
or aborts (including 2PC transactions).  An assertion in the code path
of PREPARE TRANSACTION assumed that this data should always be set, so
it would trigger when using replication origins without setting up an
origin LSN.  Some tests are added to cover more this kind of scenario.

Oversight in commit 1eb6d65.

Per discussion with Amit Kapila and Masahiko Sawada.

Discussion: https://postgr.es/m/[email protected]
Backpatch-through: 11

contrib/test_decoding/expected/replorigin.out
contrib/test_decoding/sql/replorigin.sql
src/backend/access/transam/twophase.c

index 3b249f4856f3fd4ec59f3eddb920126ca0fe273a..01645a9174ffc5a4e629eda13d1800c9c58b885f 100644 (file)
@@ -152,3 +152,79 @@ SELECT pg_replication_origin_drop('regress_test_decoding: regression_slot');
  
 (1 row)
 
+-- Set of transactions with no origin LSNs and commit timestamps set for
+-- this session.
+SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot_no_lsn', 'test_decoding');
+ ?column? 
+----------
+ init
+(1 row)
+
+SELECT pg_replication_origin_create('regress_test_decoding: regression_slot_no_lsn');
+ pg_replication_origin_create 
+------------------------------
+                            1
+(1 row)
+
+-- mark session as replaying
+SELECT pg_replication_origin_session_setup('regress_test_decoding: regression_slot_no_lsn');
+ pg_replication_origin_session_setup 
+-------------------------------------
+(1 row)
+
+-- Simple transactions
+BEGIN;
+INSERT INTO origin_tbl(data) VALUES ('no_lsn, commit');
+COMMIT;
+BEGIN;
+INSERT INTO origin_tbl(data) VALUES ('no_lsn, rollback');
+ROLLBACK;
+-- 2PC transactions
+BEGIN;
+INSERT INTO origin_tbl(data) VALUES ('no_lsn, commit prepared');
+PREPARE TRANSACTION 'replorigin_prepared';
+COMMIT PREPARED 'replorigin_prepared';
+BEGIN;
+INSERT INTO origin_tbl(data) VALUES ('no_lsn, rollback prepared');
+PREPARE TRANSACTION 'replorigin_prepared';
+ROLLBACK PREPARED 'replorigin_prepared';
+SELECT local_id, external_id,
+       remote_lsn <> '0/0' AS valid_remote_lsn,
+       local_lsn <> '0/0' AS valid_local_lsn
+       FROM pg_replication_origin_status;
+ local_id |                  external_id                  | valid_remote_lsn | valid_local_lsn 
+----------+-----------------------------------------------+------------------+-----------------
+        1 | regress_test_decoding: regression_slot_no_lsn | f                | t
+(1 row)
+
+SELECT data FROM pg_logical_slot_get_changes('regression_slot_no_lsn', NULL, NULL, 'skip-empty-xacts', '1', 'include-xids', '0');
+                                        data                                         
+-------------------------------------------------------------------------------------
+ BEGIN
+ table public.origin_tbl: INSERT: id[integer]:4 data[text]:'no_lsn, commit'
+ COMMIT
+ BEGIN
+ table public.origin_tbl: INSERT: id[integer]:6 data[text]:'no_lsn, commit prepared'
+ COMMIT
+(6 rows)
+
+-- Clean up
+SELECT pg_replication_origin_session_reset();
+ pg_replication_origin_session_reset 
+-------------------------------------
+(1 row)
+
+SELECT pg_drop_replication_slot('regression_slot_no_lsn');
+ pg_drop_replication_slot 
+--------------------------
+(1 row)
+
+SELECT pg_replication_origin_drop('regress_test_decoding: regression_slot_no_lsn');
+ pg_replication_origin_drop 
+----------------------------
+(1 row)
+
index 8979b30616054508b6a337c7b3d08cc2bfe4e4f3..b854fbb247c80133b1e932af3580c3df88fee095 100644 (file)
@@ -69,3 +69,35 @@ SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'inc
 
 SELECT pg_drop_replication_slot('regression_slot');
 SELECT pg_replication_origin_drop('regress_test_decoding: regression_slot');
+
+-- Set of transactions with no origin LSNs and commit timestamps set for
+-- this session.
+SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot_no_lsn', 'test_decoding');
+SELECT pg_replication_origin_create('regress_test_decoding: regression_slot_no_lsn');
+-- mark session as replaying
+SELECT pg_replication_origin_session_setup('regress_test_decoding: regression_slot_no_lsn');
+-- Simple transactions
+BEGIN;
+INSERT INTO origin_tbl(data) VALUES ('no_lsn, commit');
+COMMIT;
+BEGIN;
+INSERT INTO origin_tbl(data) VALUES ('no_lsn, rollback');
+ROLLBACK;
+-- 2PC transactions
+BEGIN;
+INSERT INTO origin_tbl(data) VALUES ('no_lsn, commit prepared');
+PREPARE TRANSACTION 'replorigin_prepared';
+COMMIT PREPARED 'replorigin_prepared';
+BEGIN;
+INSERT INTO origin_tbl(data) VALUES ('no_lsn, rollback prepared');
+PREPARE TRANSACTION 'replorigin_prepared';
+ROLLBACK PREPARED 'replorigin_prepared';
+SELECT local_id, external_id,
+       remote_lsn <> '0/0' AS valid_remote_lsn,
+       local_lsn <> '0/0' AS valid_local_lsn
+       FROM pg_replication_origin_status;
+SELECT data FROM pg_logical_slot_get_changes('regression_slot_no_lsn', NULL, NULL, 'skip-empty-xacts', '1', 'include-xids', '0');
+-- Clean up
+SELECT pg_replication_origin_session_reset();
+SELECT pg_drop_replication_slot('regression_slot_no_lsn');
+SELECT pg_replication_origin_drop('regress_test_decoding: regression_slot_no_lsn');
index ba11b5331461edf56feb7264af0376a45b7e78d3..b1a221849a3d287bb96b88098988627ab3d208b9 100644 (file)
@@ -1134,7 +1134,6 @@ EndPrepare(GlobalTransaction gxact)
 
    if (replorigin)
    {
-       Assert(replorigin_session_origin_lsn != InvalidXLogRecPtr);
        hdr->origin_lsn = replorigin_session_origin_lsn;
        hdr->origin_timestamp = replorigin_session_origin_timestamp;
    }