summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNoah Misch2025-04-20 15:28:48 +0000
committerNoah Misch2025-04-20 15:28:48 +0000
commit2d5350cfbdc6e61124214d68713295bb060bc541 (patch)
tree6088897867f4840f6a2d9802cb48e28a2f78f9bc
parentd47f922246b54f0290811951e0b73a3d6110437c (diff)
Avoid ERROR at ON COMMIT DELETE ROWS after relhassubclass=f.
Commit 7102070329d8147246d2791321f9915c3b5abf31 fixed a similar bug, but it missed the case of database-wide ANALYZE ("use_own_xacts" mode). Commit a07e03fd8fa7daf4d1356f7cb501ffe784ea6257 changed consequences from silent discard of a pg_class stats (relpages et al.) update to ERROR "tuple to be updated was already modified". Losing a relpages update of an ON COMMIT DELETE ROWS table was negligible, but a COMMIT-time error isn't negligible. Back-patch to v13 (all supported versions). Reported-by: Richard Guo <[email protected] Reported-by: Robins Tharakan <[email protected]> Discussion: https://postgr.es/m/CAMbWs4-XwMKMKJ_GT=p3_-_=j9rQSEs1FbDFUnW9zHuKPsPNEQ@mail.gmail.com Backpatch-through: 13
-rw-r--r--src/backend/commands/vacuum.c2
-rw-r--r--src/test/regress/expected/maintain_every.out33
-rw-r--r--src/test/regress/parallel_schedule4
-rw-r--r--src/test/regress/sql/maintain_every.sql26
4 files changed, 65 insertions, 0 deletions
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index db5da3ce826..33a33bf6b1c 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -657,6 +657,8 @@ vacuum(List *relations, VacuumParams *params, BufferAccessStrategy bstrategy,
if (use_own_xacts)
{
PopActiveSnapshot();
+ /* standard_ProcessUtility() does CCI if !use_own_xacts */
+ CommandCounterIncrement();
CommitTransactionCommand();
}
else
diff --git a/src/test/regress/expected/maintain_every.out b/src/test/regress/expected/maintain_every.out
new file mode 100644
index 00000000000..dea1089c249
--- /dev/null
+++ b/src/test/regress/expected/maintain_every.out
@@ -0,0 +1,33 @@
+-- Test maintenance commands that visit every eligible relation. Run as a
+-- non-superuser, to skip other users' tables.
+CREATE ROLE regress_maintain;
+SET ROLE regress_maintain;
+-- Test database-wide ANALYZE ("use_own_xacts" mode) setting relhassubclass=f
+-- for non-partitioning inheritance, w/ ON COMMIT DELETE ROWS building an
+-- empty index.
+CREATE TEMP TABLE past_inh_db_other (); -- need 2 tables for "use_own_xacts"
+CREATE TEMP TABLE past_inh_db_parent () ON COMMIT DELETE ROWS;
+CREATE TEMP TABLE past_inh_db_child () INHERITS (past_inh_db_parent);
+CREATE INDEX ON past_inh_db_parent ((1));
+ANALYZE past_inh_db_parent;
+SELECT reltuples, relhassubclass
+ FROM pg_class WHERE oid = 'past_inh_db_parent'::regclass;
+ reltuples | relhassubclass
+-----------+----------------
+ 0 | t
+(1 row)
+
+DROP TABLE past_inh_db_child;
+SET client_min_messages = error; -- hide WARNINGs for other users' tables
+ANALYZE;
+RESET client_min_messages;
+SELECT reltuples, relhassubclass
+ FROM pg_class WHERE oid = 'past_inh_db_parent'::regclass;
+ reltuples | relhassubclass
+-----------+----------------
+ 0 | f
+(1 row)
+
+DROP TABLE past_inh_db_parent, past_inh_db_other;
+RESET ROLE;
+DROP ROLE regress_maintain;
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index 0f38caa0d24..a424be2a6bf 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -91,6 +91,10 @@ test: select_parallel
test: write_parallel
test: vacuum_parallel
+# Run this alone, because concurrent DROP TABLE would make non-superuser
+# "ANALYZE;" fail with "relation with OID $n does not exist".
+test: maintain_every
+
# no relation related tests can be put in this group
test: publication subscription
diff --git a/src/test/regress/sql/maintain_every.sql b/src/test/regress/sql/maintain_every.sql
new file mode 100644
index 00000000000..263e97272d5
--- /dev/null
+++ b/src/test/regress/sql/maintain_every.sql
@@ -0,0 +1,26 @@
+-- Test maintenance commands that visit every eligible relation. Run as a
+-- non-superuser, to skip other users' tables.
+
+CREATE ROLE regress_maintain;
+SET ROLE regress_maintain;
+
+-- Test database-wide ANALYZE ("use_own_xacts" mode) setting relhassubclass=f
+-- for non-partitioning inheritance, w/ ON COMMIT DELETE ROWS building an
+-- empty index.
+CREATE TEMP TABLE past_inh_db_other (); -- need 2 tables for "use_own_xacts"
+CREATE TEMP TABLE past_inh_db_parent () ON COMMIT DELETE ROWS;
+CREATE TEMP TABLE past_inh_db_child () INHERITS (past_inh_db_parent);
+CREATE INDEX ON past_inh_db_parent ((1));
+ANALYZE past_inh_db_parent;
+SELECT reltuples, relhassubclass
+ FROM pg_class WHERE oid = 'past_inh_db_parent'::regclass;
+DROP TABLE past_inh_db_child;
+SET client_min_messages = error; -- hide WARNINGs for other users' tables
+ANALYZE;
+RESET client_min_messages;
+SELECT reltuples, relhassubclass
+ FROM pg_class WHERE oid = 'past_inh_db_parent'::regclass;
+DROP TABLE past_inh_db_parent, past_inh_db_other;
+
+RESET ROLE;
+DROP ROLE regress_maintain;