Skip to content

Commit 094bdf2

Browse files
committed
patch applied
1 parent a6f22e8 commit 094bdf2

File tree

16 files changed

+1242
-81
lines changed

16 files changed

+1242
-81
lines changed

contrib/test_decoding/expected/prepared.out

Lines changed: 207 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,69 +6,254 @@ SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot', 'test_d
66
init
77
(1 row)
88

9-
CREATE TABLE test_prepared1(id int);
10-
CREATE TABLE test_prepared2(id int);
9+
SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot_2pc', 'test_decoding');
10+
?column?
11+
----------
12+
init
13+
(1 row)
14+
15+
CREATE TABLE test_prepared1(id integer primary key);
16+
CREATE TABLE test_prepared2(id integer primary key);
17+
-- Reused queries
18+
\set get_no2pc 'SELECT data FROM pg_logical_slot_get_changes(''regression_slot_2pc'', NULL, NULL, ''include-xids'', ''0'', ''skip-empty-xacts'', ''1'');'
19+
\set get_with2pc 'SELECT data FROM pg_logical_slot_get_changes(''regression_slot'', NULL, NULL, ''include-xids'', ''0'', ''skip-empty-xacts'', ''1'', ''twophase-decoding'', ''1'');'
20+
\set get_with2pc_nofilter 'SELECT data FROM pg_logical_slot_get_changes(''regression_slot'', NULL, NULL, ''include-xids'', ''0'', ''skip-empty-xacts'', ''1'', ''twophase-decoding'', ''1'', ''twophase-decode-with-catalog-changes'', ''1'');'
1121
-- test simple successful use of a prepared xact
1222
BEGIN;
1323
INSERT INTO test_prepared1 VALUES (1);
1424
PREPARE TRANSACTION 'test_prepared#1';
25+
:get_with2pc
26+
data
27+
----------------------------------------------------
28+
BEGIN
29+
table public.test_prepared1: INSERT: id[integer]:1
30+
PREPARE TRANSACTION 'test_prepared#1'
31+
(3 rows)
32+
33+
:get_no2pc
34+
data
35+
------
36+
(0 rows)
37+
1538
COMMIT PREPARED 'test_prepared#1';
39+
:get_with2pc
40+
data
41+
------
42+
(0 rows)
43+
44+
:get_no2pc
45+
data
46+
----------------------------------------------------
47+
BEGIN
48+
table public.test_prepared1: INSERT: id[integer]:1
49+
COMMIT
50+
(3 rows)
51+
1652
INSERT INTO test_prepared1 VALUES (2);
1753
-- test abort of a prepared xact
1854
BEGIN;
1955
INSERT INTO test_prepared1 VALUES (3);
2056
PREPARE TRANSACTION 'test_prepared#2';
57+
:get_no2pc
58+
data
59+
----------------------------------------------------
60+
BEGIN
61+
table public.test_prepared1: INSERT: id[integer]:2
62+
COMMIT
63+
(3 rows)
64+
65+
:get_with2pc
66+
data
67+
----------------------------------------------------
68+
BEGIN
69+
table public.test_prepared1: INSERT: id[integer]:2
70+
COMMIT
71+
BEGIN
72+
table public.test_prepared1: INSERT: id[integer]:3
73+
PREPARE TRANSACTION 'test_prepared#2'
74+
(6 rows)
75+
2176
ROLLBACK PREPARED 'test_prepared#2';
77+
:get_no2pc
78+
data
79+
------
80+
(0 rows)
81+
82+
:get_with2pc
83+
data
84+
------
85+
(0 rows)
86+
2287
INSERT INTO test_prepared1 VALUES (4);
2388
-- test prepared xact containing ddl
2489
BEGIN;
2590
INSERT INTO test_prepared1 VALUES (5);
2691
ALTER TABLE test_prepared1 ADD COLUMN data text;
2792
INSERT INTO test_prepared1 VALUES (6, 'frakbar');
2893
PREPARE TRANSACTION 'test_prepared#3';
29-
-- test that we decode correctly while an uncommitted prepared xact
30-
-- with ddl exists.
31-
-- separate table because of the lock from the ALTER
32-
-- this will come before the '5' row above, as this commits before it.
33-
INSERT INTO test_prepared2 VALUES (7);
34-
COMMIT PREPARED 'test_prepared#3';
35-
-- make sure stuff still works
36-
INSERT INTO test_prepared1 VALUES (8);
37-
INSERT INTO test_prepared2 VALUES (9);
38-
-- cleanup
39-
DROP TABLE test_prepared1;
40-
DROP TABLE test_prepared2;
41-
-- show results
42-
SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1');
43-
data
44-
-------------------------------------------------------------------------
94+
SELECT 'test_prepared_1' AS relation, locktype, mode
95+
FROM pg_locks
96+
WHERE locktype = 'relation'
97+
AND relation = 'test_prepared1'::regclass;
98+
relation | locktype | mode
99+
-----------------+----------+---------------------
100+
test_prepared_1 | relation | RowExclusiveLock
101+
test_prepared_1 | relation | AccessExclusiveLock
102+
(2 rows)
103+
104+
:get_no2pc
105+
data
106+
----------------------------------------------------
45107
BEGIN
46-
table public.test_prepared1: INSERT: id[integer]:1
108+
table public.test_prepared1: INSERT: id[integer]:4
47109
COMMIT
110+
(3 rows)
111+
112+
:get_with2pc
113+
data
114+
----------------------------------------------------
48115
BEGIN
49-
table public.test_prepared1: INSERT: id[integer]:2
116+
table public.test_prepared1: INSERT: id[integer]:4
50117
COMMIT
118+
(3 rows)
119+
120+
-- Test that we decode correctly while an uncommitted prepared xact
121+
-- with ddl exists. Our 2pc filter callback will skip decoding of xacts
122+
-- with catalog changes at PREPARE time, so we don't decode it now.
123+
--
124+
-- Use a separate table for the concurrent transaction because the lock from
125+
-- the ALTER will stop us inserting into the other one.
126+
--
127+
-- We should see '7' before '5' in our results since it commits first.
128+
--
129+
INSERT INTO test_prepared2 VALUES (7);
130+
:get_with2pc
131+
data
132+
----------------------------------------------------
51133
BEGIN
52-
table public.test_prepared1: INSERT: id[integer]:4
134+
table public.test_prepared2: INSERT: id[integer]:7
53135
COMMIT
136+
(3 rows)
137+
138+
:get_no2pc
139+
data
140+
----------------------------------------------------
54141
BEGIN
55142
table public.test_prepared2: INSERT: id[integer]:7
56143
COMMIT
144+
(3 rows)
145+
146+
COMMIT PREPARED 'test_prepared#3';
147+
:get_no2pc
148+
data
149+
-------------------------------------------------------------------------
57150
BEGIN
58151
table public.test_prepared1: INSERT: id[integer]:5
59152
table public.test_prepared1: INSERT: id[integer]:6 data[text]:'frakbar'
60153
COMMIT
154+
(4 rows)
155+
156+
:get_with2pc
157+
data
158+
-------------------------------------------------------------------------
159+
BEGIN
160+
table public.test_prepared1: INSERT: id[integer]:5
161+
table public.test_prepared1: INSERT: id[integer]:6 data[text]:'frakbar'
162+
PREPARE TRANSACTION 'test_prepared#3';
163+
COMMIT PREPARED 'test_prepared#3';
164+
(5 rows)
165+
166+
-- make sure stuff still works
167+
INSERT INTO test_prepared1 VALUES (8);
168+
INSERT INTO test_prepared2 VALUES (9);
169+
:get_with2pc
170+
data
171+
--------------------------------------------------------------------
172+
BEGIN
173+
table public.test_prepared1: INSERT: id[integer]:8 data[text]:null
174+
COMMIT
175+
BEGIN
176+
table public.test_prepared2: INSERT: id[integer]:9
177+
COMMIT
178+
(6 rows)
179+
180+
:get_no2pc
181+
data
182+
--------------------------------------------------------------------
61183
BEGIN
62184
table public.test_prepared1: INSERT: id[integer]:8 data[text]:null
63185
COMMIT
64186
BEGIN
65187
table public.test_prepared2: INSERT: id[integer]:9
66188
COMMIT
67-
(22 rows)
189+
(6 rows)
190+
191+
-- If we do something that takes a strong lock on a catalog relation we need to
192+
-- read in order to decode a transaction we deadlock; we can't finish decoding
193+
-- until the lock is released, but we're waiting for decoding to finish so we
194+
-- can make a commit/abort decision.
195+
---
196+
BEGIN;
197+
INSERT INTO test_prepared1 VALUES (10, 'othercol');
198+
CLUSTER test_prepared1 USING test_prepared1_pkey;
199+
INSERT INTO test_prepared1 VALUES (11, 'othercol2');
200+
PREPARE TRANSACTION 'test_prepared_lock';
201+
SELECT 'pg_class' AS relation, locktype, mode
202+
FROM pg_locks
203+
WHERE locktype = 'relation'
204+
AND relation = 'pg_class'::regclass;
205+
relation | locktype | mode
206+
----------+----------+------
207+
(0 rows)
68208

