postgres.git / summary / log / commit / refs

commit    5dbb63fc82b72ccc6f9e7be0361efdeee5deeb50
Author:   Álvaro Herrera <alvherre@kurilemu.de>
Date:     Mon Apr 20 13:44:23 2026 +0000

    REPACK: do not require REPLICATION or LOGIN
    
    Although REPACK (CONCURRENTLY) uses replication slots, there is no
    concern that the slot will leak data of other users, because the
    MAINTAIN privilege on the table is required anyway; requiring
    REPLICATION is user-unfriendly without providing any actual protection.
    
    A related aspect is that the REPLICATION attribute is not needed to
    prevent REPACK from stealing slots from logical replication, since
    commit e76d8c749c31 made REPACK use a separate pool of replication
    slots.
    
    Similarly, there's no reason to require that the table owner has the
    LOGIN privilege.  Bypass the default behavior in the background worker
    launch sequence.
    
    Because there are now successful concurrent repack runs in the
    regression tests, we're forced to run test_plan_advice under
    wal_level=replica, so add that.  Also, move the cluster.sql test to a
    different parallel group in parallel_schedule: apparently the use of the
    repack worker causes it to exceed the maximum limit of processes in some
    runs (the actual limit reached is the number of XIDs in a snapshot's xip
    array).
    
    Author: Antonin Houska <ah@cybertec.at>
    Reported-by: Justin Pryzby <pryzby@telsasoft.com>
    Reviewed-by: Chao Li <lic@highgo.com>
    Discussion: https://postgr.es/m/aeJHPNmL4vVy3oPw@pryzbyj2023


