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