diff options
Diffstat (limited to 'src/backend/executor/nodeModifyTable.c')
-rw-r--r-- | src/backend/executor/nodeModifyTable.c | 166 |
1 files changed, 60 insertions, 106 deletions
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c index fe62da06ead..76175aaa6be 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -255,7 +255,6 @@ ExecInsert(ModifyTableState *mtstate, EState *estate, bool canSetTag) { - HeapTuple tuple; ResultRelInfo *resultRelInfo; Relation resultRelationDesc; List *recheckIndexes = NIL; @@ -264,11 +263,7 @@ ExecInsert(ModifyTableState *mtstate, ModifyTable *node = (ModifyTable *) mtstate->ps.plan; OnConflictAction onconflict = node->onConflictAction; - /* - * get the heap tuple out of the tuple table slot, making sure we have a - * writable copy - */ - tuple = ExecFetchSlotHeapTuple(slot, true, NULL); + ExecMaterializeSlot(slot); /* * get information on the (current) result relation @@ -288,26 +283,16 @@ ExecInsert(ModifyTableState *mtstate, if (resultRelInfo->ri_TrigDesc && resultRelInfo->ri_TrigDesc->trig_insert_before_row) { - slot = ExecBRInsertTriggers(estate, resultRelInfo, slot); - - if (slot == NULL) /* "do nothing" */ - return NULL; - - /* trigger might have changed tuple */ - tuple = ExecFetchSlotHeapTuple(slot, true, NULL); + if (!ExecBRInsertTriggers(estate, resultRelInfo, slot)) + return NULL; /* "do nothing" */ } /* INSTEAD OF ROW INSERT Triggers */ if (resultRelInfo->ri_TrigDesc && resultRelInfo->ri_TrigDesc->trig_insert_instead_row) { - slot = ExecIRInsertTriggers(estate, resultRelInfo, slot); - - if (slot == NULL) /* "do nothing" */ - return NULL; - - /* trigger might have changed tuple */ - tuple = ExecFetchSlotHeapTuple(slot, true, NULL); + if (!ExecIRInsertTriggers(estate, resultRelInfo, slot)) + return NULL; /* "do nothing" */ } else if (resultRelInfo->ri_FdwRoutine) { @@ -322,9 +307,6 @@ ExecInsert(ModifyTableState *mtstate, if (slot == NULL) /* "do nothing" */ return NULL; - /* FDW might have changed tuple */ - tuple = ExecFetchSlotHeapTuple(slot, true, NULL); - /* * AFTER ROW Triggers or RETURNING expressions might reference the * tableoid column, so (re-)initialize tts_tableOid before evaluating @@ -336,6 +318,7 @@ ExecInsert(ModifyTableState *mtstate, else { WCOKind wco_kind; + HeapTuple inserttuple; /* * Constraints might reference the tableoid column, so (re-)initialize @@ -441,6 +424,8 @@ ExecInsert(ModifyTableState *mtstate, } } + inserttuple = ExecFetchSlotHeapTuple(slot, true, NULL); + /* * Before we start insertion proper, acquire our "speculative * insertion lock". Others can use that to wait for us to decide @@ -448,26 +433,26 @@ ExecInsert(ModifyTableState *mtstate, * waiting for the whole transaction to complete. */ specToken = SpeculativeInsertionLockAcquire(GetCurrentTransactionId()); - HeapTupleHeaderSetSpeculativeToken(tuple->t_data, specToken); + HeapTupleHeaderSetSpeculativeToken(inserttuple->t_data, specToken); /* insert the tuple, with the speculative token */ - heap_insert(resultRelationDesc, tuple, + heap_insert(resultRelationDesc, inserttuple, estate->es_output_cid, HEAP_INSERT_SPECULATIVE, NULL); slot->tts_tableOid = RelationGetRelid(resultRelationDesc); - ItemPointerCopy(&tuple->t_self, &slot->tts_tid); + ItemPointerCopy(&inserttuple->t_self, &slot->tts_tid); /* insert index entries for tuple */ - recheckIndexes = ExecInsertIndexTuples(slot, &(tuple->t_self), + recheckIndexes = ExecInsertIndexTuples(slot, &(inserttuple->t_self), estate, true, &specConflict, arbiterIndexes); /* adjust the tuple's state accordingly */ if (!specConflict) - heap_finish_speculative(resultRelationDesc, tuple); + heap_finish_speculative(resultRelationDesc, inserttuple); else - heap_abort_speculative(resultRelationDesc, tuple); + heap_abort_speculative(resultRelationDesc, inserttuple); /* * Wake up anyone waiting for our decision. They will re-check @@ -499,15 +484,16 @@ ExecInsert(ModifyTableState *mtstate, * Note: heap_insert returns the tid (location) of the new tuple * in the t_self field. */ - heap_insert(resultRelationDesc, tuple, + inserttuple = ExecFetchSlotHeapTuple(slot, true, NULL); + heap_insert(resultRelationDesc, inserttuple, estate->es_output_cid, 0, NULL); slot->tts_tableOid = RelationGetRelid(resultRelationDesc); - ItemPointerCopy(&tuple->t_self, &slot->tts_tid); + ItemPointerCopy(&inserttuple->t_self, &slot->tts_tid); /* insert index entries for tuple */ if (resultRelInfo->ri_NumIndices > 0) - recheckIndexes = ExecInsertIndexTuples(slot, &(tuple->t_self), + recheckIndexes = ExecInsertIndexTuples(slot, &(inserttuple->t_self), estate, false, NULL, NIL); } @@ -531,7 +517,7 @@ ExecInsert(ModifyTableState *mtstate, { ExecARUpdateTriggers(estate, resultRelInfo, NULL, NULL, - tuple, + slot, NULL, mtstate->mt_transition_capture); @@ -543,7 +529,7 @@ ExecInsert(ModifyTableState *mtstate, } /* AFTER ROW INSERT Triggers */ - ExecARInsertTriggers(estate, resultRelInfo, tuple, recheckIndexes, + ExecARInsertTriggers(estate, resultRelInfo, slot, recheckIndexes, ar_insert_trig_tcs); list_free(recheckIndexes); @@ -603,7 +589,7 @@ ExecDelete(ModifyTableState *mtstate, bool canSetTag, bool changingPart, bool *tupleDeleted, - TupleTableSlot **epqslot) + TupleTableSlot **epqreturnslot) { ResultRelInfo *resultRelInfo; Relation resultRelationDesc; @@ -628,7 +614,7 @@ ExecDelete(ModifyTableState *mtstate, bool dodelete; dodelete = ExecBRDeleteTriggers(estate, epqstate, resultRelInfo, - tupleid, oldtuple, epqslot); + tupleid, oldtuple, epqreturnslot); if (!dodelete) /* "do nothing" */ return NULL; @@ -651,14 +637,10 @@ ExecDelete(ModifyTableState *mtstate, /* * delete from foreign table: let the FDW do it * - * We offer the trigger tuple slot as a place to store RETURNING data, - * although the FDW can return some other slot if it wants. Set up - * the slot's tupdesc so the FDW doesn't need to do that for itself. + * We offer the returning slot as a place to store RETURNING data, + * although the FDW can return some other slot if it wants. */ - slot = estate->es_trig_tuple_slot; - if (slot->tts_tupleDescriptor != RelationGetDescr(resultRelationDesc)) - ExecSetSlotDescriptor(slot, RelationGetDescr(resultRelationDesc)); - + slot = ExecGetReturningSlot(estate, resultRelInfo); slot = resultRelInfo->ri_FdwRoutine->ExecForeignDelete(estate, resultRelInfo, slot, @@ -673,6 +655,8 @@ ExecDelete(ModifyTableState *mtstate, */ if (TTS_EMPTY(slot)) ExecStoreAllNullTuple(slot); + ExecMaterializeSlot(slot); + slot->tts_tableOid = RelationGetRelid(resultRelationDesc); } else @@ -762,9 +746,9 @@ ldelete:; * If requested, skip delete and pass back the updated * row. */ - if (epqslot) + if (epqreturnslot) { - *epqslot = my_epqslot; + *epqreturnslot = my_epqslot; return NULL; } else @@ -832,34 +816,37 @@ ldelete:; * gotta fetch it. We can use the trigger tuple slot. */ TupleTableSlot *rslot; - HeapTupleData deltuple; - Buffer delbuffer; if (resultRelInfo->ri_FdwRoutine) { /* FDW must have provided a slot containing the deleted row */ Assert(!TupIsNull(slot)); - delbuffer = InvalidBuffer; } else { - slot = estate->es_trig_tuple_slot; + slot = ExecGetReturningSlot(estate, resultRelInfo); if (oldtuple != NULL) { - deltuple = *oldtuple; - delbuffer = InvalidBuffer; + ExecForceStoreHeapTuple(oldtuple, slot); } else { - deltuple.t_self = *tupleid; + BufferHeapTupleTableSlot *bslot; + HeapTuple deltuple; + Buffer buffer; + + Assert(TTS_IS_BUFFERTUPLE(slot)); + ExecClearTuple(slot); + bslot = (BufferHeapTupleTableSlot *) slot; + deltuple = &bslot->base.tupdata; + + deltuple->t_self = *tupleid; if (!heap_fetch(resultRelationDesc, SnapshotAny, - &deltuple, &delbuffer, false, NULL)) + deltuple, &buffer, false, NULL)) elog(ERROR, "failed to fetch deleted tuple for DELETE RETURNING"); - } - if (slot->tts_tupleDescriptor != RelationGetDescr(resultRelationDesc)) - ExecSetSlotDescriptor(slot, RelationGetDescr(resultRelationDesc)); - ExecStoreHeapTuple(&deltuple, slot, false); + ExecStorePinnedBufferHeapTuple(deltuple, slot, buffer); + } } rslot = ExecProcessReturning(resultRelInfo, slot, planSlot); @@ -871,8 +858,6 @@ ldelete:; ExecMaterializeSlot(rslot); ExecClearTuple(slot); - if (BufferIsValid(delbuffer)) - ReleaseBuffer(delbuffer); return rslot; } @@ -912,7 +897,7 @@ ExecUpdate(ModifyTableState *mtstate, EState *estate, bool canSetTag) { - HeapTuple tuple; + HeapTuple updatetuple; ResultRelInfo *resultRelInfo; Relation resultRelationDesc; HTSU_Result result; @@ -926,11 +911,7 @@ ExecUpdate(ModifyTableState *mtstate, if (IsBootstrapProcessingMode()) elog(ERROR, "cannot UPDATE during bootstrap"); - /* - * get the heap tuple out of the tuple table slot, making sure we have a - * writable copy - */ - tuple = ExecFetchSlotHeapTuple(slot, true, NULL); + ExecMaterializeSlot(slot); /* * get information on the (current) result relation @@ -942,28 +923,18 @@ ExecUpdate(ModifyTableState *mtstate, if (resultRelInfo->ri_TrigDesc && resultRelInfo->ri_TrigDesc->trig_update_before_row) { - slot = ExecBRUpdateTriggers(estate, epqstate, resultRelInfo, - tupleid, oldtuple, slot); - - if (slot == NULL) /* "do nothing" */ - return NULL; - - /* trigger might have changed tuple */ - tuple = ExecFetchSlotHeapTuple(slot, true, NULL); + if (!ExecBRUpdateTriggers(estate, epqstate, resultRelInfo, + tupleid, oldtuple, slot)) + return NULL; /* "do nothing" */ } /* INSTEAD OF ROW UPDATE Triggers */ if (resultRelInfo->ri_TrigDesc && resultRelInfo->ri_TrigDesc->trig_update_instead_row) { - slot = ExecIRUpdateTriggers(estate, resultRelInfo, - oldtuple, slot); - - if (slot == NULL) /* "do nothing" */ - return NULL; - - /* trigger might have changed tuple */ - tuple = ExecFetchSlotHeapTuple(slot, true, NULL); + if (!ExecIRUpdateTriggers(estate, resultRelInfo, + oldtuple, slot)) + return NULL; /* "do nothing" */ } else if (resultRelInfo->ri_FdwRoutine) { @@ -978,9 +949,6 @@ ExecUpdate(ModifyTableState *mtstate, if (slot == NULL) /* "do nothing" */ return NULL; - /* FDW might have changed tuple */ - tuple = ExecFetchSlotHeapTuple(slot, true, NULL); - /* * AFTER ROW Triggers or RETURNING expressions might reference the * tableoid column, so (re-)initialize tts_tableOid before evaluating @@ -1107,7 +1075,6 @@ lreplace:; else { slot = ExecFilterJunk(resultRelInfo->ri_junkFilter, epqslot); - tuple = ExecFetchSlotHeapTuple(slot, true, NULL); goto lreplace; } } @@ -1178,12 +1145,14 @@ lreplace:; * needed for referential integrity updates in transaction-snapshot * mode transactions. */ - result = heap_update(resultRelationDesc, tupleid, tuple, + updatetuple = ExecFetchSlotHeapTuple(slot, true, NULL); + result = heap_update(resultRelationDesc, tupleid, + updatetuple, estate->es_output_cid, estate->es_crosscheck_snapshot, true /* wait for commit */ , &hufd, &lockmode); - ItemPointerCopy(&tuple->t_self, &slot->tts_tid); + ItemPointerCopy(&updatetuple->t_self, &slot->tts_tid); switch (result) { @@ -1249,7 +1218,6 @@ lreplace:; { *tupleid = hufd.ctid; slot = ExecFilterJunk(resultRelInfo->ri_junkFilter, epqslot); - tuple = ExecFetchSlotHeapTuple(slot, true, NULL); goto lreplace; } } @@ -1277,8 +1245,8 @@ lreplace:; * * If it's a HOT update, we mustn't insert new index entries. */ - if (resultRelInfo->ri_NumIndices > 0 && !HeapTupleIsHeapOnly(tuple)) - recheckIndexes = ExecInsertIndexTuples(slot, &(tuple->t_self), + if (resultRelInfo->ri_NumIndices > 0 && !HeapTupleIsHeapOnly(updatetuple)) + recheckIndexes = ExecInsertIndexTuples(slot, &(updatetuple->t_self), estate, false, NULL, NIL); } @@ -1286,7 +1254,7 @@ lreplace:; (estate->es_processed)++; /* AFTER ROW UPDATE Triggers */ - ExecARUpdateTriggers(estate, resultRelInfo, tupleid, oldtuple, tuple, + ExecARUpdateTriggers(estate, resultRelInfo, tupleid, oldtuple, slot, recheckIndexes, mtstate->operation == CMD_INSERT ? mtstate->mt_oc_transition_capture : @@ -1669,7 +1637,6 @@ ExecPrepareTupleRouting(ModifyTableState *mtstate, ModifyTable *node; ResultRelInfo *partrel; PartitionRoutingInfo *partrouteinfo; - HeapTuple tuple; TupleConversionMap *map; /* @@ -1688,9 +1655,6 @@ ExecPrepareTupleRouting(ModifyTableState *mtstate, */ estate->es_result_relation_info = partrel; - /* Get the heap tuple out of the given slot. */ - tuple = ExecFetchSlotHeapTuple(slot, true, NULL); - /* * If we're capturing transition tuples, we might need to convert from the * partition rowtype to root partitioned table's rowtype. @@ -1714,7 +1678,7 @@ ExecPrepareTupleRouting(ModifyTableState *mtstate, * Otherwise, just remember the original unconverted tuple, to * avoid a needless round trip conversion. */ - mtstate->mt_transition_capture->tcs_original_insert_tuple = tuple; + mtstate->mt_transition_capture->tcs_original_insert_tuple = slot; mtstate->mt_transition_capture->tcs_map = NULL; } } @@ -2542,16 +2506,6 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) } /* - * Set up a tuple table slot for use for trigger output tuples. In a plan - * containing multiple ModifyTable nodes, all can share one such slot, so - * we keep it in the estate. The tuple being inserted doesn't come from a - * buffer. - */ - if (estate->es_trig_tuple_slot == NULL) - estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate, NULL, - &TTSOpsHeapTuple); - - /* * Lastly, if this is not the primary (canSetTag) ModifyTable node, add it * to estate->es_auxmodifytables so that it will be run to completion by * ExecPostprocessPlan. (It'd actually work fine to add the primary |