partitioned-table-ctid-check.diff

application/octet-stream

Filename: partitioned-table-ctid-check.diff
Type: application/octet-stream
Part: 0
Message: Re: BUG #19099: Conditional DELETE from partitioned table with non-updatable partition raises internal error
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 4c5647ac38a..78394be67ea 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -4348,8 +4348,13 @@ ExecModifyTable(PlanState *pstate)
 				relkind == RELKIND_MATVIEW ||
 				relkind == RELKIND_PARTITIONED_TABLE)
 			{
-				/* ri_RowIdAttNo refers to a ctid attribute */
-				Assert(AttributeNumberIsValid(resultRelInfo->ri_RowIdAttNo));
+				/*
+				 * ri_RowIdAttNo refers to a ctid attribute.  It may be missing
+				 * only for non-MERGE operations on partitioned tables.
+				 */
+				Assert(AttributeNumberIsValid(resultRelInfo->ri_RowIdAttNo) ||
+					   (relkind == RELKIND_PARTITIONED_TABLE &&
+						operation != CMD_MERGE));
 				datum = ExecGetJunkAttribute(slot,
 											 resultRelInfo->ri_RowIdAttNo,
 											 &isNull);
@@ -4863,7 +4868,14 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
 			{
 				resultRelInfo->ri_RowIdAttNo =
 					ExecFindJunkAttributeInTlist(subplan->targetlist, "ctid");
-				if (!AttributeNumberIsValid(resultRelInfo->ri_RowIdAttNo))
+
+				/*
+				 * For heap relations, a ctid junk attribute must be present.
+				 * For partitioned tables, require it only for MERGE; allow it to be
+				 * missing for non-MERGE operations.
+				 */
+				if (!AttributeNumberIsValid(resultRelInfo->ri_RowIdAttNo) &&
+					(relkind != RELKIND_PARTITIONED_TABLE || operation == CMD_MERGE))
 					elog(ERROR, "could not find junk ctid column");
 			}
 			else if (relkind == RELKIND_FOREIGN_TABLE)