209+
-- Shouldn't see anything with 2pc decoding off
210+
:get_no2pc
211+
data
212+
------
213+
(0 rows)
214+
215+
-- If we try to decode it now we'll deadlock
216+
SET statement_timeout = '10s';
217+
:get_with2pc_nofilter
218+
-- FIXME we expect a timeout here, but it actually works...
219+
ERROR: statement timed out
220+
221+
RESET statement_timeout;
222+
-- we can decode past it by skipping xacts with catalog changes
223+
-- and let it be decoded after COMMIT PREPARED, though.
224+
:get_with2pc
225+
data
226+
------
227+
(0 rows)
228+
229+
COMMIT PREPARED 'test_prepared_lock';
230+
-- Both will work normally after we commit
231+
:get_no2pc
232+
data
233+
----------------------------------------------------------------------------
234+
BEGIN
235+
table public.test_prepared1: INSERT: id[integer]:10 data[text]:'othercol'
236+
table public.test_prepared1: INSERT: id[integer]:11 data[text]:'othercol2'
237+
COMMIT
238+
(4 rows)
239+
240+
:get_with2pc
241+
data
242+
------
243+
(0 rows)
244+
245+
-- cleanup
246+
DROP TABLE test_prepared1;
247+
DROP TABLE test_prepared2;
69248
SELECT pg_drop_replication_slot('regression_slot');
70249
pg_drop_replication_slot
71250
--------------------------
72251

