From 0e11b2c2e72df0009ca7d3bd8c6f7e1a05e1773d Mon Sep 17 00:00:00 2001 From: Amul Sul Date: Tue, 13 Feb 2018 12:37:33 +0530 Subject: [PATCH 2/2] isolation tests v5 v5: - As per Andres Freund suggestion[4], added test for ON CONFLICT DO NOTHING - TODO: 1. Cannot add ON CONFLICT DO UPDATE test since it's not supported for partitioned table, may be after proposed patch[5] v4: - Rebased on Invalidate ip_blkid v5. v3: - Rebase on "UPDATE of partition key v35" patch[2] and latest maste head[3]. v2: - Error message changed. - Can't add isolation test[1] for RelationFindReplTupleByIndex & RelationFindReplTupleSeq - In ExecOnConflictUpdate, the error report is converted to assert check. v1: Added isolation tests to hit an error in the following functions: 1. ExecUpdate -> specs/partition-key-update-1 2. ExecDelete -> specs/partition-key-update-1 3. GetTupleForTrigger -> specs/partition-key-update-2 4. ExecLockRows -> specs/partition-key-update-3 ------------ References: ------------ 1] https://postgr.es/m/CA+TgmoYsMRo2PHFTGUFifv4ZSCZ9LNJASbOyb=9it2=UA4j4vw@mail.gmail.com 2] https://postgr.es/m/CAJ3gD9dixkkMzNnnP1CaZ1H17-U17ok_sVbjZZo+wnB=rJH6yg@mail.gmail.com 3] Commit id bdb70c12b3a2e69eec6e51411df60d9f43ecc841 4] https://postgr.es/m/20180305232353.gpue7jldnm4bjf4i@alap3.anarazel.de 5] https://postgr.es/m/20180228004602.cwdyralmg5ejdqkq@alvherre.pgsql --- .../isolation/expected/partition-key-update-1.out | 35 ++++++ .../isolation/expected/partition-key-update-2.out | 18 +++ .../isolation/expected/partition-key-update-3.out | 8 ++ .../isolation/expected/partition-key-update-4.out | 29 +++++ .../isolation/expected/partition-key-update-5.out | 139 +++++++++++++++++++++ src/test/isolation/isolation_schedule | 5 + .../isolation/specs/partition-key-update-1.spec | 37 ++++++ .../isolation/specs/partition-key-update-2.spec | 39 ++++++ .../isolation/specs/partition-key-update-3.spec | 30 +++++ .../isolation/specs/partition-key-update-4.spec | 45 +++++++ .../isolation/specs/partition-key-update-5.spec | 44 +++++++ 11 files changed, 429 insertions(+) create mode 100644 src/test/isolation/expected/partition-key-update-1.out create mode 100644 src/test/isolation/expected/partition-key-update-2.out create mode 100644 src/test/isolation/expected/partition-key-update-3.out create mode 100644 src/test/isolation/expected/partition-key-update-4.out create mode 100644 src/test/isolation/expected/partition-key-update-5.out create mode 100644 src/test/isolation/specs/partition-key-update-1.spec create mode 100644 src/test/isolation/specs/partition-key-update-2.spec create mode 100644 src/test/isolation/specs/partition-key-update-3.spec create mode 100644 src/test/isolation/specs/partition-key-update-4.spec create mode 100644 src/test/isolation/specs/partition-key-update-5.spec diff --git a/src/test/isolation/expected/partition-key-update-1.out b/src/test/isolation/expected/partition-key-update-1.out new file mode 100644 index 0000000000..56bf4450b0 --- /dev/null +++ b/src/test/isolation/expected/partition-key-update-1.out @@ -0,0 +1,35 @@ +Parsed test spec with 2 sessions + +starting permutation: s1u s1c s2u +step s1u: UPDATE foo SET a=2 WHERE a=1; +step s1c: COMMIT; +step s2u: UPDATE foo SET b='EFG' WHERE a=1; + +starting permutation: s1u s2u s1c +step s1u: UPDATE foo SET a=2 WHERE a=1; +step s2u: UPDATE foo SET b='EFG' WHERE a=1; +step s1c: COMMIT; +step s2u: <... completed> +error in steps s1c s2u: ERROR: tuple to be updated was already moved to another partition due to concurrent update + +starting permutation: s2u s1u s1c +step s2u: UPDATE foo SET b='EFG' WHERE a=1; +step s1u: UPDATE foo SET a=2 WHERE a=1; +step s1c: COMMIT; + +starting permutation: s1u s1c s2d +step s1u: UPDATE foo SET a=2 WHERE a=1; +step s1c: COMMIT; +step s2d: DELETE FROM foo WHERE a=1; + +starting permutation: s1u s2d s1c +step s1u: UPDATE foo SET a=2 WHERE a=1; +step s2d: DELETE FROM foo WHERE a=1; +step s1c: COMMIT; +step s2d: <... completed> +error in steps s1c s2d: ERROR: tuple to be updated was already moved to another partition due to concurrent update + +starting permutation: s2d s1u s1c +step s2d: DELETE FROM foo WHERE a=1; +step s1u: UPDATE foo SET a=2 WHERE a=1; +step s1c: COMMIT; diff --git a/src/test/isolation/expected/partition-key-update-2.out b/src/test/isolation/expected/partition-key-update-2.out new file mode 100644 index 0000000000..195ec4cedf --- /dev/null +++ b/src/test/isolation/expected/partition-key-update-2.out @@ -0,0 +1,18 @@ +Parsed test spec with 2 sessions + +starting permutation: s1u s1c s2u +step s1u: UPDATE foo SET b='EFG' WHERE a=1; +step s1c: COMMIT; +step s2u: UPDATE foo SET b='XYZ' WHERE a=1; + +starting permutation: s1u s2u s1c +step s1u: UPDATE foo SET b='EFG' WHERE a=1; +step s2u: UPDATE foo SET b='XYZ' WHERE a=1; +step s1c: COMMIT; +step s2u: <... completed> +error in steps s1c s2u: ERROR: tuple to be locked was already moved to another partition due to concurrent update + +starting permutation: s2u s1u s1c +step s2u: UPDATE foo SET b='XYZ' WHERE a=1; +step s1u: UPDATE foo SET b='EFG' WHERE a=1; +step s1c: COMMIT; diff --git a/src/test/isolation/expected/partition-key-update-3.out b/src/test/isolation/expected/partition-key-update-3.out new file mode 100644 index 0000000000..1922bdce46 --- /dev/null +++ b/src/test/isolation/expected/partition-key-update-3.out @@ -0,0 +1,8 @@ +Parsed test spec with 2 sessions + +starting permutation: s1u3 s2i s1c +step s1u3: UPDATE foo_r SET a=11 WHERE a=7 AND b = 'ABC'; +step s2i: INSERT INTO bar VALUES(7); +step s1c: COMMIT; +step s2i: <... completed> +error in steps s1c s2i: ERROR: tuple to be locked was already moved to another partition due to concurrent update diff --git a/src/test/isolation/expected/partition-key-update-4.out b/src/test/isolation/expected/partition-key-update-4.out new file mode 100644 index 0000000000..363de0d69c --- /dev/null +++ b/src/test/isolation/expected/partition-key-update-4.out @@ -0,0 +1,29 @@ +Parsed test spec with 3 sessions + +starting permutation: s1u s2donothing s3donothing s1c s2c s3select s3c +step s1u: UPDATE foo SET a=2, b=b || ' -> moved by session-1' WHERE a=1; +step s2donothing: INSERT INTO foo VALUES(1, 'session-2 donothing') ON CONFLICT DO NOTHING; +step s3donothing: INSERT INTO foo VALUES(2, 'session-3 donothing') ON CONFLICT DO NOTHING; +step s1c: COMMIT; +step s2donothing: <... completed> +step s3donothing: <... completed> +step s2c: COMMIT; +step s3select: SELECT * FROM foo ORDER BY a; +a b + +1 session-2 donothing +2 initial tuple -> moved by session-1 +step s3c: COMMIT; + +starting permutation: s2donothing s1u s3donothing s1c s2c s3select s3c +step s2donothing: INSERT INTO foo VALUES(1, 'session-2 donothing') ON CONFLICT DO NOTHING; +step s1u: UPDATE foo SET a=2, b=b || ' -> moved by session-1' WHERE a=1; +step s3donothing: INSERT INTO foo VALUES(2, 'session-3 donothing') ON CONFLICT DO NOTHING; +step s1c: COMMIT; +step s3donothing: <... completed> +step s2c: COMMIT; +step s3select: SELECT * FROM foo ORDER BY a; +a b + +2 initial tuple -> moved by session-1 +step s3c: COMMIT; diff --git a/src/test/isolation/expected/partition-key-update-5.out b/src/test/isolation/expected/partition-key-update-5.out new file mode 100644 index 0000000000..42dfe64ad3 --- /dev/null +++ b/src/test/isolation/expected/partition-key-update-5.out @@ -0,0 +1,139 @@ +Parsed test spec with 3 sessions + +starting permutation: s2beginrr s3beginrr s1u s2donothing s1c s2c s3donothing s3c s2select +step s2beginrr: BEGIN ISOLATION LEVEL REPEATABLE READ; +step s3beginrr: BEGIN ISOLATION LEVEL REPEATABLE READ; +step s1u: UPDATE foo SET a=2, b=b || ' -> moved by session-1' WHERE a=1; +step s2donothing: INSERT INTO foo VALUES(1, 'session-2 donothing') ON CONFLICT DO NOTHING; +step s1c: COMMIT; +step s2donothing: <... completed> +step s2c: COMMIT; +step s3donothing: INSERT INTO foo VALUES(2, 'session-3 donothing'), (2, 'session-3 donothing2') ON CONFLICT DO NOTHING; +step s3c: COMMIT; +step s2select: SELECT * FROM foo ORDER BY a; +a b + +1 session-2 donothing +2 initial tuple -> moved by session-1 + +starting permutation: s2beginrr s3beginrr s1u s3donothing s1c s3c s2donothing s2c s2select +step s2beginrr: BEGIN ISOLATION LEVEL REPEATABLE READ; +step s3beginrr: BEGIN ISOLATION LEVEL REPEATABLE READ; +step s1u: UPDATE foo SET a=2, b=b || ' -> moved by session-1' WHERE a=1; +step s3donothing: INSERT INTO foo VALUES(2, 'session-3 donothing'), (2, 'session-3 donothing2') ON CONFLICT DO NOTHING; +step s1c: COMMIT; +step s3donothing: <... completed> +error in steps s1c s3donothing: ERROR: could not serialize access due to concurrent update +step s3c: COMMIT; +step s2donothing: INSERT INTO foo VALUES(1, 'session-2 donothing') ON CONFLICT DO NOTHING; +step s2c: COMMIT; +step s2select: SELECT * FROM foo ORDER BY a; +a b + +1 session-2 donothing +2 initial tuple -> moved by session-1 + +starting permutation: s2beginrr s3beginrr s1u s2donothing s3donothing s1c s2c s3c s2select +step s2beginrr: BEGIN ISOLATION LEVEL REPEATABLE READ; +step s3beginrr: BEGIN ISOLATION LEVEL REPEATABLE READ; +step s1u: UPDATE foo SET a=2, b=b || ' -> moved by session-1' WHERE a=1; +step s2donothing: INSERT INTO foo VALUES(1, 'session-2 donothing') ON CONFLICT DO NOTHING; +step s3donothing: INSERT INTO foo VALUES(2, 'session-3 donothing'), (2, 'session-3 donothing2') ON CONFLICT DO NOTHING; +step s1c: COMMIT; +step s2donothing: <... completed> +step s3donothing: <... completed> +error in steps s1c s2donothing s3donothing: ERROR: could not serialize access due to concurrent update +step s2c: COMMIT; +step s3c: COMMIT; +step s2select: SELECT * FROM foo ORDER BY a; +a b + +1 session-2 donothing +2 initial tuple -> moved by session-1 + +starting permutation: s2beginrr s3beginrr s1u s3donothing s2donothing s1c s3c s2c s2select +step s2beginrr: BEGIN ISOLATION LEVEL REPEATABLE READ; +step s3beginrr: BEGIN ISOLATION LEVEL REPEATABLE READ; +step s1u: UPDATE foo SET a=2, b=b || ' -> moved by session-1' WHERE a=1; +step s3donothing: INSERT INTO foo VALUES(2, 'session-3 donothing'), (2, 'session-3 donothing2') ON CONFLICT DO NOTHING; +step s2donothing: INSERT INTO foo VALUES(1, 'session-2 donothing') ON CONFLICT DO NOTHING; +step s1c: COMMIT; +step s3donothing: <... completed> +step s2donothing: <... completed> +error in steps s1c s3donothing s2donothing: ERROR: could not serialize access due to concurrent update +step s3c: COMMIT; +step s2c: COMMIT; +step s2select: SELECT * FROM foo ORDER BY a; +a b + +1 session-2 donothing +2 initial tuple -> moved by session-1 + +starting permutation: s2begins s3begins s1u s2donothing s1c s2c s3donothing s3c s2select +step s2begins: BEGIN ISOLATION LEVEL SERIALIZABLE; +step s3begins: BEGIN ISOLATION LEVEL SERIALIZABLE; +step s1u: UPDATE foo SET a=2, b=b || ' -> moved by session-1' WHERE a=1; +step s2donothing: INSERT INTO foo VALUES(1, 'session-2 donothing') ON CONFLICT DO NOTHING; +step s1c: COMMIT; +step s2donothing: <... completed> +step s2c: COMMIT; +step s3donothing: INSERT INTO foo VALUES(2, 'session-3 donothing'), (2, 'session-3 donothing2') ON CONFLICT DO NOTHING; +step s3c: COMMIT; +step s2select: SELECT * FROM foo ORDER BY a; +a b + +1 session-2 donothing +2 initial tuple -> moved by session-1 + +starting permutation: s2begins s3begins s1u s3donothing s1c s3c s2donothing s2c s2select +step s2begins: BEGIN ISOLATION LEVEL SERIALIZABLE; +step s3begins: BEGIN ISOLATION LEVEL SERIALIZABLE; +step s1u: UPDATE foo SET a=2, b=b || ' -> moved by session-1' WHERE a=1; +step s3donothing: INSERT INTO foo VALUES(2, 'session-3 donothing'), (2, 'session-3 donothing2') ON CONFLICT DO NOTHING; +step s1c: COMMIT; +step s3donothing: <... completed> +error in steps s1c s3donothing: ERROR: could not serialize access due to concurrent update +step s3c: COMMIT; +step s2donothing: INSERT INTO foo VALUES(1, 'session-2 donothing') ON CONFLICT DO NOTHING; +step s2c: COMMIT; +step s2select: SELECT * FROM foo ORDER BY a; +a b + +1 session-2 donothing +2 initial tuple -> moved by session-1 + +starting permutation: s2begins s3begins s1u s2donothing s3donothing s1c s2c s3c s2select +step s2begins: BEGIN ISOLATION LEVEL SERIALIZABLE; +step s3begins: BEGIN ISOLATION LEVEL SERIALIZABLE; +step s1u: UPDATE foo SET a=2, b=b || ' -> moved by session-1' WHERE a=1; +step s2donothing: INSERT INTO foo VALUES(1, 'session-2 donothing') ON CONFLICT DO NOTHING; +step s3donothing: INSERT INTO foo VALUES(2, 'session-3 donothing'), (2, 'session-3 donothing2') ON CONFLICT DO NOTHING; +step s1c: COMMIT; +step s2donothing: <... completed> +step s3donothing: <... completed> +error in steps s1c s2donothing s3donothing: ERROR: could not serialize access due to concurrent update +step s2c: COMMIT; +step s3c: COMMIT; +step s2select: SELECT * FROM foo ORDER BY a; +a b + +1 session-2 donothing +2 initial tuple -> moved by session-1 + +starting permutation: s2begins s3begins s1u s3donothing s2donothing s1c s3c s2c s2select +step s2begins: BEGIN ISOLATION LEVEL SERIALIZABLE; +step s3begins: BEGIN ISOLATION LEVEL SERIALIZABLE; +step s1u: UPDATE foo SET a=2, b=b || ' -> moved by session-1' WHERE a=1; +step s3donothing: INSERT INTO foo VALUES(2, 'session-3 donothing'), (2, 'session-3 donothing2') ON CONFLICT DO NOTHING; +step s2donothing: INSERT INTO foo VALUES(1, 'session-2 donothing') ON CONFLICT DO NOTHING; +step s1c: COMMIT; +step s3donothing: <... completed> +step s2donothing: <... completed> +error in steps s1c s3donothing s2donothing: ERROR: could not serialize access due to concurrent update +step s3c: COMMIT; +step s2c: COMMIT; +step s2select: SELECT * FROM foo ORDER BY a; +a b + +1 session-2 donothing +2 initial tuple -> moved by session-1 diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index 74d7d59546..26f88c50b6 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -66,3 +66,8 @@ test: async-notify test: vacuum-reltuples test: timeouts test: vacuum-concurrent-drop +test: partition-key-update-1 +test: partition-key-update-2 +test: partition-key-update-3 +test: partition-key-update-4 +test: partition-key-update-5 diff --git a/src/test/isolation/specs/partition-key-update-1.spec b/src/test/isolation/specs/partition-key-update-1.spec new file mode 100644 index 0000000000..db76c9a9b5 --- /dev/null +++ b/src/test/isolation/specs/partition-key-update-1.spec @@ -0,0 +1,37 @@ +# Concurrency error from ExecUpdate and ExecDelete. + +# Throw an error to indicate that the targeted row has been already moved to +# another partition in the case of concurrency where a session trying to +# update/delete a row that's locked for a concurrent update by the another +# session cause tuple movement to the another partition due update of partition +# key. + +setup +{ + CREATE TABLE foo (a int, b text) PARTITION BY LIST(a); + CREATE TABLE foo1 PARTITION OF foo FOR VALUES IN (1); + CREATE TABLE foo2 PARTITION OF foo FOR VALUES IN (2); + INSERT INTO foo VALUES (1, 'ABC'); +} + +teardown +{ + DROP TABLE foo; +} + +session "s1" +setup { BEGIN; } +step "s1u" { UPDATE foo SET a=2 WHERE a=1; } +step "s1c" { COMMIT; } + +session "s2" +step "s2u" { UPDATE foo SET b='EFG' WHERE a=1; } +step "s2d" { DELETE FROM foo WHERE a=1; } + +permutation "s1u" "s1c" "s2u" +permutation "s1u" "s2u" "s1c" +permutation "s2u" "s1u" "s1c" + +permutation "s1u" "s1c" "s2d" +permutation "s1u" "s2d" "s1c" +permutation "s2d" "s1u" "s1c" diff --git a/src/test/isolation/specs/partition-key-update-2.spec b/src/test/isolation/specs/partition-key-update-2.spec new file mode 100644 index 0000000000..b09e76ce21 --- /dev/null +++ b/src/test/isolation/specs/partition-key-update-2.spec @@ -0,0 +1,39 @@ +# Concurrency error from GetTupleForTrigger + +# Like partition-key-update-1.spec, throw an error where a session trying to +# update a row that has been moved to another partition due to a concurrent +# update by other seesion. + +setup +{ + CREATE TABLE foo (a int, b text) PARTITION BY LIST(a); + CREATE TABLE foo1 PARTITION OF foo FOR VALUES IN (1); + CREATE TABLE foo2 PARTITION OF foo FOR VALUES IN (2); + INSERT INTO foo VALUES (1, 'ABC'); + CREATE FUNCTION func_foo_mod_a() RETURNS TRIGGER AS $$ + BEGIN + NEW.a = 2; -- This is changing partition key column. + RETURN NEW; + END $$ LANGUAGE PLPGSQL; + CREATE TRIGGER foo_mod_a BEFORE UPDATE ON foo1 + FOR EACH ROW EXECUTE PROCEDURE func_foo_mod_a(); +} + +teardown +{ + DROP TRIGGER foo_mod_a ON foo1; + DROP FUNCTION func_foo_mod_a(); + DROP TABLE foo; +} + +session "s1" +setup { BEGIN; } +step "s1u" { UPDATE foo SET b='EFG' WHERE a=1; } +step "s1c" { COMMIT; } + +session "s2" +step "s2u" { UPDATE foo SET b='XYZ' WHERE a=1; } + +permutation "s1u" "s1c" "s2u" +permutation "s1u" "s2u" "s1c" +permutation "s2u" "s1u" "s1c" diff --git a/src/test/isolation/specs/partition-key-update-3.spec b/src/test/isolation/specs/partition-key-update-3.spec new file mode 100644 index 0000000000..c1f547d9ba --- /dev/null +++ b/src/test/isolation/specs/partition-key-update-3.spec @@ -0,0 +1,30 @@ +# Concurrency error from ExecLockRows + +# Like partition-key-update-1.spec, throw an error where a session trying to +# lock a row that has been moved to another partition due to a concurrent +# update by other seesion. + +setup +{ + CREATE TABLE foo_r (a int, b text) PARTITION BY RANGE(a); + CREATE TABLE foo_r1 PARTITION OF foo_r FOR VALUES FROM (1) TO (10); + CREATE TABLE foo_r2 PARTITION OF foo_r FOR VALUES FROM (10) TO (20); + INSERT INTO foo_r VALUES(7, 'ABC'); + CREATE UNIQUE INDEX foo_r1_a_unique ON foo_r1 (a); + CREATE TABLE bar (a int REFERENCES foo_r1(a)); +} + +teardown +{ + DROP TABLE bar, foo_r; +} + +session "s1" +setup { BEGIN; } +step "s1u3" { UPDATE foo_r SET a=11 WHERE a=7 AND b = 'ABC'; } +step "s1c" { COMMIT; } + +session "s2" +step "s2i" { INSERT INTO bar VALUES(7); } + +permutation "s1u3" "s2i" "s1c" diff --git a/src/test/isolation/specs/partition-key-update-4.spec b/src/test/isolation/specs/partition-key-update-4.spec new file mode 100644 index 0000000000..48ebe6c7d5 --- /dev/null +++ b/src/test/isolation/specs/partition-key-update-4.spec @@ -0,0 +1,45 @@ +# Concurrent update of a partition key and INSERT...ON CONFLICT DO NOTHING test +# +# This test tries to expose problems with the interaction between concurrent +# sessions during an update of the partition key and INSERT...ON CONFLICT DO +# NOTHING on a partitioned table. +# +# The convention here is that session 1 moves row from one partition to +# another due update of the partition key and session 2 always ends up +# inserting, and session 3 always ends up doing nothing. +# +# Note: This test is slightly resemble to insert-conflict-do-nothing test. + +setup +{ + CREATE TABLE foo (a int primary key, b text) PARTITION BY LIST(a); + CREATE TABLE foo1 PARTITION OF foo FOR VALUES IN (1); + CREATE TABLE foo2 PARTITION OF foo FOR VALUES IN (2); + INSERT INTO foo VALUES (1, 'initial tuple'); +} + +teardown +{ + DROP TABLE foo; +} + +session "s1" +setup { BEGIN; } +step "s1u" { UPDATE foo SET a=2, b=b || ' -> moved by session-1' WHERE a=1; } +step "s1c" { COMMIT; } + +session "s2" +setup { BEGIN ISOLATION LEVEL READ COMMITTED; } +step "s2donothing" { INSERT INTO foo VALUES(1, 'session-2 donothing') ON CONFLICT DO NOTHING; } +step "s2c" { COMMIT; } + +session "s3" +setup { BEGIN ISOLATION LEVEL READ COMMITTED; } +step "s3donothing" { INSERT INTO foo VALUES(2, 'session-3 donothing') ON CONFLICT DO NOTHING; } +step "s3select" { SELECT * FROM foo ORDER BY a; } +step "s3c" { COMMIT; } + +# Regular case where one session block-waits on another to determine if it +# should proceed with an insert or do nothing. +permutation "s1u" "s2donothing" "s3donothing" "s1c" "s2c" "s3select" "s3c" +permutation "s2donothing" "s1u" "s3donothing" "s1c" "s2c" "s3select" "s3c" diff --git a/src/test/isolation/specs/partition-key-update-5.spec b/src/test/isolation/specs/partition-key-update-5.spec new file mode 100644 index 0000000000..7f9a06913a --- /dev/null +++ b/src/test/isolation/specs/partition-key-update-5.spec @@ -0,0 +1,44 @@ +# Concurrent update of a partition key and INSERT...ON CONFLICT DO NOTHING +# test on partitioned table with multiple rows in higher isolation levels. +# +# Note: This test is resemble to insert-conflict-do-nothing-2 test + +setup +{ + CREATE TABLE foo (a int primary key, b text) PARTITION BY LIST(a); + CREATE TABLE foo1 PARTITION OF foo FOR VALUES IN (1); + CREATE TABLE foo2 PARTITION OF foo FOR VALUES IN (2); + INSERT INTO foo VALUES (1, 'initial tuple'); +} + +teardown +{ + DROP TABLE foo; +} + +session "s1" +setup { BEGIN; } +step "s1u" { UPDATE foo SET a=2, b=b || ' -> moved by session-1' WHERE a=1; } +step "s1c" { COMMIT; } + +session "s2" +step "s2beginrr" { BEGIN ISOLATION LEVEL REPEATABLE READ; } +step "s2begins" { BEGIN ISOLATION LEVEL SERIALIZABLE; } +step "s2donothing" { INSERT INTO foo VALUES(1, 'session-2 donothing') ON CONFLICT DO NOTHING; } +step "s2c" { COMMIT; } +step "s2select" { SELECT * FROM foo ORDER BY a; } + +session "s3" +step "s3beginrr" { BEGIN ISOLATION LEVEL REPEATABLE READ; } +step "s3begins" { BEGIN ISOLATION LEVEL SERIALIZABLE; } +step "s3donothing" { INSERT INTO foo VALUES(2, 'session-3 donothing'), (2, 'session-3 donothing2') ON CONFLICT DO NOTHING; } +step "s3c" { COMMIT; } + +permutation "s2beginrr" "s3beginrr" "s1u" "s2donothing" "s1c" "s2c" "s3donothing" "s3c" "s2select" +permutation "s2beginrr" "s3beginrr" "s1u" "s3donothing" "s1c" "s3c" "s2donothing" "s2c" "s2select" +permutation "s2beginrr" "s3beginrr" "s1u" "s2donothing" "s3donothing" "s1c" "s2c" "s3c" "s2select" +permutation "s2beginrr" "s3beginrr" "s1u" "s3donothing" "s2donothing" "s1c" "s3c" "s2c" "s2select" +permutation "s2begins" "s3begins" "s1u" "s2donothing" "s1c" "s2c" "s3donothing" "s3c" "s2select" +permutation "s2begins" "s3begins" "s1u" "s3donothing" "s1c" "s3c" "s2donothing" "s2c" "s2select" +permutation "s2begins" "s3begins" "s1u" "s2donothing" "s3donothing" "s1c" "s2c" "s3c" "s2select" +permutation "s2begins" "s3begins" "s1u" "s3donothing" "s2donothing" "s1c" "s3c" "s2c" "s2select" -- 2.14.1