Add some isolation tests for CLUSTER
authorMichael Paquier <[email protected]>
Tue, 26 Apr 2022 04:41:17 +0000 (13:41 +0900)
committerMichael Paquier <[email protected]>
Tue, 26 Apr 2022 04:41:17 +0000 (13:41 +0900)
This commit adds two isolation tests for CLUSTER, using:
- A normal table, making sure that CLUSTER blocks and completes if the
table is locked by a concurrent session.
- A partitioned table with a partition owned by a different user.  If
the partitioned table is locked by a concurrent session, CLUSTER on the
partitioned table should block.  If the partition owned by a different
user is locked, CLUSTER on its partitioned table should complete and
skip the partition.  3f19e17 has added an early check to ignore such a
partition with a SQL regression test, but this was not checking that
CLUSTER should not block.

Discussion: https://postgr.es/m/[email protected]

src/test/isolation/expected/cluster-conflict-partition.out [new file with mode: 0644]
src/test/isolation/expected/cluster-conflict.out [new file with mode: 0644]
src/test/isolation/isolation_schedule
src/test/isolation/specs/cluster-conflict-partition.spec [new file with mode: 0644]
src/test/isolation/specs/cluster-conflict.spec [new file with mode: 0644]

diff --git a/src/test/isolation/expected/cluster-conflict-partition.out b/src/test/isolation/expected/cluster-conflict-partition.out
new file mode 100644 (file)
index 0000000..7acb675
--- /dev/null
@@ -0,0 +1,35 @@
+Parsed test spec with 2 sessions
+
+starting permutation: s1_begin s1_lock_parent s2_auth s2_cluster s1_commit s2_reset
+step s1_begin: BEGIN;
+step s1_lock_parent: LOCK cluster_part_tab IN SHARE UPDATE EXCLUSIVE MODE;
+step s2_auth: SET ROLE regress_cluster_part;
+step s2_cluster: CLUSTER cluster_part_tab USING cluster_part_ind; <waiting ...>
+step s1_commit: COMMIT;
+step s2_cluster: <... completed>
+step s2_reset: RESET ROLE;
+
+starting permutation: s1_begin s2_auth s1_lock_parent s2_cluster s1_commit s2_reset
+step s1_begin: BEGIN;
+step s2_auth: SET ROLE regress_cluster_part;
+step s1_lock_parent: LOCK cluster_part_tab IN SHARE UPDATE EXCLUSIVE MODE;
+step s2_cluster: CLUSTER cluster_part_tab USING cluster_part_ind; <waiting ...>
+step s1_commit: COMMIT;
+step s2_cluster: <... completed>
+step s2_reset: RESET ROLE;
+
+starting permutation: s1_begin s1_lock_child s2_auth s2_cluster s1_commit s2_reset
+step s1_begin: BEGIN;
+step s1_lock_child: LOCK cluster_part_tab1 IN SHARE UPDATE EXCLUSIVE MODE;
+step s2_auth: SET ROLE regress_cluster_part;
+step s2_cluster: CLUSTER cluster_part_tab USING cluster_part_ind;
+step s1_commit: COMMIT;
+step s2_reset: RESET ROLE;
+
+starting permutation: s1_begin s2_auth s1_lock_child s2_cluster s1_commit s2_reset
+step s1_begin: BEGIN;
+step s2_auth: SET ROLE regress_cluster_part;
+step s1_lock_child: LOCK cluster_part_tab1 IN SHARE UPDATE EXCLUSIVE MODE;
+step s2_cluster: CLUSTER cluster_part_tab USING cluster_part_ind;
+step s1_commit: COMMIT;
+step s2_reset: RESET ROLE;
diff --git a/src/test/isolation/expected/cluster-conflict.out b/src/test/isolation/expected/cluster-conflict.out
new file mode 100644 (file)
index 0000000..614d8f9
--- /dev/null
@@ -0,0 +1,19 @@
+Parsed test spec with 2 sessions
+
+starting permutation: s1_begin s1_lock s2_auth s2_cluster s1_commit s2_reset
+step s1_begin: BEGIN;
+step s1_lock: LOCK cluster_tab IN SHARE UPDATE EXCLUSIVE MODE;
+step s2_auth: SET ROLE regress_cluster_conflict;
+step s2_cluster: CLUSTER cluster_tab USING cluster_ind; <waiting ...>
+step s1_commit: COMMIT;
+step s2_cluster: <... completed>
+step s2_reset: RESET ROLE;
+
+starting permutation: s1_begin s2_auth s1_lock s2_cluster s1_commit s2_reset
+step s1_begin: BEGIN;
+step s2_auth: SET ROLE regress_cluster_conflict;
+step s1_lock: LOCK cluster_tab IN SHARE UPDATE EXCLUSIVE MODE;
+step s2_cluster: CLUSTER cluster_tab USING cluster_ind; <waiting ...>
+step s1_commit: COMMIT;
+step s2_cluster: <... completed>
+step s2_reset: RESET ROLE;
index 607760386eed49c2917a356df2e698a200be3e63..529a4cbd4da0f717fdd0c61507990f5fc7326a11 100644 (file)
@@ -102,6 +102,8 @@ test: partition-key-update-2
 test: partition-key-update-3
 test: partition-key-update-4
 test: plpgsql-toast
