v52-0001-refactor-MergePartitionsMoveRows.no-cfbot

application/octet-stream

Filename: v52-0001-refactor-MergePartitionsMoveRows.no-cfbot
Type: application/octet-stream
Part: 0
Message: Re: Add SPLIT PARTITION/MERGE PARTITIONS commands
From a89bce4f39c16dc9e3ad247401b238554e520b87 Mon Sep 17 00:00:00 2001
From: jian he <jian.universality@gmail.com>
Date: Thu, 21 Aug 2025 10:49:50 +0800
Subject: [PATCH v52 1/1] refactor MergePartitionsMoveRows

mainly make MergePartitionsMoveRows more aligned with ATRewriteTable.
based on v52-0001-Implement-ALTER-TABLE-.-MERGE-PARTITIONS-.-comma.patch

also convert one ereport(ERROR...) to elog(ERROR ...)
within createTableConstraints.
---
 src/backend/commands/tablecmds.c | 105 ++++++++++++++-----------------
 1 file changed, 48 insertions(+), 57 deletions(-)

diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index cc24a92c504..9ecd1838077 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -22133,52 +22133,6 @@ buildExpressionExecutionStates(AlteredTableInfo *tab, Relation newPartRel, EStat
 	}
 }
 
-/*
- * evaluateGeneratedExpressionsAndCheckConstraints: evaluate any generated
- * expressions for "tab" (AlteredTableInfo structure) whose inputs come from
- * the new tuple (insertslot) of new partition (newPartRel).
- */
-static void
-evaluateGeneratedExpressionsAndCheckConstraints(AlteredTableInfo *tab,
-												Relation newPartRel,
-												TupleTableSlot *insertslot,
-												ExprContext *econtext)
-{
-	econtext->ecxt_scantuple = insertslot;
-
-	foreach_ptr(NewColumnValue, ex, tab->newvals)
-	{
-		if (!ex->is_generated)
-			continue;
-
-		insertslot->tts_values[ex->attnum - 1]
-			= ExecEvalExpr(ex->exprstate,
-						   econtext,
-						   &insertslot->tts_isnull[ex->attnum - 1]);
-	}
-
-	foreach_ptr(NewConstraint, con, tab->constraints)
-	{
-		switch (con->contype)
-		{
-			case CONSTR_CHECK:
-				if (!ExecCheck(con->qualstate, econtext))
-					ereport(ERROR,
-							errcode(ERRCODE_CHECK_VIOLATION),
-							errmsg("check constraint \"%s\" of relation \"%s\" is violated by some row",
-								   con->name, RelationGetRelationName(newPartRel)),
-							errtableconstraint(newPartRel, con->name));
-				break;
-			case CONSTR_NOTNULL:
-			case CONSTR_FOREIGN:
-				/* Nothing to do here */
-				break;
-			default:
-				elog(ERROR, "unrecognized constraint type: %d",
-					 (int) con->contype);
-		}
-	}
-}
 
 /*
  * getAttributesList: build a list of columns (ColumnDef) based on parent_rel
@@ -22363,12 +22317,9 @@ createTableConstraints(List **wqueue, AlteredTableInfo *tab,
 		 * possible to guarantee it would work in future.
 		 */
 		if (found_whole_row)
-			ereport(ERROR,
-					errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-					errmsg("cannot convert whole-row table reference"),
-					errdetail("Constraint \"%s\" contains a whole-row reference to table \"%s\".",
-							  ccname,
-							  RelationGetRelationName(parent_rel)));
+			elog(ERROR, "Constraint \"%s\" contains a whole-row reference to table \"%s\".",
+						 ccname,
+						 RelationGetRelationName(parent_rel));
 
 		constr = makeNode(Constraint);
 		constr->contype = CONSTR_CHECK;
