From: Justin Pryzby Date: Sat, 2 Mar 2024 07:23:00 -0600 Subject: [PATCH 2/2] f --- src/backend/commands/tablecmds.c | 74 +++++++++++--------------------- 1 file changed, 25 insertions(+), 49 deletions(-) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index cf595329b6c..3f26379b1bd 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -183,8 +183,8 @@ typedef struct AlteredTableInfo List *afterStmts; /* List of utility command parsetrees */ bool verify_new_notnull; /* T if we should recheck NOT NULL */ int rewrite; /* Reason for forced rewrite, if any */ - Oid newAccessMethod; /* new access method; 0 means no change */ - bool defaultAccessMethod; /* true if SET ACCESS METHOD DEFAULT */ + bool chgAccessMethod; /* T if SET ACCESS METHOD is used */ + Oid newAccessMethod; /* new access method; 0 means no change - if above is true */ Oid newTableSpace; /* new tablespace; 0 means no change */ bool chgPersistence; /* T if SET LOGGED/UNLOGGED is used */ char newrelpersistence; /* if above is true */ @@ -590,8 +590,7 @@ static ObjectAddress ATExecClusterOn(Relation rel, const char *indexName, LOCKMODE lockmode); static void ATExecDropCluster(Relation rel, LOCKMODE lockmode); static void ATPrepSetAccessMethod(AlteredTableInfo *tab, Relation rel, const char *amname); -static void ATExecSetAccessMethodNoStorage(Relation rel, Oid newAccessMethod, - bool defaultAccessMethod); +static void ATExecSetAccessMethodNoStorage(Relation rel, Oid newAccessMethod); static bool ATPrepChangePersistence(Relation rel, bool toLogged); static void ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel, const char *tablespacename, LOCKMODE lockmode); @@ -5053,7 +5052,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_MATVIEW); /* check if another access method change was already requested */ - if (OidIsValid(tab->newAccessMethod)) + if (tab->chgAccessMethod) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot have multiple SET ACCESS METHOD subcommands"))); @@ -5413,9 +5412,8 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, * Only do this for partitioned tables, for which this is just a * catalog change. Tables with storage are handled by Phase 3. */ - if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) - ATExecSetAccessMethodNoStorage(rel, tab->newAccessMethod, - tab->defaultAccessMethod); + if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE && tab->chgAccessMethod) + ATExecSetAccessMethodNoStorage(rel, tab->newAccessMethod); break; case AT_SetTableSpace: /* SET TABLESPACE */ @@ -5821,7 +5819,7 @@ ATRewriteTables(AlterTableStmt *parsetree, List **wqueue, LOCKMODE lockmode, * Select destination access method (same as original unless user * requested a change) */ - if (OidIsValid(tab->newAccessMethod)) + if (tab->chgAccessMethod) NewAccessMethod = tab->newAccessMethod; else NewAccessMethod = OldHeap->rd_rel->relam; @@ -6408,7 +6406,7 @@ ATGetQueueEntry(List **wqueue, Relation rel) tab->relkind = rel->rd_rel->relkind; tab->oldDesc = CreateTupleDescCopyConstr(RelationGetDescr(rel)); tab->newAccessMethod = InvalidOid; - tab->defaultAccessMethod = false; + tab->chgAccessMethod = false; tab->newTableSpace = InvalidOid; tab->newrelpersistence = RELPERSISTENCE_PERMANENT; tab->chgPersistence = false; @@ -15225,39 +15223,25 @@ ATPrepSetAccessMethod(AlteredTableInfo *tab, Relation rel, const char *amname) { Oid amoid; - /* Check that the table access method exists */ - amoid = get_table_am_oid(amname ? amname : default_table_access_method, - false); + /* + * Check that the table access method exists. + * Use the access method, if specified, otherwise (when not specified) 0 + * for partitioned tables or the configured default AM. + */ + if (amname != NULL) + amoid = get_table_am_oid(amname, false); + else if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) + amoid = 0; + else + amoid = get_table_am_oid(default_table_access_method, false); - if (RELKIND_HAS_STORAGE(rel->rd_rel->relkind) && - rel->rd_rel->relam == amoid) + if (rel->rd_rel->relam == amoid) return; - /* Partitioned tables are handled here */ - if (!RELKIND_HAS_STORAGE(rel->rd_rel->relkind)) - { - if (amname == NULL) - { - /* DEFAULT implied, leave if relam is already InvalidOid */ - if (!OidIsValid(rel->rd_rel->relam)) - return; - } - else - { - /* - * Access method set by query, leave if only this matches with its - * relam. - */ - if (OidIsValid(rel->rd_rel->relam) && - amoid == rel->rd_rel->relam) - return; - } - } - /* Save info for Phase 3 to do the real work */ tab->rewrite |= AT_REWRITE_ACCESS_METHOD; tab->newAccessMethod = amoid; - tab->defaultAccessMethod = (amname == NULL); + tab->chgAccessMethod = true; } /* @@ -15587,12 +15571,10 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode) * storage that have an interest in preserving AM. * * Since these have no storage, setting the access method is a catalog only - * operation. defaultAccessMethod tracks if a default value is wanted for - * the access method. + * operation. */ static void -ATExecSetAccessMethodNoStorage(Relation rel, Oid newAccessMethodId, - bool defaultAccessMethod) +ATExecSetAccessMethodNoStorage(Relation rel, Oid newAccessMethodId) { Relation pg_class; Oid oldAccessMethodId; @@ -15600,12 +15582,6 @@ ATExecSetAccessMethodNoStorage(Relation rel, Oid newAccessMethodId, Form_pg_class rd_rel; Oid reloid = RelationGetRelid(rel); - if (!OidIsValid(newAccessMethodId)) - { - /* if the access method is unchanged, leave */ - return; - } - /* * Shouldn't be called on relations having storage; these are processed in * phase 3. @@ -15622,7 +15598,7 @@ ATExecSetAccessMethodNoStorage(Relation rel, Oid newAccessMethodId, /* Update the pg_class row. */ oldAccessMethodId = rd_rel->relam; - rd_rel->relam = defaultAccessMethod ? InvalidOid : newAccessMethodId; + rd_rel->relam = newAccessMethodId; /* Leave if no update required */ if (rd_rel->relam == oldAccessMethodId) @@ -15640,7 +15616,7 @@ ATExecSetAccessMethodNoStorage(Relation rel, Oid newAccessMethodId, * that this has to compare the previous value stored in pg_class with the * new one. */ - if (!OidIsValid(oldAccessMethodId) && OidIsValid(rd_rel->relam)) + if (!OidIsValid(oldAccessMethodId) && OidIsValid(newAccessMethodId)) { ObjectAddress relobj, referenced; -- 2.42.0 --Ssywp6WJwi1+mehD--