From 77e3c1f8772f52f0f7e99801b3daaa7e770f729b Mon Sep 17 00:00:00 2001 From: Alexandre Felipe Date: Wed, 16 Sep 2026 08:42:31 +0100 Subject: [PATCH-v1 2/4] logging and testcase This patch adds clearer logging and a (failing) test case on regress tablespace to be fixed by the next patch. To facilitate the review this patch keep DEBUG1 messages in the testcase To spot the bug keep an eie on repeated ctids, e.g. SELECT ctid, a FROM defer_t ORDER BY a; ctid | a -------+--- (0,1) | 1 (0,2) | 3 <- (0,2) | 3 <- (0,3) | 4 --- src/backend/catalog/storage.c | 13 +++ src/backend/commands/tablecmds.c | 8 ++ src/backend/commands/tablespace.c | 8 ++ src/backend/storage/smgr/md.c | 10 +- src/backend/utils/cache/relcache.c | 5 + src/test/regress/sql/tablespace.sql | 156 ++++++++++++++++++++++++++++ 6 files changed, 196 insertions(+), 4 deletions(-) diff --git a/src/backend/catalog/storage.c b/src/backend/catalog/storage.c index e443a4993c5..db4653b27e8 100644 --- a/src/backend/catalog/storage.c +++ b/src/backend/catalog/storage.c @@ -26,6 +26,7 @@ #include "access/xlogutils.h" #include "catalog/storage.h" #include "catalog/storage_xlog.h" +#include "common/relpath.h" #include "miscadmin.h" #include "pgstat.h" #include "storage/bulk_write.h" @@ -150,6 +151,9 @@ RelationCreateStorage(RelFileLocator rlocator, char relpersistence, srel = smgropen(rlocator, procNumber); smgrcreate(srel, MAIN_FORKNUM, false); + elog(DEBUG1, "RelationCreateStorage: %s", + relpathperm(rlocator, MAIN_FORKNUM).str); + if (needs_wal) log_smgrcreate(&srel->smgr_rlocator.locator, MAIN_FORKNUM); @@ -208,6 +212,10 @@ RelationDropStorage(Relation rel) { PendingRelDelete *pending; + elog(DEBUG1, "RelationDropStorage: oid %u %s", + RelationGetRelid(rel), + relpathperm(rel->rd_locator, MAIN_FORKNUM).str); + /* Add the relation to the list of stuff to delete at commit */ pending = (PendingRelDelete *) MemoryContextAlloc(TopMemoryContext, sizeof(PendingRelDelete)); @@ -701,6 +709,11 @@ smgrDoPendingDeletes(bool isCommit) { SMgrRelation srel; + elog(DEBUG1, + "smgrDoPendingDeletes: %s %s", + isCommit ? "commit" : "abort", + relpathperm(pending->rlocator, MAIN_FORKNUM).str); + srel = smgropen(pending->rlocator, pending->procNumber); /* allocate the initial array, or extend it, if needed */ diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 2f073ddb84a..1e6d0b1611f 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -69,6 +69,7 @@ #include "commands/user.h" #include "commands/vacuum.h" #include "common/int.h" +#include "common/relpath.h" #include "executor/executor.h" #include "foreign/fdwapi.h" #include "foreign/foreign.h" @@ -17560,6 +17561,13 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode) newrlocator.relNumber = newrelfilenumber; newrlocator.spcOid = newTableSpace; + elog(DEBUG1, + "SET TABLESPACE copy: rel \"%s\" oid %u, from %s to %s", + RelationGetRelationName(rel), + RelationGetRelid(rel), + relpathperm(rel->rd_locator, MAIN_FORKNUM).str, + relpathperm(newrlocator, MAIN_FORKNUM).str); + /* hand off to AM to actually create new rel storage and copy the data */ if (rel->rd_rel->relkind == RELKIND_INDEX) { diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c index e01fb2db913..bba656e9b78 100644 --- a/src/backend/commands/tablespace.c +++ b/src/backend/commands/tablespace.c @@ -176,6 +176,8 @@ TablespaceCreateDbspace(Oid spcOid, Oid dbOid, bool isRedo) errmsg("could not create directory \"%s\": %m", dir))); } + + elog(DEBUG1, "TablespaceCreateDbspace: %s", dir); } LWLockRelease(TablespaceCreateLock); @@ -677,6 +679,12 @@ create_tablespace_directories(const char *location, const Oid tablespaceoid) errmsg("could not create symbolic link \"%s\": %m", linkloc))); + if (in_place) + elog(DEBUG1, "tablespace directories: %s", linkloc); + else + elog(DEBUG1, "tablespace directories: %s -> %s", + linkloc, location_with_version_dir); + pfree(linkloc); pfree(location_with_version_dir); } diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c index 780c88c0630..f5906afa17b 100644 --- a/src/backend/storage/smgr/md.c +++ b/src/backend/storage/smgr/md.c @@ -245,6 +245,8 @@ mdcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo) path = relpath(reln->smgr_rlocator, forknum); + elog(DEBUG1, "mdcreate: %s", path.str); + fd = PathNameOpenFile(path.str, _mdfd_open_flags() | O_CREAT | O_EXCL); if (fd < 0) diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 541f30f0972..46e5501dd7e 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -61,6 +61,7 @@ #include "catalog/pg_statistic_ext.h" #include "catalog/pg_subscription.h" #include "catalog/pg_tablespace.h" +#include "common/relpath.h" #include "catalog/pg_trigger.h" #include "catalog/pg_type.h" #include "catalog/schemapg.h" @@ -3982,6 +3983,10 @@ RelationAssumeNewRelfilelocator(Relation relation) if (relation->rd_firstRelfilelocatorSubid == InvalidSubTransactionId) relation->rd_firstRelfilelocatorSubid = relation->rd_newRelfilelocatorSubid; + elog(DEBUG1, "RelationAssumeNewRelfilelocator: oid %u %s", + RelationGetRelid(relation), + relpathperm(relation->rd_locator, MAIN_FORKNUM).str); + /* Flag relation as needing eoxact cleanup (to clear these fields) */ EOXactListAdd(relation); } diff --git a/src/test/regress/sql/tablespace.sql b/src/test/regress/sql/tablespace.sql index c43a59e5957..52ebf9e3b6b 100644 --- a/src/test/regress/sql/tablespace.sql +++ b/src/test/regress/sql/tablespace.sql @@ -437,6 +437,162 @@ name"; -- Should succeed DROP TABLESPACE regress_tblspace_renamed; +-- +-- Deferred heap copy for ALTER TABLE SET TABLESPACE on indexed tables +-- +SET allow_in_place_tablespaces = true; +SET client_min_messages = DEBUG1; +SET enable_seqscan = off; +SET enable_bitmapscan = off; +CREATE TABLESPACE regress_tblspace LOCATION ''; +CREATE TABLESPACE regress_tblspace2 LOCATION ''; + +-- COMMIT +CREATE TABLE defer_t (a int); +CREATE INDEX defer_t_idx ON defer_t (a); +INSERT INTO defer_t VALUES (1); +BEGIN; +INSERT INTO defer_t VALUES (2); +ALTER TABLE defer_t SET TABLESPACE regress_tblspace; +INSERT INTO defer_t VALUES (3); +COMMIT; +INSERT INTO defer_t VALUES (4), (5); +SELECT ctid, a FROM defer_t ORDER BY a; +DROP TABLE defer_t; + +-- ROLLBACK +CREATE TABLE defer_t (a int); +CREATE INDEX defer_t_idx ON defer_t (a); +INSERT INTO defer_t VALUES (1); +BEGIN; +INSERT INTO defer_t VALUES (2); +ALTER TABLE defer_t SET TABLESPACE regress_tblspace; +INSERT INTO defer_t VALUES (3); +ROLLBACK; +INSERT INTO defer_t VALUES (4), (5); +SELECT ctid, a FROM defer_t ORDER BY a; +DROP TABLE defer_t; + +-- PREPARE TRANSACTION, COMMIT PREPARED +CREATE TABLE defer_t (a int); +CREATE INDEX defer_t_idx ON defer_t (a); +INSERT INTO defer_t VALUES (1); +BEGIN; +INSERT INTO defer_t VALUES (2); +ALTER TABLE defer_t SET TABLESPACE regress_tblspace; +INSERT INTO defer_t VALUES (3); +PREPARE TRANSACTION 'defer_tblsp_prep_commit'; +COMMIT PREPARED 'defer_tblsp_prep_commit'; +INSERT INTO defer_t VALUES (4), (5); +SELECT ctid, a FROM defer_t ORDER BY a; +DROP TABLE defer_t; + +-- PREPARE TRANSACTION, ROLLBACK PREPARED +CREATE TABLE defer_t (a int); +CREATE INDEX defer_t_idx ON defer_t (a); +INSERT INTO defer_t VALUES (1); +BEGIN; +INSERT INTO defer_t VALUES (2); +ALTER TABLE defer_t SET TABLESPACE regress_tblspace2; +INSERT INTO defer_t VALUES (3); +PREPARE TRANSACTION 'defer_tblsp_prep_rollback'; +ROLLBACK PREPARED 'defer_tblsp_prep_rollback'; +INSERT INTO defer_t VALUES (4), (5); +SELECT ctid, a FROM defer_t ORDER BY a; +DROP TABLE defer_t; + +-- Subtransaction: move in savepoint, subcommit, then top-level commit +CREATE TABLE defer_t (a int); +CREATE INDEX defer_t_idx ON defer_t (a); +INSERT INTO defer_t VALUES (1); +BEGIN; +INSERT INTO defer_t VALUES (2); +SAVEPOINT sp1; +INSERT INTO defer_t VALUES (3); +ALTER TABLE defer_t SET TABLESPACE regress_tblspace; +INSERT INTO defer_t VALUES (4); +RELEASE SAVEPOINT sp1; +INSERT INTO defer_t VALUES (5); +COMMIT; +INSERT INTO defer_t VALUES (6), (7); +SELECT ctid, a FROM defer_t ORDER BY a; +DROP TABLE defer_t; + +-- Subtransaction: move in savepoint, then rollback to savepoint +CREATE TABLE defer_t (a int); +CREATE INDEX defer_t_idx ON defer_t (a); +INSERT INTO defer_t VALUES (1); +BEGIN; +INSERT INTO defer_t VALUES (2); +SAVEPOINT sp1; +INSERT INTO defer_t VALUES (3); +ALTER TABLE defer_t SET TABLESPACE regress_tblspace; +INSERT INTO defer_t VALUES (4); +ROLLBACK TO SAVEPOINT sp1; +INSERT INTO defer_t VALUES (5); +COMMIT; +INSERT INTO defer_t VALUES (6), (7), (8); +SELECT ctid, a FROM defer_t ORDER BY a; +DROP TABLE defer_t; + +-- Subtransaction: subcommit move, then top-level rollback cancels move +CREATE TABLE defer_t (a int); +CREATE INDEX defer_t_idx ON defer_t (a); +INSERT INTO defer_t VALUES (1); +BEGIN; +INSERT INTO defer_t VALUES (2); +SAVEPOINT sp1; +INSERT INTO defer_t VALUES (3); +ALTER TABLE defer_t SET TABLESPACE regress_tblspace; +INSERT INTO defer_t VALUES (4); +RELEASE SAVEPOINT sp1; +INSERT INTO defer_t VALUES (5); +ROLLBACK; +INSERT INTO defer_t VALUES (6), (7), (8); +SELECT ctid, a FROM defer_t ORDER BY a; +DROP TABLE defer_t; + +-- Subtransaction: two deferred moves in one transaction +CREATE TABLE defer_t (a int); +CREATE INDEX defer_t_idx ON defer_t (a); +INSERT INTO defer_t VALUES (1); +BEGIN; +INSERT INTO defer_t VALUES (2); +SAVEPOINT sp1; +INSERT INTO defer_t VALUES (3); +ALTER TABLE defer_t SET TABLESPACE regress_tblspace; +INSERT INTO defer_t VALUES (4); +SAVEPOINT sp2; +INSERT INTO defer_t VALUES (5); +ALTER TABLE defer_t SET TABLESPACE regress_tblspace2; +INSERT INTO defer_t VALUES (6); +COMMIT; +INSERT INTO defer_t VALUES (7), (8), (9); +SELECT ctid, a FROM defer_t ORDER BY a; +DROP TABLE defer_t; + +CREATE TABLE defer_t (a int); +CREATE INDEX defer_t_idx ON defer_t (a); +INSERT INTO defer_t VALUES (1); +BEGIN; +INSERT INTO defer_t VALUES (2); +SAVEPOINT sp1; +INSERT INTO defer_t VALUES (3); +ALTER TABLE defer_t SET TABLESPACE regress_tblspace; +INSERT INTO defer_t VALUES (4); +SAVEPOINT sp2; +INSERT INTO defer_t VALUES (5); +ALTER TABLE defer_t SET TABLESPACE regress_tblspace2; +INSERT INTO defer_t VALUES (6); +ROLLBACK; +INSERT INTO defer_t VALUES (7), (8), (9); +SELECT ctid, a FROM defer_t ORDER BY a; +DROP TABLE defer_t; +RESET enable_sort; + +DROP TABLESPACE regress_tblspace; +DROP TABLESPACE regress_tblspace2; + DROP SCHEMA testschema CASCADE; DROP ROLE regress_tablespace_user1; -- 2.53.0