]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Cover additional errors and corner conditions in repack.c
authorÁlvaro Herrera <alvherre@kurilemu.de>
Fri, 29 May 2026 09:54:00 +0000 (11:54 +0200)
committerÁlvaro Herrera <alvherre@kurilemu.de>
Fri, 29 May 2026 09:54:00 +0000 (11:54 +0200)
The coverage report shows that some error cases were not being tested;
add test cases for them.

While at it, move some recently added ones to the test_decoding suite:
the preventative check added in 43649b6a53e9 now causes servers with
wal_level=minimal to error out earlier than before.

Author: Álvaro Herrera <alvherre@kurilemu.de>
Reviewed-by: Baji Shaik <baji.pgdev@gmail.com>
Discussion: https://postgr.es/m/ahiwD29RNfVT4tjQ@alvherre.pgsql

contrib/test_decoding/expected/repack.out
contrib/test_decoding/sql/repack.sql
src/test/regress/expected/cluster.out
src/test/regress/sql/cluster.sql

index cf93c1f0d3dad7e9a8c9e40a8a1c2c268ed022d7..6204e620b43eac538c2b12e32703d603a591dd38 100644 (file)
@@ -51,3 +51,53 @@ SELECT * FROM rpk_missing;
 (3 rows)
 
 DROP TABLE rpk_missing;
+-- Error cases for concurrent mode
+-- Doesn't like partitioned tables
+CREATE TABLE clstrpart (a int) PARTITION BY RANGE (a);
+REPACK (CONCURRENTLY) clstrpart;
+ERROR:  REPACK (CONCURRENTLY) is not supported for partitioned tables
+HINT:  Consider running the command on individual partitions.
+-- Disallowed in catalogs
+REPACK (CONCURRENTLY) pg_class;
+ERROR:  cannot execute REPACK (CONCURRENTLY) on relation "pg_class"
+HINT:  REPACK (CONCURRENTLY) is not supported for catalog relations.
+-- Doesn't support TOAST tables directly
+CREATE TABLE repack_conc_toast (t text);
+SELECT reltoastrelid::regclass AS toast_rel
+FROM pg_class WHERE oid = 'repack_conc_toast'::regclass \gset
+\set VERBOSITY sqlstate
+REPACK (CONCURRENTLY) :toast_rel;
+ERROR:  0A000
+\set VERBOSITY default
+DROP TABLE repack_conc_toast;
+-- Only support permanent tables, temp and unlogged tables are not supported
+CREATE TEMP TABLE repack_conc_temp (i int PRIMARY KEY);
+REPACK (CONCURRENTLY) repack_conc_temp;
+ERROR:  cannot execute REPACK (CONCURRENTLY) on relation "repack_conc_temp"
+HINT:  REPACK (CONCURRENTLY) is only allowed for permanent relations.
+DROP TABLE repack_conc_temp;
+CREATE UNLOGGED TABLE repack_conc_unlogged (i int PRIMARY KEY);
+REPACK (CONCURRENTLY) repack_conc_unlogged;
+ERROR:  cannot execute REPACK (CONCURRENTLY) on relation "repack_conc_unlogged"
+HINT:  REPACK (CONCURRENTLY) is only allowed for permanent relations.
+DROP TABLE repack_conc_unlogged;
+-- Doesn't support tables with REPLICA IDENTITY NOTHING, even if they have a primary key
+CREATE TABLE repack_conc_replident (i int PRIMARY KEY);
+ALTER TABLE repack_conc_replident REPLICA IDENTITY NOTHING;
+REPACK (CONCURRENTLY) repack_conc_replident;
+ERROR:  cannot execute REPACK (CONCURRENTLY) on relation "repack_conc_replident"
+DETAIL:  REPACK (CONCURRENTLY) does not support tables with REPLICA IDENTITY NOTHING.
+-- Doesn't support tables without a primary key or replica identity index
+ALTER TABLE repack_conc_replident DROP CONSTRAINT repack_conc_replident_pkey;
+ALTER TABLE repack_conc_replident REPLICA IDENTITY DEFAULT;
+REPACK (CONCURRENTLY) repack_conc_replident;
+ERROR:  cannot execute REPACK (CONCURRENTLY) on relation "repack_conc_replident"
+HINT:  Relation "repack_conc_replident" has no identity index.
+-- Doesn't support tables with deferrable primary keys
+ALTER TABLE repack_conc_replident ADD PRIMARY KEY (i) DEFERRABLE;
+REPACK (CONCURRENTLY) repack_conc_replident;
+ERROR:  cannot execute REPACK (CONCURRENTLY) on relation "repack_conc_replident"
+DETAIL:  REPACK (CONCURRENTLY) does not support deferrable primary keys.
+HINT:  Use ALTER TABLE ... REPLICA IDENTITY USING INDEX to designate another index as replica identity.
+-- clean up
+DROP TABLE repack_conc_replident, clstrpart;
index 6164dd4235fc69afe08c0cf2773bd5670e590882..cea3bd336895da7308be6c9d50a7749dc4ab22d4 100644 (file)
@@ -32,3 +32,46 @@ SELECT * FROM rpk_missing;
 REPACK (CONCURRENTLY) rpk_missing;
 SELECT * FROM rpk_missing;
 DROP TABLE rpk_missing;
