2424 *		values plus row-locating info for UPDATE and MERGE cases, or just the 
2525 *		row-locating info for DELETE cases. 
2626 * 
27-  *		The relation to modify can be an ordinary table, a view having an 
28-  *		INSTEAD OF trigger, or a foreign table.  Earlier processing already 
29-  *		pointed ModifyTable to the underlying relations of any automatically 
30-  *		updatable view not using an INSTEAD OF trigger, so code here can 
31-  *		assume it won't have one as a modification target.  This node does 
32-  *		process ri_WithCheckOptions, which may have expressions from those 
27+  *		The relation to modify can be an ordinary table, a foreign table, or a 
28+  *		view.  If it's a view, either it has sufficient INSTEAD OF triggers or 
29+  *		this node executes only MERGE ... DO NOTHING.  If the original MERGE 
30+  *		targeted a view not in one of those two categories, earlier processing 
31+  *		already pointed the ModifyTable result relation to an underlying 
32+  *		relation of that other view.  This node does process 
33+  *		ri_WithCheckOptions, which may have expressions from those other, 
3334 *		automatically updatable views. 
3435 * 
3536 *		MERGE runs a join between the source relation and the target table. 
@@ -2726,10 +2727,10 @@ ExecMerge(ModifyTableContext *context, ResultRelInfo *resultRelInfo,
27262727
27272728	/*----- 
27282729	 * If we are dealing with a WHEN MATCHED case, tupleid or oldtuple is 
2729- 	 * valid, depending on whether the result relation is a table or a view 
2730- 	 * having an INSTEAD OF trigger.   We execute the first action for which 
2731- 	 * the additional WHEN MATCHED AND  quals pass.  If an action without quals 
2732- 	 * is found, that action is  executed. 
2730+ 	 * valid, depending on whether the result relation is a table or a view.  
2731+ 	 * We execute the first action for which the additional WHEN MATCHED AND  
2732+ 	 * quals pass.  If an action without quals is found, that action is  
2733+ 	 * executed. 
27332734	 * 
27342735	 * Similarly, in the WHEN NOT MATCHED BY SOURCE case, tupleid or oldtuple 
27352736	 * is valid, and we look at the given WHEN NOT MATCHED BY SOURCE actions 
@@ -2820,8 +2821,8 @@ ExecMerge(ModifyTableContext *context, ResultRelInfo *resultRelInfo,
28202821 * Check and execute the first qualifying MATCHED or NOT MATCHED BY SOURCE 
28212822 * action, depending on whether the join quals are satisfied.  If the target 
28222823 * relation is a table, the current target tuple is identified by tupleid. 
2823-  * Otherwise, if the target relation is a view having an INSTEAD OF trigger,  
2824-  * oldtuple is the current target  tuple from the view. 
2824+  * Otherwise, if the target relation is a view, oldtuple is the current target  
2825+  * tuple from the view. 
28252826 * 
28262827 * We start from the first WHEN MATCHED or WHEN NOT MATCHED BY SOURCE action 
28272828 * and check if the WHEN quals pass, if any. If the WHEN quals for the first 
@@ -2887,11 +2888,8 @@ ExecMergeMatched(ModifyTableContext *context, ResultRelInfo *resultRelInfo,
28872888	 */ 
28882889	Assert (tupleid  !=  NULL  ||  oldtuple  !=  NULL );
28892890	if  (oldtuple  !=  NULL )
2890- 	{
2891- 		Assert (resultRelInfo -> ri_TrigDesc );
28922891		ExecForceStoreHeapTuple (oldtuple , resultRelInfo -> ri_oldTupleSlot ,
28932892								false);
2894- 	}
28952893	else  if  (!table_tuple_fetch_row_version (resultRelInfo -> ri_RelationDesc ,
28962894											tupleid ,
28972895											SnapshotAny ,
@@ -2983,6 +2981,9 @@ ExecMergeMatched(ModifyTableContext *context, ResultRelInfo *resultRelInfo,
29832981				}
29842982				else 
29852983				{
2984+ 					/* called table_tuple_fetch_row_version() above */ 
2985+ 					Assert (oldtuple  ==  NULL );
2986+ 
29862987					result  =  ExecUpdateAct (context , resultRelInfo , tupleid ,
29872988										   NULL , newslot , canSetTag ,
29882989										   & updateCxt );
@@ -3031,8 +3032,13 @@ ExecMergeMatched(ModifyTableContext *context, ResultRelInfo *resultRelInfo,
30313032						return  NULL ;	/* "do nothing" */ 
30323033				}
30333034				else 
3035+ 				{
3036+ 					/* called table_tuple_fetch_row_version() above */ 
3037+ 					Assert (oldtuple  ==  NULL );
3038+ 
30343039					result  =  ExecDeleteAct (context , resultRelInfo , tupleid ,
30353040										   false);
3041+ 				}
30363042
30373043				if  (result  ==  TM_Ok )
30383044				{
@@ -4004,8 +4010,8 @@ ExecModifyTable(PlanState *pstate)
40044010			 * know enough here to set t_tableOid.  Quite separately from 
40054011			 * this, the FDW may fetch its own junk attrs to identify the row. 
40064012			 * 
4007- 			 * Other relevant relkinds, currently limited to views having  
4008- 			 * INSTEAD OF triggers, always  have a wholerow attribute. 
4013+ 			 * Other relevant relkinds, currently limited to views, always  
4014+ 			 * have a wholerow attribute. 
40094015			 */ 
40104016			else  if  (AttributeNumberIsValid (resultRelInfo -> ri_RowIdAttNo ))
40114017			{
0 commit comments