src/backend/commands/repack_worker.c | 6 +++--- .../modules/test_plan_advice/t/001_replan_regress.pl | 1 + src/test/regress/expected/cluster.out | 18 +++++++++++++++++- src/test/regress/parallel_schedule | 4 ++-- src/test/regress/sql/cluster.sql | 9 ++++++++- 5 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/backend/commands/repack_worker.c b/src/backend/commands/repack_worker.c index b17edd771e2..c40f8c98e06 100644 --- a/src/backend/commands/repack_worker.c +++ b/src/backend/commands/repack_worker.c @@ -106,8 +106,9 @@ RepackWorkerMain(Datum main_arg) pq_set_parallel_leader(shared->backend_pid, shared->backend_proc_number); - /* Connect to the database. */ - BackgroundWorkerInitializeConnectionByOid(shared->dbid, shared->roleid, 0); + /* Connect to the database. LOGIN is not required. */ + BackgroundWorkerInitializeConnectionByOid(shared->dbid, shared->roleid, + BGWORKER_BYPASS_ROLELOGINCHECK); /* * Transaction is needed to open relation, and it also provides us with a @@ -214,7 +215,6 @@ repack_setup_logical_decoding(Oid relid) /* * Make sure we can use logical decoding. */ - CheckSlotPermissions(); CheckLogicalDecodingRequirements(true); /* diff --git a/src/test/modules/test_plan_advice/t/001_replan_regress.pl b/src/test/modules/test_plan_advice/t/001_replan_regress.pl index 38ffa4d11ae..452b179a665 100644 --- a/src/test/modules/test_plan_advice/t/001_replan_regress.pl +++ b/src/test/modules/test_plan_advice/t/001_replan_regress.pl @@ -18,6 +18,7 @@ $node->init(); # Set up our desired configuration. $node->append_conf('postgresql.conf', <<EOM); shared_preload_libraries='test_plan_advice' +wal_level=replica pg_plan_advice.always_explain_supplied_advice=false pg_plan_advice.feedback_warnings=true EOM diff --git a/src/test/regress/expected/cluster.out b/src/test/regress/expected/cluster.out index 6127b215a86..71270134985 100644 --- a/src/test/regress/expected/cluster.out +++ b/src/test/regress/expected/cluster.out @@ -543,7 +543,7 @@ ERROR: REPACK (CONCURRENTLY) is not supported for partitioned tables HINT: Consider running the command on individual partitions. DROP TABLE clstrpart; -- Ownership of partitions is checked -CREATE TABLE ptnowner(i int unique) PARTITION BY LIST (i); +CREATE TABLE ptnowner(i int unique not null) PARTITION BY LIST (i); CREATE INDEX ptnowner_i_idx ON ptnowner(i); CREATE TABLE ptnowner1 PARTITION OF ptnowner FOR VALUES IN (1); CREATE ROLE regress_ptnowner; @@ -552,6 +552,8 @@ ALTER TABLE ptnowner1 OWNER TO regress_ptnowner; SET SESSION AUTHORIZATION regress_ptnowner; CLUSTER ptnowner USING ptnowner_i_idx; ERROR: permission denied for table ptnowner +ALTER TABLE ptnowner1 REPLICA IDENTITY USING INDEX ptnowner1_i_key; +REPACK (CONCURRENTLY) ptnowner1; RESET SESSION AUTHORIZATION; ALTER TABLE ptnowner OWNER TO regress_ptnowner; CREATE TEMP TABLE ptnowner_oldnodes AS @@ -560,6 +562,11 @@ CREATE TEMP TABLE ptnowner_oldnodes AS SET SESSION AUTHORIZATION regress_ptnowner; CLUSTER ptnowner USING ptnowner_i_idx; WARNING: permission denied to execute CLUSTER on "ptnowner2", skipping it +-- still can't repack without a replica identity +ALTER TABLE ptnowner1 REPLICA IDENTITY DEFAULT; +REPACK (CONCURRENTLY) ptnowner1; +ERROR: cannot process relation "ptnowner1" +HINT: Relation "ptnowner1" has no identity index. RESET SESSION AUTHORIZATION; SELECT a.relname, a.relfilenode=b.relfilenode FROM pg_class a JOIN ptnowner_oldnodes b USING (oid) ORDER BY a.relname COLLATE "C"; @@ -570,6 +577,15 @@ SELECT a.relname, a.relfilenode=b.relfilenode FROM pg_class a ptnowner2 | t (3 rows) +SELECT a.relname, a.relfilenode=b.relfilenode FROM pg_class a + JOIN ptnowner_oldnodes b USING (oid) ORDER BY a.relname COLLATE "C"; + relname | ?column? +-----------+---------- + ptnowner | t + ptnowner1 | f + ptnowner2 | t +(3 rows) + DROP TABLE ptnowner; DROP ROLE regress_ptnowner; -- Test CLUSTER with external tuplesorting diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 288e94dc408..5d4f910155e 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -102,7 +102,7 @@ test: publication subscription # Another group of parallel tests # select_views depends on create_view # ---------- -test: select_views portals_p2 foreign_key cluster dependency guc bitmapops combocid tsearch tsdicts foreign_data window xmlmap functional_deps advisory_lock indirect_toast equivclass stats_rewrite graph_table +test: select_views portals_p2 foreign_key dependency guc bitmapops combocid tsearch tsdicts foreign_data window xmlmap functional_deps advisory_lock indirect_toast equivclass stats_rewrite graph_table # ---------- # Another group of parallel tests (JSON related) @@ -128,7 +128,7 @@ test: partition_merge partition_split partition_join partition_prune reloptions # ---------- # Another group of parallel tests (compression) # ---------- -test: compression compression_lz4 compression_pglz +test: compression compression_lz4 compression_pglz cluster # event_trigger depends on create_am and cannot run concurrently with # any test that runs DDL diff --git a/src/test/regress/sql/cluster.sql b/src/test/regress/sql/cluster.sql index d14063a9683..6746236ffec 100644 --- a/src/test/regress/sql/cluster.sql +++ b/src/test/regress/sql/cluster.sql @@ -254,7 +254,7 @@ REPACK (CONCURRENTLY) clstrpart; DROP TABLE clstrpart; -- Ownership of partitions is checked -CREATE TABLE ptnowner(i int unique) PARTITION BY LIST (i); +CREATE TABLE ptnowner(i int unique not null) PARTITION BY LIST (i); CREATE INDEX ptnowner_i_idx ON ptnowner(i); CREATE TABLE ptnowner1 PARTITION OF ptnowner FOR VALUES IN (1); CREATE ROLE regress_ptnowner; @@ -262,6 +262,8 @@ CREATE TABLE ptnowner2 PARTITION OF ptnowner FOR VALUES IN (2); ALTER TABLE ptnowner1 OWNER TO regress_ptnowner; SET SESSION AUTHORIZATION regress_ptnowner; CLUSTER ptnowner USING ptnowner_i_idx; +ALTER TABLE ptnowner1 REPLICA IDENTITY USING INDEX ptnowner1_i_key; +REPACK (CONCURRENTLY) ptnowner1; RESET SESSION AUTHORIZATION; ALTER TABLE ptnowner OWNER TO regress_ptnowner; CREATE TEMP TABLE ptnowner_oldnodes AS @@ -269,7 +271,12 @@ CREATE TEMP TABLE ptnowner_oldnodes AS JOIN pg_class AS c ON c.oid=tree.relid; SET SESSION AUTHORIZATION regress_ptnowner; CLUSTER ptnowner USING ptnowner_i_idx; +-- still can't repack without a replica identity +ALTER TABLE ptnowner1 REPLICA IDENTITY DEFAULT; +REPACK (CONCURRENTLY) ptnowner1; RESET SESSION AUTHORIZATION; +SELECT a.relname, a.relfilenode=b.relfilenode FROM pg_class a + JOIN ptnowner_oldnodes b USING (oid) ORDER BY a.relname COLLATE "C"; SELECT a.relname, a.relfilenode=b.relfilenode FROM pg_class a JOIN ptnowner_oldnodes b USING (oid) ORDER BY a.relname COLLATE "C"; DROP TABLE ptnowner; [parent: 158d8fadd79f]