+
+-- Error cases for concurrent mode
+
+-- Doesn't like partitioned tables
+CREATE TABLE clstrpart (a int) PARTITION BY RANGE (a);
+REPACK (CONCURRENTLY) clstrpart;
+
+-- Disallowed in catalogs
+REPACK (CONCURRENTLY) pg_class;
+
+-- Doesn't support TOAST tables directly
+CREATE TABLE repack_conc_toast (t text);
+SELECT reltoastrelid::regclass AS toast_rel
+FROM pg_class WHERE oid = 'repack_conc_toast'::regclass \gset
+\set VERBOSITY sqlstate
+REPACK (CONCURRENTLY) :toast_rel;
+\set VERBOSITY default
+DROP TABLE repack_conc_toast;
+
+-- Only support permanent tables, temp and unlogged tables are not supported
+CREATE TEMP TABLE repack_conc_temp (i int PRIMARY KEY);
+REPACK (CONCURRENTLY) repack_conc_temp;
+DROP TABLE repack_conc_temp;
+CREATE UNLOGGED TABLE repack_conc_unlogged (i int PRIMARY KEY);
+REPACK (CONCURRENTLY) repack_conc_unlogged;
+DROP TABLE repack_conc_unlogged;
+
+-- Doesn't support tables with REPLICA IDENTITY NOTHING, even if they have a primary key
+CREATE TABLE repack_conc_replident (i int PRIMARY KEY);
+ALTER TABLE repack_conc_replident REPLICA IDENTITY NOTHING;
+REPACK (CONCURRENTLY) repack_conc_replident;
+
+-- Doesn't support tables without a primary key or replica identity index
+ALTER TABLE repack_conc_replident DROP CONSTRAINT repack_conc_replident_pkey;
+ALTER TABLE repack_conc_replident REPLICA IDENTITY DEFAULT;
+REPACK (CONCURRENTLY) repack_conc_replident;
+
+-- Doesn't support tables with deferrable primary keys
+ALTER TABLE repack_conc_replident ADD PRIMARY KEY (i) DEFERRABLE;
+REPACK (CONCURRENTLY) repack_conc_replident;
+
+-- clean up
+DROP TABLE repack_conc_replident, clstrpart;
index 23f312c62a3cbb637cf062388c6d4773fd6bd76b..d1bc8a13286e73efa51cff69328b353df77480ae 100644 (file)
@@ -697,6 +697,39 @@ SELECT * FROM clstr_expression WHERE -a = -3 ORDER BY -a, b;
 (4 rows)
 
 COMMIT;
+-- verify some error cases
+CREATE TABLE clstr_table_one (id int, val text);
+CREATE TABLE clstr_table_two (id int, val text);
+CREATE INDEX clstr_idx_b ON clstr_table_two (id);
+CLUSTER clstr_table_one USING clstr_idx_b;
+ERROR:  "clstr_idx_b" is not an index for table "clstr_table_one"
+CLUSTER clstr_table_one USING nonexistant;
+ERROR:  index "nonexistant" for table "clstr_table_one" does not exist
+CREATE INDEX clstr_hash_idx ON clstr_table_one USING hash (id);
+CLUSTER clstr_table_one USING clstr_hash_idx;
+ERROR:  cannot cluster on index "clstr_hash_idx" because access method does not support clustering
+CREATE INDEX clstr_partial_idx ON clstr_table_one (id) WHERE id > 0;
+CLUSTER clstr_table_one USING clstr_partial_idx;
+ERROR:  cannot cluster on partial index "clstr_partial_idx"
+REPACK pg_class USING INDEX pg_class_oid_index;
+ERROR:  permission denied: "pg_class" is a system catalog
+DETAIL:  System catalogs can only be clustered by the index they're already clustered on, if any, unless "allow_system_table_mods" is enabled.
+DROP TABLE clstr_table_one, clstr_table_two;
+-- verify that CLUSTER/REPACK don't touch a NO DATA matview
+CREATE MATERIALIZED VIEW clstr_matview AS
+    SELECT i FROM generate_series(1, 5) i
+    WITH NO DATA;
+CREATE INDEX clstr_matview_idx ON clstr_matview (i);
+SELECT relfilenode FROM pg_class WHERE oid = 'clstr_matview'::regclass \gset
+CLUSTER clstr_matview USING clstr_matview_idx;
+REPACK clstr_matview USING INDEX clstr_matview_idx;
+SELECT relfilenode = :relfilenode FROM pg_class WHERE oid = 'clstr_matview'::regclass;
+ ?column? 
+----------
+ t
+(1 row)
+
+DROP MATERIALIZED VIEW clstr_matview;
 ----------------------------------------------------------------------
 --
 -- REPACK
