1 /*-------------------------------------------------------------------------
4 * top level executor interface routines
11 * The old ExecutorMain() has been replaced by ExecutorStart(),
12 * ExecutorRun() and ExecutorEnd()
14 * These three procedures are the external interfaces to the executor.
15 * In each case, the query descriptor and the execution state is required
18 * ExecutorStart() must be called at the beginning of any execution of any
19 * query plan and ExecutorEnd() should always be called at the end of
20 * execution of a plan.
22 * ExecutorRun accepts 'feature' and 'count' arguments that specify whether
23 * the plan is to be executed forwards, backwards, and for how many tuples.
25 * Copyright (c) 1994, Regents of the University of California
29 * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.98 1999/10/30 23:13:30 tgl Exp $
31 *-------------------------------------------------------------------------
35 #include "access/heapam.h"
36 #include "catalog/heap.h"
37 #include "commands/trigger.h"
38 #include "executor/execdebug.h"
39 #include "executor/execdefs.h"
40 #include "executor/executor.h"
41 #include "miscadmin.h"
42 #include "optimizer/var.h"
43 #include "parser/parsetree.h"
44 #include "utils/acl.h"
45 #include "utils/builtins.h"
46 #include "utils/syscache.h"
48 void ExecCheckPerms(CmdType operation, int resultRelation, List *rangeTable,
52 /* decls for local routines only used within this module */
53 static TupleDesc InitPlan(CmdType operation,
57 static void EndPlan(Plan *plan,
59 static TupleTableSlot *ExecutePlan(EState *estate, Plan *plan,
63 ScanDirection direction,
64 DestReceiver *destfunc);
65 static void ExecRetrieve(TupleTableSlot *slot,
66 DestReceiver *destfunc,
68 static void ExecAppend(TupleTableSlot *slot, ItemPointer tupleid,
70 static void ExecDelete(TupleTableSlot *slot, ItemPointer tupleid,
72 static void ExecReplace(TupleTableSlot *slot, ItemPointer tupleid,
75 TupleTableSlot *EvalPlanQual(EState *estate, Index rti, ItemPointer tid);
76 static TupleTableSlot *EvalPlanQualNext(EState *estate);
79 /* end of local decls */
81 /* ----------------------------------------------------------------
84 * This routine must be called at the beginning of any execution of any
87 * returns (AttrInfo*) which describes the attributes of the tuples to
88 * be returned by the query.
90 * ----------------------------------------------------------------
93 ExecutorStart(QueryDesc *queryDesc, EState *estate)
98 Assert(queryDesc != NULL);
100 if (queryDesc->plantree->nParamExec > 0)
102 estate->es_param_exec_vals = (ParamExecData *)
103 palloc(queryDesc->plantree->nParamExec * sizeof(ParamExecData));
104 memset(estate->es_param_exec_vals, 0, queryDesc->plantree->nParamExec * sizeof(ParamExecData));
108 * Make our own private copy of the current queries snapshot data
110 if (QuerySnapshot == NULL)
111 estate->es_snapshot = NULL;
114 estate->es_snapshot = (Snapshot) palloc(sizeof(SnapshotData));
115 memcpy(estate->es_snapshot, QuerySnapshot, sizeof(SnapshotData));
116 if (estate->es_snapshot->xcnt > 0)
118 estate->es_snapshot->xip = (TransactionId *)
119 palloc(estate->es_snapshot->xcnt * sizeof(TransactionId));
120 memcpy(estate->es_snapshot->xip, QuerySnapshot->xip,
121 estate->es_snapshot->xcnt * sizeof(TransactionId));
126 * Initialize the plan
128 result = InitPlan(queryDesc->operation,
129 queryDesc->parsetree,
136 /* ----------------------------------------------------------------
139 * This is the main routine of the executor module. It accepts
140 * the query descriptor from the traffic cop and executes the
143 * ExecutorStart must have been called already.
145 * the different features supported are:
146 * EXEC_RUN: retrieve all tuples in the forward direction
147 * EXEC_FOR: retrieve 'count' number of tuples in the forward dir
148 * EXEC_BACK: retrieve 'count' number of tuples in the backward dir
149 * EXEC_RETONE: return one tuple but don't 'retrieve' it
150 * used in postquel function processing
153 * ----------------------------------------------------------------
156 ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature,
157 Node *limoffset, Node *limcount)
161 TupleTableSlot *result;
163 DestReceiver *destfunc;
170 Assert(queryDesc != NULL);
173 * extract information from the query descriptor and the query
176 operation = queryDesc->operation;
177 plan = queryDesc->plantree;
178 dest = queryDesc->dest;
179 destfunc = DestToFunction(dest);
180 estate->es_processed = 0;
181 estate->es_lastoid = InvalidOid;
184 * FIXME: the dest setup function ought to be handed the tuple desc
185 * for the tuples to be output, but I'm not quite sure how to get that
186 * info at this point. For now, passing NULL is OK because no
187 * existing dest setup function actually uses the pointer.
189 (*destfunc->setup) (destfunc, (TupleDesc) NULL);
192 * if given get the offset of the LIMIT clause
194 if (limoffset != NULL)
198 ParamListInfo paramLI;
201 switch (nodeTag(limoffset))
204 coffset = (Const *) limoffset;
205 offset = (int) (coffset->constvalue);
209 poffset = (Param *) limoffset;
210 paramLI = estate->es_param_list_info;
213 elog(ERROR, "parameter for limit offset not in executor state");
214 for (i = 0; paramLI[i].kind != PARAM_INVALID; i++)
216 if (paramLI[i].kind == PARAM_NUM && paramLI[i].id == poffset->paramid)
219 if (paramLI[i].kind == PARAM_INVALID)
220 elog(ERROR, "parameter for limit offset not in executor state");
221 if (paramLI[i].isnull)
222 elog(ERROR, "limit offset cannot be NULL value");
223 offset = (int) (paramLI[i].value);
228 elog(ERROR, "unexpected node type %d as limit offset", nodeTag(limoffset));
232 elog(ERROR, "limit offset cannot be negative");
236 * if given get the count of the LIMIT clause
238 if (limcount != NULL)
242 ParamListInfo paramLI;
245 switch (nodeTag(limcount))
248 ccount = (Const *) limcount;
249 count = (int) (ccount->constvalue);
253 pcount = (Param *) limcount;
254 paramLI = estate->es_param_list_info;
257 elog(ERROR, "parameter for limit count not in executor state");
258 for (i = 0; paramLI[i].kind != PARAM_INVALID; i++)
260 if (paramLI[i].kind == PARAM_NUM && paramLI[i].id == pcount->paramid)
263 if (paramLI[i].kind == PARAM_INVALID)
264 elog(ERROR, "parameter for limit count not in executor state");
265 if (paramLI[i].isnull)
266 elog(ERROR, "limit count cannot be NULL value");
267 count = (int) (paramLI[i].value);
272 elog(ERROR, "unexpected node type %d as limit count", nodeTag(limcount));
276 elog(ERROR, "limit count cannot be negative");
283 result = ExecutePlan(estate,
288 ForwardScanDirection,
292 result = ExecutePlan(estate,
297 ForwardScanDirection,
302 * retrieve next n "backward" tuples
305 result = ExecutePlan(estate,
310 BackwardScanDirection,
315 * return one tuple but don't "retrieve" it. (this is used by
316 * the rule manager..) -cim 9/14/89
319 result = ExecutePlan(estate,
324 ForwardScanDirection,
329 elog(DEBUG, "ExecutorRun: Unknown feature %d", feature);
333 (*destfunc->cleanup) (destfunc);
338 /* ----------------------------------------------------------------
341 * This routine must be called at the end of any execution of any
344 * returns (AttrInfo*) which describes the attributes of the tuples to
345 * be returned by the query.
347 * ----------------------------------------------------------------
350 ExecutorEnd(QueryDesc *queryDesc, EState *estate)
353 Assert(queryDesc != NULL);
355 EndPlan(queryDesc->plantree, estate);
357 /* XXX - clean up some more from ExecutorStart() - er1p */
358 if (NULL == estate->es_snapshot)
360 /* nothing to free */
364 if (estate->es_snapshot->xcnt > 0)
365 pfree(estate->es_snapshot->xip);
366 pfree(estate->es_snapshot);
369 if (NULL == estate->es_param_exec_vals)
371 /* nothing to free */
375 pfree(estate->es_param_exec_vals);
376 estate->es_param_exec_vals = NULL;
381 ExecCheckPerms(CmdType operation,
393 aclcheck_result = -1;
398 #define CHECK(MODE) pg_aclcheck(rname.data, userName, MODE)
400 userName = GetPgUserName();
402 foreach(lp, rangeTable)
404 RangeTblEntry *rte = lfirst(lp);
410 * This happens if the access to this table is due to a view
411 * query rewriting - the rewrite handler checked the
412 * permissions against the view owner, so we just skip this
419 htup = SearchSysCacheTuple(RELOID,
420 ObjectIdGetDatum(relid),
422 if (!HeapTupleIsValid(htup))
423 elog(ERROR, "ExecCheckPerms: bogus RT relid: %u", relid);
425 ((Form_pg_class) GETSTRUCT(htup))->relname.data,
427 if (i == resultRelation)
428 { /* this is the result relation */
429 qvars = pull_varnos(parseTree->qual);
430 tvars = pull_varnos((Node *) parseTree->targetList);
431 if (intMember(resultRelation, qvars) ||
432 intMember(resultRelation, tvars))
434 /* result relation is scanned */
435 ok = ((aclcheck_result = CHECK(ACL_RD)) == ACLCHECK_OK);
443 ok = ((aclcheck_result = CHECK(ACL_AP)) == ACLCHECK_OK) ||
444 ((aclcheck_result = CHECK(ACL_WR)) == ACLCHECK_OK);
449 ok = ((aclcheck_result = CHECK(ACL_WR)) == ACLCHECK_OK);
453 elog(ERROR, "ExecCheckPerms: bogus operation %d",
459 ok = ((aclcheck_result = CHECK(ACL_RD)) == ACLCHECK_OK);
467 elog(ERROR, "%s: %s", rname.data, aclcheck_error_strings[aclcheck_result]);
469 if (parseTree != NULL && parseTree->rowMark != NULL)
471 foreach(lp, parseTree->rowMark)
473 RowMark *rm = lfirst(lp);
475 if (!(rm->info & ROW_ACL_FOR_UPDATE))
478 relid = ((RangeTblEntry *) nth(rm->rti - 1, rangeTable))->relid;
479 htup = SearchSysCacheTuple(RELOID,
480 ObjectIdGetDatum(relid),
482 if (!HeapTupleIsValid(htup))
483 elog(ERROR, "ExecCheckPerms: bogus RT relid: %u", relid);
485 ((Form_pg_class) GETSTRUCT(htup))->relname.data,
487 ok = ((aclcheck_result = CHECK(ACL_WR)) == ACLCHECK_OK);
490 elog(ERROR, "%s: %s", rname.data, aclcheck_error_strings[aclcheck_result]);
495 /* ===============================================================
496 * ===============================================================
497 static routines follow
498 * ===============================================================
499 * ===============================================================
502 typedef struct execRowMark
509 typedef struct evalPlanQual
514 struct evalPlanQual *free;
517 /* ----------------------------------------------------------------
520 * Initializes the query plan: open files, allocate storage
521 * and start up the rule manager
522 * ----------------------------------------------------------------
525 InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
529 Relation intoRelationDesc;
534 * get information from query descriptor
536 rangeTable = parseTree->rtable;
537 resultRelation = parseTree->resultRelation;
540 ExecCheckPerms(operation, resultRelation, rangeTable, parseTree);
544 * initialize the node's execution state
546 estate->es_range_table = rangeTable;
549 * initialize the BaseId counter so node base_id's are assigned
550 * correctly. Someday baseid's will have to be stored someplace other
551 * than estate because they should be unique per query planned.
553 estate->es_BaseId = 1;
556 * initialize result relation stuff
559 if (resultRelation != 0 && operation != CMD_SELECT)
563 * if we have a result relation, open it and initialize the result
564 * relation info stuff.
566 RelationInfo *resultRelationInfo;
567 Index resultRelationIndex;
568 RangeTblEntry *rtentry;
569 Oid resultRelationOid;
570 Relation resultRelationDesc;
572 resultRelationIndex = resultRelation;
573 rtentry = rt_fetch(resultRelationIndex, rangeTable);
574 resultRelationOid = rtentry->relid;
575 resultRelationDesc = heap_open(resultRelationOid, RowExclusiveLock);
577 if (resultRelationDesc->rd_rel->relkind == RELKIND_SEQUENCE)
578 elog(ERROR, "You can't change sequence relation %s",
579 resultRelationDesc->rd_rel->relname.data);
581 resultRelationInfo = makeNode(RelationInfo);
582 resultRelationInfo->ri_RangeTableIndex = resultRelationIndex;
583 resultRelationInfo->ri_RelationDesc = resultRelationDesc;
584 resultRelationInfo->ri_NumIndices = 0;
585 resultRelationInfo->ri_IndexRelationDescs = NULL;
586 resultRelationInfo->ri_IndexRelationInfo = NULL;
589 * open indices on result relation and save descriptors in the
590 * result relation information..
592 if (operation != CMD_DELETE)
593 ExecOpenIndices(resultRelationOid, resultRelationInfo);
595 estate->es_result_relation_info = resultRelationInfo;
601 * if no result relation, then set state appropriately
603 estate->es_result_relation_info = NULL;
607 * Have to lock relations selected for update
609 estate->es_rowMark = NULL;
610 if (parseTree->rowMark != NULL)
618 foreach(l, parseTree->rowMark)
621 relid = ((RangeTblEntry *) nth(rm->rti - 1, rangeTable))->relid;
622 relation = heap_open(relid, RowShareLock);
623 if (!(rm->info & ROW_MARK_FOR_UPDATE))
625 erm = (execRowMark *) palloc(sizeof(execRowMark));
626 erm->relation = relation;
628 sprintf(erm->resname, "ctid%u", rm->rti);
629 estate->es_rowMark = lappend(estate->es_rowMark, erm);
634 * initialize the executor "tuple" table.
637 int nSlots = ExecCountSlotsNode(plan);
638 TupleTable tupleTable = ExecCreateTupleTable(nSlots + 10); /* why add ten? - jolly */
640 estate->es_tupleTable = tupleTable;
644 * initialize the private state information for all the nodes in the
645 * query tree. This opens files, allocates storage and leaves us
646 * ready to start processing tuples..
648 ExecInitNode(plan, estate, NULL);
651 * get the tuple descriptor describing the type of tuples to return..
652 * (this is especially important if we are creating a relation with
655 tupType = ExecGetTupType(plan); /* tuple descriptor */
656 targetList = plan->targetlist;
659 * Now that we have the target list, initialize the junk filter if needed.
660 * SELECT and INSERT queries need a filter if there are any junk attrs
661 * in the tlist. UPDATE and DELETE always need one, since there's always
662 * a junk 'ctid' attribute present --- no need to look first.
665 bool junk_filter_needed = false;
672 foreach(tlist, targetList)
674 TargetEntry *tle = (TargetEntry *) lfirst(tlist);
676 if (tle->resdom->resjunk)
678 junk_filter_needed = true;
685 junk_filter_needed = true;
691 if (junk_filter_needed)
693 JunkFilter *j = ExecInitJunkFilter(targetList, tupType);
695 estate->es_junkFilter = j;
697 if (operation == CMD_SELECT)
698 tupType = j->jf_cleanTupType;
701 estate->es_junkFilter = NULL;
705 * initialize the "into" relation
707 intoRelationDesc = (Relation) NULL;
709 if (operation == CMD_SELECT)
715 if (!parseTree->isPortal)
719 * a select into table
721 if (parseTree->into != NULL)
725 * create the "into" relation
727 intoName = parseTree->into;
730 * have to copy tupType to get rid of constraints
732 tupdesc = CreateTupleDescCopy(tupType);
734 intoRelationId = heap_create_with_catalog(intoName,
735 tupdesc, RELKIND_RELATION, parseTree->isTemp);
737 FreeTupleDesc(tupdesc);
740 * XXX rather than having to call setheapoverride(true)
741 * and then back to false, we should change the arguments
742 * to heap_open() instead..
744 setheapoverride(true);
746 intoRelationDesc = heap_open(intoRelationId,
747 AccessExclusiveLock);
749 setheapoverride(false);
754 estate->es_into_relation_descriptor = intoRelationDesc;
756 estate->es_origPlan = plan;
757 estate->es_evalPlanQual = NULL;
758 estate->es_evTuple = NULL;
759 estate->es_useEvalPlan = false;
764 /* ----------------------------------------------------------------
767 * Cleans up the query plan -- closes files and free up storages
768 * ----------------------------------------------------------------
771 EndPlan(Plan *plan, EState *estate)
773 RelationInfo *resultRelationInfo;
774 Relation intoRelationDesc;
777 * get information from state
779 resultRelationInfo = estate->es_result_relation_info;
780 intoRelationDesc = estate->es_into_relation_descriptor;
783 * shut down the query
785 ExecEndNode(plan, plan);
788 * destroy the executor "tuple" table.
791 TupleTable tupleTable = (TupleTable) estate->es_tupleTable;
793 ExecDestroyTupleTable(tupleTable, true);
794 estate->es_tupleTable = NULL;
798 * close the result relations if necessary,
799 * but hold locks on them until xact commit
801 if (resultRelationInfo != NULL)
803 Relation resultRelationDesc;
805 resultRelationDesc = resultRelationInfo->ri_RelationDesc;
806 heap_close(resultRelationDesc, NoLock);
809 * close indices on the result relation
811 ExecCloseIndices(resultRelationInfo);
815 * close the "into" relation if necessary
817 if (intoRelationDesc != NULL)
818 heap_close(intoRelationDesc, NoLock);
821 /* ----------------------------------------------------------------
824 * processes the query plan to retrieve 'tupleCount' tuples in the
825 * direction specified.
826 * Retrieves all tuples if tupleCount is 0
828 * result is either a slot containing a tuple in the case
829 * of a RETRIEVE or NULL otherwise.
831 * ----------------------------------------------------------------
834 /* the ctid attribute is a 'junk' attribute that is removed before the
837 static TupleTableSlot *
838 ExecutePlan(EState *estate,
843 ScanDirection direction,
844 DestReceiver *destfunc)
846 JunkFilter *junkfilter;
847 TupleTableSlot *slot;
848 ItemPointer tupleid = NULL;
849 ItemPointerData tuple_ctid;
850 int current_tuple_count;
851 TupleTableSlot *result;
854 * initialize local variables
857 current_tuple_count = 0;
863 estate->es_direction = direction;
866 * Loop until we've processed the proper number of tuples from the
874 * Execute the plan and obtain a tuple
876 /* at the top level, the parent of a plan (2nd arg) is itself */
878 if (estate->es_useEvalPlan)
880 slot = EvalPlanQualNext(estate);
882 slot = ExecProcNode(plan, plan);
885 slot = ExecProcNode(plan, plan);
888 * if the tuple is null, then we assume there is nothing more to
889 * process so we just return null...
898 * For now we completely execute the plan and skip result tuples
899 * if requested by LIMIT offset. Finally we should try to do it in
900 * deeper levels if possible (during index scan) - Jan
902 if (offsetTuples > 0)
909 * if we have a junk filter, then project a new tuple with the
912 * Store this new "clean" tuple in the place of the original tuple.
914 * Also, extract all the junk information we need.
916 if ((junkfilter = estate->es_junkFilter) != (JunkFilter *) NULL)
923 * extract the 'ctid' junk attribute.
925 if (operation == CMD_UPDATE || operation == CMD_DELETE)
927 if (!ExecGetJunkAttribute(junkfilter,
932 elog(ERROR, "ExecutePlan: NO (junk) `ctid' was found!");
935 elog(ERROR, "ExecutePlan: (junk) `ctid' is NULL!");
937 tupleid = (ItemPointer) DatumGetPointer(datum);
938 tuple_ctid = *tupleid; /* make sure we don't free the
940 tupleid = &tuple_ctid;
942 else if (estate->es_rowMark != NULL)
948 TupleTableSlot *newSlot;
952 foreach(l, estate->es_rowMark)
955 if (!ExecGetJunkAttribute(junkfilter,
960 elog(ERROR, "ExecutePlan: NO (junk) `%s' was found!", erm->resname);
963 elog(ERROR, "ExecutePlan: (junk) `%s' is NULL!", erm->resname);
965 tuple.t_self = *((ItemPointer) DatumGetPointer(datum));
966 test = heap_mark4update(erm->relation, &tuple, &buffer);
967 ReleaseBuffer(buffer);
970 case HeapTupleSelfUpdated:
971 case HeapTupleMayBeUpdated:
974 case HeapTupleUpdated:
975 if (XactIsoLevel == XACT_SERIALIZABLE)
977 elog(ERROR, "Can't serialize access due to concurrent update");
980 else if (!(ItemPointerEquals(&(tuple.t_self),
981 (ItemPointer) DatumGetPointer(datum))))
983 newSlot = EvalPlanQual(estate, erm->rti, &(tuple.t_self));
984 if (!(TupIsNull(newSlot)))
987 estate->es_useEvalPlan = true;
993 * if tuple was deleted or PlanQual failed for
994 * updated tuple - we have not return this
1000 elog(ERROR, "Unknown status %u from heap_mark4update", test);
1007 * Finally create a new "clean" tuple with all junk attributes
1010 newTuple = ExecRemoveJunk(junkfilter, slot);
1012 slot = ExecStoreTuple(newTuple, /* tuple to store */
1013 slot, /* destination slot */
1014 InvalidBuffer, /* this tuple has no
1016 true); /* tuple should be pfreed */
1017 } /* if (junkfilter... */
1020 * now that we have a tuple, do the appropriate thing with it..
1021 * either return it to the user, add it to a relation someplace,
1022 * delete it from a relation, or modify some of it's attributes.
1028 ExecRetrieve(slot, /* slot containing tuple */
1029 destfunc, /* destination's tuple-receiver
1036 ExecAppend(slot, tupleid, estate);
1041 ExecDelete(slot, tupleid, estate);
1046 ExecReplace(slot, tupleid, estate);
1051 elog(DEBUG, "ExecutePlan: unknown operation in queryDesc");
1057 * check our tuple count.. if we've returned the proper number
1058 * then return, else loop again and process more tuples..
1060 current_tuple_count += 1;
1061 if (numberTuples == current_tuple_count)
1066 * here, result is either a slot containing a tuple in the case of a
1067 * RETRIEVE or NULL otherwise.
1072 /* ----------------------------------------------------------------
1075 * RETRIEVEs are easy.. we just pass the tuple to the appropriate
1076 * print function. The only complexity is when we do a
1077 * "retrieve into", in which case we insert the tuple into
1078 * the appropriate relation (note: this is a newly created relation
1079 * so we don't need to worry about indices or locks.)
1080 * ----------------------------------------------------------------
1083 ExecRetrieve(TupleTableSlot *slot,
1084 DestReceiver *destfunc,
1091 * get the heap tuple out of the tuple table slot
1094 attrtype = slot->ttc_tupleDescriptor;
1097 * insert the tuple into the "into relation"
1099 if (estate->es_into_relation_descriptor != NULL)
1101 heap_insert(estate->es_into_relation_descriptor, tuple);
1106 * send the tuple to the front end (or the screen)
1108 (*destfunc->receiveTuple) (tuple, attrtype, destfunc);
1110 (estate->es_processed)++;
1113 /* ----------------------------------------------------------------
1116 * APPENDs are trickier.. we have to insert the tuple into
1117 * the base relation and insert appropriate tuples into the
1119 * ----------------------------------------------------------------
1123 ExecAppend(TupleTableSlot *slot,
1124 ItemPointer tupleid,
1128 RelationInfo *resultRelationInfo;
1129 Relation resultRelationDesc;
1134 * get the heap tuple out of the tuple table slot
1139 * get information on the result relation
1141 resultRelationInfo = estate->es_result_relation_info;
1142 resultRelationDesc = resultRelationInfo->ri_RelationDesc;
1145 * have to add code to preform unique checking here. cim -12/1/89
1148 /* BEFORE ROW INSERT Triggers */
1149 if (resultRelationDesc->trigdesc &&
1150 resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_INSERT] > 0)
1154 newtuple = ExecBRInsertTriggers(resultRelationDesc, tuple);
1156 if (newtuple == NULL) /* "do nothing" */
1159 if (newtuple != tuple) /* modified by Trigger(s) */
1161 Assert(slot->ttc_shouldFree);
1163 slot->val = tuple = newtuple;
1168 * Check the constraints of a tuple
1171 if (resultRelationDesc->rd_att->constr)
1172 ExecConstraints("ExecAppend", resultRelationDesc, tuple, estate);
1177 newId = heap_insert(resultRelationDesc, /* relation desc */
1178 tuple); /* heap tuple */
1184 * Note: heap_insert adds a new tuple to a relation. As a side effect,
1185 * the tupleid of the new tuple is placed in the new tuple's t_ctid
1188 numIndices = resultRelationInfo->ri_NumIndices;
1190 ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false);
1191 (estate->es_processed)++;
1192 estate->es_lastoid = newId;
1194 /* AFTER ROW INSERT Triggers */
1195 if (resultRelationDesc->trigdesc)
1196 ExecARInsertTriggers(resultRelationDesc, tuple);
1199 /* ----------------------------------------------------------------
1202 * DELETE is like append, we delete the tuple and its
1204 * ----------------------------------------------------------------
1207 ExecDelete(TupleTableSlot *slot,
1208 ItemPointer tupleid,
1211 RelationInfo *resultRelationInfo;
1212 Relation resultRelationDesc;
1213 ItemPointerData ctid;
1217 * get the result relation information
1219 resultRelationInfo = estate->es_result_relation_info;
1220 resultRelationDesc = resultRelationInfo->ri_RelationDesc;
1222 /* BEFORE ROW DELETE Triggers */
1223 if (resultRelationDesc->trigdesc &&
1224 resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_DELETE] > 0)
1228 dodelete = ExecBRDeleteTriggers(estate, tupleid);
1230 if (!dodelete) /* "do nothing" */
1238 result = heap_delete(resultRelationDesc, tupleid, &ctid);
1241 case HeapTupleSelfUpdated:
1244 case HeapTupleMayBeUpdated:
1247 case HeapTupleUpdated:
1248 if (XactIsoLevel == XACT_SERIALIZABLE)
1249 elog(ERROR, "Can't serialize access due to concurrent update");
1250 else if (!(ItemPointerEquals(tupleid, &ctid)))
1252 TupleTableSlot *epqslot = EvalPlanQual(estate,
1253 resultRelationInfo->ri_RangeTableIndex, &ctid);
1255 if (!TupIsNull(epqslot))
1264 elog(ERROR, "Unknown status %u from heap_delete", result);
1269 (estate->es_processed)++;
1272 * Note: Normally one would think that we have to delete index tuples
1273 * associated with the heap tuple now..
1275 * ... but in POSTGRES, we have no need to do this because the vacuum
1276 * daemon automatically opens an index scan and deletes index tuples
1277 * when it finds deleted heap tuples. -cim 9/27/89
1280 /* AFTER ROW DELETE Triggers */
1281 if (resultRelationDesc->trigdesc)
1282 ExecARDeleteTriggers(estate, tupleid);
1286 /* ----------------------------------------------------------------
1289 * note: we can't run replace queries with transactions
1290 * off because replaces are actually appends and our
1291 * scan will mistakenly loop forever, replacing the tuple
1292 * it just appended.. This should be fixed but until it
1293 * is, we don't want to get stuck in an infinite loop
1294 * which corrupts your database..
1295 * ----------------------------------------------------------------
1298 ExecReplace(TupleTableSlot *slot,
1299 ItemPointer tupleid,
1303 RelationInfo *resultRelationInfo;
1304 Relation resultRelationDesc;
1305 ItemPointerData ctid;
1310 * abort the operation if not running transactions
1312 if (IsBootstrapProcessingMode())
1314 elog(DEBUG, "ExecReplace: replace can't run without transactions");
1319 * get the heap tuple out of the tuple table slot
1324 * get the result relation information
1326 resultRelationInfo = estate->es_result_relation_info;
1327 resultRelationDesc = resultRelationInfo->ri_RelationDesc;
1330 * have to add code to preform unique checking here. in the event of
1331 * unique tuples, this becomes a deletion of the original tuple
1332 * affected by the replace. cim -12/1/89
1335 /* BEFORE ROW UPDATE Triggers */
1336 if (resultRelationDesc->trigdesc &&
1337 resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_UPDATE] > 0)
1341 newtuple = ExecBRUpdateTriggers(estate, tupleid, tuple);
1343 if (newtuple == NULL) /* "do nothing" */
1346 if (newtuple != tuple) /* modified by Trigger(s) */
1348 Assert(slot->ttc_shouldFree);
1350 slot->val = tuple = newtuple;
1355 * Check the constraints of a tuple
1358 if (resultRelationDesc->rd_att->constr)
1359 ExecConstraints("ExecReplace", resultRelationDesc, tuple, estate);
1362 * replace the heap tuple
1365 result = heap_replace(resultRelationDesc, tupleid, tuple, &ctid);
1368 case HeapTupleSelfUpdated:
1371 case HeapTupleMayBeUpdated:
1374 case HeapTupleUpdated:
1375 if (XactIsoLevel == XACT_SERIALIZABLE)
1376 elog(ERROR, "Can't serialize access due to concurrent update");
1377 else if (!(ItemPointerEquals(tupleid, &ctid)))
1379 TupleTableSlot *epqslot = EvalPlanQual(estate,
1380 resultRelationInfo->ri_RangeTableIndex, &ctid);
1382 if (!TupIsNull(epqslot))
1385 tuple = ExecRemoveJunk(estate->es_junkFilter, epqslot);
1386 slot = ExecStoreTuple(tuple, slot, InvalidBuffer, true);
1393 elog(ERROR, "Unknown status %u from heap_replace", result);
1398 (estate->es_processed)++;
1401 * Note: instead of having to update the old index tuples associated
1402 * with the heap tuple, all we do is form and insert new index
1403 * tuples.. This is because replaces are actually deletes and inserts
1404 * and index tuple deletion is done automagically by the vaccuum
1405 * deamon.. All we do is insert new index tuples. -cim 9/27/89
1411 * heap_replace updates a tuple in the base relation by invalidating it
1412 * and then appending a new tuple to the relation. As a side effect,
1413 * the tupleid of the new tuple is placed in the new tuple's t_ctid
1414 * field. So we now insert index tuples using the new tupleid stored
1418 numIndices = resultRelationInfo->ri_NumIndices;
1420 ExecInsertIndexTuples(slot, &(tuple->t_self), estate, true);
1422 /* AFTER ROW UPDATE Triggers */
1423 if (resultRelationDesc->trigdesc)
1424 ExecARUpdateTriggers(estate, tupleid, tuple);
1429 ExecAttrDefault(Relation rel, HeapTuple tuple)
1431 int ndef = rel->rd_att->constr->num_defval;
1432 AttrDefault *attrdef = rel->rd_att->constr->defval;
1433 ExprContext *econtext = makeNode(ExprContext);
1439 Datum *replValue = NULL;
1440 char *replNull = NULL;
1444 econtext->ecxt_scantuple = NULL; /* scan tuple slot */
1445 econtext->ecxt_innertuple = NULL; /* inner tuple slot */
1446 econtext->ecxt_outertuple = NULL; /* outer tuple slot */
1447 econtext->ecxt_relation = NULL; /* relation */
1448 econtext->ecxt_relid = 0; /* relid */
1449 econtext->ecxt_param_list_info = NULL; /* param list info */
1450 econtext->ecxt_param_exec_vals = NULL; /* exec param values */
1451 econtext->ecxt_range_table = NULL; /* range table */
1452 for (i = 0; i < ndef; i++)
1454 if (!heap_attisnull(tuple, attrdef[i].adnum))
1456 expr = (Node *) stringToNode(attrdef[i].adbin);
1458 val = ExecEvalExpr(expr, econtext, &isnull, &isdone);
1467 repl = (char *) palloc(rel->rd_att->natts * sizeof(char));
1468 replNull = (char *) palloc(rel->rd_att->natts * sizeof(char));
1469 replValue = (Datum *) palloc(rel->rd_att->natts * sizeof(Datum));
1470 MemSet(repl, ' ', rel->rd_att->natts * sizeof(char));
1473 repl[attrdef[i].adnum - 1] = 'r';
1474 replNull[attrdef[i].adnum - 1] = ' ';
1475 replValue[attrdef[i].adnum - 1] = val;
1484 newtuple = heap_modifytuple(tuple, rel, replValue, replNull, repl);
1498 ExecRelCheck(Relation rel, HeapTuple tuple, EState *estate)
1500 int ncheck = rel->rd_att->constr->num_check;
1501 ConstrCheck *check = rel->rd_att->constr->check;
1502 ExprContext *econtext = makeNode(ExprContext);
1503 TupleTableSlot *slot = makeNode(TupleTableSlot);
1504 RangeTblEntry *rte = makeNode(RangeTblEntry);
1511 slot->ttc_shouldFree = false;
1512 slot->ttc_descIsNew = true;
1513 slot->ttc_tupleDescriptor = rel->rd_att;
1514 slot->ttc_buffer = InvalidBuffer;
1515 slot->ttc_whichplan = -1;
1516 rte->relname = nameout(&(rel->rd_rel->relname));
1517 rte->refname = rte->relname;
1518 rte->relid = RelationGetRelid(rel);
1519 /* inh, inFromCl, inJoinSet, skipAcl won't be used, leave them zero */
1520 rtlist = lcons(rte, NIL);
1521 econtext->ecxt_scantuple = slot; /* scan tuple slot */
1522 econtext->ecxt_innertuple = NULL; /* inner tuple slot */
1523 econtext->ecxt_outertuple = NULL; /* outer tuple slot */
1524 econtext->ecxt_relation = rel; /* relation */
1525 econtext->ecxt_relid = 0; /* relid */
1526 econtext->ecxt_param_list_info = NULL; /* param list info */
1527 econtext->ecxt_param_exec_vals = NULL; /* exec param values */
1528 econtext->ecxt_range_table = rtlist; /* range table */
1530 if (estate->es_result_relation_constraints == NULL)
1532 estate->es_result_relation_constraints =
1533 (List **) palloc(ncheck * sizeof(List *));
1535 for (i = 0; i < ncheck; i++)
1537 qual = (List *) stringToNode(check[i].ccbin);
1538 estate->es_result_relation_constraints[i] = qual;
1542 for (i = 0; i < ncheck; i++)
1544 qual = estate->es_result_relation_constraints[i];
1546 res = ExecQual(qual, econtext);
1549 return check[i].ccname;
1553 pfree(rte->relname);
1558 return (char *) NULL;
1563 ExecConstraints(char *caller, Relation rel, HeapTuple tuple, EState *estate)
1566 Assert(rel->rd_att->constr);
1568 if (rel->rd_att->constr->has_not_null)
1572 for (attrChk = 1; attrChk <= rel->rd_att->natts; attrChk++)
1574 if (rel->rd_att->attrs[attrChk - 1]->attnotnull && heap_attisnull(tuple, attrChk))
1575 elog(ERROR, "%s: Fail to add null value in not null attribute %s",
1576 caller, rel->rd_att->attrs[attrChk - 1]->attname.data);
1580 if (rel->rd_att->constr->num_check > 0)
1584 if ((failed = ExecRelCheck(rel, tuple, estate)) != NULL)
1585 elog(ERROR, "%s: rejected due to CHECK constraint %s", caller, failed);
1592 EvalPlanQual(EState *estate, Index rti, ItemPointer tid)
1594 evalPlanQual *epq = (evalPlanQual *) estate->es_evalPlanQual;
1595 evalPlanQual *oldepq;
1596 EState *epqstate = NULL;
1599 HeapTupleData tuple;
1600 bool endNode = true;
1604 if (epq != NULL && epq->rti == 0)
1606 Assert(!(estate->es_useEvalPlan) &&
1607 epq->estate.es_evalPlanQual == NULL);
1613 * If this is request for another RTE - Ra, - then we have to check
1614 * wasn't PlanQual requested for Ra already and if so then Ra' row was
1615 * updated again and we have to re-start old execution for Ra and
1616 * forget all what we done after Ra was suspended. Cool? -:))
1618 if (epq != NULL && epq->rti != rti &&
1619 epq->estate.es_evTuple[rti - 1] != NULL)
1623 /* pop previous PlanQual from the stack */
1624 epqstate = &(epq->estate);
1625 oldepq = (evalPlanQual *) epqstate->es_evalPlanQual;
1626 Assert(oldepq->rti != 0);
1627 /* stop execution */
1628 ExecEndNode(epq->plan, epq->plan);
1629 epqstate->es_tupleTable->next = 0;
1630 pfree(epqstate->es_evTuple[epq->rti - 1]);
1631 epqstate->es_evTuple[epq->rti - 1] = NULL;
1632 /* push current PQ to freePQ stack */
1635 } while (epq->rti != rti);
1636 estate->es_evalPlanQual = (Pointer) epq;
1640 * If we are requested for another RTE then we have to suspend
1641 * execution of current PlanQual and start execution for new one.
1643 if (epq == NULL || epq->rti != rti)
1645 /* try to reuse plan used previously */
1646 evalPlanQual *newepq = (epq != NULL) ? epq->free : NULL;
1648 if (newepq == NULL) /* first call or freePQ stack is empty */
1650 newepq = (evalPlanQual *) palloc(sizeof(evalPlanQual));
1652 epqstate = &(newepq->estate);
1653 memset(epqstate, 0, sizeof(EState));
1654 epqstate->type = T_EState;
1655 epqstate->es_direction = ForwardScanDirection;
1656 epqstate->es_snapshot = estate->es_snapshot;
1657 epqstate->es_range_table = estate->es_range_table;
1658 epqstate->es_param_list_info = estate->es_param_list_info;
1659 if (estate->es_origPlan->nParamExec > 0)
1660 epqstate->es_param_exec_vals = (ParamExecData *)
1661 palloc(estate->es_origPlan->nParamExec *
1662 sizeof(ParamExecData));
1663 epqstate->es_tupleTable =
1664 ExecCreateTupleTable(estate->es_tupleTable->size);
1666 newepq->plan = copyObject(estate->es_origPlan);
1667 newepq->free = NULL;
1668 epqstate->es_evTupleNull = (bool *)
1669 palloc(length(estate->es_range_table) * sizeof(bool));
1670 if (epq == NULL) /* first call */
1672 epqstate->es_evTuple = (HeapTuple *)
1673 palloc(length(estate->es_range_table) * sizeof(HeapTuple));
1674 memset(epqstate->es_evTuple, 0,
1675 length(estate->es_range_table) * sizeof(HeapTuple));
1678 epqstate->es_evTuple = epq->estate.es_evTuple;
1681 epqstate = &(newepq->estate);
1682 /* push current PQ to the stack */
1683 epqstate->es_evalPlanQual = (Pointer) epq;
1685 estate->es_evalPlanQual = (Pointer) epq;
1690 epqstate = &(epq->estate);
1693 * Ok - we're requested for the same RTE (-:)). I'm not sure about
1694 * ability to use ExecReScan instead of ExecInitNode, so...
1698 ExecEndNode(epq->plan, epq->plan);
1699 epqstate->es_tupleTable->next = 0;
1702 /* free old RTE' tuple */
1703 if (epqstate->es_evTuple[epq->rti - 1] != NULL)
1705 pfree(epqstate->es_evTuple[epq->rti - 1]);
1706 epqstate->es_evTuple[epq->rti - 1] = NULL;
1709 /* ** fetch tid tuple ** */
1710 if (estate->es_result_relation_info != NULL &&
1711 estate->es_result_relation_info->ri_RangeTableIndex == rti)
1712 relation = estate->es_result_relation_info->ri_RelationDesc;
1717 foreach(l, estate->es_rowMark)
1719 if (((execRowMark *) lfirst(l))->rti == rti)
1722 relation = ((execRowMark *) lfirst(l))->relation;
1724 tuple.t_self = *tid;
1727 heap_fetch(relation, SnapshotDirty, &tuple, &buffer);
1728 if (tuple.t_data != NULL)
1730 TransactionId xwait = SnapshotDirty->xmax;
1732 if (TransactionIdIsValid(SnapshotDirty->xmin))
1734 elog(NOTICE, "EvalPlanQual: t_xmin is uncommitted ?!");
1735 Assert(!TransactionIdIsValid(SnapshotDirty->xmin));
1736 elog(ERROR, "Aborting this transaction");
1740 * If tuple is being updated by other transaction then we have
1741 * to wait for its commit/abort.
1743 if (TransactionIdIsValid(xwait))
1745 ReleaseBuffer(buffer);
1746 XactLockTableWait(xwait);
1751 * Nice! We got tuple - now copy it.
1753 if (epqstate->es_evTuple[epq->rti - 1] != NULL)
1754 pfree(epqstate->es_evTuple[epq->rti - 1]);
1755 epqstate->es_evTuple[epq->rti - 1] = heap_copytuple(&tuple);
1756 ReleaseBuffer(buffer);
1761 * Ops! Invalid tuple. Have to check is it updated or deleted.
1762 * Note that it's possible to get invalid SnapshotDirty->tid if
1763 * tuple updated by this transaction. Have we to check this ?
1765 if (ItemPointerIsValid(&(SnapshotDirty->tid)) &&
1766 !(ItemPointerEquals(&(tuple.t_self), &(SnapshotDirty->tid))))
1768 tuple.t_self = SnapshotDirty->tid; /* updated ... */
1773 * Deleted or updated by this transaction. Do not (re-)start
1774 * execution of this PQ. Continue previous PQ.
1776 oldepq = (evalPlanQual *) epqstate->es_evalPlanQual;
1779 Assert(oldepq->rti != 0);
1780 /* push current PQ to freePQ stack */
1783 epqstate = &(epq->estate);
1784 estate->es_evalPlanQual = (Pointer) epq;
1788 epq->rti = 0; /* this is the first (oldest) */
1789 estate->es_useEvalPlan = false; /* PQ - mark as free and */
1790 return (NULL); /* continue Query execution */
1794 if (estate->es_origPlan->nParamExec > 0)
1795 memset(epqstate->es_param_exec_vals, 0,
1796 estate->es_origPlan->nParamExec * sizeof(ParamExecData));
1797 memset(epqstate->es_evTupleNull, false,
1798 length(estate->es_range_table) * sizeof(bool));
1799 Assert(epqstate->es_tupleTable->next == 0);
1800 ExecInitNode(epq->plan, epqstate, NULL);
1803 * For UPDATE/DELETE we have to return tid of actual row we're
1806 *tid = tuple.t_self;
1808 return (EvalPlanQualNext(estate));
1811 static TupleTableSlot *
1812 EvalPlanQualNext(EState *estate)
1814 evalPlanQual *epq = (evalPlanQual *) estate->es_evalPlanQual;
1815 EState *epqstate = &(epq->estate);
1816 evalPlanQual *oldepq;
1817 TupleTableSlot *slot;
1819 Assert(epq->rti != 0);
1822 slot = ExecProcNode(epq->plan, epq->plan);
1825 * No more tuples for this PQ. Continue previous one.
1827 if (TupIsNull(slot))
1829 ExecEndNode(epq->plan, epq->plan);
1830 epqstate->es_tupleTable->next = 0;
1831 pfree(epqstate->es_evTuple[epq->rti - 1]);
1832 epqstate->es_evTuple[epq->rti - 1] = NULL;
1833 /* pop old PQ from the stack */
1834 oldepq = (evalPlanQual *) epqstate->es_evalPlanQual;
1835 if (oldepq == (evalPlanQual *) NULL)
1837 epq->rti = 0; /* this is the first (oldest) */
1838 estate->es_useEvalPlan = false; /* PQ - mark as free and */
1839 return (NULL); /* continue Query execution */
1841 Assert(oldepq->rti != 0);
1842 /* push current PQ to freePQ stack */
1845 epqstate = &(epq->estate);
1846 estate->es_evalPlanQual = (Pointer) epq;