Skip to content

Commit bcbecbc

Browse files
committed
Don't propagate a null subtransaction snapshot up to parent transaction.
This oversight could cause logical decoding to fail to decode an outer transaction containing changes, if a subtransaction had an XID but no actual changes. Per bug #14279 from Marko Tiikkaja. Patch by Marko based on analysis by Andrew Gierth. Discussion: <20160804191757.1430.39011@wrigleys.postgresql.org>
1 parent 3676631 commit bcbecbc

File tree

3 files changed

+40
-6
lines changed

3 files changed

+40
-6
lines changed

contrib/test_decoding/expected/xact.out

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot', 'test_d
66
init
77
(1 row)
88

9-
-- bug #13844, xids in non-decoded records need to be inspected
109
CREATE TABLE xact_test(data text);
1110
INSERT INTO xact_test VALUES ('before-test');
11+
-- bug #13844, xids in non-decoded records need to be inspected
1212
BEGIN;
1313
-- perform operation in xact that creates and logs xid, but isn't decoded
1414
SELECT * FROM xact_test FOR UPDATE;
@@ -33,6 +33,28 @@ SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'inc
3333
COMMIT
3434
(6 rows)
3535

36+
-- bug #14279, do not propagate null snapshot from subtransaction
37+
BEGIN;
38+
-- first insert
39+
INSERT INTO xact_test VALUES ('main-txn');
40+
SAVEPOINT foo;
41+
-- now perform operation in subxact that creates and logs xid, but isn't decoded
42+
SELECT 1 FROM xact_test FOR UPDATE LIMIT 1;
43+
?column?
44+
----------
45+
1
46+
(1 row)
47+
48+
COMMIT;
49+
-- and now show those changes
50+
SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1');
51+
data
52+
-------------------------------------------------------
53+
BEGIN
54+
table public.xact_test: INSERT: data[text]:'main-txn'
55+
COMMIT
56+
(3 rows)
57+
3658
DROP TABLE xact_test;
3759
SELECT pg_drop_replication_slot('regression_slot');
3860
pg_drop_replication_slot

contrib/test_decoding/sql/xact.sql

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ SET synchronous_commit = on;
33

44
SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot', 'test_decoding');
55

6-
-- bug #13844, xids in non-decoded records need to be inspected
76
CREATE TABLE xact_test(data text);
87
INSERT INTO xact_test VALUES ('before-test');
98

9+
-- bug #13844, xids in non-decoded records need to be inspected
1010
BEGIN;
1111
-- perform operation in xact that creates and logs xid, but isn't decoded
1212
SELECT * FROM xact_test FOR UPDATE;
@@ -17,6 +17,17 @@ COMMIT;
1717
-- and now show those changes
1818
SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1');
1919

20+
-- bug #14279, do not propagate null snapshot from subtransaction
21+
BEGIN;
22+
-- first insert
23+
INSERT INTO xact_test VALUES ('main-txn');
24+
SAVEPOINT foo;
25+
-- now perform operation in subxact that creates and logs xid, but isn't decoded
26+
SELECT 1 FROM xact_test FOR UPDATE LIMIT 1;
27+
COMMIT;
28+
-- and now show those changes
29+
SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1');
30+
2031
DROP TABLE xact_test;
2132

2233
SELECT pg_drop_replication_slot('regression_slot');

src/backend/replication/logical/reorderbuffer.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -807,13 +807,14 @@ ReorderBufferCommitChild(ReorderBuffer *rb, TransactionId xid,
807807
elog(ERROR, "subxact logged without previous toplevel record");
808808

809809
/*
810-
* Pass the our base snapshot to the parent transaction if it doesn't have
810+
* Pass our base snapshot to the parent transaction if it doesn't have
811811
* one, or ours is older. That can happen if there are no changes in the
812812
* toplevel transaction but in one of the child transactions. This allows
813-
* the parent to simply use it's base snapshot initially.
813+
* the parent to simply use its base snapshot initially.
814814
*/
815-
if (txn->base_snapshot == NULL ||
816-
txn->base_snapshot_lsn > subtxn->base_snapshot_lsn)
815+
if (subtxn->base_snapshot != NULL &&
816+
(txn->base_snapshot == NULL ||
817+
txn->base_snapshot_lsn > subtxn->base_snapshot_lsn))
817818
{
818819
txn->base_snapshot = subtxn->base_snapshot;
819820
txn->base_snapshot_lsn = subtxn->base_snapshot_lsn;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy