From 068900d2c41aa7383363b304636c1f11cd9c1f8b Mon Sep 17 00:00:00 2001
From: "Chao Li (Evan)" <lic@highgo.com>
Date: Mon, 29 Sep 2025 17:11:25 +0800
Subject: [PATCH v4 2/2] The other implementation.

Author: Chao Li <lic@highgo.com>
---
 src/backend/commands/tablecmds.c | 47 ++++++++++++--------------------
 1 file changed, 17 insertions(+), 30 deletions(-)

diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 4443b69c156..3791666834c 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -5296,20 +5296,7 @@ ATRewriteCatalogs(List **wqueue, LOCKMODE lockmode,
 				  AlterTableUtilityContext *context)
 {
 	ListCell   *ltab;
-	List		*relids = NIL;
-
-	/*
-	 * Collect relation that both type and generation expression are changed.
-	*/
-	foreach(ltab, *wqueue)
-	{
-		AlteredTableInfo *tab = (AlteredTableInfo *) lfirst(ltab);
-		List	   *subcmds1 = tab->subcmds[AT_PASS_SET_EXPRESSION];
-		List	   *subcmds2 = tab->subcmds[AT_PASS_ALTER_TYPE];
-
-		if (subcmds1 != NIL && subcmds2 != NIL)
-			relids = lappend_oid(relids, tab->relid);
-	}
+	AlteredTableInfo		**tabsForAltTypeCleanup = palloc0(sizeof(AlteredTableInfo *) * list_length(*wqueue));
 
 	/*
 	 * We process all the tables "in parallel", one pass at a time.  This is
@@ -5320,6 +5307,8 @@ ATRewriteCatalogs(List **wqueue, LOCKMODE lockmode,
 	 */
 	for (AlterTablePass pass = 0; pass < AT_NUM_PASSES; pass++)
 	{
+		int tabIdx = -1;
+
 		/* Go through each table that needs to be processed */
 		foreach(ltab, *wqueue)
 		{
@@ -5327,6 +5316,17 @@ ATRewriteCatalogs(List **wqueue, LOCKMODE lockmode,
 			List	   *subcmds = tab->subcmds[pass];
 			ListCell   *lcmd;
 
+			/*
+			 * Cleanup work for ALTER TYPE or SET EXPRESSION. We must perform
+			 * this cleanup after both ALTER TYPE and SET EXPRESSION are done.
+			 */
+			tabIdx += 1;
+			if (pass == AT_PASS_SET_EXPRESSION+1 && tabsForAltTypeCleanup[tabIdx] != NULL)
+			{
+				ATPostAlterTypeCleanup(wqueue, tabsForAltTypeCleanup[tabIdx], lockmode);
+				tabsForAltTypeCleanup[tabIdx] = NULL;
+			}
+
 			if (subcmds == NIL)
 				continue;
 
@@ -5342,22 +5342,8 @@ ATRewriteCatalogs(List **wqueue, LOCKMODE lockmode,
 						  lfirst_node(AlterTableCmd, lcmd),
 						  lockmode, pass, context);
 
-			/*
-			 * After the ALTER TYPE or SET EXPRESSION pass, do cleanup work
-			 * (this is not done in ATExecAlterColumnType since it should be
-			 * done only once if multiple columns of a table are altered).
-			 */
-			if (list_member_oid(relids, tab->relid))
-			{
-				/*
-				 * If both type and generation expression being changed, do the
-				 * cleanup at AT_PASS_SET_EXPRESSION
-				 */
-				if (pass == AT_PASS_SET_EXPRESSION)
-					ATPostAlterTypeCleanup(wqueue, tab, lockmode);
-			}
-			else if (pass == AT_PASS_ALTER_TYPE || pass == AT_PASS_SET_EXPRESSION)
-				ATPostAlterTypeCleanup(wqueue, tab, lockmode);
+			if (pass == AT_PASS_ALTER_TYPE || pass == AT_PASS_SET_EXPRESSION)
+				tabsForAltTypeCleanup[tabIdx] = tab;
 
 			if (tab->rel)
 			{
@@ -5366,6 +5352,7 @@ ATRewriteCatalogs(List **wqueue, LOCKMODE lockmode,
 			}
 		}
 	}
+	pfree(tabsForAltTypeCleanup);
 
 	/* Check to see if a toast table must be added. */
 	foreach(ltab, *wqueue)
-- 
2.39.5 (Apple Git-154)

