|
|
|
|
@ -26,7 +26,7 @@ |
|
|
|
|
* |
|
|
|
|
* |
|
|
|
|
* IDENTIFICATION |
|
|
|
|
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.55 1998/09/01 04:28:16 momjian Exp $ |
|
|
|
|
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.56 1998/09/25 13:38:30 thomas Exp $ |
|
|
|
|
* |
|
|
|
|
*------------------------------------------------------------------------- |
|
|
|
|
*/ |
|
|
|
|
@ -168,16 +168,16 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count) |
|
|
|
|
CommandDest dest; |
|
|
|
|
void (*destination) (); |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* sanity checks |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
Assert(queryDesc != NULL); |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* extract information from the query descriptor |
|
|
|
|
* and the query feature. |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
operation = queryDesc->operation; |
|
|
|
|
parseTree = queryDesc->parsetree; |
|
|
|
|
@ -209,9 +209,9 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count) |
|
|
|
|
destination); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* retrieve next n "backward" tuples |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
case EXEC_BACK: |
|
|
|
|
result = ExecutePlan(estate, |
|
|
|
|
@ -223,10 +223,10 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count) |
|
|
|
|
destination); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* return one tuple but don't "retrieve" it. |
|
|
|
|
* (this is used by the rule manager..) -cim 9/14/89 |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
case EXEC_RETONE: |
|
|
|
|
result = ExecutePlan(estate, |
|
|
|
|
@ -389,40 +389,40 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) |
|
|
|
|
List *targetList; |
|
|
|
|
int len; |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* get information from query descriptor |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
rangeTable = parseTree->rtable; |
|
|
|
|
resultRelation = parseTree->resultRelation; |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* initialize the node's execution state |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
estate->es_range_table = rangeTable; |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* initialize the BaseId counter so node base_id's |
|
|
|
|
* are assigned correctly. Someday baseid's will have to |
|
|
|
|
* be stored someplace other than estate because they |
|
|
|
|
* should be unique per query planned. |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
estate->es_BaseId = 1; |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* initialize result relation stuff |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
if (resultRelation != 0 && operation != CMD_SELECT) |
|
|
|
|
{ |
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* if we have a result relation, open it and |
|
|
|
|
|
|
|
|
|
* initialize the result relation info stuff. |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
RelationInfo *resultRelationInfo; |
|
|
|
|
Index resultRelationIndex; |
|
|
|
|
@ -455,10 +455,10 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) |
|
|
|
|
resultRelationInfo->ri_IndexRelationDescs = NULL; |
|
|
|
|
resultRelationInfo->ri_IndexRelationInfo = NULL; |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* open indices on result relation and save descriptors |
|
|
|
|
* in the result relation information.. |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
ExecOpenIndices(resultRelationOid, resultRelationInfo); |
|
|
|
|
|
|
|
|
|
@ -466,9 +466,9 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* if no result relation, then set state appropriately |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
estate->es_result_relation_info = NULL; |
|
|
|
|
} |
|
|
|
|
@ -477,9 +477,9 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) |
|
|
|
|
ExecCheckPerms(operation, resultRelation, rangeTable, parseTree); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* initialize the executor "tuple" table. |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
{ |
|
|
|
|
int nSlots = ExecCountSlotsNode(plan); |
|
|
|
|
@ -488,33 +488,33 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) |
|
|
|
|
estate->es_tupleTable = tupleTable; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* initialize the private state information for |
|
|
|
|
* all the nodes in the query tree. This opens |
|
|
|
|
* files, allocates storage and leaves us ready |
|
|
|
|
* to start processing tuples.. |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
ExecInitNode(plan, estate, NULL); |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* get the tuple descriptor describing the type |
|
|
|
|
* of tuples to return.. (this is especially important |
|
|
|
|
* if we are creating a relation with "retrieve into") |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
tupType = ExecGetTupType(plan); /* tuple descriptor */ |
|
|
|
|
targetList = plan->targetlist; |
|
|
|
|
len = ExecTargetListLength(targetList); /* number of attributes */ |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* now that we have the target list, initialize the junk filter |
|
|
|
|
* if this is a REPLACE or a DELETE query. |
|
|
|
|
* We also init the junk filter if this is an append query |
|
|
|
|
* (there might be some rule lock info there...) |
|
|
|
|
* NOTE: in the future we might want to initialize the junk |
|
|
|
|
* filter for all queries. |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
* SELECT added by daveh@insightdist.com 5/20/98 to allow |
|
|
|
|
* ORDER/GROUP BY have an identifier missing from the target. |
|
|
|
|
*/ |
|
|
|
|
@ -551,9 +551,9 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) |
|
|
|
|
estate->es_junkFilter = NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* initialize the "into" relation |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
intoRelationDesc = (Relation) NULL; |
|
|
|
|
|
|
|
|
|
@ -571,9 +571,9 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) |
|
|
|
|
*/ |
|
|
|
|
if (parseTree->into != NULL) |
|
|
|
|
{ |
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* create the "into" relation |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
intoName = parseTree->into; |
|
|
|
|
|
|
|
|
|
@ -587,11 +587,11 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) |
|
|
|
|
|
|
|
|
|
FreeTupleDesc(tupdesc); |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* XXX rather than having to call setheapoverride(true) |
|
|
|
|
* and then back to false, we should change the |
|
|
|
|
* arguments to heap_open() instead.. |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
setheapoverride(true); |
|
|
|
|
|
|
|
|
|
@ -619,22 +619,22 @@ EndPlan(Plan *plan, EState *estate) |
|
|
|
|
RelationInfo *resultRelationInfo; |
|
|
|
|
Relation intoRelationDesc; |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* get information from state |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
resultRelationInfo = estate->es_result_relation_info; |
|
|
|
|
intoRelationDesc = estate->es_into_relation_descriptor; |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* shut down the query |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
ExecEndNode(plan, plan); |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* destroy the executor "tuple" table. |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
{ |
|
|
|
|
TupleTable tupleTable = (TupleTable) estate->es_tupleTable; |
|
|
|
|
@ -643,9 +643,9 @@ EndPlan(Plan *plan, EState *estate) |
|
|
|
|
estate->es_tupleTable = NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* close the result relations if necessary |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
if (resultRelationInfo != NULL) |
|
|
|
|
{ |
|
|
|
|
@ -654,16 +654,16 @@ EndPlan(Plan *plan, EState *estate) |
|
|
|
|
resultRelationDesc = resultRelationInfo->ri_RelationDesc; |
|
|
|
|
heap_close(resultRelationDesc); |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* close indices on the result relation |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
ExecCloseIndices(resultRelationInfo); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* close the "into" relation if necessary |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
if (intoRelationDesc != NULL) |
|
|
|
|
heap_close(intoRelationDesc); |
|
|
|
|
@ -702,42 +702,42 @@ ExecutePlan(EState *estate, |
|
|
|
|
int current_tuple_count; |
|
|
|
|
TupleTableSlot *result; |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* initialize local variables |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
slot = NULL; |
|
|
|
|
current_tuple_count = 0; |
|
|
|
|
result = NULL; |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* Set the direction. |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
estate->es_direction = direction; |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* Loop until we've processed the proper number |
|
|
|
|
* of tuples from the plan.. |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
for (;;) |
|
|
|
|
{ |
|
|
|
|
if (operation != CMD_NOTIFY) |
|
|
|
|
{ |
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* Execute the plan and obtain a tuple |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
/* at the top level, the parent of a plan (2nd arg) is itself */ |
|
|
|
|
slot = ExecProcNode(plan, plan); |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* if the tuple is null, then we assume |
|
|
|
|
* there is nothing more to process so |
|
|
|
|
* we just return null... |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
if (TupIsNull(slot)) |
|
|
|
|
{ |
|
|
|
|
@ -746,15 +746,15 @@ ExecutePlan(EState *estate, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* if we have a junk filter, then project a new |
|
|
|
|
* tuple with the junk removed. |
|
|
|
|
* |
|
|
|
|
* Store this new "clean" tuple in the place of the |
|
|
|
|
* original tuple. |
|
|
|
|
* |
|
|
|
|
* Also, extract all the junk ifnormation we need. |
|
|
|
|
* ---------------- |
|
|
|
|
* Also, extract all the junk information we need. |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
if ((junkfilter = estate->es_junkFilter) != (JunkFilter *) NULL) |
|
|
|
|
{ |
|
|
|
|
@ -764,9 +764,9 @@ ExecutePlan(EState *estate, |
|
|
|
|
HeapTuple newTuple; |
|
|
|
|
bool isNull; |
|
|
|
|
|
|
|
|
|
/* ---------------
|
|
|
|
|
/******************
|
|
|
|
|
* extract the 'ctid' junk attribute. |
|
|
|
|
* --------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
if (operation == CMD_UPDATE || operation == CMD_DELETE) |
|
|
|
|
{ |
|
|
|
|
@ -786,10 +786,10 @@ ExecutePlan(EState *estate, |
|
|
|
|
tupleid = &tuple_ctid; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* ---------------
|
|
|
|
|
/******************
|
|
|
|
|
* Finally create a new "clean" tuple with all junk attributes |
|
|
|
|
* removed |
|
|
|
|
* --------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
newTuple = ExecRemoveJunk(junkfilter, slot); |
|
|
|
|
|
|
|
|
|
@ -800,12 +800,12 @@ ExecutePlan(EState *estate, |
|
|
|
|
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) |
|
|
|
|
@ -855,21 +855,21 @@ ExecutePlan(EState *estate, |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
@ -892,16 +892,16 @@ ExecRetrieve(TupleTableSlot *slot, |
|
|
|
|
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) |
|
|
|
|
{ |
|
|
|
|
@ -909,9 +909,9 @@ ExecRetrieve(TupleTableSlot *slot, |
|
|
|
|
IncrAppended(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* send the tuple to the front end (or the screen) |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
(*printfunc) (tuple, attrtype); |
|
|
|
|
IncrRetrieved(); |
|
|
|
|
@ -938,23 +938,23 @@ ExecAppend(TupleTableSlot *slot, |
|
|
|
|
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 */ |
|
|
|
|
@ -976,9 +976,9 @@ ExecAppend(TupleTableSlot *slot, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* Check the constraints of a tuple |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
if (resultRelationDesc->rd_att->constr) |
|
|
|
|
@ -995,21 +995,21 @@ ExecAppend(TupleTableSlot *slot, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* 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) |
|
|
|
|
@ -1038,9 +1038,9 @@ ExecDelete(TupleTableSlot *slot, |
|
|
|
|
RelationInfo *resultRelationInfo; |
|
|
|
|
Relation resultRelationDesc; |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* get the result relation information |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
resultRelationInfo = estate->es_result_relation_info; |
|
|
|
|
resultRelationDesc = resultRelationInfo->ri_RelationDesc; |
|
|
|
|
@ -1057,9 +1057,9 @@ ExecDelete(TupleTableSlot *slot, |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* delete the tuple |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
if (heap_delete(resultRelationDesc, /* relation desc */ |
|
|
|
|
tupleid)) /* item pointer to tuple */ |
|
|
|
|
@ -1068,7 +1068,7 @@ ExecDelete(TupleTableSlot *slot, |
|
|
|
|
IncrDeleted(); |
|
|
|
|
(estate->es_processed)++; |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* Note: Normally one would think that we have to |
|
|
|
|
* delete index tuples associated with the |
|
|
|
|
* heap tuple now.. |
|
|
|
|
@ -1077,7 +1077,7 @@ ExecDelete(TupleTableSlot *slot, |
|
|
|
|
* 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 */ |
|
|
|
|
@ -1109,9 +1109,9 @@ ExecReplace(TupleTableSlot *slot, |
|
|
|
|
Relation resultRelationDesc; |
|
|
|
|
int numIndices; |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* abort the operation if not running transactions |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
if (IsBootstrapProcessingMode()) |
|
|
|
|
{ |
|
|
|
|
@ -1119,25 +1119,25 @@ ExecReplace(TupleTableSlot *slot, |
|
|
|
|
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 */ |
|
|
|
|
@ -1159,9 +1159,9 @@ ExecReplace(TupleTableSlot *slot, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* Check the constraints of a tuple |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
if (resultRelationDesc->rd_att->constr) |
|
|
|
|
@ -1178,13 +1178,13 @@ ExecReplace(TupleTableSlot *slot, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* replace the heap tuple |
|
|
|
|
* |
|
|
|
|
* Don't want to continue if our heap_replace didn't actually |
|
|
|
|
* do a replace. This would be the case if heap_replace |
|
|
|
|
* detected a non-functional update. -kw 12/30/93 |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
if (heap_replace(resultRelationDesc, /* relation desc */ |
|
|
|
|
tupleid, /* item ptr of tuple to replace */ |
|
|
|
|
@ -1196,7 +1196,7 @@ ExecReplace(TupleTableSlot *slot, |
|
|
|
|
IncrReplaced(); |
|
|
|
|
(estate->es_processed)++; |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* Note: instead of having to update the old index tuples |
|
|
|
|
* associated with the heap tuple, all we do is form |
|
|
|
|
* and insert new index tuples.. This is because |
|
|
|
|
@ -1204,10 +1204,10 @@ ExecReplace(TupleTableSlot *slot, |
|
|
|
|
* index tuple deletion is done automagically by |
|
|
|
|
* the vaccuum deamon.. All we do is insert new |
|
|
|
|
* index tuples. -cim 9/27/89 |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
|
/******************
|
|
|
|
|
* process indices |
|
|
|
|
* |
|
|
|
|
* heap_replace updates a tuple in the base relation by invalidating |
|
|
|
|
@ -1215,7 +1215,7 @@ ExecReplace(TupleTableSlot *slot, |
|
|
|
|
* effect, the tupleid of the new tuple is placed in the new |
|
|
|
|
* tuple's t_ctid field. So we now insert index tuples using |
|
|
|
|
* the new tupleid stored there. |
|
|
|
|
* ---------------- |
|
|
|
|
****************** |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
numIndices = resultRelationInfo->ri_NumIndices; |
|
|
|
|
|