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
This commit is contained in:
Michael Paquier 2022-04-26 13:41:17 +09:00
parent b787c554c2
commit 21a10368eb
5 changed files with 123 additions and 0 deletions

View File

@ -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;

View File

@ -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;

View 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

View File

@ -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

View File

@ -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