@@ -22580,7 +22531,6 @@ MergePartitionsMoveRows(List **wqueue, List *mergingPartitions, Relation newPart
 {
 	CommandId	mycid;
 	EState	   *estate;
-	ExprContext *econtext;
 	AlteredTableInfo *tab;
 	ListCell   *ltab;
 
@@ -22597,8 +22547,6 @@ MergePartitionsMoveRows(List **wqueue, List *mergingPartitions, Relation newPart
 
 	buildExpressionExecutionStates(tab, newPartRel, estate);
 
-	econtext = GetPerTupleExprContext(estate);
-
 	mycid = GetCurrentCommandId(true);
 
 	/* Prepare a BulkInsertState for table_tuple_insert. */
@@ -22609,12 +22557,16 @@ MergePartitionsMoveRows(List **wqueue, List *mergingPartitions, Relation newPart
 
 	foreach_oid(merging_oid, mergingPartitions)
 	{
+		ExprContext *econtext;
 		TupleTableSlot *srcslot;
 		TupleConversionMap *tuple_map;
 		TableScanDesc scan;
+		MemoryContext oldCxt;
 		Snapshot	snapshot;
 		Relation	mergingPartition;
 
+		econtext = GetPerTupleExprContext(estate);
+
 		/*
 		 * Partition is already locked in the transformPartitionCmdForMerge
 		 * function.
@@ -22635,6 +22587,12 @@ MergePartitionsMoveRows(List **wqueue, List *mergingPartitions, Relation newPart
 		snapshot = RegisterSnapshot(GetLatestSnapshot());
 		scan = table_beginscan(mergingPartition, snapshot, 0, NULL);
 
+		/*
+		 * Switch to per-tuple memory context and reset it for each tuple
+		 * produced, so we don't leak memory.
+		 */
+		oldCxt = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
+
 		while (table_scan_getnextslot(scan, ForwardScanDirection, srcslot))
 		{
 			TupleTableSlot *insertslot;
@@ -22676,9 +22634,41 @@ MergePartitionsMoveRows(List **wqueue, List *mergingPartitions, Relation newPart
 			 * the new tuple.  We assume these columns won't reference each
 			 * other, so that there's no ordering dependency.
 			 */
-			evaluateGeneratedExpressionsAndCheckConstraints(tab, newPartRel,
-															insertslot, econtext);
+			econtext->ecxt_scantuple = insertslot;
 
+			foreach_ptr(NewColumnValue, ex, tab->newvals)
+			{
+				if (!ex->is_generated)
+					continue;
+
+				insertslot->tts_values[ex->attnum - 1]
+					= ExecEvalExpr(ex->exprstate,
+								econtext,
+								&insertslot->tts_isnull[ex->attnum - 1]);
+			}
+
+			/* Now check any constraints */
+			foreach_ptr(NewConstraint, con, tab->constraints)
+			{
+				switch (con->contype)
+				{
+					case CONSTR_CHECK:
+						if (!ExecCheck(con->qualstate, econtext))
+							ereport(ERROR,
+									errcode(ERRCODE_CHECK_VIOLATION),
+									errmsg("check constraint \"%s\" of relation \"%s\" is violated by some row",
+										   con->name, RelationGetRelationName(newPartRel)),
+									errtableconstraint(newPartRel, con->name));
+						break;
+					case CONSTR_NOTNULL:
+					case CONSTR_FOREIGN:
+						/* Nothing to do here */
+						break;
+					default:
+						elog(ERROR, "unrecognized constraint type: %d",
+									(int) con->contype);
+				}
+			}
 			/* Write the tuple out to the new relation. */
 			table_tuple_insert(newPartRel, insertslot, mycid,
 							   ti_options, bistate);
@@ -22686,6 +22676,7 @@ MergePartitionsMoveRows(List **wqueue, List *mergingPartitions, Relation newPart
 			ResetExprContext(econtext);
 		}
 
+		MemoryContextSwitchTo(oldCxt);
 		table_endscan(scan);
 		UnregisterSnapshot(snapshot);
 
-- 
2.34.1