1
0
mirror of https://github.com/postgres/postgres.git synced 2025-05-05 09:19:17 +03:00

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 <guofenglinux@gmail.com
Reported-by: Robins Tharakan <tharakan@gmail.com>
Discussion: https://postgr.es/m/CAMbWs4-XwMKMKJ_GT=p3_-_=j9rQSEs1FbDFUnW9zHuKPsPNEQ@mail.gmail.com
Backpatch-through: 13
This commit is contained in:
Noah Misch 2025-04-20 08:28:48 -07:00
parent 065ce49a10
commit d0a049987e
4 changed files with 65 additions and 0 deletions

View File

@ -642,6 +642,8 @@ vacuum(List *relations, VacuumParams *params, BufferAccessStrategy bstrategy,
if (use_own_xacts)
{
PopActiveSnapshot();
/* standard_ProcessUtility() does CCI if !use_own_xacts */
CommandCounterIncrement();
CommitTransactionCommand();
}
else

View File

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

View File

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

View File

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