@@ -796,61 +829,7 @@ ORDER BY o.relname;
  clstr_3
 (2 rows)
 
---
--- Check concurrent mode requirements
---
--- Disallowed in catalogs
-REPACK (CONCURRENTLY) pg_class;
-ERROR:  cannot execute REPACK (CONCURRENTLY) on relation "pg_class"
-HINT:  REPACK (CONCURRENTLY) is not supported for catalog relations.
--- Doesn't like partitioned tables
-REPACK (CONCURRENTLY) clstrpart;
-ERROR:  REPACK (CONCURRENTLY) is not supported for partitioned tables
-HINT:  Consider running the command on individual partitions.
--- Doesn't support catalog tables
-REPACK (CONCURRENTLY) pg_class;
-ERROR:  cannot execute REPACK (CONCURRENTLY) on relation "pg_class"
-HINT:  REPACK (CONCURRENTLY) is not supported for catalog relations.
--- Only support permanent tables, temp and unlogged tables are not supported
-CREATE TEMP TABLE repack_conc_temp (i int PRIMARY KEY);
-REPACK (CONCURRENTLY) repack_conc_temp;
-ERROR:  cannot execute REPACK (CONCURRENTLY) on relation "repack_conc_temp"
-HINT:  REPACK (CONCURRENTLY) is only allowed for permanent relations.
-DROP TABLE repack_conc_temp;
-CREATE UNLOGGED TABLE repack_conc_unlogged (i int PRIMARY KEY);
-REPACK (CONCURRENTLY) repack_conc_unlogged;
-ERROR:  cannot execute REPACK (CONCURRENTLY) on relation "repack_conc_unlogged"
-HINT:  REPACK (CONCURRENTLY) is only allowed for permanent relations.
-DROP TABLE repack_conc_unlogged;
--- Doesn't support TOAST tables directly
-CREATE TABLE repack_conc_toast (t text);
-SELECT reltoastrelid::regclass AS toast_rel
-FROM pg_class WHERE oid = 'repack_conc_toast'::regclass \gset
-\set VERBOSITY sqlstate
-REPACK (CONCURRENTLY) :toast_rel;
-ERROR:  0A000
-\set VERBOSITY default
-DROP TABLE repack_conc_toast;
--- Doesn't support tables with REPLICA IDENTITY NOTHING, even if they have a primary key
-CREATE TABLE repack_conc_replident (i int PRIMARY KEY);
-ALTER TABLE repack_conc_replident REPLICA IDENTITY NOTHING;
-REPACK (CONCURRENTLY) repack_conc_replident;
-ERROR:  cannot execute REPACK (CONCURRENTLY) on relation "repack_conc_replident"
-DETAIL:  REPACK (CONCURRENTLY) does not support tables with REPLICA IDENTITY NOTHING.
--- Doesn't support tables without a primary key or replica identity index
-ALTER TABLE repack_conc_replident DROP CONSTRAINT repack_conc_replident_pkey;
-ALTER TABLE repack_conc_replident REPLICA IDENTITY DEFAULT;
-REPACK (CONCURRENTLY) repack_conc_replident;
-ERROR:  cannot execute REPACK (CONCURRENTLY) on relation "repack_conc_replident"
-HINT:  Relation "repack_conc_replident" has no identity index.
--- Doesn't support tables with deferrable primary keys
-ALTER TABLE repack_conc_replident ADD PRIMARY KEY (i) DEFERRABLE;
-REPACK (CONCURRENTLY) repack_conc_replident;
-ERROR:  cannot execute REPACK (CONCURRENTLY) on relation "repack_conc_replident"
-DETAIL:  REPACK (CONCURRENTLY) does not support deferrable primary keys.
-HINT:  Use ALTER TABLE ... REPLICA IDENTITY USING INDEX to designate another index as replica identity.
 -- clean up
-DROP TABLE repack_conc_replident;
 DROP TABLE clustertest;
 DROP TABLE clstr_1;
 DROP TABLE clstr_2;