73252
(1 row)
74253

254+
SELECT pg_drop_replication_slot('regression_slot_2pc');
255+
pg_drop_replication_slot
256+
--------------------------
257+
258+
(1 row)
259+
Lines changed: 73 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,36 @@
11
-- predictability
22
SET synchronous_commit = on;
33
SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot', 'test_decoding');
4+
SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot_2pc', 'test_decoding');
45

5-
CREATE TABLE test_prepared1(id int);
6-
CREATE TABLE test_prepared2(id int);
6+
CREATE TABLE test_prepared1(id integer primary key);
7+
CREATE TABLE test_prepared2(id integer primary key);
8+
9+
-- Reused queries
10+
\set get_no2pc 'SELECT data FROM pg_logical_slot_get_changes(''regression_slot_2pc'', NULL, NULL, ''include-xids'', ''0'', ''skip-empty-xacts'', ''1'');'
11+
\set get_with2pc 'SELECT data FROM pg_logical_slot_get_changes(''regression_slot'', NULL, NULL, ''include-xids'', ''0'', ''skip-empty-xacts'', ''1'', ''twophase-decoding'', ''1'');'
12+
\set get_with2pc_nofilter 'SELECT data FROM pg_logical_slot_get_changes(''regression_slot'', NULL, NULL, ''include-xids'', ''0'', ''skip-empty-xacts'', ''1'', ''twophase-decoding'', ''1'', ''twophase-decode-with-catalog-changes'', ''1'');'
713

