From: Michael Paquier Date: Tue, 26 Apr 2022 04:41:17 +0000 (+0900) Subject: Add some isolation tests for CLUSTER X-Git-Tag: REL_15_BETA1~104 X-Git-Url: http://git.postgresql.org/gitweb/?a=commitdiff_plain;h=21a10368eb3fce73f146d7e48b4d81496f60d965;p=postgresql.git Add some isolation tests for CLUSTER 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/YlqveniXn9AI6RFZ@paquier.xyz --- diff --git a/src/test/isolation/expected/cluster-conflict-partition.out b/src/test/isolation/expected/cluster-conflict-partition.out new file mode 100644 index 00000000000..7acb675c97d --- /dev/null +++ b/src/test/isolation/expected/cluster-conflict-partition.out @@ -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; +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; +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 index 00000000000..614d8f9d157 --- /dev/null +++ b/src/test/isolation/expected/cluster-conflict.out @@ -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; +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; +step s1_commit: COMMIT; +step s2_cluster: <... completed> +step s2_reset: RESET ROLE; diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index 607760386ee..529a4cbd4da 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -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 index 00000000000..5091f684a97 --- /dev/null +++ b/src/test/isolation/specs/cluster-conflict-partition.spec @@ -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 index 00000000000..2e1d547f013 --- /dev/null +++ b/src/test/isolation/specs/cluster-conflict.spec @@ -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