index c2f329ecd1bbcf52cff77a19b9d7eae3915e3c69..e7a62367adfd898eb3828b22120b4ae196dd64ee 100644 (file)
@@ -328,6 +328,34 @@ EXPLAIN (COSTS OFF) SELECT * FROM clstr_expression WHERE -a = -3 ORDER BY -a, b;
 SELECT * FROM clstr_expression WHERE -a = -3 ORDER BY -a, b;
 COMMIT;
 
+-- verify some error cases
+CREATE TABLE clstr_table_one (id int, val text);
+CREATE TABLE clstr_table_two (id int, val text);
+CREATE INDEX clstr_idx_b ON clstr_table_two (id);
+CLUSTER clstr_table_one USING clstr_idx_b;
+CLUSTER clstr_table_one USING nonexistant;
+
+CREATE INDEX clstr_hash_idx ON clstr_table_one USING hash (id);
+CLUSTER clstr_table_one USING clstr_hash_idx;
+
+CREATE INDEX clstr_partial_idx ON clstr_table_one (id) WHERE id > 0;
+CLUSTER clstr_table_one USING clstr_partial_idx;
+
+REPACK pg_class USING INDEX pg_class_oid_index;
+
+DROP TABLE clstr_table_one, clstr_table_two;
+
+-- verify that CLUSTER/REPACK don't touch a NO DATA matview
+CREATE MATERIALIZED VIEW clstr_matview AS
+    SELECT i FROM generate_series(1, 5) i
+    WITH NO DATA;
+CREATE INDEX clstr_matview_idx ON clstr_matview (i);
+SELECT relfilenode FROM pg_class WHERE oid = 'clstr_matview'::regclass \gset
+CLUSTER clstr_matview USING clstr_matview_idx;
+REPACK clstr_matview USING INDEX clstr_matview_idx;
+SELECT relfilenode = :relfilenode FROM pg_class WHERE oid = 'clstr_matview'::regclass;
+DROP MATERIALIZED VIEW clstr_matview;
+
 ----------------------------------------------------------------------
 --
 -- REPACK
@@ -383,52 +411,7 @@ JOIN relnodes_new n ON o.relname = n.relname
 WHERE o.relfilenode <> n.relfilenode
 ORDER BY o.relname;
 
---
--- Check concurrent mode requirements
---
-
--- Disallowed in catalogs
-REPACK (CONCURRENTLY) pg_class;
-
--- Doesn't like partitioned tables
-REPACK (CONCURRENTLY) clstrpart;
-
--- Doesn't support catalog tables
-REPACK (CONCURRENTLY) pg_class;
-
--- Only support permanent tables, temp and unlogged tables are not supported
-CREATE TEMP TABLE repack_conc_temp (i int PRIMARY KEY);
-REPACK (CONCURRENTLY) repack_conc_temp;
-DROP TABLE repack_conc_temp;
-CREATE UNLOGGED TABLE repack_conc_unlogged (i int PRIMARY KEY);
-REPACK (CONCURRENTLY) repack_conc_unlogged;
-DROP TABLE repack_conc_unlogged;
-
--- Doesn't support TOAST tables directly
-CREATE TABLE repack_conc_toast (t text);
-SELECT reltoastrelid::regclass AS toast_rel
-FROM pg_class WHERE oid = 'repack_conc_toast'::regclass \gset
-\set VERBOSITY sqlstate
-REPACK (CONCURRENTLY) :toast_rel;
-\set VERBOSITY default
-DROP TABLE repack_conc_toast;
-
--- Doesn't support tables with REPLICA IDENTITY NOTHING, even if they have a primary key
-CREATE TABLE repack_conc_replident (i int PRIMARY KEY);
-ALTER TABLE repack_conc_replident REPLICA IDENTITY NOTHING;
-REPACK (CONCURRENTLY) repack_conc_replident;
-
--- Doesn't support tables without a primary key or replica identity index
-ALTER TABLE repack_conc_replident DROP CONSTRAINT repack_conc_replident_pkey;
-ALTER TABLE repack_conc_replident REPLICA IDENTITY DEFAULT;
-REPACK (CONCURRENTLY) repack_conc_replident;
-
--- Doesn't support tables with deferrable primary keys
-ALTER TABLE repack_conc_replident ADD PRIMARY KEY (i) DEFERRABLE;
-REPACK (CONCURRENTLY) repack_conc_replident;
-
 -- clean up
-DROP TABLE repack_conc_replident;
 DROP TABLE clustertest;
 DROP TABLE clstr_1;
 DROP TABLE clstr_2;