Hi, David Your answer explains that we still need to ModifyTable node without Leaf partitions. You are right about this.
But you can review the source code again, ``` /* * Fetch rows from subplan, and execute the required table modification * for each row. */ for (;;) { ... /* No more tuples to process? */ if (TupIsNull(planSlot)) break; .... /* * For UPDATE/DELETE, fetch the row identity info for the tuple to be * updated/deleted. For a heap relation, that's a TID; otherwise we * may have a wholerow junk attr that carries the old tuple in toto. * Keep this in step with the part of ExecInitModifyTable that sets up * ri_RowIdAttNo. */ if (operation == CMD_UPDATE || operation == CMD_DELETE) { char relkind; Datum datum; bool isNull; relkind = resultRelInfo->ri_RelationDesc->rd_rel->relkind; if (relkind == RELKIND_RELATION || relkind == RELKIND_MATVIEW || relkind == RELKIND_PARTITIONED_TABLE) ... } ``` We can see that if the scanned tuple is NULL, it will break. Therefore, this step will never be achieved that is to extract ctid. >We'll need some sort of ResultRelInfo in the case that all partitions >are pruned. In this case, the tuple returned should be null. >Using the one for the partitioned table is convenient. I >believe that's required if there are any statement-level triggers on >the partitioned table or if there's a RETURNING clause. If the tuple to be modified is null, you do not need to process RETURNING clause. statement-level triggers cannot use tuple, and triggers on partitioned tables cannot have transition tables. I set Assert(relkind! = RELKIND_PARTITIONED_TABLE); in the code, But it never arrives. Did I not understand your expression clearly? Could you provide me with a case to verify it? Thank you very much for your answer. Regards & Thanks Adger