+test: cluster-conflict
+test: cluster-conflict-partition
 test: truncate-conflict
 test: serializable-parallel
 test: serializable-parallel-2
diff --git a/src/test/isolation/specs/cluster-conflict-partition.spec b/src/test/isolation/specs/cluster-conflict-partition.spec
new file mode 100644 (file)
index 0000000..5091f68
--- /dev/null
@@ -0,0 +1,37 @@
+# Tests for locking conflicts with CLUSTER command and partitions.
+
+setup
+{
+   CREATE ROLE regress_cluster_part;
+   CREATE TABLE cluster_part_tab (a int) PARTITION BY LIST (a);
+   CREATE TABLE cluster_part_tab1 PARTITION OF cluster_part_tab FOR VALUES IN (1);
+   CREATE TABLE cluster_part_tab2 PARTITION OF cluster_part_tab FOR VALUES IN (2);
+   CREATE INDEX cluster_part_ind ON cluster_part_tab(a);
+   ALTER TABLE cluster_part_tab OWNER TO regress_cluster_part;
+}
+
+teardown
+{
+   DROP TABLE cluster_part_tab;
+   DROP ROLE regress_cluster_part;
+}
+
+session s1
+step s1_begin          { BEGIN; }
+step s1_lock_parent    { LOCK cluster_part_tab IN SHARE UPDATE EXCLUSIVE MODE; }
+step s1_lock_child     { LOCK cluster_part_tab1 IN SHARE UPDATE EXCLUSIVE MODE; }
+step s1_commit         { COMMIT; }
+
+session s2
+step s2_auth           { SET ROLE regress_cluster_part; }
+step s2_cluster        { CLUSTER cluster_part_tab USING cluster_part_ind; }
+step s2_reset          { RESET ROLE; }
+
+# CLUSTER on the parent waits if locked, passes for all cases.
+permutation s1_begin s1_lock_parent s2_auth s2_cluster s1_commit s2_reset
+permutation s1_begin s2_auth s1_lock_parent s2_cluster s1_commit s2_reset
+
+# When taking a lock on a partition leaf, CLUSTER on the parent skips
+# the leaf, passes for all cases.
+permutation s1_begin s1_lock_child s2_auth s2_cluster s1_commit s2_reset
+permutation s1_begin s2_auth s1_lock_child s2_cluster s1_commit s2_reset
diff --git a/src/test/isolation/specs/cluster-conflict.spec b/src/test/isolation/specs/cluster-conflict.spec
new file mode 100644 (file)
index 0000000..2e1d547
--- /dev/null
@@ -0,0 +1,30 @@
+# Tests for locking conflicts with CLUSTER command.
+
+setup
+{
+   CREATE ROLE regress_cluster_conflict;
+   CREATE TABLE cluster_tab (a int);
+   CREATE INDEX cluster_ind ON cluster_tab(a);
+   ALTER TABLE cluster_tab OWNER TO regress_cluster_conflict;
+}
+
+teardown
+{
+   DROP TABLE cluster_tab;
+   DROP ROLE regress_cluster_conflict;
+}
+
+session s1
+step s1_begin          { BEGIN; }
+step s1_lock           { LOCK cluster_tab IN SHARE UPDATE EXCLUSIVE MODE; }
+step s1_commit         { COMMIT; }
+
+session s2
+step s2_auth           { SET ROLE regress_cluster_conflict; }
+step s2_cluster        { CLUSTER cluster_tab USING cluster_ind; }
+step s2_reset          { RESET ROLE; }
+
+# The role has privileges to cluster the table, CLUSTER will block if
+# another session holds a lock on the table and succeed in all cases.
+permutation s1_begin s1_lock s2_auth s2_cluster s1_commit s2_reset
+permutation s1_begin s2_auth s1_lock s2_cluster s1_commit s2_reset