814
-- test simple successful use of a prepared xact
915
BEGIN;
1016
INSERT INTO test_prepared1 VALUES (1);
1117
PREPARE TRANSACTION 'test_prepared#1';
18+
:get_with2pc
19+
:get_no2pc
1220
COMMIT PREPARED 'test_prepared#1';
21+
:get_with2pc
22+
:get_no2pc
1323
INSERT INTO test_prepared1 VALUES (2);
1424

1525
-- test abort of a prepared xact
1626
BEGIN;
1727
INSERT INTO test_prepared1 VALUES (3);
1828
PREPARE TRANSACTION 'test_prepared#2';
29+
:get_no2pc
30+
:get_with2pc
1931
ROLLBACK PREPARED 'test_prepared#2';
32+
:get_no2pc
33+
:get_with2pc
2034

2135
INSERT INTO test_prepared1 VALUES (4);
2236

@@ -27,24 +41,74 @@ ALTER TABLE test_prepared1 ADD COLUMN data text;
2741
INSERT INTO test_prepared1 VALUES (6, 'frakbar');
2842
PREPARE TRANSACTION 'test_prepared#3';
2943

30-
-- test that we decode correctly while an uncommitted prepared xact
31-
-- with ddl exists.
44+
SELECT 'test_prepared_1' AS relation, locktype, mode
45+
FROM pg_locks
46+
WHERE locktype = 'relation'
47+
AND relation = 'test_prepared1'::regclass;
48+
49+
:get_no2pc
50+
:get_with2pc
3251

33-
-- separate table because of the lock from the ALTER
34-
-- this will come before the '5' row above, as this commits before it.
52+
-- Test that we decode correctly while an uncommitted prepared xact
53+
-- with ddl exists. Our 2pc filter callback will skip decoding of xacts
54+
-- with catalog changes at PREPARE time, so we don't decode it now.
55+
--
56+
-- Use a separate table for the concurrent transaction because the lock from
57+
-- the ALTER will stop us inserting into the other one.
58+
--
59+
-- We should see '7' before '5' in our results since it commits first.
60+
--
3561
INSERT INTO test_prepared2 VALUES (7);
62+
:get_with2pc
63+
:get_no2pc
3664

3765
COMMIT PREPARED 'test_prepared#3';
66+
:get_no2pc
67+
:get_with2pc
3868

3969
-- make sure stuff still works
4070
INSERT INTO test_prepared1 VALUES (8);
4171
INSERT INTO test_prepared2 VALUES (9);
72+
:get_with2pc
73+
:get_no2pc
74+
75+
-- If we do something that takes a strong lock on a catalog relation we need to
76+
-- read in order to decode a transaction we deadlock; we can't finish decoding
77+
-- until the lock is released, but we're waiting for decoding to finish so we
78+
-- can make a commit/abort decision.
79+
---
80+
BEGIN;
81+
INSERT INTO test_prepared1 VALUES (10, 'othercol');
82+
CLUSTER test_prepared1 USING test_prepared1_pkey;
83+
INSERT INTO test_prepared1 VALUES (11, 'othercol2');
84+
PREPARE TRANSACTION 'test_prepared_lock';
85+
86+
SELECT 'pg_class' AS relation, locktype, mode
87+
FROM pg_locks
88+
WHERE locktype = 'relation'
89+
AND relation = 'pg_class'::regclass;
90+
91+
-- Shouldn't see anything with 2pc decoding off
92+
:get_no2pc
93+
94+
-- If we try to decode it now we'll deadlock
95+
SET statement_timeout = '10s';
96+
:get_with2pc_nofilter
97+
RESET statement_timeout;
98+
99+
-- we can decode past it by skipping xacts with catalog changes
100+
-- and let it be decoded after COMMIT PREPARED, though.
101+
:get_with2pc
102+
103+
COMMIT PREPARED 'test_prepared_lock';
104+
105+
-- Both will work normally after we commit
106+
:get_no2pc
107+
:get_with2pc
42108

43109
-- cleanup
44110
DROP TABLE test_prepared1;
45111
DROP TABLE test_prepared2;
46112

47-
-- show results
48-
SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1');
49-
50113
SELECT pg_drop_replication_slot('regression_slot');
114+
SELECT pg_drop_replication_slot('regression_slot_2pc');

0 commit comments

Comments
 (0)