From a89bce4f39c16dc9e3ad247401b238554e520b87 Mon Sep 17 00:00:00 2001 From: jian he 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