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 direction and count arguments that specify whether
23 * the plan is to be executed forwards, backwards, and for how many tuples.
25 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
26 * Portions Copyright (c) 1994, Regents of the University of California
30 * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.162 2002/05/21 22:05:55 tgl Exp $
32 *-------------------------------------------------------------------------
36 #include "access/heapam.h"
37 #include "catalog/heap.h"
38 #include "catalog/namespace.h"
39 #include "commands/tablecmds.h"
40 #include "commands/trigger.h"
41 #include "executor/execdebug.h"
42 #include "executor/execdefs.h"
43 #include "miscadmin.h"
44 #include "optimizer/var.h"
45 #include "parser/parsetree.h"
46 #include "utils/acl.h"
47 #include "utils/lsyscache.h"
50 /* decls for local routines only used within this module */
51 static TupleDesc InitPlan(CmdType operation,
55 static void initResultRelInfo(ResultRelInfo *resultRelInfo,
56 Index resultRelationIndex,
59 static void EndPlan(Plan *plan, EState *estate);
60 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,
74 static TupleTableSlot *EvalPlanQualNext(EState *estate);
75 static void EndEvalPlanQual(EState *estate);
76 static void ExecCheckQueryPerms(CmdType operation, Query *parseTree,
78 static void ExecCheckPlanPerms(Plan *plan, List *rangeTable,
80 static void ExecCheckRTPerms(List *rangeTable, CmdType operation);
81 static void ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation);
83 /* end of local decls */
86 /* ----------------------------------------------------------------
89 * This routine must be called at the beginning of any execution of any
92 * returns a TupleDesc which describes the attributes of the tuples to
93 * be returned by the query. (Same value is saved in queryDesc)
95 * NB: the CurrentMemoryContext when this is called must be the context
96 * to be used as the per-query context for the query plan. ExecutorRun()
97 * and ExecutorEnd() must be called in this same memory context.
98 * ----------------------------------------------------------------
101 ExecutorStart(QueryDesc *queryDesc, EState *estate)
104 Snapshot es_snapshot;
107 Assert(queryDesc != NULL);
109 if (queryDesc->plantree->nParamExec > 0)
111 estate->es_param_exec_vals = (ParamExecData *)
112 palloc(queryDesc->plantree->nParamExec * sizeof(ParamExecData));
113 MemSet(estate->es_param_exec_vals, 0,
114 queryDesc->plantree->nParamExec * sizeof(ParamExecData));
118 * Make our own private copy of the current query snapshot data.
120 * This "freezes" our idea of which tuples are good and which are not
121 * for the life of this query, even if it outlives the current command
122 * and current snapshot.
124 if (QuerySnapshot == NULL) /* should be set already, but... */
127 es_snapshot = (Snapshot) palloc(sizeof(SnapshotData));
128 memcpy(es_snapshot, QuerySnapshot, sizeof(SnapshotData));
129 if (es_snapshot->xcnt > 0)
131 es_snapshot->xip = (TransactionId *)
132 palloc(es_snapshot->xcnt * sizeof(TransactionId));
133 memcpy(es_snapshot->xip, QuerySnapshot->xip,
134 es_snapshot->xcnt * sizeof(TransactionId));
137 es_snapshot->xip = NULL;
139 estate->es_snapshot = es_snapshot;
142 * Initialize the plan
144 result = InitPlan(queryDesc->operation,
145 queryDesc->parsetree,
149 queryDesc->tupDesc = result;
154 /* ----------------------------------------------------------------
157 * This is the main routine of the executor module. It accepts
158 * the query descriptor from the traffic cop and executes the
161 * ExecutorStart must have been called already.
163 * If direction is NoMovementScanDirection then nothing is done
164 * except to start up/shut down the destination. Otherwise,
165 * we retrieve up to 'count' tuples in the specified direction.
167 * Note: count = 0 is interpreted as no portal limit, e.g. run to
170 * ----------------------------------------------------------------
173 ExecutorRun(QueryDesc *queryDesc, EState *estate,
174 ScanDirection direction, long count)
179 DestReceiver *destfunc;
180 TupleTableSlot *result;
185 Assert(queryDesc != NULL);
188 * extract information from the query descriptor and the query
191 operation = queryDesc->operation;
192 plan = queryDesc->plantree;
193 dest = queryDesc->dest;
196 * startup tuple receiver
198 estate->es_processed = 0;
199 estate->es_lastoid = InvalidOid;
201 destfunc = DestToFunction(dest);
202 (*destfunc->setup) (destfunc, (int) operation,
203 queryDesc->portalName, queryDesc->tupDesc);
208 if (direction == NoMovementScanDirection)
211 result = ExecutePlan(estate,
221 (*destfunc->cleanup) (destfunc);
226 /* ----------------------------------------------------------------
229 * This routine must be called at the end of execution of any
231 * ----------------------------------------------------------------
234 ExecutorEnd(QueryDesc *queryDesc, EState *estate)
237 Assert(queryDesc != NULL);
239 EndPlan(queryDesc->plantree, estate);
241 if (estate->es_snapshot != NULL)
243 if (estate->es_snapshot->xcnt > 0)
244 pfree(estate->es_snapshot->xip);
245 pfree(estate->es_snapshot);
246 estate->es_snapshot = NULL;
249 if (estate->es_param_exec_vals != NULL)
251 pfree(estate->es_param_exec_vals);
252 estate->es_param_exec_vals = NULL;
258 * ExecCheckQueryPerms
259 * Check access permissions for all relations referenced in a query.
262 ExecCheckQueryPerms(CmdType operation, Query *parseTree, Plan *plan)
265 * Check RTEs in the query's primary rangetable.
267 ExecCheckRTPerms(parseTree->rtable, operation);
270 * Search for subplans and APPEND nodes to check their rangetables.
272 ExecCheckPlanPerms(plan, parseTree->rtable, operation);
277 * Recursively scan the plan tree to check access permissions in
281 ExecCheckPlanPerms(Plan *plan, List *rangeTable, CmdType operation)
288 /* Check subplans, which we assume are plain SELECT queries */
290 foreach(subp, plan->initPlan)
292 SubPlan *subplan = (SubPlan *) lfirst(subp);
294 ExecCheckRTPerms(subplan->rtable, CMD_SELECT);
295 ExecCheckPlanPerms(subplan->plan, subplan->rtable, CMD_SELECT);
297 foreach(subp, plan->subPlan)
299 SubPlan *subplan = (SubPlan *) lfirst(subp);
301 ExecCheckRTPerms(subplan->rtable, CMD_SELECT);
302 ExecCheckPlanPerms(subplan->plan, subplan->rtable, CMD_SELECT);
305 /* Check lower plan nodes */
307 ExecCheckPlanPerms(plan->lefttree, rangeTable, operation);
308 ExecCheckPlanPerms(plan->righttree, rangeTable, operation);
310 /* Do node-type-specific checks */
312 switch (nodeTag(plan))
316 SubqueryScan *scan = (SubqueryScan *) plan;
319 /* Recursively check the subquery */
320 rte = rt_fetch(scan->scan.scanrelid, rangeTable);
321 Assert(rte->rtekind == RTE_SUBQUERY);
322 ExecCheckQueryPerms(operation, rte->subquery, scan->subplan);
327 Append *app = (Append *) plan;
330 foreach(appendplans, app->appendplans)
332 ExecCheckPlanPerms((Plan *) lfirst(appendplans),
346 * Check access permissions for all relations listed in a range table.
349 ExecCheckRTPerms(List *rangeTable, CmdType operation)
353 foreach(lp, rangeTable)
355 RangeTblEntry *rte = lfirst(lp);
357 ExecCheckRTEPerms(rte, operation);
363 * Check access permissions for a single RTE.
366 ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation)
370 AclResult aclcheck_result;
373 * Only plain-relation RTEs need to be checked here. Subquery RTEs
374 * will be checked when ExecCheckPlanPerms finds the SubqueryScan node,
375 * and function RTEs are checked by init_fcache when the function is
376 * prepared for execution. Join and special RTEs need no checks.
378 if (rte->rtekind != RTE_RELATION)
384 * userid to check as: current user unless we have a setuid
387 * Note: GetUserId() is presently fast enough that there's no harm in
388 * calling it separately for each RTE. If that stops being true, we
389 * could call it once in ExecCheckQueryPerms and pass the userid down
390 * from there. But for now, no need for the extra clutter.
392 userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
394 #define CHECK(MODE) pg_class_aclcheck(relOid, userid, MODE)
396 if (rte->checkForRead)
398 aclcheck_result = CHECK(ACL_SELECT);
399 if (aclcheck_result != ACLCHECK_OK)
400 aclcheck_error(aclcheck_result, get_rel_name(relOid));
403 if (rte->checkForWrite)
406 * Note: write access in a SELECT context means SELECT FOR UPDATE.
407 * Right now we don't distinguish that from true update as far as
408 * permissions checks are concerned.
413 aclcheck_result = CHECK(ACL_INSERT);
417 aclcheck_result = CHECK(ACL_UPDATE);
420 aclcheck_result = CHECK(ACL_DELETE);
423 elog(ERROR, "ExecCheckRTEPerms: bogus operation %d",
425 aclcheck_result = ACLCHECK_OK; /* keep compiler quiet */
428 if (aclcheck_result != ACLCHECK_OK)
429 aclcheck_error(aclcheck_result, get_rel_name(relOid));
434 /* ===============================================================
435 * ===============================================================
436 static routines follow
437 * ===============================================================
438 * ===============================================================
441 typedef struct execRowMark
448 typedef struct evalPlanQual
453 struct evalPlanQual *free;
456 /* ----------------------------------------------------------------
459 * Initializes the query plan: open files, allocate storage
460 * and start up the rule manager
461 * ----------------------------------------------------------------
464 InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
467 Relation intoRelationDesc;
471 * Do permissions checks.
473 ExecCheckQueryPerms(operation, parseTree, plan);
476 * get information from query descriptor
478 rangeTable = parseTree->rtable;
481 * initialize the node's execution state
483 estate->es_range_table = rangeTable;
486 * if there is a result relation, initialize result relation stuff
488 if (parseTree->resultRelation != 0 && operation != CMD_SELECT)
490 List *resultRelations = parseTree->resultRelations;
491 int numResultRelations;
492 ResultRelInfo *resultRelInfos;
494 if (resultRelations != NIL)
497 * Multiple result relations (due to inheritance)
498 * parseTree->resultRelations identifies them all
500 ResultRelInfo *resultRelInfo;
502 numResultRelations = length(resultRelations);
503 resultRelInfos = (ResultRelInfo *)
504 palloc(numResultRelations * sizeof(ResultRelInfo));
505 resultRelInfo = resultRelInfos;
506 while (resultRelations != NIL)
508 initResultRelInfo(resultRelInfo,
509 lfirsti(resultRelations),
513 resultRelations = lnext(resultRelations);
519 * Single result relation identified by
520 * parseTree->resultRelation
522 numResultRelations = 1;
523 resultRelInfos = (ResultRelInfo *) palloc(sizeof(ResultRelInfo));
524 initResultRelInfo(resultRelInfos,
525 parseTree->resultRelation,
530 estate->es_result_relations = resultRelInfos;
531 estate->es_num_result_relations = numResultRelations;
532 /* Initialize to first or only result rel */
533 estate->es_result_relation_info = resultRelInfos;
538 * if no result relation, then set state appropriately
540 estate->es_result_relations = NULL;
541 estate->es_num_result_relations = 0;
542 estate->es_result_relation_info = NULL;
546 * Have to lock relations selected for update
548 estate->es_rowMark = NIL;
549 if (parseTree->rowMarks != NIL)
553 foreach(l, parseTree->rowMarks)
555 Index rti = lfirsti(l);
556 Oid relid = getrelid(rti, rangeTable);
560 relation = heap_open(relid, RowShareLock);
561 erm = (execRowMark *) palloc(sizeof(execRowMark));
562 erm->relation = relation;
564 sprintf(erm->resname, "ctid%u", rti);
565 estate->es_rowMark = lappend(estate->es_rowMark, erm);
570 * initialize the executor "tuple" table. We need slots for all the
571 * plan nodes, plus possibly output slots for the junkfilter(s). At
572 * this point we aren't sure if we need junkfilters, so just add slots
573 * for them unconditionally.
576 int nSlots = ExecCountSlotsNode(plan);
578 if (parseTree->resultRelations != NIL)
579 nSlots += length(parseTree->resultRelations);
582 estate->es_tupleTable = ExecCreateTupleTable(nSlots);
585 /* mark EvalPlanQual not active */
586 estate->es_origPlan = plan;
587 estate->es_evalPlanQual = NULL;
588 estate->es_evTuple = NULL;
589 estate->es_evTupleNull = NULL;
590 estate->es_useEvalPlan = false;
593 * initialize the private state information for all the nodes in the
594 * query tree. This opens files, allocates storage and leaves us
595 * ready to start processing tuples.
597 ExecInitNode(plan, estate, NULL);
600 * Get the tuple descriptor describing the type of tuples to return.
601 * (this is especially important if we are creating a relation with
604 tupType = ExecGetTupType(plan); /* tuple descriptor */
607 * Initialize the junk filter if needed. SELECT and INSERT queries
608 * need a filter if there are any junk attrs in the tlist. UPDATE and
609 * DELETE always need one, since there's always a junk 'ctid'
610 * attribute present --- no need to look first.
613 bool junk_filter_needed = false;
620 foreach(tlist, plan->targetlist)
622 TargetEntry *tle = (TargetEntry *) lfirst(tlist);
624 if (tle->resdom->resjunk)
626 junk_filter_needed = true;
633 junk_filter_needed = true;
639 if (junk_filter_needed)
642 * If there are multiple result relations, each one needs its
643 * own junk filter. Note this is only possible for
644 * UPDATE/DELETE, so we can't be fooled by some needing a
645 * filter and some not.
647 if (parseTree->resultRelations != NIL)
650 ResultRelInfo *resultRelInfo;
652 /* Top plan had better be an Append here. */
653 Assert(IsA(plan, Append));
654 Assert(((Append *) plan)->isTarget);
655 subplans = ((Append *) plan)->appendplans;
656 Assert(length(subplans) == estate->es_num_result_relations);
657 resultRelInfo = estate->es_result_relations;
658 while (subplans != NIL)
660 Plan *subplan = (Plan *) lfirst(subplans);
663 j = ExecInitJunkFilter(subplan->targetlist,
664 ExecGetTupType(subplan),
665 ExecAllocTableSlot(estate->es_tupleTable));
666 resultRelInfo->ri_junkFilter = j;
668 subplans = lnext(subplans);
672 * Set active junkfilter too; at this point ExecInitAppend
673 * has already selected an active result relation...
675 estate->es_junkFilter =
676 estate->es_result_relation_info->ri_junkFilter;
680 /* Normal case with just one JunkFilter */
683 j = ExecInitJunkFilter(plan->targetlist,
685 ExecAllocTableSlot(estate->es_tupleTable));
686 estate->es_junkFilter = j;
687 if (estate->es_result_relation_info)
688 estate->es_result_relation_info->ri_junkFilter = j;
690 /* For SELECT, want to return the cleaned tuple type */
691 if (operation == CMD_SELECT)
692 tupType = j->jf_cleanTupType;
696 estate->es_junkFilter = NULL;
700 * initialize the "into" relation
702 intoRelationDesc = (Relation) NULL;
704 if (operation == CMD_SELECT)
706 if (!parseTree->isPortal)
709 * a select into table --- need to create the "into" table
711 if (parseTree->into != NULL)
719 * find namespace to create in, check permissions
721 intoName = parseTree->into->relname;
722 namespaceId = RangeVarGetCreationNamespace(parseTree->into);
724 if (!isTempNamespace(namespaceId))
728 aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
730 if (aclresult != ACLCHECK_OK)
731 aclcheck_error(aclresult,
732 get_namespace_name(namespaceId));
736 * have to copy tupType to get rid of constraints
738 tupdesc = CreateTupleDescCopy(tupType);
741 heap_create_with_catalog(intoName,
747 allowSystemTableMods);
749 FreeTupleDesc(tupdesc);
752 * Advance command counter so that the newly-created
753 * relation's catalog tuples will be visible to heap_open.
755 CommandCounterIncrement();
758 * If necessary, create a TOAST table for the into
759 * relation. Note that AlterTableCreateToastTable ends
760 * with CommandCounterIncrement(), so that the TOAST table
761 * will be visible for insertion.
763 AlterTableCreateToastTable(intoRelationId, true);
765 intoRelationDesc = heap_open(intoRelationId,
766 AccessExclusiveLock);
771 estate->es_into_relation_descriptor = intoRelationDesc;
777 * Initialize ResultRelInfo data for one result relation
780 initResultRelInfo(ResultRelInfo *resultRelInfo,
781 Index resultRelationIndex,
785 Oid resultRelationOid;
786 Relation resultRelationDesc;
788 resultRelationOid = getrelid(resultRelationIndex, rangeTable);
789 resultRelationDesc = heap_open(resultRelationOid, RowExclusiveLock);
791 switch (resultRelationDesc->rd_rel->relkind)
793 case RELKIND_SEQUENCE:
794 elog(ERROR, "You can't change sequence relation %s",
795 RelationGetRelationName(resultRelationDesc));
797 case RELKIND_TOASTVALUE:
798 elog(ERROR, "You can't change toast relation %s",
799 RelationGetRelationName(resultRelationDesc));
802 elog(ERROR, "You can't change view relation %s",
803 RelationGetRelationName(resultRelationDesc));
807 MemSet(resultRelInfo, 0, sizeof(ResultRelInfo));
808 resultRelInfo->type = T_ResultRelInfo;
809 resultRelInfo->ri_RangeTableIndex = resultRelationIndex;
810 resultRelInfo->ri_RelationDesc = resultRelationDesc;
811 resultRelInfo->ri_NumIndices = 0;
812 resultRelInfo->ri_IndexRelationDescs = NULL;
813 resultRelInfo->ri_IndexRelationInfo = NULL;
814 resultRelInfo->ri_TrigDesc = resultRelationDesc->trigdesc;
815 resultRelInfo->ri_TrigFunctions = NULL;
816 resultRelInfo->ri_ConstraintExprs = NULL;
817 resultRelInfo->ri_junkFilter = NULL;
820 * If there are indices on the result relation, open them and save
821 * descriptors in the result relation info, so that we can add new
822 * index entries for the tuples we add/update. We need not do this
823 * for a DELETE, however, since deletion doesn't affect indexes.
825 if (resultRelationDesc->rd_rel->relhasindex &&
826 operation != CMD_DELETE)
827 ExecOpenIndices(resultRelInfo);
830 /* ----------------------------------------------------------------
833 * Cleans up the query plan -- closes files and free up storages
834 * ----------------------------------------------------------------
837 EndPlan(Plan *plan, EState *estate)
839 ResultRelInfo *resultRelInfo;
844 * shut down any PlanQual processing we were doing
846 if (estate->es_evalPlanQual != NULL)
847 EndEvalPlanQual(estate);
850 * shut down the node-type-specific query processing
852 ExecEndNode(plan, NULL);
855 * destroy the executor "tuple" table.
857 ExecDropTupleTable(estate->es_tupleTable, true);
858 estate->es_tupleTable = NULL;
861 * close the result relation(s) if any, but hold locks until xact
862 * commit. Also clean up junkfilters if present.
864 resultRelInfo = estate->es_result_relations;
865 for (i = estate->es_num_result_relations; i > 0; i--)
867 /* Close indices and then the relation itself */
868 ExecCloseIndices(resultRelInfo);
869 heap_close(resultRelInfo->ri_RelationDesc, NoLock);
870 /* Delete the junkfilter if any */
871 if (resultRelInfo->ri_junkFilter != NULL)
872 ExecFreeJunkFilter(resultRelInfo->ri_junkFilter);
877 * close the "into" relation if necessary, again keeping lock
879 if (estate->es_into_relation_descriptor != NULL)
880 heap_close(estate->es_into_relation_descriptor, NoLock);
883 * There might be a junkfilter without a result relation.
885 if (estate->es_num_result_relations == 0 &&
886 estate->es_junkFilter != NULL)
888 ExecFreeJunkFilter(estate->es_junkFilter);
889 estate->es_junkFilter = NULL;
893 * close any relations selected FOR UPDATE, again keeping locks
895 foreach(l, estate->es_rowMark)
897 execRowMark *erm = lfirst(l);
899 heap_close(erm->relation, NoLock);
903 /* ----------------------------------------------------------------
906 * processes the query plan to retrieve 'numberTuples' tuples in the
907 * direction specified.
908 * Retrieves all tuples if numberTuples is 0
910 * result is either a slot containing the last tuple in the case
911 * of a RETRIEVE or NULL otherwise.
913 * Note: the ctid attribute is a 'junk' attribute that is removed before the
915 * ----------------------------------------------------------------
917 static TupleTableSlot *
918 ExecutePlan(EState *estate,
922 ScanDirection direction,
923 DestReceiver *destfunc)
925 JunkFilter *junkfilter;
926 TupleTableSlot *slot;
927 ItemPointer tupleid = NULL;
928 ItemPointerData tuple_ctid;
929 long current_tuple_count;
930 TupleTableSlot *result;
933 * initialize local variables
936 current_tuple_count = 0;
942 estate->es_direction = direction;
945 * Loop until we've processed the proper number of tuples from the
951 /* Reset the per-output-tuple exprcontext */
952 ResetPerTupleExprContext(estate);
955 * Execute the plan and obtain a tuple
958 if (estate->es_useEvalPlan)
960 slot = EvalPlanQualNext(estate);
962 slot = ExecProcNode(plan, NULL);
965 slot = ExecProcNode(plan, NULL);
968 * if the tuple is null, then we assume there is nothing more to
969 * process so we just return null...
978 * if we have a junk filter, then project a new tuple with the
981 * Store this new "clean" tuple in the junkfilter's resultSlot.
982 * (Formerly, we stored it back over the "dirty" tuple, which is
983 * WRONG because that tuple slot has the wrong descriptor.)
985 * Also, extract all the junk information we need.
987 if ((junkfilter = estate->es_junkFilter) != (JunkFilter *) NULL)
994 * extract the 'ctid' junk attribute.
996 if (operation == CMD_UPDATE || operation == CMD_DELETE)
998 if (!ExecGetJunkAttribute(junkfilter,
1003 elog(ERROR, "ExecutePlan: NO (junk) `ctid' was found!");
1005 /* shouldn't ever get a null result... */
1007 elog(ERROR, "ExecutePlan: (junk) `ctid' is NULL!");
1009 tupleid = (ItemPointer) DatumGetPointer(datum);
1010 tuple_ctid = *tupleid; /* make sure we don't free the
1012 tupleid = &tuple_ctid;
1014 else if (estate->es_rowMark != NIL)
1019 foreach(l, estate->es_rowMark)
1021 execRowMark *erm = lfirst(l);
1023 HeapTupleData tuple;
1024 TupleTableSlot *newSlot;
1027 if (!ExecGetJunkAttribute(junkfilter,
1032 elog(ERROR, "ExecutePlan: NO (junk) `%s' was found!",
1035 /* shouldn't ever get a null result... */
1037 elog(ERROR, "ExecutePlan: (junk) `%s' is NULL!",
1040 tuple.t_self = *((ItemPointer) DatumGetPointer(datum));
1041 test = heap_mark4update(erm->relation, &tuple, &buffer,
1042 estate->es_snapshot->curcid);
1043 ReleaseBuffer(buffer);
1046 case HeapTupleSelfUpdated:
1047 case HeapTupleMayBeUpdated:
1050 case HeapTupleUpdated:
1051 if (XactIsoLevel == XACT_SERIALIZABLE)
1052 elog(ERROR, "Can't serialize access due to concurrent update");
1053 if (!(ItemPointerEquals(&(tuple.t_self),
1054 (ItemPointer) DatumGetPointer(datum))))
1056 newSlot = EvalPlanQual(estate, erm->rti, &(tuple.t_self));
1057 if (!(TupIsNull(newSlot)))
1060 estate->es_useEvalPlan = true;
1066 * if tuple was deleted or PlanQual failed for
1067 * updated tuple - we must not return this
1073 elog(ERROR, "Unknown status %u from heap_mark4update", test);
1080 * Finally create a new "clean" tuple with all junk attributes
1083 newTuple = ExecRemoveJunk(junkfilter, slot);
1085 slot = ExecStoreTuple(newTuple, /* tuple to store */
1086 junkfilter->jf_resultSlot, /* dest slot */
1087 InvalidBuffer, /* this tuple has no
1089 true); /* tuple should be pfreed */
1090 } /* if (junkfilter... */
1093 * now that we have a tuple, do the appropriate thing with it..
1094 * either return it to the user, add it to a relation someplace,
1095 * delete it from a relation, or modify some of its attributes.
1101 ExecRetrieve(slot, /* slot containing tuple */
1102 destfunc, /* destination's tuple-receiver
1109 ExecAppend(slot, tupleid, estate);
1114 ExecDelete(slot, tupleid, estate);
1119 ExecReplace(slot, tupleid, estate);
1124 elog(LOG, "ExecutePlan: unknown operation in queryDesc");
1130 * check our tuple count.. if we've processed the proper number
1131 * then quit, else loop again and process more tuples..
1133 current_tuple_count++;
1134 if (numberTuples == current_tuple_count)
1139 * here, result is either a slot containing a tuple in the case of a
1140 * RETRIEVE or NULL otherwise.
1145 /* ----------------------------------------------------------------
1148 * RETRIEVEs are easy.. we just pass the tuple to the appropriate
1149 * print function. The only complexity is when we do a
1150 * "retrieve into", in which case we insert the tuple into
1151 * the appropriate relation (note: this is a newly created relation
1152 * so we don't need to worry about indices or locks.)
1153 * ----------------------------------------------------------------
1156 ExecRetrieve(TupleTableSlot *slot,
1157 DestReceiver *destfunc,
1164 * get the heap tuple out of the tuple table slot
1167 attrtype = slot->ttc_tupleDescriptor;
1170 * insert the tuple into the "into relation"
1172 if (estate->es_into_relation_descriptor != NULL)
1174 heap_insert(estate->es_into_relation_descriptor, tuple,
1175 estate->es_snapshot->curcid);
1180 * send the tuple to the front end (or the screen)
1182 (*destfunc->receiveTuple) (tuple, attrtype, destfunc);
1184 (estate->es_processed)++;
1187 /* ----------------------------------------------------------------
1190 * APPENDs are trickier.. we have to insert the tuple into
1191 * the base relation and insert appropriate tuples into the
1193 * ----------------------------------------------------------------
1197 ExecAppend(TupleTableSlot *slot,
1198 ItemPointer tupleid,
1202 ResultRelInfo *resultRelInfo;
1203 Relation resultRelationDesc;
1208 * get the heap tuple out of the tuple table slot
1213 * get information on the (current) result relation
1215 resultRelInfo = estate->es_result_relation_info;
1216 resultRelationDesc = resultRelInfo->ri_RelationDesc;
1218 /* BEFORE ROW INSERT Triggers */
1219 if (resultRelInfo->ri_TrigDesc &&
1220 resultRelInfo->ri_TrigDesc->n_before_row[TRIGGER_EVENT_INSERT] > 0)
1224 newtuple = ExecBRInsertTriggers(estate, resultRelInfo, tuple);
1226 if (newtuple == NULL) /* "do nothing" */
1229 if (newtuple != tuple) /* modified by Trigger(s) */
1232 * Insert modified tuple into tuple table slot, replacing the
1233 * original. We assume that it was allocated in per-tuple
1234 * memory context, and therefore will go away by itself. The
1235 * tuple table slot should not try to clear it.
1237 ExecStoreTuple(newtuple, slot, InvalidBuffer, false);
1243 * Check the constraints of the tuple
1245 if (resultRelationDesc->rd_att->constr)
1246 ExecConstraints("ExecAppend", resultRelInfo, slot, estate);
1251 newId = heap_insert(resultRelationDesc, tuple,
1252 estate->es_snapshot->curcid);
1255 (estate->es_processed)++;
1256 estate->es_lastoid = newId;
1257 setLastTid(&(tuple->t_self));
1262 * Note: heap_insert adds a new tuple to a relation. As a side effect,
1263 * the tupleid of the new tuple is placed in the new tuple's t_ctid
1266 numIndices = resultRelInfo->ri_NumIndices;
1268 ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false);
1270 /* AFTER ROW INSERT Triggers */
1271 if (resultRelInfo->ri_TrigDesc)
1272 ExecARInsertTriggers(estate, resultRelInfo, tuple);
1275 /* ----------------------------------------------------------------
1278 * DELETE is like append, we delete the tuple and its
1280 * ----------------------------------------------------------------
1283 ExecDelete(TupleTableSlot *slot,
1284 ItemPointer tupleid,
1287 ResultRelInfo *resultRelInfo;
1288 Relation resultRelationDesc;
1289 ItemPointerData ctid;
1293 * get information on the (current) result relation
1295 resultRelInfo = estate->es_result_relation_info;
1296 resultRelationDesc = resultRelInfo->ri_RelationDesc;
1298 /* BEFORE ROW DELETE Triggers */
1299 if (resultRelInfo->ri_TrigDesc &&
1300 resultRelInfo->ri_TrigDesc->n_before_row[TRIGGER_EVENT_DELETE] > 0)
1304 dodelete = ExecBRDeleteTriggers(estate, resultRelInfo, tupleid);
1306 if (!dodelete) /* "do nothing" */
1314 result = heap_delete(resultRelationDesc, tupleid,
1316 estate->es_snapshot->curcid);
1319 case HeapTupleSelfUpdated:
1322 case HeapTupleMayBeUpdated:
1325 case HeapTupleUpdated:
1326 if (XactIsoLevel == XACT_SERIALIZABLE)
1327 elog(ERROR, "Can't serialize access due to concurrent update");
1328 else if (!(ItemPointerEquals(tupleid, &ctid)))
1330 TupleTableSlot *epqslot = EvalPlanQual(estate,
1331 resultRelInfo->ri_RangeTableIndex, &ctid);
1333 if (!TupIsNull(epqslot))
1339 /* tuple already deleted; nothing to do */
1343 elog(ERROR, "Unknown status %u from heap_delete", result);
1348 (estate->es_processed)++;
1351 * Note: Normally one would think that we have to delete index tuples
1352 * associated with the heap tuple now..
1354 * ... but in POSTGRES, we have no need to do this because the vacuum
1355 * daemon automatically opens an index scan and deletes index tuples
1356 * when it finds deleted heap tuples. -cim 9/27/89
1359 /* AFTER ROW DELETE Triggers */
1360 if (resultRelInfo->ri_TrigDesc)
1361 ExecARDeleteTriggers(estate, resultRelInfo, tupleid);
1364 /* ----------------------------------------------------------------
1367 * note: we can't run replace queries with transactions
1368 * off because replaces are actually appends and our
1369 * scan will mistakenly loop forever, replacing the tuple
1370 * it just appended.. This should be fixed but until it
1371 * is, we don't want to get stuck in an infinite loop
1372 * which corrupts your database..
1373 * ----------------------------------------------------------------
1376 ExecReplace(TupleTableSlot *slot,
1377 ItemPointer tupleid,
1381 ResultRelInfo *resultRelInfo;
1382 Relation resultRelationDesc;
1383 ItemPointerData ctid;
1388 * abort the operation if not running transactions
1390 if (IsBootstrapProcessingMode())
1392 elog(WARNING, "ExecReplace: replace can't run without transactions");
1397 * get the heap tuple out of the tuple table slot
1402 * get information on the (current) result relation
1404 resultRelInfo = estate->es_result_relation_info;
1405 resultRelationDesc = resultRelInfo->ri_RelationDesc;
1407 /* BEFORE ROW UPDATE Triggers */
1408 if (resultRelInfo->ri_TrigDesc &&
1409 resultRelInfo->ri_TrigDesc->n_before_row[TRIGGER_EVENT_UPDATE] > 0)
1413 newtuple = ExecBRUpdateTriggers(estate, resultRelInfo,
1416 if (newtuple == NULL) /* "do nothing" */
1419 if (newtuple != tuple) /* modified by Trigger(s) */
1422 * Insert modified tuple into tuple table slot, replacing the
1423 * original. We assume that it was allocated in per-tuple
1424 * memory context, and therefore will go away by itself. The
1425 * tuple table slot should not try to clear it.
1427 ExecStoreTuple(newtuple, slot, InvalidBuffer, false);
1433 * Check the constraints of the tuple
1435 * If we generate a new candidate tuple after EvalPlanQual testing, we
1436 * must loop back here and recheck constraints. (We don't need to
1437 * redo triggers, however. If there are any BEFORE triggers then
1438 * trigger.c will have done mark4update to lock the correct tuple, so
1439 * there's no need to do them again.)
1442 if (resultRelationDesc->rd_att->constr)
1443 ExecConstraints("ExecReplace", resultRelInfo, slot, estate);
1446 * replace the heap tuple
1448 result = heap_update(resultRelationDesc, tupleid, tuple,
1450 estate->es_snapshot->curcid);
1453 case HeapTupleSelfUpdated:
1456 case HeapTupleMayBeUpdated:
1459 case HeapTupleUpdated:
1460 if (XactIsoLevel == XACT_SERIALIZABLE)
1461 elog(ERROR, "Can't serialize access due to concurrent update");
1462 else if (!(ItemPointerEquals(tupleid, &ctid)))
1464 TupleTableSlot *epqslot = EvalPlanQual(estate,
1465 resultRelInfo->ri_RangeTableIndex, &ctid);
1467 if (!TupIsNull(epqslot))
1470 tuple = ExecRemoveJunk(estate->es_junkFilter, epqslot);
1471 slot = ExecStoreTuple(tuple,
1472 estate->es_junkFilter->jf_resultSlot,
1473 InvalidBuffer, true);
1477 /* tuple already deleted; nothing to do */
1481 elog(ERROR, "Unknown status %u from heap_update", result);
1486 (estate->es_processed)++;
1489 * Note: instead of having to update the old index tuples associated
1490 * with the heap tuple, all we do is form and insert new index tuples.
1491 * This is because replaces are actually deletes and inserts and index
1492 * tuple deletion is done automagically by the vacuum daemon. All we
1493 * do is insert new index tuples. -cim 9/27/89
1499 * heap_update updates a tuple in the base relation by invalidating it
1500 * and then appending a new tuple to the relation. As a side effect,
1501 * the tupleid of the new tuple is placed in the new tuple's t_ctid
1502 * field. So we now insert index tuples using the new tupleid stored
1506 numIndices = resultRelInfo->ri_NumIndices;
1508 ExecInsertIndexTuples(slot, &(tuple->t_self), estate, true);
1510 /* AFTER ROW UPDATE Triggers */
1511 if (resultRelInfo->ri_TrigDesc)
1512 ExecARUpdateTriggers(estate, resultRelInfo, tupleid, tuple);
1516 ExecRelCheck(ResultRelInfo *resultRelInfo,
1517 TupleTableSlot *slot, EState *estate)
1519 Relation rel = resultRelInfo->ri_RelationDesc;
1520 int ncheck = rel->rd_att->constr->num_check;
1521 ConstrCheck *check = rel->rd_att->constr->check;
1522 ExprContext *econtext;
1523 MemoryContext oldContext;
1528 * If first time through for this result relation, build expression
1529 * nodetrees for rel's constraint expressions. Keep them in the
1530 * per-query memory context so they'll survive throughout the query.
1532 if (resultRelInfo->ri_ConstraintExprs == NULL)
1534 oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
1535 resultRelInfo->ri_ConstraintExprs =
1536 (List **) palloc(ncheck * sizeof(List *));
1537 for (i = 0; i < ncheck; i++)
1539 qual = (List *) stringToNode(check[i].ccbin);
1540 resultRelInfo->ri_ConstraintExprs[i] = qual;
1542 MemoryContextSwitchTo(oldContext);
1546 * We will use the EState's per-tuple context for evaluating
1547 * constraint expressions (creating it if it's not already there).
1549 econtext = GetPerTupleExprContext(estate);
1551 /* Arrange for econtext's scan tuple to be the tuple under test */
1552 econtext->ecxt_scantuple = slot;
1554 /* And evaluate the constraints */
1555 for (i = 0; i < ncheck; i++)
1557 qual = resultRelInfo->ri_ConstraintExprs[i];
1560 * NOTE: SQL92 specifies that a NULL result from a constraint
1561 * expression is not to be treated as a failure. Therefore, tell
1562 * ExecQual to return TRUE for NULL.
1564 if (!ExecQual(qual, econtext, true))
1565 return check[i].ccname;
1568 /* NULL result means no error */
1569 return (char *) NULL;
1573 ExecConstraints(char *caller, ResultRelInfo *resultRelInfo,
1574 TupleTableSlot *slot, EState *estate)
1576 Relation rel = resultRelInfo->ri_RelationDesc;
1577 HeapTuple tuple = slot->val;
1578 TupleConstr *constr = rel->rd_att->constr;
1582 if (constr->has_not_null)
1584 int natts = rel->rd_att->natts;
1587 for (attrChk = 1; attrChk <= natts; attrChk++)
1589 if (rel->rd_att->attrs[attrChk - 1]->attnotnull &&
1590 heap_attisnull(tuple, attrChk))
1591 elog(ERROR, "%s: Fail to add null value in not null attribute %s",
1592 caller, NameStr(rel->rd_att->attrs[attrChk - 1]->attname));
1596 if (constr->num_check > 0)
1600 if ((failed = ExecRelCheck(resultRelInfo, slot, estate)) != NULL)
1601 elog(ERROR, "%s: rejected due to CHECK constraint %s",
1607 * Check a modified tuple to see if we want to process its updated version
1608 * under READ COMMITTED rules.
1610 * See backend/executor/README for some info about how this works.
1613 EvalPlanQual(EState *estate, Index rti, ItemPointer tid)
1618 HeapTupleData tuple;
1619 HeapTuple copyTuple = NULL;
1626 * find relation containing target tuple
1628 if (estate->es_result_relation_info != NULL &&
1629 estate->es_result_relation_info->ri_RangeTableIndex == rti)
1630 relation = estate->es_result_relation_info->ri_RelationDesc;
1636 foreach(l, estate->es_rowMark)
1638 if (((execRowMark *) lfirst(l))->rti == rti)
1640 relation = ((execRowMark *) lfirst(l))->relation;
1644 if (relation == NULL)
1645 elog(ERROR, "EvalPlanQual: can't find RTE %d", (int) rti);
1651 * Loop here to deal with updated or busy tuples
1653 tuple.t_self = *tid;
1658 heap_fetch(relation, SnapshotDirty, &tuple, &buffer, NULL);
1659 if (tuple.t_data != NULL)
1661 TransactionId xwait = SnapshotDirty->xmax;
1663 if (TransactionIdIsValid(SnapshotDirty->xmin))
1664 elog(ERROR, "EvalPlanQual: t_xmin is uncommitted ?!");
1667 * If tuple is being updated by other transaction then we have
1668 * to wait for its commit/abort.
1670 if (TransactionIdIsValid(xwait))
1672 ReleaseBuffer(buffer);
1673 XactLockTableWait(xwait);
1678 * We got tuple - now copy it for use by recheck query.
1680 copyTuple = heap_copytuple(&tuple);
1681 ReleaseBuffer(buffer);
1686 * Oops! Invalid tuple. Have to check is it updated or deleted.
1687 * Note that it's possible to get invalid SnapshotDirty->tid if
1688 * tuple updated by this transaction. Have we to check this ?
1690 if (ItemPointerIsValid(&(SnapshotDirty->tid)) &&
1691 !(ItemPointerEquals(&(tuple.t_self), &(SnapshotDirty->tid))))
1693 /* updated, so look at the updated copy */
1694 tuple.t_self = SnapshotDirty->tid;
1699 * Deleted or updated by this transaction; forget it.
1705 * For UPDATE/DELETE we have to return tid of actual row we're
1708 *tid = tuple.t_self;
1711 * Need to run a recheck subquery. Find or create a PQ stack entry.
1713 epq = (evalPlanQual *) estate->es_evalPlanQual;
1714 rtsize = length(estate->es_range_table);
1717 if (epq != NULL && epq->rti == 0)
1719 /* Top PQ stack entry is idle, so re-use it */
1720 Assert(!(estate->es_useEvalPlan) &&
1721 epq->estate.es_evalPlanQual == NULL);
1727 * If this is request for another RTE - Ra, - then we have to check
1728 * wasn't PlanQual requested for Ra already and if so then Ra' row was
1729 * updated again and we have to re-start old execution for Ra and
1730 * forget all what we done after Ra was suspended. Cool? -:))
1732 if (epq != NULL && epq->rti != rti &&
1733 epq->estate.es_evTuple[rti - 1] != NULL)
1737 evalPlanQual *oldepq;
1739 /* pop previous PlanQual from the stack */
1740 epqstate = &(epq->estate);
1741 oldepq = (evalPlanQual *) epqstate->es_evalPlanQual;
1742 Assert(oldepq->rti != 0);
1743 /* stop execution */
1744 ExecEndNode(epq->plan, NULL);
1745 ExecDropTupleTable(epqstate->es_tupleTable, true);
1746 epqstate->es_tupleTable = NULL;
1747 heap_freetuple(epqstate->es_evTuple[epq->rti - 1]);
1748 epqstate->es_evTuple[epq->rti - 1] = NULL;
1749 /* push current PQ to freePQ stack */
1752 estate->es_evalPlanQual = (Pointer) epq;
1753 } while (epq->rti != rti);
1757 * If we are requested for another RTE then we have to suspend
1758 * execution of current PlanQual and start execution for new one.
1760 if (epq == NULL || epq->rti != rti)
1762 /* try to reuse plan used previously */
1763 evalPlanQual *newepq = (epq != NULL) ? epq->free : NULL;
1765 if (newepq == NULL) /* first call or freePQ stack is empty */
1767 newepq = (evalPlanQual *) palloc(sizeof(evalPlanQual));
1768 newepq->free = NULL;
1771 * Each stack level has its own copy of the plan tree. This
1772 * is wasteful, but necessary as long as plan nodes point to
1773 * exec state nodes rather than vice versa. Note that
1774 * copyfuncs.c doesn't attempt to copy the exec state nodes,
1775 * which is a good thing in this situation.
1777 newepq->plan = copyObject(estate->es_origPlan);
1780 * Init stack level's EState. We share top level's copy of
1781 * es_result_relations array and other non-changing status. We
1782 * need our own tupletable, es_param_exec_vals, and other
1785 epqstate = &(newepq->estate);
1786 memcpy(epqstate, estate, sizeof(EState));
1787 epqstate->es_direction = ForwardScanDirection;
1788 if (estate->es_origPlan->nParamExec > 0)
1789 epqstate->es_param_exec_vals = (ParamExecData *)
1790 palloc(estate->es_origPlan->nParamExec *
1791 sizeof(ParamExecData));
1792 epqstate->es_tupleTable = NULL;
1793 epqstate->es_per_tuple_exprcontext = NULL;
1796 * Each epqstate must have its own es_evTupleNull state, but
1797 * all the stack entries share es_evTuple state. This allows
1798 * sub-rechecks to inherit the value being examined by an
1801 epqstate->es_evTupleNull = (bool *) palloc(rtsize * sizeof(bool));
1804 /* first PQ stack entry */
1805 epqstate->es_evTuple = (HeapTuple *)
1806 palloc(rtsize * sizeof(HeapTuple));
1807 memset(epqstate->es_evTuple, 0, rtsize * sizeof(HeapTuple));
1811 /* later stack entries share the same storage */
1812 epqstate->es_evTuple = epq->estate.es_evTuple;
1817 /* recycle previously used EState */
1818 epqstate = &(newepq->estate);
1820 /* push current PQ to the stack */
1821 epqstate->es_evalPlanQual = (Pointer) epq;
1823 estate->es_evalPlanQual = (Pointer) epq;
1828 Assert(epq->rti == rti);
1829 epqstate = &(epq->estate);
1832 * Ok - we're requested for the same RTE. Unfortunately we still have
1833 * to end and restart execution of the plan, because ExecReScan
1834 * wouldn't ensure that upper plan nodes would reset themselves. We
1835 * could make that work if insertion of the target tuple were
1836 * integrated with the Param mechanism somehow, so that the upper plan
1837 * nodes know that their children's outputs have changed.
1841 /* stop execution */
1842 ExecEndNode(epq->plan, NULL);
1843 ExecDropTupleTable(epqstate->es_tupleTable, true);
1844 epqstate->es_tupleTable = NULL;
1848 * free old RTE' tuple, if any, and store target tuple where
1849 * relation's scan node will see it
1851 if (epqstate->es_evTuple[rti - 1] != NULL)
1852 heap_freetuple(epqstate->es_evTuple[rti - 1]);
1853 epqstate->es_evTuple[rti - 1] = copyTuple;
1856 * Initialize for new recheck query; be careful to copy down state
1857 * that might have changed in top EState.
1859 epqstate->es_result_relation_info = estate->es_result_relation_info;
1860 epqstate->es_junkFilter = estate->es_junkFilter;
1861 if (estate->es_origPlan->nParamExec > 0)
1862 memset(epqstate->es_param_exec_vals, 0,
1863 estate->es_origPlan->nParamExec * sizeof(ParamExecData));
1864 memset(epqstate->es_evTupleNull, false, rtsize * sizeof(bool));
1865 epqstate->es_useEvalPlan = false;
1866 Assert(epqstate->es_tupleTable == NULL);
1867 epqstate->es_tupleTable =
1868 ExecCreateTupleTable(estate->es_tupleTable->size);
1870 ExecInitNode(epq->plan, epqstate, NULL);
1872 return EvalPlanQualNext(estate);
1875 static TupleTableSlot *
1876 EvalPlanQualNext(EState *estate)
1878 evalPlanQual *epq = (evalPlanQual *) estate->es_evalPlanQual;
1879 EState *epqstate = &(epq->estate);
1880 evalPlanQual *oldepq;
1881 TupleTableSlot *slot;
1883 Assert(epq->rti != 0);
1886 slot = ExecProcNode(epq->plan, NULL);
1889 * No more tuples for this PQ. Continue previous one.
1891 if (TupIsNull(slot))
1893 /* stop execution */
1894 ExecEndNode(epq->plan, NULL);
1895 ExecDropTupleTable(epqstate->es_tupleTable, true);
1896 epqstate->es_tupleTable = NULL;
1897 heap_freetuple(epqstate->es_evTuple[epq->rti - 1]);
1898 epqstate->es_evTuple[epq->rti - 1] = NULL;
1899 /* pop old PQ from the stack */
1900 oldepq = (evalPlanQual *) epqstate->es_evalPlanQual;
1901 if (oldepq == (evalPlanQual *) NULL)
1903 epq->rti = 0; /* this is the first (oldest) */
1904 estate->es_useEvalPlan = false; /* PQ - mark as free and */
1905 return (NULL); /* continue Query execution */
1907 Assert(oldepq->rti != 0);
1908 /* push current PQ to freePQ stack */
1911 epqstate = &(epq->estate);
1912 estate->es_evalPlanQual = (Pointer) epq;
1920 EndEvalPlanQual(EState *estate)
1922 evalPlanQual *epq = (evalPlanQual *) estate->es_evalPlanQual;
1923 EState *epqstate = &(epq->estate);
1924 evalPlanQual *oldepq;
1926 if (epq->rti == 0) /* plans already shutdowned */
1928 Assert(epq->estate.es_evalPlanQual == NULL);
1934 /* stop execution */
1935 ExecEndNode(epq->plan, NULL);
1936 ExecDropTupleTable(epqstate->es_tupleTable, true);
1937 epqstate->es_tupleTable = NULL;
1938 if (epqstate->es_evTuple[epq->rti - 1] != NULL)
1940 heap_freetuple(epqstate->es_evTuple[epq->rti - 1]);
1941 epqstate->es_evTuple[epq->rti - 1] = NULL;
1943 /* pop old PQ from the stack */
1944 oldepq = (evalPlanQual *) epqstate->es_evalPlanQual;
1945 if (oldepq == (evalPlanQual *) NULL)
1947 epq->rti = 0; /* this is the first (oldest) */
1948 estate->es_useEvalPlan = false; /* PQ - mark as free */
1951 Assert(oldepq->rti != 0);
1952 /* push current PQ to freePQ stack */
1955 epqstate = &(epq->estate);
1956 estate->es_evalPlanQual = (Pointer) epq;