/* * Insert tuple represented in the slot to the relation, update the indexes, * and execute any constraints and per-row triggers. * * Caller is responsible for opening the indexes. */ void ExecSimpleRelationInsert(EState *estate, TupleTableSlot *slot) { bool skip_tuple = false; HeapTuple tuple; ResultRelInfo *resultRelInfo = estate->es_result_relation_info; Relation rel = resultRelInfo->ri_RelationDesc; /* For now we support only tables. */ Assert(rel->rd_rel->relkind == RELKIND_RELATION); CheckCmdReplicaIdentity(rel, CMD_INSERT); /* BEFORE ROW INSERT Triggers */ if (resultRelInfo->ri_TrigDesc && resultRelInfo->ri_TrigDesc->trig_insert_before_row) { slot = ExecBRInsertTriggers(estate, resultRelInfo, slot); if (slot == NULL) /* "do nothing" */ skip_tuple = true; } if (!skip_tuple) { List *recheckIndexes = NIL; /* Check the constraints of the tuple */ if (rel->rd_att->constr) ExecConstraints(resultRelInfo, slot, estate); if (resultRelInfo->ri_PartitionCheck) ExecPartitionCheck(resultRelInfo, slot, estate, true); /* Materialize slot into a tuple that we can scribble upon. */ tuple = ExecFetchSlotHeapTuple(slot, true, NULL); /* OK, store the tuple and create index entries for it */ simple_heap_insert(rel, tuple); if (resultRelInfo->ri_NumIndices > 0) recheckIndexes = ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false, NULL, NIL); /* AFTER ROW INSERT Triggers */ ExecARInsertTriggers(estate, resultRelInfo, tuple, recheckIndexes, NULL); /* * XXX we should in theory pass a TransitionCaptureState object to the * above to capture transition tuples, but after statement triggers * don't actually get fired by replication yet anyway */ list_free(recheckIndexes); } }
/* * Find the searchslot tuple and update it with data in the slot, * update the indexes, and execute any constraints and per-row triggers. * * Caller is responsible for opening the indexes. */ void ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate, TupleTableSlot *searchslot, TupleTableSlot *slot) { bool skip_tuple = false; HeapTuple tuple; ResultRelInfo *resultRelInfo = estate->es_result_relation_info; Relation rel = resultRelInfo->ri_RelationDesc; /* For now we support only tables. */ Assert(rel->rd_rel->relkind == RELKIND_RELATION); CheckCmdReplicaIdentity(rel, CMD_UPDATE); /* BEFORE ROW INSERT Triggers */ if (resultRelInfo->ri_TrigDesc && resultRelInfo->ri_TrigDesc->trig_update_before_row) { slot = ExecBRUpdateTriggers(estate, epqstate, resultRelInfo, &searchslot->tts_tuple->t_self, NULL, slot); if (slot == NULL) /* "do nothing" */ skip_tuple = true; } if (!skip_tuple) { List *recheckIndexes = NIL; /* Check the constraints of the tuple */ if (rel->rd_att->constr) ExecConstraints(resultRelInfo, slot, estate); /* Store the slot into tuple that we can write. */ tuple = ExecMaterializeSlot(slot); /* OK, update the tuple and index entries for it */ simple_heap_update(rel, &searchslot->tts_tuple->t_self, slot->tts_tuple); if (resultRelInfo->ri_NumIndices > 0 && !HeapTupleIsHeapOnly(slot->tts_tuple)) recheckIndexes = ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false, NULL, NIL); /* AFTER ROW UPDATE Triggers */ ExecARUpdateTriggers(estate, resultRelInfo, &searchslot->tts_tuple->t_self, NULL, tuple, recheckIndexes); list_free(recheckIndexes); } }
/* * Find the searchslot tuple and delete it, and execute any constraints * and per-row triggers. * * Caller is responsible for opening the indexes. */ void ExecSimpleRelationDelete(EState *estate, EPQState *epqstate, TupleTableSlot *searchslot) { bool skip_tuple = false; ResultRelInfo *resultRelInfo = estate->es_result_relation_info; Relation rel = resultRelInfo->ri_RelationDesc; HeapTupleTableSlot *hsearchslot = (HeapTupleTableSlot *)searchslot; /* For now we support only tables and heap tuples. */ Assert(rel->rd_rel->relkind == RELKIND_RELATION); Assert(TTS_IS_HEAPTUPLE(searchslot) || TTS_IS_BUFFERTUPLE(searchslot)); CheckCmdReplicaIdentity(rel, CMD_DELETE); /* BEFORE ROW DELETE Triggers */ if (resultRelInfo->ri_TrigDesc && resultRelInfo->ri_TrigDesc->trig_delete_before_row) { skip_tuple = !ExecBRDeleteTriggers(estate, epqstate, resultRelInfo, &hsearchslot->tuple->t_self, NULL, NULL); } if (!skip_tuple) { List *recheckIndexes = NIL; /* OK, delete the tuple */ simple_heap_delete(rel, &hsearchslot->tuple->t_self); /* AFTER ROW DELETE Triggers */ ExecARDeleteTriggers(estate, resultRelInfo, &hsearchslot->tuple->t_self, NULL, NULL); list_free(recheckIndexes); } }
/* * Find the searchslot tuple and update it with data in the slot, * update the indexes, and execute any constraints and per-row triggers. * * Caller is responsible for opening the indexes. */ void ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate, TupleTableSlot *searchslot, TupleTableSlot *slot) { bool skip_tuple = false; HeapTuple tuple; ResultRelInfo *resultRelInfo = estate->es_result_relation_info; Relation rel = resultRelInfo->ri_RelationDesc; HeapTupleTableSlot *hsearchslot = (HeapTupleTableSlot *)searchslot; HeapTupleTableSlot *hslot = (HeapTupleTableSlot *)slot; /* We expect both searchslot and the slot to contain a heap tuple. */ Assert(TTS_IS_HEAPTUPLE(searchslot) || TTS_IS_BUFFERTUPLE(searchslot)); Assert(TTS_IS_HEAPTUPLE(slot) || TTS_IS_BUFFERTUPLE(slot)); /* For now we support only tables. */ Assert(rel->rd_rel->relkind == RELKIND_RELATION); CheckCmdReplicaIdentity(rel, CMD_UPDATE); /* BEFORE ROW UPDATE Triggers */ if (resultRelInfo->ri_TrigDesc && resultRelInfo->ri_TrigDesc->trig_update_before_row) { slot = ExecBRUpdateTriggers(estate, epqstate, resultRelInfo, &hsearchslot->tuple->t_self, NULL, slot); if (slot == NULL) /* "do nothing" */ skip_tuple = true; } if (!skip_tuple) { List *recheckIndexes = NIL; /* Check the constraints of the tuple */ if (rel->rd_att->constr) ExecConstraints(resultRelInfo, slot, estate); if (resultRelInfo->ri_PartitionCheck) ExecPartitionCheck(resultRelInfo, slot, estate, true); /* Materialize slot into a tuple that we can scribble upon. */ tuple = ExecFetchSlotHeapTuple(slot, true, NULL); /* OK, update the tuple and index entries for it */ simple_heap_update(rel, &hsearchslot->tuple->t_self, hslot->tuple); if (resultRelInfo->ri_NumIndices > 0 && !HeapTupleIsHeapOnly(hslot->tuple)) recheckIndexes = ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false, NULL, NIL); /* AFTER ROW UPDATE Triggers */ ExecARUpdateTriggers(estate, resultRelInfo, &hsearchslot->tuple->t_self, NULL, tuple, recheckIndexes, NULL); list_free(recheckIndexes); } }