]> granicus.if.org Git - postgresql/blob - src/backend/executor/execMain.c
Phase 1 of read-only-plans project: cause executor state nodes to point
[postgresql] / src / backend / executor / execMain.c
1 /*-------------------------------------------------------------------------
2  *
3  * execMain.c
4  *        top level executor interface routines
5  *
6  * INTERFACE ROUTINES
7  *      ExecutorStart()
8  *      ExecutorRun()
9  *      ExecutorEnd()
10  *
11  *      The old ExecutorMain() has been replaced by ExecutorStart(),
12  *      ExecutorRun() and ExecutorEnd()
13  *
14  *      These three procedures are the external interfaces to the executor.
15  *      In each case, the query descriptor is required as an argument.
16  *
17  *      ExecutorStart() must be called at the beginning of execution of any
18  *      query plan and ExecutorEnd() should always be called at the end of
19  *      execution of a plan.
20  *
21  *      ExecutorRun accepts direction and count arguments that specify whether
22  *      the plan is to be executed forwards, backwards, and for how many tuples.
23  *
24  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
25  * Portions Copyright (c) 1994, Regents of the University of California
26  *
27  *
28  * IDENTIFICATION
29  *        $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.190 2002/12/05 15:50:30 tgl Exp $
30  *
31  *-------------------------------------------------------------------------
32  */
33 #include "postgres.h"
34
35 #include "access/heapam.h"
36 #include "catalog/heap.h"
37 #include "catalog/namespace.h"
38 #include "commands/tablecmds.h"
39 #include "commands/trigger.h"
40 #include "executor/execdebug.h"
41 #include "executor/execdefs.h"
42 #include "miscadmin.h"
43 #include "optimizer/var.h"
44 #include "parser/parsetree.h"
45 #include "utils/acl.h"
46 #include "utils/lsyscache.h"
47
48
49 /* decls for local routines only used within this module */
50 static void InitPlan(QueryDesc *queryDesc);
51 static void initResultRelInfo(ResultRelInfo *resultRelInfo,
52                                   Index resultRelationIndex,
53                                   List *rangeTable,
54                                   CmdType operation);
55 static void EndPlan(PlanState *planstate, EState *estate);
56 static TupleTableSlot *ExecutePlan(EState *estate, PlanState *planstate,
57                         CmdType operation,
58                         long numberTuples,
59                         ScanDirection direction,
60                         DestReceiver *destfunc);
61 static void ExecSelect(TupleTableSlot *slot,
62                    DestReceiver *destfunc,
63                    EState *estate);
64 static void ExecInsert(TupleTableSlot *slot, ItemPointer tupleid,
65                    EState *estate);
66 static void ExecDelete(TupleTableSlot *slot, ItemPointer tupleid,
67                    EState *estate);
68 static void ExecUpdate(TupleTableSlot *slot, ItemPointer tupleid,
69                    EState *estate);
70 static TupleTableSlot *EvalPlanQualNext(EState *estate);
71 static void EndEvalPlanQual(EState *estate);
72 static void ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation);
73
74 /* end of local decls */
75
76
77 /* ----------------------------------------------------------------
78  *              ExecutorStart
79  *
80  *              This routine must be called at the beginning of any execution of any
81  *              query plan
82  *
83  * Takes a QueryDesc previously created by CreateQueryDesc (it's not real
84  * clear why we bother to separate the two functions, but...).  The tupDesc
85  * field of the QueryDesc is filled in to describe the tuples that will be
86  * returned, and the internal fields (estate and planstate) are set up.
87  *
88  * XXX this will change soon:
89  * NB: the CurrentMemoryContext when this is called must be the context
90  * to be used as the per-query context for the query plan.      ExecutorRun()
91  * and ExecutorEnd() must be called in this same memory context.
92  * ----------------------------------------------------------------
93  */
94 void
95 ExecutorStart(QueryDesc *queryDesc)
96 {
97         EState     *estate;
98
99         /* sanity checks: queryDesc must not be started already */
100         Assert(queryDesc != NULL);
101         Assert(queryDesc->estate == NULL);
102
103         /*
104          * Build EState, fill with parameters from queryDesc
105          */
106         estate = CreateExecutorState();
107         queryDesc->estate = estate;
108
109         estate->es_param_list_info = queryDesc->params;
110
111         if (queryDesc->plantree->nParamExec > 0)
112                 estate->es_param_exec_vals = (ParamExecData *)
113                         palloc0(queryDesc->plantree->nParamExec * sizeof(ParamExecData));
114
115         estate->es_instrument = queryDesc->doInstrument;
116
117         /*
118          * Make our own private copy of the current query snapshot data.
119          *
120          * This "freezes" our idea of which tuples are good and which are not for
121          * the life of this query, even if it outlives the current command and
122          * current snapshot.
123          */
124         estate->es_snapshot = CopyQuerySnapshot();
125
126         /*
127          * Initialize the plan state tree
128          */
129         InitPlan(queryDesc);
130 }
131
132 /* ----------------------------------------------------------------
133  *              ExecutorRun
134  *
135  *              This is the main routine of the executor module. It accepts
136  *              the query descriptor from the traffic cop and executes the
137  *              query plan.
138  *
139  *              ExecutorStart must have been called already.
140  *
141  *              If direction is NoMovementScanDirection then nothing is done
142  *              except to start up/shut down the destination.  Otherwise,
143  *              we retrieve up to 'count' tuples in the specified direction.
144  *
145  *              Note: count = 0 is interpreted as no portal limit, e.g. run to
146  *              completion.
147  *
148  * ----------------------------------------------------------------
149  */
150 TupleTableSlot *
151 ExecutorRun(QueryDesc *queryDesc,
152                         ScanDirection direction, long count)
153 {
154         CmdType         operation;
155         EState     *estate;
156         CommandDest dest;
157         DestReceiver *destfunc;
158         TupleTableSlot *result;
159
160         /*
161          * sanity checks
162          */
163         Assert(queryDesc != NULL);
164
165         /*
166          * extract information from the query descriptor and the query
167          * feature.
168          */
169         operation = queryDesc->operation;
170         estate = queryDesc->estate;
171         dest = queryDesc->dest;
172
173         /*
174          * startup tuple receiver
175          */
176         estate->es_processed = 0;
177         estate->es_lastoid = InvalidOid;
178
179         destfunc = DestToFunction(dest);
180         (*destfunc->setup) (destfunc, (int) operation,
181                                                 queryDesc->portalName, queryDesc->tupDesc);
182
183         /*
184          * run plan
185          */
186         if (direction == NoMovementScanDirection)
187                 result = NULL;
188         else
189                 result = ExecutePlan(estate,
190                                                          queryDesc->planstate,
191                                                          operation,
192                                                          count,
193                                                          direction,
194                                                          destfunc);
195
196         /*
197          * shutdown receiver
198          */
199         (*destfunc->cleanup) (destfunc);
200
201         return result;
202 }
203
204 /* ----------------------------------------------------------------
205  *              ExecutorEnd
206  *
207  *              This routine must be called at the end of execution of any
208  *              query plan
209  * ----------------------------------------------------------------
210  */
211 void
212 ExecutorEnd(QueryDesc *queryDesc)
213 {
214         EState     *estate;
215
216         /* sanity checks */
217         Assert(queryDesc != NULL);
218
219         estate = queryDesc->estate;
220
221         EndPlan(queryDesc->planstate, estate);
222
223         if (estate->es_snapshot != NULL)
224         {
225                 if (estate->es_snapshot->xcnt > 0)
226                         pfree(estate->es_snapshot->xip);
227                 pfree(estate->es_snapshot);
228                 estate->es_snapshot = NULL;
229         }
230
231         if (estate->es_param_exec_vals != NULL)
232         {
233                 pfree(estate->es_param_exec_vals);
234                 estate->es_param_exec_vals = NULL;
235         }
236 }
237
238
239 /*
240  * CreateExecutorState
241  */
242 EState *
243 CreateExecutorState(void)
244 {
245         EState     *state;
246
247         /*
248          * create a new executor state
249          */
250         state = makeNode(EState);
251
252         /*
253          * initialize the Executor State structure
254          */
255         state->es_direction = ForwardScanDirection;
256         state->es_range_table = NIL;
257
258         state->es_result_relations = NULL;
259         state->es_num_result_relations = 0;
260         state->es_result_relation_info = NULL;
261
262         state->es_junkFilter = NULL;
263
264         state->es_into_relation_descriptor = NULL;
265
266         state->es_param_list_info = NULL;
267         state->es_param_exec_vals = NULL;
268
269         state->es_tupleTable = NULL;
270
271         state->es_query_cxt = CurrentMemoryContext;
272
273         state->es_instrument = false;
274
275         state->es_per_tuple_exprcontext = NULL;
276
277         /*
278          * return the executor state structure
279          */
280         return state;
281 }
282
283
284 /*
285  * ExecCheckRTPerms
286  *              Check access permissions for all relations listed in a range table.
287  */
288 void
289 ExecCheckRTPerms(List *rangeTable, CmdType operation)
290 {
291         List       *lp;
292
293         foreach(lp, rangeTable)
294         {
295                 RangeTblEntry *rte = lfirst(lp);
296
297                 ExecCheckRTEPerms(rte, operation);
298         }
299 }
300
301 /*
302  * ExecCheckRTEPerms
303  *              Check access permissions for a single RTE.
304  */
305 static void
306 ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation)
307 {
308         Oid                     relOid;
309         AclId           userid;
310         AclResult       aclcheck_result;
311
312         /*
313          * If it's a subquery, recursively examine its rangetable.
314          */
315         if (rte->rtekind == RTE_SUBQUERY)
316         {
317                 ExecCheckRTPerms(rte->subquery->rtable, operation);
318                 return;
319         }
320
321         /*
322          * Otherwise, only plain-relation RTEs need to be checked here.
323          * Function RTEs are checked by init_fcache when the function is prepared
324          * for execution. Join and special RTEs need no checks.
325          */
326         if (rte->rtekind != RTE_RELATION)
327                 return;
328
329         relOid = rte->relid;
330
331         /*
332          * userid to check as: current user unless we have a setuid
333          * indication.
334          *
335          * Note: GetUserId() is presently fast enough that there's no harm in
336          * calling it separately for each RTE.  If that stops being true, we
337          * could call it once in ExecCheckRTPerms and pass the userid down
338          * from there.  But for now, no need for the extra clutter.
339          */
340         userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
341
342 #define CHECK(MODE)             pg_class_aclcheck(relOid, userid, MODE)
343
344         if (rte->checkForRead)
345         {
346                 aclcheck_result = CHECK(ACL_SELECT);
347                 if (aclcheck_result != ACLCHECK_OK)
348                         aclcheck_error(aclcheck_result, get_rel_name(relOid));
349         }
350
351         if (rte->checkForWrite)
352         {
353                 /*
354                  * Note: write access in a SELECT context means SELECT FOR UPDATE.
355                  * Right now we don't distinguish that from true update as far as
356                  * permissions checks are concerned.
357                  */
358                 switch (operation)
359                 {
360                         case CMD_INSERT:
361                                 aclcheck_result = CHECK(ACL_INSERT);
362                                 break;
363                         case CMD_SELECT:
364                         case CMD_UPDATE:
365                                 aclcheck_result = CHECK(ACL_UPDATE);
366                                 break;
367                         case CMD_DELETE:
368                                 aclcheck_result = CHECK(ACL_DELETE);
369                                 break;
370                         default:
371                                 elog(ERROR, "ExecCheckRTEPerms: bogus operation %d",
372                                          operation);
373                                 aclcheck_result = ACLCHECK_OK;  /* keep compiler quiet */
374                                 break;
375                 }
376                 if (aclcheck_result != ACLCHECK_OK)
377                         aclcheck_error(aclcheck_result, get_rel_name(relOid));
378         }
379 }
380
381
382 /* ===============================================================
383  * ===============================================================
384                                                  static routines follow
385  * ===============================================================
386  * ===============================================================
387  */
388
389 typedef struct execRowMark
390 {
391         Relation        relation;
392         Index           rti;
393         char            resname[32];
394 } execRowMark;
395
396 typedef struct evalPlanQual
397 {
398         Plan       *plan;                       /* XXX temporary */
399         PlanState  *planstate;
400         Index           rti;
401         EState          estate;
402         struct evalPlanQual *free;
403 } evalPlanQual;
404
405 /* ----------------------------------------------------------------
406  *              InitPlan
407  *
408  *              Initializes the query plan: open files, allocate storage
409  *              and start up the rule manager
410  * ----------------------------------------------------------------
411  */
412 static void
413 InitPlan(QueryDesc *queryDesc)
414 {
415         CmdType         operation = queryDesc->operation;
416         Query *parseTree = queryDesc->parsetree;
417         Plan *plan = queryDesc->plantree;
418         EState *estate = queryDesc->estate;
419         PlanState  *planstate;
420         List       *rangeTable;
421         Relation        intoRelationDesc;
422         TupleDesc       tupType;
423
424         /*
425          * Do permissions checks.  It's sufficient to examine the query's
426          * top rangetable here --- subplan RTEs will be checked during
427          * ExecInitSubPlan().
428          */
429         ExecCheckRTPerms(parseTree->rtable, operation);
430
431         /*
432          * get information from query descriptor
433          */
434         rangeTable = parseTree->rtable;
435
436         /*
437          * initialize the node's execution state
438          */
439         estate->es_range_table = rangeTable;
440
441         /*
442          * if there is a result relation, initialize result relation stuff
443          */
444         if (parseTree->resultRelation != 0 && operation != CMD_SELECT)
445         {
446                 List       *resultRelations = parseTree->resultRelations;
447                 int                     numResultRelations;
448                 ResultRelInfo *resultRelInfos;
449
450                 if (resultRelations != NIL)
451                 {
452                         /*
453                          * Multiple result relations (due to inheritance)
454                          * parseTree->resultRelations identifies them all
455                          */
456                         ResultRelInfo *resultRelInfo;
457
458                         numResultRelations = length(resultRelations);
459                         resultRelInfos = (ResultRelInfo *)
460                                 palloc(numResultRelations * sizeof(ResultRelInfo));
461                         resultRelInfo = resultRelInfos;
462                         while (resultRelations != NIL)
463                         {
464                                 initResultRelInfo(resultRelInfo,
465                                                                   lfirsti(resultRelations),
466                                                                   rangeTable,
467                                                                   operation);
468                                 resultRelInfo++;
469                                 resultRelations = lnext(resultRelations);
470                         }
471                 }
472                 else
473                 {
474                         /*
475                          * Single result relation identified by
476                          * parseTree->resultRelation
477                          */
478                         numResultRelations = 1;
479                         resultRelInfos = (ResultRelInfo *) palloc(sizeof(ResultRelInfo));
480                         initResultRelInfo(resultRelInfos,
481                                                           parseTree->resultRelation,
482                                                           rangeTable,
483                                                           operation);
484                 }
485
486                 estate->es_result_relations = resultRelInfos;
487                 estate->es_num_result_relations = numResultRelations;
488                 /* Initialize to first or only result rel */
489                 estate->es_result_relation_info = resultRelInfos;
490         }
491         else
492         {
493                 /*
494                  * if no result relation, then set state appropriately
495                  */
496                 estate->es_result_relations = NULL;
497                 estate->es_num_result_relations = 0;
498                 estate->es_result_relation_info = NULL;
499         }
500
501         /*
502          * Have to lock relations selected for update
503          */
504         estate->es_rowMark = NIL;
505         if (parseTree->rowMarks != NIL)
506         {
507                 List       *l;
508
509                 foreach(l, parseTree->rowMarks)
510                 {
511                         Index           rti = lfirsti(l);
512                         Oid                     relid = getrelid(rti, rangeTable);
513                         Relation        relation;
514                         execRowMark *erm;
515
516                         relation = heap_open(relid, RowShareLock);
517                         erm = (execRowMark *) palloc(sizeof(execRowMark));
518                         erm->relation = relation;
519                         erm->rti = rti;
520                         snprintf(erm->resname, 32, "ctid%u", rti);
521                         estate->es_rowMark = lappend(estate->es_rowMark, erm);
522                 }
523         }
524
525         /*
526          * initialize the executor "tuple" table.  We need slots for all the
527          * plan nodes, plus possibly output slots for the junkfilter(s). At
528          * this point we aren't sure if we need junkfilters, so just add slots
529          * for them unconditionally.
530          */
531         {
532                 int                     nSlots = ExecCountSlotsNode(plan);
533
534                 if (parseTree->resultRelations != NIL)
535                         nSlots += length(parseTree->resultRelations);
536                 else
537                         nSlots += 1;
538                 estate->es_tupleTable = ExecCreateTupleTable(nSlots);
539         }
540
541         /* mark EvalPlanQual not active */
542         estate->es_origPlan = plan;
543         estate->es_evalPlanQual = NULL;
544         estate->es_evTuple = NULL;
545         estate->es_evTupleNull = NULL;
546         estate->es_useEvalPlan = false;
547
548         /*
549          * initialize the private state information for all the nodes in the
550          * query tree.  This opens files, allocates storage and leaves us
551          * ready to start processing tuples.
552          */
553         planstate = ExecInitNode(plan, estate);
554
555         /*
556          * Get the tuple descriptor describing the type of tuples to return.
557          * (this is especially important if we are creating a relation with
558          * "SELECT INTO")
559          */
560         tupType = ExecGetTupType(planstate);
561
562         /*
563          * Initialize the junk filter if needed. SELECT and INSERT queries
564          * need a filter if there are any junk attrs in the tlist.      UPDATE and
565          * DELETE always need one, since there's always a junk 'ctid'
566          * attribute present --- no need to look first.
567          */
568         {
569                 bool            junk_filter_needed = false;
570                 List       *tlist;
571
572                 switch (operation)
573                 {
574                         case CMD_SELECT:
575                         case CMD_INSERT:
576                                 foreach(tlist, plan->targetlist)
577                                 {
578                                         TargetEntry *tle = (TargetEntry *) lfirst(tlist);
579
580                                         if (tle->resdom->resjunk)
581                                         {
582                                                 junk_filter_needed = true;
583                                                 break;
584                                         }
585                                 }
586                                 break;
587                         case CMD_UPDATE:
588                         case CMD_DELETE:
589                                 junk_filter_needed = true;
590                                 break;
591                         default:
592                                 break;
593                 }
594
595                 if (junk_filter_needed)
596                 {
597                         /*
598                          * If there are multiple result relations, each one needs its
599                          * own junk filter.  Note this is only possible for
600                          * UPDATE/DELETE, so we can't be fooled by some needing a
601                          * filter and some not.
602                          */
603                         if (parseTree->resultRelations != NIL)
604                         {
605                                 PlanState **appendplans;
606                                 int                     as_nplans;
607                                 ResultRelInfo *resultRelInfo;
608                                 int                     i;
609
610                                 /* Top plan had better be an Append here. */
611                                 Assert(IsA(plan, Append));
612                                 Assert(((Append *) plan)->isTarget);
613                                 Assert(IsA(planstate, AppendState));
614                                 appendplans = ((AppendState *) planstate)->appendplans;
615                                 as_nplans = ((AppendState *) planstate)->as_nplans;
616                                 Assert(as_nplans == estate->es_num_result_relations);
617                                 resultRelInfo = estate->es_result_relations;
618                                 for (i = 0; i < as_nplans; i++)
619                                 {
620                                         PlanState  *subplan = appendplans[i];
621                                         JunkFilter *j;
622
623                                         j = ExecInitJunkFilter(subplan->plan->targetlist,
624                                                                                    ExecGetTupType(subplan),
625                                                           ExecAllocTableSlot(estate->es_tupleTable));
626                                         resultRelInfo->ri_junkFilter = j;
627                                         resultRelInfo++;
628                                 }
629
630                                 /*
631                                  * Set active junkfilter too; at this point ExecInitAppend
632                                  * has already selected an active result relation...
633                                  */
634                                 estate->es_junkFilter =
635                                         estate->es_result_relation_info->ri_junkFilter;
636                         }
637                         else
638                         {
639                                 /* Normal case with just one JunkFilter */
640                                 JunkFilter *j;
641
642                                 j = ExecInitJunkFilter(planstate->plan->targetlist,
643                                                                            tupType,
644                                                           ExecAllocTableSlot(estate->es_tupleTable));
645                                 estate->es_junkFilter = j;
646                                 if (estate->es_result_relation_info)
647                                         estate->es_result_relation_info->ri_junkFilter = j;
648
649                                 /* For SELECT, want to return the cleaned tuple type */
650                                 if (operation == CMD_SELECT)
651                                         tupType = j->jf_cleanTupType;
652                         }
653                 }
654                 else
655                         estate->es_junkFilter = NULL;
656         }
657
658         /*
659          * initialize the "into" relation
660          */
661         intoRelationDesc = (Relation) NULL;
662
663         if (operation == CMD_SELECT)
664         {
665                 if (!parseTree->isPortal)
666                 {
667                         /*
668                          * a select into table --- need to create the "into" table
669                          */
670                         if (parseTree->into != NULL)
671                         {
672                                 char       *intoName;
673                                 Oid                     namespaceId;
674                                 AclResult       aclresult;
675                                 Oid                     intoRelationId;
676                                 TupleDesc       tupdesc;
677
678                                 /*
679                                  * find namespace to create in, check permissions
680                                  */
681                                 intoName = parseTree->into->relname;
682                                 namespaceId = RangeVarGetCreationNamespace(parseTree->into);
683
684                                 aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
685                                                                                                   ACL_CREATE);
686                                 if (aclresult != ACLCHECK_OK)
687                                         aclcheck_error(aclresult,
688                                                                    get_namespace_name(namespaceId));
689
690                                 /*
691                                  * have to copy tupType to get rid of constraints
692                                  */
693                                 tupdesc = CreateTupleDescCopy(tupType);
694
695                                 /*
696                                  * Formerly we forced the output table to have OIDs, but
697                                  * as of 7.3 it will not have OIDs, because it's too late
698                                  * here to change the tupdescs of the already-initialized
699                                  * plan tree.  (Perhaps we could recurse and change them
700                                  * all, but it's not really worth the trouble IMHO...)
701                                  */
702
703                                 intoRelationId =
704                                         heap_create_with_catalog(intoName,
705                                                                                          namespaceId,
706                                                                                          tupdesc,
707                                                                                          RELKIND_RELATION,
708                                                                                          false,
709                                                                                          ONCOMMIT_NOOP,
710                                                                                          allowSystemTableMods);
711
712                                 FreeTupleDesc(tupdesc);
713
714                                 /*
715                                  * Advance command counter so that the newly-created
716                                  * relation's catalog tuples will be visible to heap_open.
717                                  */
718                                 CommandCounterIncrement();
719
720                                 /*
721                                  * If necessary, create a TOAST table for the into
722                                  * relation. Note that AlterTableCreateToastTable ends
723                                  * with CommandCounterIncrement(), so that the TOAST table
724                                  * will be visible for insertion.
725                                  */
726                                 AlterTableCreateToastTable(intoRelationId, true);
727
728                                 intoRelationDesc = heap_open(intoRelationId,
729                                                                                          AccessExclusiveLock);
730                         }
731                 }
732         }
733
734         estate->es_into_relation_descriptor = intoRelationDesc;
735
736         queryDesc->tupDesc = tupType;
737         queryDesc->planstate = planstate;
738 }
739
740 /*
741  * Initialize ResultRelInfo data for one result relation
742  */
743 static void
744 initResultRelInfo(ResultRelInfo *resultRelInfo,
745                                   Index resultRelationIndex,
746                                   List *rangeTable,
747                                   CmdType operation)
748 {
749         Oid                     resultRelationOid;
750         Relation        resultRelationDesc;
751
752         resultRelationOid = getrelid(resultRelationIndex, rangeTable);
753         resultRelationDesc = heap_open(resultRelationOid, RowExclusiveLock);
754
755         switch (resultRelationDesc->rd_rel->relkind)
756         {
757                 case RELKIND_SEQUENCE:
758                         elog(ERROR, "You can't change sequence relation %s",
759                                  RelationGetRelationName(resultRelationDesc));
760                         break;
761                 case RELKIND_TOASTVALUE:
762                         elog(ERROR, "You can't change toast relation %s",
763                                  RelationGetRelationName(resultRelationDesc));
764                         break;
765                 case RELKIND_VIEW:
766                         elog(ERROR, "You can't change view relation %s",
767                                  RelationGetRelationName(resultRelationDesc));
768                         break;
769         }
770
771         MemSet(resultRelInfo, 0, sizeof(ResultRelInfo));
772         resultRelInfo->type = T_ResultRelInfo;
773         resultRelInfo->ri_RangeTableIndex = resultRelationIndex;
774         resultRelInfo->ri_RelationDesc = resultRelationDesc;
775         resultRelInfo->ri_NumIndices = 0;
776         resultRelInfo->ri_IndexRelationDescs = NULL;
777         resultRelInfo->ri_IndexRelationInfo = NULL;
778         /* make a copy so as not to depend on relcache info not changing... */
779         resultRelInfo->ri_TrigDesc = CopyTriggerDesc(resultRelationDesc->trigdesc);
780         resultRelInfo->ri_TrigFunctions = NULL;
781         resultRelInfo->ri_ConstraintExprs = NULL;
782         resultRelInfo->ri_junkFilter = NULL;
783
784         /*
785          * If there are indices on the result relation, open them and save
786          * descriptors in the result relation info, so that we can add new
787          * index entries for the tuples we add/update.  We need not do this
788          * for a DELETE, however, since deletion doesn't affect indexes.
789          */
790         if (resultRelationDesc->rd_rel->relhasindex &&
791                 operation != CMD_DELETE)
792                 ExecOpenIndices(resultRelInfo);
793 }
794
795 /* ----------------------------------------------------------------
796  *              EndPlan
797  *
798  *              Cleans up the query plan -- closes files and frees up storage
799  * ----------------------------------------------------------------
800  */
801 static void
802 EndPlan(PlanState *planstate, EState *estate)
803 {
804         ResultRelInfo *resultRelInfo;
805         int                     i;
806         List       *l;
807
808         /*
809          * shut down any PlanQual processing we were doing
810          */
811         if (estate->es_evalPlanQual != NULL)
812                 EndEvalPlanQual(estate);
813
814         /*
815          * shut down the node-type-specific query processing
816          */
817         ExecEndNode(planstate);
818
819         /*
820          * destroy the executor "tuple" table.
821          */
822         ExecDropTupleTable(estate->es_tupleTable, true);
823         estate->es_tupleTable = NULL;
824
825         /*
826          * close the result relation(s) if any, but hold locks until xact
827          * commit.      Also clean up junkfilters if present.
828          */
829         resultRelInfo = estate->es_result_relations;
830         for (i = estate->es_num_result_relations; i > 0; i--)
831         {
832                 /* Close indices and then the relation itself */
833                 ExecCloseIndices(resultRelInfo);
834                 heap_close(resultRelInfo->ri_RelationDesc, NoLock);
835                 /* Delete the junkfilter if any */
836                 if (resultRelInfo->ri_junkFilter != NULL)
837                         ExecFreeJunkFilter(resultRelInfo->ri_junkFilter);
838                 resultRelInfo++;
839         }
840
841         /*
842          * close the "into" relation if necessary, again keeping lock
843          */
844         if (estate->es_into_relation_descriptor != NULL)
845                 heap_close(estate->es_into_relation_descriptor, NoLock);
846
847         /*
848          * There might be a junkfilter without a result relation.
849          */
850         if (estate->es_num_result_relations == 0 &&
851                 estate->es_junkFilter != NULL)
852         {
853                 ExecFreeJunkFilter(estate->es_junkFilter);
854                 estate->es_junkFilter = NULL;
855         }
856
857         /*
858          * close any relations selected FOR UPDATE, again keeping locks
859          */
860         foreach(l, estate->es_rowMark)
861         {
862                 execRowMark *erm = lfirst(l);
863
864                 heap_close(erm->relation, NoLock);
865         }
866 }
867
868 /* ----------------------------------------------------------------
869  *              ExecutePlan
870  *
871  *              processes the query plan to retrieve 'numberTuples' tuples in the
872  *              direction specified.
873  *              Retrieves all tuples if numberTuples is 0
874  *
875  *              result is either a slot containing the last tuple in the case
876  *              of a SELECT or NULL otherwise.
877  *
878  * Note: the ctid attribute is a 'junk' attribute that is removed before the
879  * user can see it
880  * ----------------------------------------------------------------
881  */
882 static TupleTableSlot *
883 ExecutePlan(EState *estate,
884                         PlanState *planstate,
885                         CmdType operation,
886                         long numberTuples,
887                         ScanDirection direction,
888                         DestReceiver *destfunc)
889 {
890         JunkFilter                      *junkfilter;
891         TupleTableSlot          *slot;
892         ItemPointer                      tupleid = NULL;
893         ItemPointerData          tuple_ctid;
894         long                             current_tuple_count;
895         TupleTableSlot          *result;
896
897         /*
898          * initialize local variables
899          */
900         slot = NULL;
901         current_tuple_count = 0;
902         result = NULL;
903
904         /*
905          * Set the direction.
906          */
907         estate->es_direction = direction;
908
909         /*
910          * Process BEFORE EACH STATEMENT triggers
911          */
912         switch (operation)
913         {
914                 case CMD_UPDATE:
915                         ExecBSUpdateTriggers(estate, estate->es_result_relation_info);
916                         break;
917                 case CMD_DELETE:
918                         ExecBSDeleteTriggers(estate, estate->es_result_relation_info);
919                         break;
920                 case CMD_INSERT:
921                         ExecBSInsertTriggers(estate, estate->es_result_relation_info);
922                         break;
923                 default:
924                         /* do nothing */
925                         break;
926         }
927
928         /*
929          * Loop until we've processed the proper number of tuples from the
930          * plan.
931          */
932
933         for (;;)
934         {
935                 /* Reset the per-output-tuple exprcontext */
936                 ResetPerTupleExprContext(estate);
937
938                 /*
939                  * Execute the plan and obtain a tuple
940                  */
941 lnext:  ;
942                 if (estate->es_useEvalPlan)
943                 {
944                         slot = EvalPlanQualNext(estate);
945                         if (TupIsNull(slot))
946                                 slot = ExecProcNode(planstate);
947                 }
948                 else
949                         slot = ExecProcNode(planstate);
950
951                 /*
952                  * if the tuple is null, then we assume there is nothing more to
953                  * process so we just return null...
954                  */
955                 if (TupIsNull(slot))
956                 {
957                         result = NULL;
958                         break;
959                 }
960
961                 /*
962                  * if we have a junk filter, then project a new tuple with the
963                  * junk removed.
964                  *
965                  * Store this new "clean" tuple in the junkfilter's resultSlot.
966                  * (Formerly, we stored it back over the "dirty" tuple, which is
967                  * WRONG because that tuple slot has the wrong descriptor.)
968                  *
969                  * Also, extract all the junk information we need.
970                  */
971                 if ((junkfilter = estate->es_junkFilter) != (JunkFilter *) NULL)
972                 {
973                         Datum           datum;
974                         HeapTuple       newTuple;
975                         bool            isNull;
976
977                         /*
978                          * extract the 'ctid' junk attribute.
979                          */
980                         if (operation == CMD_UPDATE || operation == CMD_DELETE)
981                         {
982                                 if (!ExecGetJunkAttribute(junkfilter,
983                                                                                   slot,
984                                                                                   "ctid",
985                                                                                   &datum,
986                                                                                   &isNull))
987                                         elog(ERROR, "ExecutePlan: NO (junk) `ctid' was found!");
988
989                                 /* shouldn't ever get a null result... */
990                                 if (isNull)
991                                         elog(ERROR, "ExecutePlan: (junk) `ctid' is NULL!");
992
993                                 tupleid = (ItemPointer) DatumGetPointer(datum);
994                                 tuple_ctid = *tupleid;  /* make sure we don't free the
995                                                                                  * ctid!! */
996                                 tupleid = &tuple_ctid;
997                         }
998                         else if (estate->es_rowMark != NIL)
999                         {
1000                                 List       *l;
1001
1002                 lmark:  ;
1003                                 foreach(l, estate->es_rowMark)
1004                                 {
1005                                         execRowMark *erm = lfirst(l);
1006                                         Buffer          buffer;
1007                                         HeapTupleData tuple;
1008                                         TupleTableSlot *newSlot;
1009                                         int                     test;
1010
1011                                         if (!ExecGetJunkAttribute(junkfilter,
1012                                                                                           slot,
1013                                                                                           erm->resname,
1014                                                                                           &datum,
1015                                                                                           &isNull))
1016                                                 elog(ERROR, "ExecutePlan: NO (junk) `%s' was found!",
1017                                                          erm->resname);
1018
1019                                         /* shouldn't ever get a null result... */
1020                                         if (isNull)
1021                                                 elog(ERROR, "ExecutePlan: (junk) `%s' is NULL!",
1022                                                          erm->resname);
1023
1024                                         tuple.t_self = *((ItemPointer) DatumGetPointer(datum));
1025                                         test = heap_mark4update(erm->relation, &tuple, &buffer,
1026                                                                                         estate->es_snapshot->curcid);
1027                                         ReleaseBuffer(buffer);
1028                                         switch (test)
1029                                         {
1030                                                 case HeapTupleSelfUpdated:
1031                                                         /* treat it as deleted; do not process */
1032                                                         goto lnext;
1033
1034                                                 case HeapTupleMayBeUpdated:
1035                                                         break;
1036
1037                                                 case HeapTupleUpdated:
1038                                                         if (XactIsoLevel == XACT_SERIALIZABLE)
1039                                                                 elog(ERROR, "Can't serialize access due to concurrent update");
1040                                                         if (!(ItemPointerEquals(&(tuple.t_self),
1041                                                                   (ItemPointer) DatumGetPointer(datum))))
1042                                                         {
1043                                                                 newSlot = EvalPlanQual(estate, erm->rti, &(tuple.t_self));
1044                                                                 if (!(TupIsNull(newSlot)))
1045                                                                 {
1046                                                                         slot = newSlot;
1047                                                                         estate->es_useEvalPlan = true;
1048                                                                         goto lmark;
1049                                                                 }
1050                                                         }
1051
1052                                                         /*
1053                                                          * if tuple was deleted or PlanQual failed for
1054                                                          * updated tuple - we must not return this
1055                                                          * tuple!
1056                                                          */
1057                                                         goto lnext;
1058
1059                                                 default:
1060                                                         elog(ERROR, "Unknown status %u from heap_mark4update", test);
1061                                                         return (NULL);
1062                                         }
1063                                 }
1064                         }
1065
1066                         /*
1067                          * Finally create a new "clean" tuple with all junk attributes
1068                          * removed
1069                          */
1070                         newTuple = ExecRemoveJunk(junkfilter, slot);
1071
1072                         slot = ExecStoreTuple(newTuple,         /* tuple to store */
1073                                                                   junkfilter->jf_resultSlot,    /* dest slot */
1074                                                                   InvalidBuffer,                /* this tuple has no
1075                                                                                                                  * buffer */
1076                                                                   true);                /* tuple should be pfreed */
1077                 }
1078
1079                 /*
1080                  * now that we have a tuple, do the appropriate thing with it..
1081                  * either return it to the user, add it to a relation someplace,
1082                  * delete it from a relation, or modify some of its attributes.
1083                  */
1084                 switch (operation)
1085                 {
1086                         case CMD_SELECT:
1087                                 ExecSelect(slot,        /* slot containing tuple */
1088                                                    destfunc,    /* destination's tuple-receiver
1089                                                                                  * obj */
1090                                                    estate);
1091                                 result = slot;
1092                                 break;
1093
1094                         case CMD_INSERT:
1095                                 ExecInsert(slot, tupleid, estate);
1096                                 result = NULL;
1097                                 break;
1098
1099                         case CMD_DELETE:
1100                                 ExecDelete(slot, tupleid, estate);
1101                                 result = NULL;
1102                                 break;
1103
1104                         case CMD_UPDATE:
1105                                 ExecUpdate(slot, tupleid, estate);
1106                                 result = NULL;
1107                                 break;
1108
1109                         default:
1110                                 elog(LOG, "ExecutePlan: unknown operation in queryDesc");
1111                                 result = NULL;
1112                                 break;
1113                 }
1114
1115                 /*
1116                  * check our tuple count.. if we've processed the proper number
1117                  * then quit, else loop again and process more tuples.  Zero
1118                  * number_tuples means no limit.
1119                  */
1120                 current_tuple_count++;
1121                 if (numberTuples == current_tuple_count)
1122                         break;
1123         }
1124
1125         /*
1126          * Process AFTER EACH STATEMENT triggers
1127          */
1128         switch (operation)
1129         {
1130                 case CMD_UPDATE:
1131                         ExecASUpdateTriggers(estate, estate->es_result_relation_info);
1132                         break;
1133                 case CMD_DELETE:
1134                         ExecASDeleteTriggers(estate, estate->es_result_relation_info);
1135                         break;
1136                 case CMD_INSERT:
1137                         ExecASInsertTriggers(estate, estate->es_result_relation_info);
1138                         break;
1139                 default:
1140                         /* do nothing */
1141                         break;
1142         }
1143
1144         /*
1145          * here, result is either a slot containing a tuple in the case of a
1146          * SELECT or NULL otherwise.
1147          */
1148         return result;
1149 }
1150
1151 /* ----------------------------------------------------------------
1152  *              ExecSelect
1153  *
1154  *              SELECTs are easy.. we just pass the tuple to the appropriate
1155  *              print function.  The only complexity is when we do a
1156  *              "SELECT INTO", in which case we insert the tuple into
1157  *              the appropriate relation (note: this is a newly created relation
1158  *              so we don't need to worry about indices or locks.)
1159  * ----------------------------------------------------------------
1160  */
1161 static void
1162 ExecSelect(TupleTableSlot *slot,
1163                    DestReceiver *destfunc,
1164                    EState *estate)
1165 {
1166         HeapTuple       tuple;
1167         TupleDesc       attrtype;
1168
1169         /*
1170          * get the heap tuple out of the tuple table slot
1171          */
1172         tuple = slot->val;
1173         attrtype = slot->ttc_tupleDescriptor;
1174
1175         /*
1176          * insert the tuple into the "into relation"
1177          */
1178         if (estate->es_into_relation_descriptor != NULL)
1179         {
1180                 heap_insert(estate->es_into_relation_descriptor, tuple,
1181                                         estate->es_snapshot->curcid);
1182                 IncrAppended();
1183         }
1184
1185         /*
1186          * send the tuple to the front end (or the screen)
1187          */
1188         (*destfunc->receiveTuple) (tuple, attrtype, destfunc);
1189         IncrRetrieved();
1190         (estate->es_processed)++;
1191 }
1192
1193 /* ----------------------------------------------------------------
1194  *              ExecInsert
1195  *
1196  *              INSERTs are trickier.. we have to insert the tuple into
1197  *              the base relation and insert appropriate tuples into the
1198  *              index relations.
1199  * ----------------------------------------------------------------
1200  */
1201 static void
1202 ExecInsert(TupleTableSlot *slot,
1203                    ItemPointer tupleid,
1204                    EState *estate)
1205 {
1206         HeapTuple       tuple;
1207         ResultRelInfo *resultRelInfo;
1208         Relation        resultRelationDesc;
1209         int                     numIndices;
1210         Oid                     newId;
1211
1212         /*
1213          * get the heap tuple out of the tuple table slot
1214          */
1215         tuple = slot->val;
1216
1217         /*
1218          * get information on the (current) result relation
1219          */
1220         resultRelInfo = estate->es_result_relation_info;
1221         resultRelationDesc = resultRelInfo->ri_RelationDesc;
1222
1223         /* BEFORE ROW INSERT Triggers */
1224         if (resultRelInfo->ri_TrigDesc &&
1225                 resultRelInfo->ri_TrigDesc->n_before_row[TRIGGER_EVENT_INSERT] > 0)
1226         {
1227                 HeapTuple       newtuple;
1228
1229                 newtuple = ExecBRInsertTriggers(estate, resultRelInfo, tuple);
1230
1231                 if (newtuple == NULL)   /* "do nothing" */
1232                         return;
1233
1234                 if (newtuple != tuple)  /* modified by Trigger(s) */
1235                 {
1236                         /*
1237                          * Insert modified tuple into tuple table slot, replacing the
1238                          * original.  We assume that it was allocated in per-tuple
1239                          * memory context, and therefore will go away by itself. The
1240                          * tuple table slot should not try to clear it.
1241                          */
1242                         ExecStoreTuple(newtuple, slot, InvalidBuffer, false);
1243                         tuple = newtuple;
1244                 }
1245         }
1246
1247         /*
1248          * Check the constraints of the tuple
1249          */
1250         if (resultRelationDesc->rd_att->constr)
1251                 ExecConstraints("ExecInsert", resultRelInfo, slot, estate);
1252
1253         /*
1254          * insert the tuple
1255          */
1256         newId = heap_insert(resultRelationDesc, tuple,
1257                                                 estate->es_snapshot->curcid);
1258
1259         IncrAppended();
1260         (estate->es_processed)++;
1261         estate->es_lastoid = newId;
1262         setLastTid(&(tuple->t_self));
1263
1264         /*
1265          * process indices
1266          *
1267          * Note: heap_insert adds a new tuple to a relation.  As a side effect,
1268          * the tupleid of the new tuple is placed in the new tuple's t_ctid
1269          * field.
1270          */
1271         numIndices = resultRelInfo->ri_NumIndices;
1272         if (numIndices > 0)
1273                 ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false);
1274
1275         /* AFTER ROW INSERT Triggers */
1276         ExecARInsertTriggers(estate, resultRelInfo, tuple);
1277 }
1278
1279 /* ----------------------------------------------------------------
1280  *              ExecDelete
1281  *
1282  *              DELETE is like UPDATE, we delete the tuple and its
1283  *              index tuples.
1284  * ----------------------------------------------------------------
1285  */
1286 static void
1287 ExecDelete(TupleTableSlot *slot,
1288                    ItemPointer tupleid,
1289                    EState *estate)
1290 {
1291         ResultRelInfo *resultRelInfo;
1292         Relation        resultRelationDesc;
1293         ItemPointerData ctid;
1294         int                     result;
1295
1296         /*
1297          * get information on the (current) result relation
1298          */
1299         resultRelInfo = estate->es_result_relation_info;
1300         resultRelationDesc = resultRelInfo->ri_RelationDesc;
1301
1302         /* BEFORE ROW DELETE Triggers */
1303         if (resultRelInfo->ri_TrigDesc &&
1304           resultRelInfo->ri_TrigDesc->n_before_row[TRIGGER_EVENT_DELETE] > 0)
1305         {
1306                 bool            dodelete;
1307
1308                 dodelete = ExecBRDeleteTriggers(estate, resultRelInfo, tupleid);
1309
1310                 if (!dodelete)                  /* "do nothing" */
1311                         return;
1312         }
1313
1314         /*
1315          * delete the tuple
1316          */
1317 ldelete:;
1318         result = heap_delete(resultRelationDesc, tupleid,
1319                                                  &ctid,
1320                                                  estate->es_snapshot->curcid);
1321         switch (result)
1322         {
1323                 case HeapTupleSelfUpdated:
1324                         /* already deleted by self; nothing to do */
1325                         return;
1326
1327                 case HeapTupleMayBeUpdated:
1328                         break;
1329
1330                 case HeapTupleUpdated:
1331                         if (XactIsoLevel == XACT_SERIALIZABLE)
1332                                 elog(ERROR, "Can't serialize access due to concurrent update");
1333                         else if (!(ItemPointerEquals(tupleid, &ctid)))
1334                         {
1335                                 TupleTableSlot *epqslot = EvalPlanQual(estate,
1336                                                            resultRelInfo->ri_RangeTableIndex, &ctid);
1337
1338                                 if (!TupIsNull(epqslot))
1339                                 {
1340                                         *tupleid = ctid;
1341                                         goto ldelete;
1342                                 }
1343                         }
1344                         /* tuple already deleted; nothing to do */
1345                         return;
1346
1347                 default:
1348                         elog(ERROR, "Unknown status %u from heap_delete", result);
1349                         return;
1350         }
1351
1352         IncrDeleted();
1353         (estate->es_processed)++;
1354
1355         /*
1356          * Note: Normally one would think that we have to delete index tuples
1357          * associated with the heap tuple now..
1358          *
1359          * ... but in POSTGRES, we have no need to do this because the vacuum
1360          * daemon automatically opens an index scan and deletes index tuples
1361          * when it finds deleted heap tuples. -cim 9/27/89
1362          */
1363
1364         /* AFTER ROW DELETE Triggers */
1365         ExecARDeleteTriggers(estate, resultRelInfo, tupleid);
1366 }
1367
1368 /* ----------------------------------------------------------------
1369  *              ExecUpdate
1370  *
1371  *              note: we can't run UPDATE queries with transactions
1372  *              off because UPDATEs are actually INSERTs and our
1373  *              scan will mistakenly loop forever, updating the tuple
1374  *              it just inserted..      This should be fixed but until it
1375  *              is, we don't want to get stuck in an infinite loop
1376  *              which corrupts your database..
1377  * ----------------------------------------------------------------
1378  */
1379 static void
1380 ExecUpdate(TupleTableSlot *slot,
1381                    ItemPointer tupleid,
1382                    EState *estate)
1383 {
1384         HeapTuple       tuple;
1385         ResultRelInfo *resultRelInfo;
1386         Relation        resultRelationDesc;
1387         ItemPointerData ctid;
1388         int                     result;
1389         int                     numIndices;
1390
1391         /*
1392          * abort the operation if not running transactions
1393          */
1394         if (IsBootstrapProcessingMode())
1395         {
1396                 elog(WARNING, "ExecUpdate: UPDATE can't run without transactions");
1397                 return;
1398         }
1399
1400         /*
1401          * get the heap tuple out of the tuple table slot
1402          */
1403         tuple = slot->val;
1404
1405         /*
1406          * get information on the (current) result relation
1407          */
1408         resultRelInfo = estate->es_result_relation_info;
1409         resultRelationDesc = resultRelInfo->ri_RelationDesc;
1410
1411         /* BEFORE ROW UPDATE Triggers */
1412         if (resultRelInfo->ri_TrigDesc &&
1413           resultRelInfo->ri_TrigDesc->n_before_row[TRIGGER_EVENT_UPDATE] > 0)
1414         {
1415                 HeapTuple       newtuple;
1416
1417                 newtuple = ExecBRUpdateTriggers(estate, resultRelInfo,
1418                                                                                 tupleid, tuple);
1419
1420                 if (newtuple == NULL)   /* "do nothing" */
1421                         return;
1422
1423                 if (newtuple != tuple)  /* modified by Trigger(s) */
1424                 {
1425                         /*
1426                          * Insert modified tuple into tuple table slot, replacing the
1427                          * original.  We assume that it was allocated in per-tuple
1428                          * memory context, and therefore will go away by itself. The
1429                          * tuple table slot should not try to clear it.
1430                          */
1431                         ExecStoreTuple(newtuple, slot, InvalidBuffer, false);
1432                         tuple = newtuple;
1433                 }
1434         }
1435
1436         /*
1437          * Check the constraints of the tuple
1438          *
1439          * If we generate a new candidate tuple after EvalPlanQual testing, we
1440          * must loop back here and recheck constraints.  (We don't need to
1441          * redo triggers, however.      If there are any BEFORE triggers then
1442          * trigger.c will have done mark4update to lock the correct tuple, so
1443          * there's no need to do them again.)
1444          */
1445 lreplace:;
1446         if (resultRelationDesc->rd_att->constr)
1447                 ExecConstraints("ExecUpdate", resultRelInfo, slot, estate);
1448
1449         /*
1450          * replace the heap tuple
1451          */
1452         result = heap_update(resultRelationDesc, tupleid, tuple,
1453                                                  &ctid,
1454                                                  estate->es_snapshot->curcid);
1455         switch (result)
1456         {
1457                 case HeapTupleSelfUpdated:
1458                         /* already deleted by self; nothing to do */
1459                         return;
1460
1461                 case HeapTupleMayBeUpdated:
1462                         break;
1463
1464                 case HeapTupleUpdated:
1465                         if (XactIsoLevel == XACT_SERIALIZABLE)
1466                                 elog(ERROR, "Can't serialize access due to concurrent update");
1467                         else if (!(ItemPointerEquals(tupleid, &ctid)))
1468                         {
1469                                 TupleTableSlot *epqslot = EvalPlanQual(estate,
1470                                                            resultRelInfo->ri_RangeTableIndex, &ctid);
1471
1472                                 if (!TupIsNull(epqslot))
1473                                 {
1474                                         *tupleid = ctid;
1475                                         tuple = ExecRemoveJunk(estate->es_junkFilter, epqslot);
1476                                         slot = ExecStoreTuple(tuple,
1477                                                                         estate->es_junkFilter->jf_resultSlot,
1478                                                                                   InvalidBuffer, true);
1479                                         goto lreplace;
1480                                 }
1481                         }
1482                         /* tuple already deleted; nothing to do */
1483                         return;
1484
1485                 default:
1486                         elog(ERROR, "Unknown status %u from heap_update", result);
1487                         return;
1488         }
1489
1490         IncrReplaced();
1491         (estate->es_processed)++;
1492
1493         /*
1494          * Note: instead of having to update the old index tuples associated
1495          * with the heap tuple, all we do is form and insert new index tuples.
1496          * This is because UPDATEs are actually DELETEs and INSERTs and index
1497          * tuple deletion is done automagically by the vacuum daemon. All we
1498          * do is insert new index tuples.  -cim 9/27/89
1499          */
1500
1501         /*
1502          * process indices
1503          *
1504          * heap_update updates a tuple in the base relation by invalidating it
1505          * and then inserting a new tuple to the relation.      As a side effect,
1506          * the tupleid of the new tuple is placed in the new tuple's t_ctid
1507          * field.  So we now insert index tuples using the new tupleid stored
1508          * there.
1509          */
1510
1511         numIndices = resultRelInfo->ri_NumIndices;
1512         if (numIndices > 0)
1513                 ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false);
1514
1515         /* AFTER ROW UPDATE Triggers */
1516         ExecARUpdateTriggers(estate, resultRelInfo, tupleid, tuple);
1517 }
1518
1519 static char *
1520 ExecRelCheck(ResultRelInfo *resultRelInfo,
1521                          TupleTableSlot *slot, EState *estate)
1522 {
1523         Relation        rel = resultRelInfo->ri_RelationDesc;
1524         int                     ncheck = rel->rd_att->constr->num_check;
1525         ConstrCheck *check = rel->rd_att->constr->check;
1526         ExprContext *econtext;
1527         MemoryContext oldContext;
1528         List       *qual;
1529         int                     i;
1530
1531         /*
1532          * If first time through for this result relation, build expression
1533          * nodetrees for rel's constraint expressions.  Keep them in the
1534          * per-query memory context so they'll survive throughout the query.
1535          */
1536         if (resultRelInfo->ri_ConstraintExprs == NULL)
1537         {
1538                 oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
1539                 resultRelInfo->ri_ConstraintExprs =
1540                         (List **) palloc(ncheck * sizeof(List *));
1541                 for (i = 0; i < ncheck; i++)
1542                 {
1543                         qual = (List *) stringToNode(check[i].ccbin);
1544                         resultRelInfo->ri_ConstraintExprs[i] = qual;
1545                 }
1546                 MemoryContextSwitchTo(oldContext);
1547         }
1548
1549         /*
1550          * We will use the EState's per-tuple context for evaluating
1551          * constraint expressions (creating it if it's not already there).
1552          */
1553         econtext = GetPerTupleExprContext(estate);
1554
1555         /* Arrange for econtext's scan tuple to be the tuple under test */
1556         econtext->ecxt_scantuple = slot;
1557
1558         /* And evaluate the constraints */
1559         for (i = 0; i < ncheck; i++)
1560         {
1561                 qual = resultRelInfo->ri_ConstraintExprs[i];
1562
1563                 /*
1564                  * NOTE: SQL92 specifies that a NULL result from a constraint
1565                  * expression is not to be treated as a failure.  Therefore, tell
1566                  * ExecQual to return TRUE for NULL.
1567                  */
1568                 if (!ExecQual(qual, econtext, true))
1569                         return check[i].ccname;
1570         }
1571
1572         /* NULL result means no error */
1573         return (char *) NULL;
1574 }
1575
1576 void
1577 ExecConstraints(const char *caller, ResultRelInfo *resultRelInfo,
1578                                 TupleTableSlot *slot, EState *estate)
1579 {
1580         Relation        rel = resultRelInfo->ri_RelationDesc;
1581         HeapTuple       tuple = slot->val;
1582         TupleConstr *constr = rel->rd_att->constr;
1583
1584         Assert(constr);
1585
1586         if (constr->has_not_null)
1587         {
1588                 int                     natts = rel->rd_att->natts;
1589                 int                     attrChk;
1590
1591                 for (attrChk = 1; attrChk <= natts; attrChk++)
1592                 {
1593                         if (rel->rd_att->attrs[attrChk - 1]->attnotnull &&
1594                                 heap_attisnull(tuple, attrChk))
1595                                 elog(ERROR, "%s: Fail to add null value in not null attribute %s",
1596                                          caller, NameStr(rel->rd_att->attrs[attrChk - 1]->attname));
1597                 }
1598         }
1599
1600         if (constr->num_check > 0)
1601         {
1602                 char       *failed;
1603
1604                 if ((failed = ExecRelCheck(resultRelInfo, slot, estate)) != NULL)
1605                         elog(ERROR, "%s: rejected due to CHECK constraint \"%s\" on \"%s\"",
1606                                  caller, failed, RelationGetRelationName(rel));
1607         }
1608 }
1609
1610 /*
1611  * Check a modified tuple to see if we want to process its updated version
1612  * under READ COMMITTED rules.
1613  *
1614  * See backend/executor/README for some info about how this works.
1615  */
1616 TupleTableSlot *
1617 EvalPlanQual(EState *estate, Index rti, ItemPointer tid)
1618 {
1619         evalPlanQual *epq;
1620         EState     *epqstate;
1621         Relation        relation;
1622         HeapTupleData tuple;
1623         HeapTuple       copyTuple = NULL;
1624         int                     rtsize;
1625         bool            endNode;
1626
1627         Assert(rti != 0);
1628
1629         /*
1630          * find relation containing target tuple
1631          */
1632         if (estate->es_result_relation_info != NULL &&
1633                 estate->es_result_relation_info->ri_RangeTableIndex == rti)
1634                 relation = estate->es_result_relation_info->ri_RelationDesc;
1635         else
1636         {
1637                 List       *l;
1638
1639                 relation = NULL;
1640                 foreach(l, estate->es_rowMark)
1641                 {
1642                         if (((execRowMark *) lfirst(l))->rti == rti)
1643                         {
1644                                 relation = ((execRowMark *) lfirst(l))->relation;
1645                                 break;
1646                         }
1647                 }
1648                 if (relation == NULL)
1649                         elog(ERROR, "EvalPlanQual: can't find RTE %d", (int) rti);
1650         }
1651
1652         /*
1653          * fetch tid tuple
1654          *
1655          * Loop here to deal with updated or busy tuples
1656          */
1657         tuple.t_self = *tid;
1658         for (;;)
1659         {
1660                 Buffer          buffer;
1661
1662                 if (heap_fetch(relation, SnapshotDirty, &tuple, &buffer, false, NULL))
1663                 {
1664                         TransactionId xwait = SnapshotDirty->xmax;
1665
1666                         if (TransactionIdIsValid(SnapshotDirty->xmin))
1667                                 elog(ERROR, "EvalPlanQual: t_xmin is uncommitted ?!");
1668
1669                         /*
1670                          * If tuple is being updated by other transaction then we have
1671                          * to wait for its commit/abort.
1672                          */
1673                         if (TransactionIdIsValid(xwait))
1674                         {
1675                                 ReleaseBuffer(buffer);
1676                                 XactLockTableWait(xwait);
1677                                 continue;
1678                         }
1679
1680                         /*
1681                          * We got tuple - now copy it for use by recheck query.
1682                          */
1683                         copyTuple = heap_copytuple(&tuple);
1684                         ReleaseBuffer(buffer);
1685                         break;
1686                 }
1687
1688                 /*
1689                  * Oops! Invalid tuple. Have to check is it updated or deleted.
1690                  * Note that it's possible to get invalid SnapshotDirty->tid if
1691                  * tuple updated by this transaction. Have we to check this ?
1692                  */
1693                 if (ItemPointerIsValid(&(SnapshotDirty->tid)) &&
1694                         !(ItemPointerEquals(&(tuple.t_self), &(SnapshotDirty->tid))))
1695                 {
1696                         /* updated, so look at the updated copy */
1697                         tuple.t_self = SnapshotDirty->tid;
1698                         continue;
1699                 }
1700
1701                 /*
1702                  * Deleted or updated by this transaction; forget it.
1703                  */
1704                 return NULL;
1705         }
1706
1707         /*
1708          * For UPDATE/DELETE we have to return tid of actual row we're
1709          * executing PQ for.
1710          */
1711         *tid = tuple.t_self;
1712
1713         /*
1714          * Need to run a recheck subquery.      Find or create a PQ stack entry.
1715          */
1716         epq = (evalPlanQual *) estate->es_evalPlanQual;
1717         rtsize = length(estate->es_range_table);
1718         endNode = true;
1719
1720         if (epq != NULL && epq->rti == 0)
1721         {
1722                 /* Top PQ stack entry is idle, so re-use it */
1723                 Assert(!(estate->es_useEvalPlan) &&
1724                            epq->estate.es_evalPlanQual == NULL);
1725                 epq->rti = rti;
1726                 endNode = false;
1727         }
1728
1729         /*
1730          * If this is request for another RTE - Ra, - then we have to check
1731          * wasn't PlanQual requested for Ra already and if so then Ra' row was
1732          * updated again and we have to re-start old execution for Ra and
1733          * forget all what we done after Ra was suspended. Cool? -:))
1734          */
1735         if (epq != NULL && epq->rti != rti &&
1736                 epq->estate.es_evTuple[rti - 1] != NULL)
1737         {
1738                 do
1739                 {
1740                         evalPlanQual *oldepq;
1741
1742                         /* pop previous PlanQual from the stack */
1743                         epqstate = &(epq->estate);
1744                         oldepq = (evalPlanQual *) epqstate->es_evalPlanQual;
1745                         Assert(oldepq->rti != 0);
1746                         /* stop execution */
1747                         ExecEndNode(epq->planstate);
1748                         ExecDropTupleTable(epqstate->es_tupleTable, true);
1749                         epqstate->es_tupleTable = NULL;
1750                         heap_freetuple(epqstate->es_evTuple[epq->rti - 1]);
1751                         epqstate->es_evTuple[epq->rti - 1] = NULL;
1752                         /* push current PQ to freePQ stack */
1753                         oldepq->free = epq;
1754                         epq = oldepq;
1755                         estate->es_evalPlanQual = (Pointer) epq;
1756                 } while (epq->rti != rti);
1757         }
1758
1759         /*
1760          * If we are requested for another RTE then we have to suspend
1761          * execution of current PlanQual and start execution for new one.
1762          */
1763         if (epq == NULL || epq->rti != rti)
1764         {
1765                 /* try to reuse plan used previously */
1766                 evalPlanQual *newepq = (epq != NULL) ? epq->free : NULL;
1767
1768                 if (newepq == NULL)             /* first call or freePQ stack is empty */
1769                 {
1770                         newepq = (evalPlanQual *) palloc(sizeof(evalPlanQual));
1771                         newepq->free = NULL;
1772
1773                         /*
1774                          * Each stack level has its own copy of the plan tree.  This
1775                          * is wasteful, but necessary until plan trees are fully
1776                          * read-only.
1777                          */
1778                         newepq->plan = copyObject(estate->es_origPlan);
1779
1780                         /*
1781                          * Init stack level's EState.  We share top level's copy of
1782                          * es_result_relations array and other non-changing status. We
1783                          * need our own tupletable, es_param_exec_vals, and other
1784                          * changeable state.
1785                          */
1786                         epqstate = &(newepq->estate);
1787                         memcpy(epqstate, estate, sizeof(EState));
1788                         epqstate->es_direction = ForwardScanDirection;
1789                         if (estate->es_origPlan->nParamExec > 0)
1790                                 epqstate->es_param_exec_vals = (ParamExecData *)
1791                                         palloc(estate->es_origPlan->nParamExec *
1792                                                    sizeof(ParamExecData));
1793                         epqstate->es_tupleTable = NULL;
1794                         epqstate->es_per_tuple_exprcontext = NULL;
1795
1796                         /*
1797                          * Each epqstate must have its own es_evTupleNull state, but
1798                          * all the stack entries share es_evTuple state.  This allows
1799                          * sub-rechecks to inherit the value being examined by an
1800                          * outer recheck.
1801                          */
1802                         epqstate->es_evTupleNull = (bool *) palloc(rtsize * sizeof(bool));
1803                         if (epq == NULL)
1804                                 /* first PQ stack entry */
1805                                 epqstate->es_evTuple = (HeapTuple *)
1806                                         palloc0(rtsize * sizeof(HeapTuple));
1807                         else
1808                                 /* later stack entries share the same storage */
1809                                 epqstate->es_evTuple = epq->estate.es_evTuple;
1810                 }
1811                 else
1812                 {
1813                         /* recycle previously used EState */
1814                         epqstate = &(newepq->estate);
1815                 }
1816                 /* push current PQ to the stack */
1817                 epqstate->es_evalPlanQual = (Pointer) epq;
1818                 epq = newepq;
1819                 estate->es_evalPlanQual = (Pointer) epq;
1820                 epq->rti = rti;
1821                 endNode = false;
1822         }
1823
1824         Assert(epq->rti == rti);
1825         epqstate = &(epq->estate);
1826
1827         /*
1828          * Ok - we're requested for the same RTE.  Unfortunately we still have
1829          * to end and restart execution of the plan, because ExecReScan
1830          * wouldn't ensure that upper plan nodes would reset themselves.  We
1831          * could make that work if insertion of the target tuple were
1832          * integrated with the Param mechanism somehow, so that the upper plan
1833          * nodes know that their children's outputs have changed.
1834          */
1835         if (endNode)
1836         {
1837                 /* stop execution */
1838                 ExecEndNode(epq->planstate);
1839                 ExecDropTupleTable(epqstate->es_tupleTable, true);
1840                 epqstate->es_tupleTable = NULL;
1841         }
1842
1843         /*
1844          * free old RTE' tuple, if any, and store target tuple where
1845          * relation's scan node will see it
1846          */
1847         if (epqstate->es_evTuple[rti - 1] != NULL)
1848                 heap_freetuple(epqstate->es_evTuple[rti - 1]);
1849         epqstate->es_evTuple[rti - 1] = copyTuple;
1850
1851         /*
1852          * Initialize for new recheck query; be careful to copy down state
1853          * that might have changed in top EState.
1854          */
1855         epqstate->es_result_relation_info = estate->es_result_relation_info;
1856         epqstate->es_junkFilter = estate->es_junkFilter;
1857         if (estate->es_origPlan->nParamExec > 0)
1858                 memset(epqstate->es_param_exec_vals, 0,
1859                            estate->es_origPlan->nParamExec * sizeof(ParamExecData));
1860         memset(epqstate->es_evTupleNull, false, rtsize * sizeof(bool));
1861         epqstate->es_useEvalPlan = false;
1862         Assert(epqstate->es_tupleTable == NULL);
1863         epqstate->es_tupleTable =
1864                 ExecCreateTupleTable(estate->es_tupleTable->size);
1865
1866         epq->planstate = ExecInitNode(epq->plan, epqstate);
1867
1868         return EvalPlanQualNext(estate);
1869 }
1870
1871 static TupleTableSlot *
1872 EvalPlanQualNext(EState *estate)
1873 {
1874         evalPlanQual *epq = (evalPlanQual *) estate->es_evalPlanQual;
1875         EState     *epqstate = &(epq->estate);
1876         evalPlanQual *oldepq;
1877         TupleTableSlot *slot;
1878
1879         Assert(epq->rti != 0);
1880
1881 lpqnext:;
1882         slot = ExecProcNode(epq->planstate);
1883
1884         /*
1885          * No more tuples for this PQ. Continue previous one.
1886          */
1887         if (TupIsNull(slot))
1888         {
1889                 /* stop execution */
1890                 ExecEndNode(epq->planstate);
1891                 ExecDropTupleTable(epqstate->es_tupleTable, true);
1892                 epqstate->es_tupleTable = NULL;
1893                 heap_freetuple(epqstate->es_evTuple[epq->rti - 1]);
1894                 epqstate->es_evTuple[epq->rti - 1] = NULL;
1895                 /* pop old PQ from the stack */
1896                 oldepq = (evalPlanQual *) epqstate->es_evalPlanQual;
1897                 if (oldepq == (evalPlanQual *) NULL)
1898                 {
1899                         epq->rti = 0;           /* this is the first (oldest) */
1900                         estate->es_useEvalPlan = false;         /* PQ - mark as free and          */
1901                         return (NULL);          /* continue Query execution   */
1902                 }
1903                 Assert(oldepq->rti != 0);
1904                 /* push current PQ to freePQ stack */
1905                 oldepq->free = epq;
1906                 epq = oldepq;
1907                 epqstate = &(epq->estate);
1908                 estate->es_evalPlanQual = (Pointer) epq;
1909                 goto lpqnext;
1910         }
1911
1912         return (slot);
1913 }
1914
1915 static void
1916 EndEvalPlanQual(EState *estate)
1917 {
1918         evalPlanQual *epq = (evalPlanQual *) estate->es_evalPlanQual;
1919         EState     *epqstate = &(epq->estate);
1920         evalPlanQual *oldepq;
1921
1922         if (epq->rti == 0)                      /* plans already shutdowned */
1923         {
1924                 Assert(epq->estate.es_evalPlanQual == NULL);
1925                 return;
1926         }
1927
1928         for (;;)
1929         {
1930                 /* stop execution */
1931                 ExecEndNode(epq->planstate);
1932                 ExecDropTupleTable(epqstate->es_tupleTable, true);
1933                 epqstate->es_tupleTable = NULL;
1934                 if (epqstate->es_evTuple[epq->rti - 1] != NULL)
1935                 {
1936                         heap_freetuple(epqstate->es_evTuple[epq->rti - 1]);
1937                         epqstate->es_evTuple[epq->rti - 1] = NULL;
1938                 }
1939                 /* pop old PQ from the stack */
1940                 oldepq = (evalPlanQual *) epqstate->es_evalPlanQual;
1941                 if (oldepq == (evalPlanQual *) NULL)
1942                 {
1943                         epq->rti = 0;           /* this is the first (oldest) */
1944                         estate->es_useEvalPlan = false;         /* PQ - mark as free */
1945                         break;
1946                 }
1947                 Assert(oldepq->rti != 0);
1948                 /* push current PQ to freePQ stack */
1949                 oldepq->free = epq;
1950                 epq = oldepq;
1951                 epqstate = &(epq->estate);
1952                 estate->es_evalPlanQual = (Pointer) epq;
1953         }
1954 }