|
| 1 | +# Test decoding of subtransactions whose top-transaction is before restart |
| 2 | +# point. Such transactions won't be streamed as we stream only complete |
| 3 | +# transactions, but it is good to test that they don't cause any problem. |
| 4 | + |
| 5 | +setup |
| 6 | +{ |
| 7 | + SELECT 'init' FROM pg_create_logical_replication_slot('isolation_slot', 'test_decoding'); -- must be first write in xact |
| 8 | + CREATE TABLE harvest(apples integer); |
| 9 | + CREATE OR REPLACE FUNCTION subxacts() returns void as $$ |
| 10 | + BEGIN |
| 11 | + FOR i in 1 .. 128 LOOP |
| 12 | + BEGIN |
| 13 | + INSERT INTO harvest VALUES (42); |
| 14 | + EXCEPTION |
| 15 | + WHEN OTHERS THEN |
| 16 | + RAISE; |
| 17 | + END; |
| 18 | + END LOOP; |
| 19 | + END; $$LANGUAGE 'plpgsql'; |
| 20 | +} |
| 21 | + |
| 22 | +teardown |
| 23 | +{ |
| 24 | + DROP TABLE IF EXISTS harvest; |
| 25 | + SELECT 'stop' FROM pg_drop_replication_slot('isolation_slot'); |
| 26 | +} |
| 27 | + |
| 28 | +session "s0" |
| 29 | +setup { SET synchronous_commit=on; } |
| 30 | +step "s0_begin" { BEGIN; } |
| 31 | +step "s0_first_subxact" { |
| 32 | + DO LANGUAGE plpgsql $$ |
| 33 | + BEGIN |
| 34 | + BEGIN |
| 35 | + INSERT INTO harvest VALUES (41); |
| 36 | + EXCEPTION WHEN OTHERS THEN RAISE; |
| 37 | + END; |
| 38 | + END $$; |
| 39 | +} |
| 40 | +step "s0_many_subxacts" { select subxacts(); } |
| 41 | +step "s0_commit" { COMMIT; } |
| 42 | + |
| 43 | +session "s1" |
| 44 | +setup { SET synchronous_commit=on; } |
| 45 | +step "s1_begin" { BEGIN; } |
| 46 | +step "s1_dml" { INSERT INTO harvest VALUES (43); } |
| 47 | +step "s1_commit" { COMMIT; } |
| 48 | + |
| 49 | +session "s2" |
| 50 | +setup { SET synchronous_commit=on; } |
| 51 | +step "s2_checkpoint" { CHECKPOINT; } |
| 52 | +step "s2_get_changes" { SELECT data FROM pg_logical_slot_get_changes('isolation_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1'); } |
| 53 | +step "s2_get_changes_suppress_output" { SELECT null n FROM pg_logical_slot_get_changes('isolation_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1') GROUP BY n; } |
| 54 | + |
| 55 | +# The first checkpoint establishes the potential restart point (aka |
| 56 | +# restart_lsn) for the slot after the initial subxact. The second checkpoint |
| 57 | +# followed by get_changes will ensure that the potential restart point will |
| 58 | +# become the actual restart point. We do get_changes twice because if one |
| 59 | +# more xl_running_xacts record had slipped before our s0_commit, then the |
| 60 | +# potential restart point won't become actual restart point. The s1's open |
| 61 | +# transaction till get_changes holds the potential restart point to our first |
| 62 | +# checkpoint location. |
| 63 | +permutation "s0_begin" "s0_first_subxact" "s2_checkpoint" "s1_begin" "s1_dml" "s0_many_subxacts" "s0_commit" "s2_checkpoint" "s2_get_changes_suppress_output" "s2_get_changes_suppress_output" "s1_commit" "s2_get_changes" |
0 commit comments