📄 execmain.c
字号:
Datum datum; HeapTuple newTuple; bool isNull; /* * extract the 'ctid' junk attribute. */ if (operation == CMD_UPDATE || operation == CMD_DELETE) { if (!ExecGetJunkAttribute(junkfilter, slot, "ctid", &datum, &isNull)) elog(ERROR, "ExecutePlan: NO (junk) `ctid' was found!"); if (isNull) elog(ERROR, "ExecutePlan: (junk) `ctid' is NULL!"); tupleid = (ItemPointer) DatumGetPointer(datum); tuple_ctid = *tupleid; /* make sure we don't free the * ctid!! */ tupleid = &tuple_ctid; } else if (estate->es_rowMark != NULL) { List *l; execRowMark *erm; Buffer buffer; HeapTupleData tuple; TupleTableSlot *newSlot; int test; lmark: ; foreach(l, estate->es_rowMark) { erm = lfirst(l); if (!ExecGetJunkAttribute(junkfilter, slot, erm->resname, &datum, &isNull)) elog(ERROR, "ExecutePlan: NO (junk) `%s' was found!", erm->resname); if (isNull) elog(ERROR, "ExecutePlan: (junk) `%s' is NULL!", erm->resname); tuple.t_self = *((ItemPointer) DatumGetPointer(datum)); test = heap_mark4update(erm->relation, &tuple, &buffer); ReleaseBuffer(buffer); switch (test) { case HeapTupleSelfUpdated: case HeapTupleMayBeUpdated: break; case HeapTupleUpdated: if (XactIsoLevel == XACT_SERIALIZABLE) { elog(ERROR, "Can't serialize access due to concurrent update"); return (NULL); } else if (!(ItemPointerEquals(&(tuple.t_self), (ItemPointer) DatumGetPointer(datum)))) { newSlot = EvalPlanQual(estate, erm->rti, &(tuple.t_self)); if (!(TupIsNull(newSlot))) { slot = newSlot; estate->es_useEvalPlan = true; goto lmark; } } /* * if tuple was deleted or PlanQual failed for * updated tuple - we have not return this * tuple! */ goto lnext; default: elog(ERROR, "Unknown status %u from heap_mark4update", test); return (NULL); } } } /* * Finally create a new "clean" tuple with all junk attributes * removed */ newTuple = ExecRemoveJunk(junkfilter, slot); slot = ExecStoreTuple(newTuple, /* tuple to store */ slot, /* destination slot */ InvalidBuffer, /* this tuple has no * buffer */ true); /* tuple should be pfreed */ } /* if (junkfilter... */ /* * now that we have a tuple, do the appropriate thing with it.. * either return it to the user, add it to a relation someplace, * delete it from a relation, or modify some of it's attributes. */ switch (operation) { case CMD_SELECT: ExecRetrieve(slot, /* slot containing tuple */ destfunc, /* destination's tuple-receiver * obj */ estate); /* */ result = slot; break; case CMD_INSERT: ExecAppend(slot, tupleid, estate); result = NULL; break; case CMD_DELETE: ExecDelete(slot, tupleid, estate); result = NULL; break; case CMD_UPDATE: ExecReplace(slot, tupleid, estate); result = NULL; break; default: elog(DEBUG, "ExecutePlan: unknown operation in queryDesc"); result = NULL; break; } /* * check our tuple count.. if we've returned the proper number * then return, else loop again and process more tuples.. */ current_tuple_count += 1; if (numberTuples == current_tuple_count) break; } /* * here, result is either a slot containing a tuple in the case of a * RETRIEVE or NULL otherwise. */ return result;}/* ---------------------------------------------------------------- * ExecRetrieve * * RETRIEVEs are easy.. we just pass the tuple to the appropriate * print function. The only complexity is when we do a * "retrieve into", in which case we insert the tuple into * the appropriate relation (note: this is a newly created relation * so we don't need to worry about indices or locks.) * ---------------------------------------------------------------- */static voidExecRetrieve(TupleTableSlot *slot, DestReceiver *destfunc, EState *estate){ HeapTuple tuple; TupleDesc attrtype; /* * get the heap tuple out of the tuple table slot */ tuple = slot->val; attrtype = slot->ttc_tupleDescriptor; /* * insert the tuple into the "into relation" */ if (estate->es_into_relation_descriptor != NULL) { heap_insert(estate->es_into_relation_descriptor, tuple); IncrAppended(); } /* * send the tuple to the front end (or the screen) */ (*destfunc->receiveTuple) (tuple, attrtype, destfunc); IncrRetrieved(); (estate->es_processed)++;}/* ---------------------------------------------------------------- * ExecAppend * * APPENDs are trickier.. we have to insert the tuple into * the base relation and insert appropriate tuples into the * index relations. * ---------------------------------------------------------------- */static voidExecAppend(TupleTableSlot *slot, ItemPointer tupleid, EState *estate){ HeapTuple tuple; RelationInfo *resultRelationInfo; Relation resultRelationDesc; int numIndices; Oid newId; /* * get the heap tuple out of the tuple table slot */ tuple = slot->val; /* * get information on the result relation */ resultRelationInfo = estate->es_result_relation_info; resultRelationDesc = resultRelationInfo->ri_RelationDesc; /* * have to add code to preform unique checking here. cim -12/1/89 */ /* BEFORE ROW INSERT Triggers */ if (resultRelationDesc->trigdesc && resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_INSERT] > 0) { HeapTuple newtuple; newtuple = ExecBRInsertTriggers(resultRelationDesc, tuple); if (newtuple == NULL) /* "do nothing" */ return; if (newtuple != tuple) /* modified by Trigger(s) */ { Assert(slot->ttc_shouldFree); pfree(tuple); slot->val = tuple = newtuple; } } /* * Check the constraints of a tuple */ if (resultRelationDesc->rd_att->constr) ExecConstraints("ExecAppend", resultRelationDesc, tuple, estate); /* * insert the tuple */ newId = heap_insert(resultRelationDesc, /* relation desc */ tuple); /* heap tuple */ IncrAppended(); /* * process indices * * Note: heap_insert adds a new tuple to a relation. As a side effect, * the tupleid of the new tuple is placed in the new tuple's t_ctid * field. */ numIndices = resultRelationInfo->ri_NumIndices; if (numIndices > 0) ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false); (estate->es_processed)++; estate->es_lastoid = newId; /* AFTER ROW INSERT Triggers */ if (resultRelationDesc->trigdesc && resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_INSERT] > 0) ExecARInsertTriggers(resultRelationDesc, tuple);}/* ---------------------------------------------------------------- * ExecDelete * * DELETE is like append, we delete the tuple and its * index tuples. * ---------------------------------------------------------------- */static voidExecDelete(TupleTableSlot *slot, ItemPointer tupleid, EState *estate){ RelationInfo *resultRelationInfo; Relation resultRelationDesc; ItemPointerData ctid; int result; /* * get the result relation information */ resultRelationInfo = estate->es_result_relation_info; resultRelationDesc = resultRelationInfo->ri_RelationDesc; /* BEFORE ROW DELETE Triggers */ if (resultRelationDesc->trigdesc && resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_DELETE] > 0) { bool dodelete; dodelete = ExecBRDeleteTriggers(estate, tupleid); if (!dodelete) /* "do nothing" */ return; } /* * delete the tuple */ldelete:; result = heap_delete(resultRelationDesc, tupleid, &ctid); switch (result) { case HeapTupleSelfUpdated: return; case HeapTupleMayBeUpdated: break; case HeapTupleUpdated: if (XactIsoLevel == XACT_SERIALIZABLE) elog(ERROR, "Can't serialize access due to concurrent update"); else if (!(ItemPointerEquals(tupleid, &ctid))) { TupleTableSlot *epqslot = EvalPlanQual(estate, resultRelationInfo->ri_RangeTableIndex, &ctid); if (!TupIsNull(epqslot)) { *tupleid = ctid; goto ldelete; } } return; default: elog(ERROR, "Unknown status %u from heap_delete", result); return; } IncrDeleted(); (estate->es_processed)++; /* * Note: Normally one would think that we have to delete index tuples * associated with the heap tuple now.. * * ... but in POSTGRES, we have no need to do this because the vacuum * daemon automatically opens an index scan and deletes index tuples * when it finds deleted heap tuples. -cim 9/27/89 */ /* AFTER ROW DELETE Triggers */ if (resultRelationDesc->trigdesc && resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_DELETE] > 0) ExecARDeleteTriggers(estate, tupleid);}/* ---------------------------------------------------------------- * ExecReplace * * note: we can't run replace queries with transactions * off because replaces are actually appends and our * scan will mistakenly loop forever, replacing the tuple * it just appended.. This should be fixed but until it * is, we don't want to get stuck in an infinite loop * which corrupts your database.. * ---------------------------------------------------------------- */static voidExecReplace(TupleTableSlot *slot, ItemPointer tupleid, EState *estate){ HeapTuple tuple; RelationInfo *resultRelationInfo; Relation resultRelationDesc; ItemPointerData ctid; int result; int numIndices; /* * abort the operation if not running transactions */ if (IsBootstrapProcessingMode()) { elog(DEBUG, "ExecReplace: replace can't run without transactions"); return; } /* * get the heap tuple out of the tuple table slot */ tuple = slot->val; /* * get the result relation information */ resultRelationInfo = estate->es_result_relation_info; resultRelationDesc = resultRelationInfo->ri_RelationDesc; /* * have to add code to preform unique checking here. in the event of * unique tuples, this becomes a deletion of the original tuple * affected by the replace. cim -12/1/89 */ /* BEFORE ROW UPDATE Triggers */ if (resultRelationDesc->trigdesc && resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_UPDATE] > 0) { HeapTuple newtuple; newtuple = ExecBRUpdateTriggers(estate, tupleid, tuple); if (newtuple == NULL) /* "do nothing" */ return; if (newtuple != tuple) /* modified by Trigger(s) */ { Assert(slot->ttc_shouldFree); pfree(tuple); slot->val = tuple = newtuple; } } /* * Check the constraints of a tuple */ if (resultRelationDesc->rd_att->constr) ExecConstraints("ExecReplace", resultRelationDesc, tuple, estate); /* * replace the heap tuple */lreplace:; result = heap_replace(resultRelationDesc, tupleid, tuple, &ctid); switch (result) { case HeapTupleSelfUpdated: return; case HeapTupleMayBeUpdated: break; case HeapTupleUpdated: if (XactIsoLevel == XACT_SERIALIZABLE) elog(ERROR, "Can't serialize access due to concurrent update"); else if (!(ItemPointerEquals(tupleid, &ctid))) { TupleTableSlot *epqslot = EvalPlanQual(estate, resultRelationInfo->ri_RangeTableIndex, &ctid); if (!TupIsNull(epqslot)) { *tupleid = ctid; tuple = ExecRemoveJunk(estate->es_junkFilter, epqslot);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -