@@ -230,14 +230,17 @@ setup_on_conflict_state(ResultRelInfo *ht_rri, ModifyTableState *mtstate, ChunkI
230230 Relation hyper_rel = ht_rri -> ri_RelationDesc ;
231231 ModifyTable * mt = castNode (ModifyTable , mtstate -> ps .plan );
232232
233+ /* DO UPDATE has a SET clause; DO SELECT only fetches the conflicting row. */
234+ bool do_update = mt -> onConflictAction == ONCONFLICT_UPDATE ;
235+
233236 OnConflictActionState * onconfl = makeNode (OnConflictActionState );
234237 memcpy (onconfl , ht_rri -> ri_onConflict , sizeof (OnConflictActionState ));
235238 chunk_rri -> ri_onConflict = onconfl ;
236239
237240 chunk_rri -> ri_RootToChildMap = map ;
238241 chunk_rri -> ri_RootToChildMapValid = true;
239242
240- Assert (mt -> onConflictSet );
243+ Assert (! do_update || mt -> onConflictSet );
241244 Assert (ht_rri -> ri_onConflict != NULL );
242245
243246 /*
@@ -271,18 +274,6 @@ setup_on_conflict_state(ResultRelInfo *ht_rri, ModifyTableState *mtstate, ChunkI
271274 }
272275 else
273276 {
274- List * onconflset ;
275- List * onconflcols ;
276-
277- /*
278- * Translate expressions in onConflictSet to account for
279- * different attribute numbers. For that, map partition
280- * varattnos twice: first to catch the EXCLUDED
281- * pseudo-relation (INNER_VAR), and second to handle the main
282- * target relation (firstVarno).
283- */
284- onconflset = copyObject (mt -> onConflictSet );
285-
286277 Assert (map -> outdesc == RelationGetDescr (chunk_rel ));
287278
288279 if (!chunk_map )
@@ -291,33 +282,48 @@ setup_on_conflict_state(ResultRelInfo *ht_rri, ModifyTableState *mtstate, ChunkI
291282 convert_tuples_by_name (RelationGetDescr (chunk_rel ), RelationGetDescr (hyper_rel ));
292283 }
293284
294- onconflset = translate_clause (onconflset , chunk_map , ht_rri -> ri_RangeTableIndex , chunk_rel );
295-
296285 chunk_rri -> ri_ChildToRootMap = chunk_map ;
297286 chunk_rri -> ri_ChildToRootMapValid = true;
298287
299- /* Finally, adjust the target colnos to match the chunk. */
300- if (chunk_map )
288+ if (do_update )
301289 {
302- onconflcols = adjust_chunk_colnos (mt -> onConflictCols , chunk_rri );
290+ List * onconflset ;
291+ List * onconflcols ;
292+
293+ /*
294+ * Translate expressions in onConflictSet to account for
295+ * different attribute numbers. For that, map partition
296+ * varattnos twice: first to catch the EXCLUDED
297+ * pseudo-relation (INNER_VAR), and second to handle the main
298+ * target relation (firstVarno).
299+ */
300+ onconflset = copyObject (mt -> onConflictSet );
301+ onconflset =
302+ translate_clause (onconflset , chunk_map , ht_rri -> ri_RangeTableIndex , chunk_rel );
303+
304+ /*
305+ * Finally, adjust the target colnos to match the chunk. When the
306+ * descriptors match (e.g. a direct chunk insert) there is no
307+ * child-to-root map and the parent colnos apply unchanged.
308+ */
309+ if (chunk_map )
310+ onconflcols = adjust_chunk_colnos (mt -> onConflictCols , chunk_rri );
311+ else
312+ onconflcols = mt -> onConflictCols ;
313+
314+ /* create the tuple slot for the UPDATE SET projection */
315+ onconfl -> oc_ProjSlot = table_slot_create (chunk_rel , NULL );
316+ state -> conflproj_slot = onconfl -> oc_ProjSlot ;
317+
318+ /* build UPDATE SET projection state */
319+ onconfl -> oc_ProjInfo = ExecBuildUpdateProjection (onconflset ,
320+ true,
321+ onconflcols ,
322+ RelationGetDescr (chunk_rel ),
323+ mtstate -> ps .ps_ExprContext ,
324+ onconfl -> oc_ProjSlot ,
325+ & mtstate -> ps );
303326 }
304- else
305- {
306- onconflcols = mt -> onConflictCols ;
307- }
308-
309- /* create the tuple slot for the UPDATE SET projection */
310- onconfl -> oc_ProjSlot = table_slot_create (chunk_rel , NULL );
311- state -> conflproj_slot = onconfl -> oc_ProjSlot ;
312-
313- /* build UPDATE SET projection state */
314- onconfl -> oc_ProjInfo = ExecBuildUpdateProjection (onconflset ,
315- true,
316- onconflcols ,
317- RelationGetDescr (chunk_rel ),
318- mtstate -> ps .ps_ExprContext ,
319- onconfl -> oc_ProjSlot ,
320- & mtstate -> ps );
321327
322328 Node * onconflict_where = mt -> onConflictWhere ;
323329
@@ -406,7 +412,11 @@ adjust_projections(ResultRelInfo *ht_rri, ModifyTableState *mtstate, ChunkInsert
406412 {
407413 set_arbiter_indexes (cis , ht_rri -> ri_onConflictArbiterIndexes );
408414
409- if (onConflictAction == ONCONFLICT_UPDATE )
415+ if (onConflictAction == ONCONFLICT_UPDATE
416+ #if PG19_GE
417+ || onConflictAction == ONCONFLICT_SELECT
418+ #endif
419+ )
410420 {
411421 setup_on_conflict_state (ht_rri , mtstate , cis , chunk_map );
412422 }
0 commit comments