aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/isolation/expected/partition-key-update-4.out60
-rw-r--r--src/test/isolation/isolation_schedule1
-rw-r--r--src/test/isolation/specs/partition-key-update-4.spec76
3 files changed, 137 insertions, 0 deletions
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 00000000000..774a7faf6ce
--- /dev/null
+++ b/src/test/isolation/expected/partition-key-update-4.out
@@ -0,0 +1,60 @@
+Parsed test spec with 2 sessions
+
+starting permutation: s1b s2b s2u1 s1u s2c s1c s1s
+step s1b: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2b: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2u1: UPDATE foo SET b = b || ' update2' WHERE a = 1;
+step s1u: UPDATE foo SET a = a + 1, b = b || ' update1' WHERE b like '%ABC%'; <waiting ...>
+step s2c: COMMIT;
+step s1u: <... completed>
+step s1c: COMMIT;
+step s1s: SELECT tableoid::regclass, * FROM foo ORDER BY a;
+tableoid a b
+
+foo2 2 ABC update2 update1
+
+starting permutation: s1b s2b s2ut1 s1ut s2c s1c s1st s1stl
+step s1b: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2b: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2ut1: UPDATE footrg SET b = b || ' update2' WHERE a = 1;
+step s1ut: UPDATE footrg SET a = a + 1, b = b || ' update1' WHERE b like '%ABC%'; <waiting ...>
+step s2c: COMMIT;
+step s1ut: <... completed>
+step s1c: COMMIT;
+step s1st: SELECT tableoid::regclass, * FROM footrg ORDER BY a;
+tableoid a b
+
+footrg2 2 ABC update2 update1
+step s1stl: SELECT * FROM triglog ORDER BY a;
+a b
+
+1 ABC update2 trigger
+
+starting permutation: s1b s2b s2u2 s1u s2c s1c s1s
+step s1b: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2b: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2u2: UPDATE foo SET b = 'EFG' WHERE a = 1;
+step s1u: UPDATE foo SET a = a + 1, b = b || ' update1' WHERE b like '%ABC%'; <waiting ...>
+step s2c: COMMIT;
+step s1u: <... completed>
+step s1c: COMMIT;
+step s1s: SELECT tableoid::regclass, * FROM foo ORDER BY a;
+tableoid a b
+
+foo1 1 EFG
+
+starting permutation: s1b s2b s2ut2 s1ut s2c s1c s1st s1stl
+step s1b: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2b: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2ut2: UPDATE footrg SET b = 'EFG' WHERE a = 1;
+step s1ut: UPDATE footrg SET a = a + 1, b = b || ' update1' WHERE b like '%ABC%'; <waiting ...>
+step s2c: COMMIT;
+step s1ut: <... completed>
+step s1c: COMMIT;
+step s1st: SELECT tableoid::regclass, * FROM footrg ORDER BY a;
+tableoid a b
+
+footrg1 1 EFG
+step s1stl: SELECT * FROM triglog ORDER BY a;
+a b
+
diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule
index 0e997215a80..d5594e80e23 100644
--- a/src/test/isolation/isolation_schedule
+++ b/src/test/isolation/isolation_schedule
@@ -74,4 +74,5 @@ test: predicate-gin-nomatch
test: partition-key-update-1
test: partition-key-update-2
test: partition-key-update-3
+test: partition-key-update-4
test: plpgsql-toast
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 00000000000..1d53a7d0c63
--- /dev/null
+++ b/src/test/isolation/specs/partition-key-update-4.spec
@@ -0,0 +1,76 @@
+# Test that a row that ends up in a new partition contains changes made by
+# a concurrent transaction.
+
+setup
+{
+ --
+ -- Setup to test concurrent handling of ExecDelete().
+ --
+ 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');
+
+ --
+ -- Setup to test concurrent handling of GetTupleForTrigger().
+ --
+ CREATE TABLE footrg (a int, b text) PARTITION BY LIST(a);
+ CREATE TABLE triglog as select * from footrg;
+ CREATE TABLE footrg1 PARTITION OF footrg FOR VALUES IN (1);
+ CREATE TABLE footrg2 PARTITION OF footrg FOR VALUES IN (2);
+ INSERT INTO footrg VALUES (1, 'ABC');
+ CREATE FUNCTION func_footrg() RETURNS TRIGGER AS $$
+ BEGIN
+ OLD.b = OLD.b || ' trigger';
+
+ -- This will verify that the trigger is not run *before* the row is
+ -- refetched by EvalPlanQual. The OLD row should contain the changes made
+ -- by the concurrent session.
+ INSERT INTO triglog select OLD.*;
+
+ RETURN OLD;
+ END $$ LANGUAGE PLPGSQL;
+ CREATE TRIGGER footrg_ondel BEFORE DELETE ON footrg1
+ FOR EACH ROW EXECUTE PROCEDURE func_footrg();
+
+}
+
+teardown
+{
+ DROP TABLE foo;
+ DROP TRIGGER footrg_ondel ON footrg1;
+ DROP FUNCTION func_footrg();
+ DROP TABLE footrg;
+ DROP TABLE triglog;
+}
+
+session "s1"
+step "s1b" { BEGIN ISOLATION LEVEL READ COMMITTED; }
+step "s1u" { UPDATE foo SET a = a + 1, b = b || ' update1' WHERE b like '%ABC%'; }
+step "s1ut" { UPDATE footrg SET a = a + 1, b = b || ' update1' WHERE b like '%ABC%'; }
+step "s1s" { SELECT tableoid::regclass, * FROM foo ORDER BY a; }
+step "s1st" { SELECT tableoid::regclass, * FROM footrg ORDER BY a; }
+step "s1stl" { SELECT * FROM triglog ORDER BY a; }
+step "s1c" { COMMIT; }
+
+session "s2"
+step "s2b" { BEGIN ISOLATION LEVEL READ COMMITTED; }
+step "s2u1" { UPDATE foo SET b = b || ' update2' WHERE a = 1; }
+step "s2u2" { UPDATE foo SET b = 'EFG' WHERE a = 1; }
+step "s2ut1" { UPDATE footrg SET b = b || ' update2' WHERE a = 1; }
+step "s2ut2" { UPDATE footrg SET b = 'EFG' WHERE a = 1; }
+step "s2c" { COMMIT; }
+
+
+# Session s1 is moving a row into another partition, but is waiting for
+# another session s2 that is updating the original row. The row that ends up
+# in the new partition should contain the changes made by session s2.
+permutation "s1b" "s2b" "s2u1" "s1u" "s2c" "s1c" "s1s"
+
+# Same as above, except, session s1 is waiting in GetTupleTrigger().
+permutation "s1b" "s2b" "s2ut1" "s1ut" "s2c" "s1c" "s1st" "s1stl"
+
+# Below two cases are similar to the above two; except that the session s1
+# fails EvalPlanQual() test, so partition key update does not happen.
+permutation "s1b" "s2b" "s2u2" "s1u" "s2c" "s1c" "s1s"
+permutation "s1b" "s2b" "s2ut2" "s1ut" "s2c" "s1c" "s1st" "s1stl"