From a69348b59307ab85a051ea17aabca3150a391eae Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryzbyj@telsasoft.com>
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

