]> granicus.if.org Git - postgresql/blob - src/backend/executor/execMain.c
Remove tqual.h includes not needed.
[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 'feature' and 'count' arguments that specify whether
23  *      the plan is to be executed forwards, backwards, and for how many tuples.
24  *
25  * Copyright (c) 1994, Regents of the University of California
26  *
27  *
28  * IDENTIFICATION
29  *        $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.33 1997/11/24 05:08:20 momjian Exp $
30  *
31  *-------------------------------------------------------------------------
32  */
33 #include <string.h>
34 #include "postgres.h"
35 #include "miscadmin.h"
36
37 #include "executor/executor.h"
38 #include "executor/execdefs.h"
39 #include "executor/execdebug.h"
40 #include "executor/nodeIndexscan.h"
41 #include "utils/builtins.h"
42 #include "utils/palloc.h"
43 #include "utils/acl.h"
44 #include "utils/syscache.h"
45 #include "utils/tqual.h"
46 #include "parser/parsetree.h"   /* rt_fetch() */
47 #include "storage/bufmgr.h"
48 #include "storage/lmgr.h"
49 #include "storage/smgr.h"
50 #include "commands/async.h"
51 /* #include "access/localam.h" */
52 #include "optimizer/var.h"
53 #include "access/heapam.h"
54 #include "catalog/heap.h"
55 #include "commands/trigger.h"
56
57
58
59 /* decls for local routines only used within this module */
60 static void
61 ExecCheckPerms(CmdType operation, int resultRelation, List *rangeTable,
62                            Query *parseTree);
63 static TupleDesc
64 InitPlan(CmdType operation, Query *parseTree,
65                  Plan *plan, EState *estate);
66 static void EndPlan(Plan *plan, EState *estate);
67 static TupleTableSlot *
68 ExecutePlan(EState *estate, Plan *plan,
69                         Query *parseTree, CmdType operation,
70                         int numberTuples, ScanDirection direction,
71                         void (*printfunc) ());
72 static void ExecRetrieve(TupleTableSlot *slot, void (*printfunc) (),
73                                                                          EState *estate);
74 static void
75 ExecAppend(TupleTableSlot *slot, ItemPointer tupleid,
76                    EState *estate);
77 static void
78 ExecDelete(TupleTableSlot *slot, ItemPointer tupleid,
79                    EState *estate);
80 static void
81 ExecReplace(TupleTableSlot *slot, ItemPointer tupleid,
82                         EState *estate, Query *parseTree);
83
84 /* end of local decls */
85
86 #ifdef QUERY_LIMIT
87 static int      queryLimit = ALL_TUPLES;
88
89 #undef ALL_TUPLES
90 #define ALL_TUPLES queryLimit
91
92 int ExecutorLimit(int limit);
93
94 int
95 ExecutorLimit(int limit)
96 {
97         return queryLimit = limit;
98 }
99 #endif
100
101 /* ----------------------------------------------------------------
102  *              ExecutorStart
103  *
104  *              This routine must be called at the beginning of any execution of any
105  *              query plan
106  *
107  *              returns (AttrInfo*) which describes the attributes of the tuples to
108  *              be returned by the query.
109  *
110  * ----------------------------------------------------------------
111  */
112 TupleDesc
113 ExecutorStart(QueryDesc *queryDesc, EState *estate)
114 {
115         TupleDesc       result;
116
117         /* sanity checks */
118         Assert(queryDesc != NULL);
119
120         result = InitPlan(queryDesc->operation,
121                                           queryDesc->parsetree,
122                                           queryDesc->plantree,
123                                           estate);
124
125         /*
126          * reset buffer refcount.  the current refcounts are saved and will be
127          * restored when ExecutorEnd is called
128          *
129          * this makes sure that when ExecutorRun's are called recursively as for
130          * postquel functions, the buffers pinned by one ExecutorRun will not
131          * be unpinned by another ExecutorRun.
132          */
133         BufferRefCountReset(estate->es_refcount);
134
135         return result;
136 }
137
138 /* ----------------------------------------------------------------
139  *              ExecutorRun
140  *
141  *              This is the main routine of the executor module. It accepts
142  *              the query descriptor from the traffic cop and executes the
143  *              query plan.
144  *
145  *              ExecutorStart must have been called already.
146  *
147  *              the different features supported are:
148  *                       EXEC_RUN:      retrieve all tuples in the forward direction
149  *                       EXEC_FOR:      retrieve 'count' number of tuples in the forward dir
150  *                       EXEC_BACK: retrieve 'count' number of tuples in the backward dir
151  *                       EXEC_RETONE: return one tuple but don't 'retrieve' it
152  *                                                 used in postquel function processing
153  *
154  *
155  * ----------------------------------------------------------------
156  */
157 TupleTableSlot *
158 ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count)
159 {
160         CmdType         operation;
161         Query      *parseTree;
162         Plan       *plan;
163         TupleTableSlot *result;
164         CommandDest dest;
165         void            (*destination) ();
166
167         /* ----------------
168          *      sanity checks
169          * ----------------
170          */
171         Assert(queryDesc != NULL);
172
173         /* ----------------
174          *      extract information from the query descriptor
175          *      and the query feature.
176          * ----------------
177          */
178         operation = queryDesc->operation;
179         parseTree = queryDesc->parsetree;
180         plan = queryDesc->plantree;
181         dest = queryDesc->dest;
182         destination = (void (*) ()) DestToFunction(dest);
183         estate->es_processed = 0;
184         estate->es_lastoid = InvalidOid;
185
186 #if 0
187
188         /*
189          * It doesn't work in common case (i.g. if function has a aggregate).
190          * Now we store parameter values before ExecutorStart. - vadim
191          * 01/22/97
192          */
193 #ifdef INDEXSCAN_PATCH
194
195         /*
196          * If the plan is an index scan and some of the scan key are function
197          * arguments rescan the indices after the parameter values have been
198          * stored in the execution state.  DZ - 27-8-1996
199          */
200         if ((nodeTag(plan) == T_IndexScan) &&
201                 (((IndexScan *) plan)->indxstate->iss_RuntimeKeyInfo != NULL))
202         {
203                 ExprContext *econtext;
204
205                 econtext = ((IndexScan *) plan)->scan.scanstate->cstate.cs_ExprContext;
206                 ExecIndexReScan((IndexScan *) plan, econtext, plan);
207         }
208 #endif
209 #endif
210
211         switch (feature)
212         {
213
214                 case EXEC_RUN:
215                         result = ExecutePlan(estate,
216                                                                  plan,
217                                                                  parseTree,
218                                                                  operation,
219                                                                  ALL_TUPLES,
220                                                                  ForwardScanDirection,
221                                                                  destination);
222                         break;
223                 case EXEC_FOR:
224                         result = ExecutePlan(estate,
225                                                                  plan,
226                                                                  parseTree,
227                                                                  operation,
228                                                                  count,
229                                                                  ForwardScanDirection,
230                                                                  destination);
231                         break;
232
233                         /* ----------------
234                          *              retrieve next n "backward" tuples
235                          * ----------------
236                          */
237                 case EXEC_BACK:
238                         result = ExecutePlan(estate,
239                                                                  plan,
240                                                                  parseTree,
241                                                                  operation,
242                                                                  count,
243                                                                  BackwardScanDirection,
244                                                                  destination);
245                         break;
246
247                         /* ----------------
248                          *              return one tuple but don't "retrieve" it.
249                          *              (this is used by the rule manager..) -cim 9/14/89
250                          * ----------------
251                          */
252                 case EXEC_RETONE:
253                         result = ExecutePlan(estate,
254                                                                  plan,
255                                                                  parseTree,
256                                                                  operation,
257                                                                  ONE_TUPLE,
258                                                                  ForwardScanDirection,
259                                                                  destination);
260                         break;
261                 default:
262                         result = NULL;
263                         elog(DEBUG, "ExecutorRun: Unknown feature %d", feature);
264                         break;
265         }
266
267         return result;
268 }
269
270 /* ----------------------------------------------------------------
271  *              ExecutorEnd
272  *
273  *              This routine must be called at the end of any execution of any
274  *              query plan
275  *
276  *              returns (AttrInfo*) which describes the attributes of the tuples to
277  *              be returned by the query.
278  *
279  * ----------------------------------------------------------------
280  */
281 void
282 ExecutorEnd(QueryDesc *queryDesc, EState *estate)
283 {
284         /* sanity checks */
285         Assert(queryDesc != NULL);
286
287         EndPlan(queryDesc->plantree, estate);
288
289         /* restore saved refcounts. */
290         BufferRefCountRestore(estate->es_refcount);
291 }
292
293 /* ===============================================================
294  * ===============================================================
295                                                  static routines follow
296  * ===============================================================
297  * ===============================================================
298  */
299
300 static void
301 ExecCheckPerms(CmdType operation,
302                            int resultRelation,
303                            List *rangeTable,
304                            Query *parseTree)
305 {
306         int                     i = 1;
307         Oid                     relid;
308         HeapTuple       htp;
309         List       *lp;
310         List       *qvars,
311                            *tvars;
312         int32           ok = 1,
313                                 aclcheck_result = -1;
314         char       *opstr;
315         NameData        rname;
316         char       *userName;
317
318 #define CHECK(MODE)             pg_aclcheck(rname.data, userName, MODE)
319
320         userName = GetPgUserName();
321
322         foreach(lp, rangeTable)
323         {
324                 RangeTblEntry *rte = lfirst(lp);
325
326                 relid = rte->relid;
327                 htp = SearchSysCacheTuple(RELOID,
328                                                                   ObjectIdGetDatum(relid),
329                                                                   0, 0, 0);
330                 if (!HeapTupleIsValid(htp))
331                         elog(WARN, "ExecCheckPerms: bogus RT relid: %d",
332                                  relid);
333                 StrNCpy(rname.data,
334                                 ((Form_pg_class) GETSTRUCT(htp))->relname.data,
335                                 NAMEDATALEN);
336                 if (i == resultRelation)
337                 {                                               /* this is the result relation */
338                         qvars = pull_varnos(parseTree->qual);
339                         tvars = pull_varnos((Node *) parseTree->targetList);
340                         if (intMember(resultRelation, qvars) ||
341                                 intMember(resultRelation, tvars))
342                         {
343                                 /* result relation is scanned */
344                                 ok = ((aclcheck_result = CHECK(ACL_RD)) == ACLCHECK_OK);
345                                 opstr = "read";
346                                 if (!ok)
347                                         break;
348                         }
349                         switch (operation)
350                         {
351                                 case CMD_INSERT:
352                                         ok = ((aclcheck_result = CHECK(ACL_AP)) == ACLCHECK_OK) ||
353                                                 ((aclcheck_result = CHECK(ACL_WR)) == ACLCHECK_OK);
354                                         opstr = "append";
355                                         break;
356                                 case CMD_NOTIFY:                /* what does this mean?? -- jw,
357                                                                                  * 1/6/94 */
358                                 case CMD_DELETE:
359                                 case CMD_UPDATE:
360                                         ok = ((aclcheck_result = CHECK(ACL_WR)) == ACLCHECK_OK);
361                                         opstr = "write";
362                                         break;
363                                 default:
364                                         elog(WARN, "ExecCheckPerms: bogus operation %d",
365                                                  operation);
366                         }
367                 }
368                 else
369                 {
370                         /* XXX NOTIFY?? */
371                         ok = ((aclcheck_result = CHECK(ACL_RD)) == ACLCHECK_OK);
372                         opstr = "read";
373                 }
374                 if (!ok)
375                         break;
376                 ++i;
377         }
378         if (!ok)
379         {
380                 elog(WARN, "%s: %s", rname.data, aclcheck_error_strings[aclcheck_result]);
381         }
382 }
383
384
385 /* ----------------------------------------------------------------
386  *              InitPlan
387  *
388  *              Initializes the query plan: open files, allocate storage
389  *              and start up the rule manager
390  * ----------------------------------------------------------------
391  */
392 static TupleDesc
393 InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
394 {
395         List       *rangeTable;
396         int                     resultRelation;
397         Relation        intoRelationDesc;
398
399         TupleDesc       tupType;
400         List       *targetList;
401         int                     len;
402
403         /* ----------------
404          *      get information from query descriptor
405          * ----------------
406          */
407         rangeTable = parseTree->rtable;
408         resultRelation = parseTree->resultRelation;
409
410         /* ----------------
411          *      initialize the node's execution state
412          * ----------------
413          */
414         estate->es_range_table = rangeTable;
415
416         /* ----------------
417          *      initialize the BaseId counter so node base_id's
418          *      are assigned correctly.  Someday baseid's will have to
419          *      be stored someplace other than estate because they
420          *      should be unique per query planned.
421          * ----------------
422          */
423         estate->es_BaseId = 1;
424
425         /* ----------------
426          *      initialize result relation stuff
427          * ----------------
428          */
429
430         if (resultRelation != 0 && operation != CMD_SELECT)
431         {
432                 /* ----------------
433                  *        if we have a result relation, open it and
434
435                  *        initialize the result relation info stuff.
436                  * ----------------
437                  */
438                 RelationInfo *resultRelationInfo;
439                 Index           resultRelationIndex;
440                 RangeTblEntry *rtentry;
441                 Oid                     resultRelationOid;
442                 Relation        resultRelationDesc;
443
444                 resultRelationIndex = resultRelation;
445                 rtentry = rt_fetch(resultRelationIndex, rangeTable);
446                 resultRelationOid = rtentry->relid;
447                 resultRelationDesc = heap_open(resultRelationOid);
448
449                 if (resultRelationDesc->rd_rel->relkind == RELKIND_SEQUENCE)
450                         elog(WARN, "You can't change sequence relation %s",
451                                  resultRelationDesc->rd_rel->relname.data);
452
453                 /*
454                  * Write-lock the result relation right away: if the relation is
455                  * used in a subsequent scan, we won't have to elevate the
456                  * read-lock set by heap_beginscan to a write-lock (needed by
457                  * heap_insert, heap_delete and heap_replace). This will hopefully
458                  * prevent some deadlocks.      - 01/24/94
459                  */
460                 RelationSetLockForWrite(resultRelationDesc);
461
462                 resultRelationInfo = makeNode(RelationInfo);
463                 resultRelationInfo->ri_RangeTableIndex = resultRelationIndex;
464                 resultRelationInfo->ri_RelationDesc = resultRelationDesc;
465                 resultRelationInfo->ri_NumIndices = 0;
466                 resultRelationInfo->ri_IndexRelationDescs = NULL;
467                 resultRelationInfo->ri_IndexRelationInfo = NULL;
468
469                 /* ----------------
470                  *      open indices on result relation and save descriptors
471                  *      in the result relation information..
472                  * ----------------
473                  */
474                 ExecOpenIndices(resultRelationOid, resultRelationInfo);
475
476                 estate->es_result_relation_info = resultRelationInfo;
477         }
478         else
479         {
480                 /* ----------------
481                  *              if no result relation, then set state appropriately
482                  * ----------------
483                  */
484                 estate->es_result_relation_info = NULL;
485         }
486
487 #ifndef NO_SECURITY
488         ExecCheckPerms(operation, resultRelation, rangeTable, parseTree);
489 #endif
490
491         /* ----------------
492          *        initialize the executor "tuple" table.
493          * ----------------
494          */
495         {
496                 int                     nSlots = ExecCountSlotsNode(plan);
497                 TupleTable      tupleTable = ExecCreateTupleTable(nSlots + 10);         /* why add ten? - jolly */
498
499                 estate->es_tupleTable = tupleTable;
500         }
501
502         /* ----------------
503          *         initialize the private state information for
504          *         all the nodes in the query tree.  This opens
505          *         files, allocates storage and leaves us ready
506          *         to start processing tuples..
507          * ----------------
508          */
509         ExecInitNode(plan, estate, NULL);
510
511         /* ----------------
512          *         get the tuple descriptor describing the type
513          *         of tuples to return.. (this is especially important
514          *         if we are creating a relation with "retrieve into")
515          * ----------------
516          */
517         tupType = ExecGetTupType(plan);         /* tuple descriptor */
518         targetList = plan->targetlist;
519         len = ExecTargetListLength(targetList);         /* number of attributes */
520
521         /* ----------------
522          *        now that we have the target list, initialize the junk filter
523          *        if this is a REPLACE or a DELETE query.
524          *        We also init the junk filter if this is an append query
525          *        (there might be some rule lock info there...)
526          *        NOTE: in the future we might want to initialize the junk
527          *        filter for all queries.
528          * ----------------
529          */
530         if (operation == CMD_UPDATE || operation == CMD_DELETE ||
531                 operation == CMD_INSERT)
532         {
533
534                 JunkFilter *j = (JunkFilter *) ExecInitJunkFilter(targetList);
535
536                 estate->es_junkFilter = j;
537         }
538         else
539                 estate->es_junkFilter = NULL;
540
541         /* ----------------
542          *      initialize the "into" relation
543          * ----------------
544          */
545         intoRelationDesc = (Relation) NULL;
546
547         if (operation == CMD_SELECT)
548         {
549                 char       *intoName;
550                 Oid                     intoRelationId;
551                 TupleDesc       tupdesc;
552
553                 if (!parseTree->isPortal)
554                 {
555
556                         /*
557                          * a select into table
558                          */
559                         if (parseTree->into != NULL)
560                         {
561                                 /* ----------------
562                                  *      create the "into" relation
563                                  * ----------------
564                                  */
565                                 intoName = parseTree->into;
566
567                                 /*
568                                  * have to copy tupType to get rid of constraints
569                                  */
570                                 tupdesc = CreateTupleDescCopy(tupType);
571
572                                 /* fixup to prevent zero-length columns in create */
573                                 setVarAttrLenForCreateTable(tupdesc, targetList, rangeTable);
574
575                                 intoRelationId = heap_create(intoName, tupdesc);
576 #ifdef NOT_USED                                 /* it's copy ... */
577                                 resetVarAttrLenForCreateTable(tupdesc);
578 #endif
579                                 FreeTupleDesc(tupdesc);
580
581                                 /* ----------------
582                                  *      XXX rather than having to call setheapoverride(true)
583                                  *              and then back to false, we should change the
584                                  *              arguments to heap_open() instead..
585                                  * ----------------
586                                  */
587                                 setheapoverride(true);
588
589                                 intoRelationDesc = heap_open(intoRelationId);
590
591                                 setheapoverride(false);
592                         }
593                 }
594         }
595
596         estate->es_into_relation_descriptor = intoRelationDesc;
597
598         /* ----------------
599          *      return the type information..
600          * ----------------
601          */
602 /*
603         attinfo = (AttrInfo *)palloc(sizeof(AttrInfo));
604         attinfo->numAttr = len;
605         attinfo->attrs = tupType->attrs;
606 */
607
608         return tupType;
609 }
610
611 /* ----------------------------------------------------------------
612  *              EndPlan
613  *
614  *              Cleans up the query plan -- closes files and free up storages
615  * ----------------------------------------------------------------
616  */
617 static void
618 EndPlan(Plan *plan, EState *estate)
619 {
620         RelationInfo *resultRelationInfo;
621         Relation        intoRelationDesc;
622
623         /* ----------------
624          *      get information from state
625          * ----------------
626          */
627         resultRelationInfo = estate->es_result_relation_info;
628         intoRelationDesc = estate->es_into_relation_descriptor;
629
630         /* ----------------
631          *       shut down the query
632          * ----------------
633          */
634         ExecEndNode(plan, plan);
635
636         /* ----------------
637          *        destroy the executor "tuple" table.
638          * ----------------
639          */
640         {
641                 TupleTable      tupleTable = (TupleTable) estate->es_tupleTable;
642
643                 ExecDestroyTupleTable(tupleTable, true);                /* was missing last arg */
644                 estate->es_tupleTable = NULL;
645         }
646
647         /* ----------------
648          *       close the result relations if necessary
649          * ----------------
650          */
651         if (resultRelationInfo != NULL)
652         {
653                 Relation        resultRelationDesc;
654
655                 resultRelationDesc = resultRelationInfo->ri_RelationDesc;
656                 heap_close(resultRelationDesc);
657
658                 /* ----------------
659                  *      close indices on the result relation
660                  * ----------------
661                  */
662                 ExecCloseIndices(resultRelationInfo);
663         }
664
665         /* ----------------
666          *       close the "into" relation if necessary
667          * ----------------
668          */
669         if (intoRelationDesc != NULL)
670         {
671                 heap_close(intoRelationDesc);
672         }
673 }
674
675 /* ----------------------------------------------------------------
676  *              ExecutePlan
677  *
678  *              processes the query plan to retrieve 'tupleCount' tuples in the
679  *              direction specified.
680  *              Retrieves all tuples if tupleCount is 0
681  *
682  *              result is either a slot containing a tuple in the case
683  *              of a RETRIEVE or NULL otherwise.
684  *
685  * ----------------------------------------------------------------
686  */
687
688 /* the ctid attribute is a 'junk' attribute that is removed before the
689    user can see it*/
690
691 static TupleTableSlot *
692 ExecutePlan(EState *estate,
693                         Plan *plan,
694                         Query *parseTree,
695                         CmdType operation,
696                         int numberTuples,
697                         ScanDirection direction,
698                         void (*printfunc) ())
699 {
700         JunkFilter *junkfilter;
701
702         TupleTableSlot *slot;
703         ItemPointer tupleid = NULL;
704         ItemPointerData tuple_ctid;
705         int                     current_tuple_count;
706         TupleTableSlot *result;
707
708         /* ----------------
709          *      initialize local variables
710          * ----------------
711          */
712         slot = NULL;
713         current_tuple_count = 0;
714         result = NULL;
715
716         /* ----------------
717          *      Set the direction.
718          * ----------------
719          */
720         estate->es_direction = direction;
721
722         /* ----------------
723          *      Loop until we've processed the proper number
724          *      of tuples from the plan..
725          * ----------------
726          */
727
728         for (;;)
729         {
730                 if (operation != CMD_NOTIFY)
731                 {
732                         /* ----------------
733                          *      Execute the plan and obtain a tuple
734                          * ----------------
735                          */
736                         /* at the top level, the parent of a plan (2nd arg) is itself */
737                         slot = ExecProcNode(plan, plan);
738
739                         /* ----------------
740                          *      if the tuple is null, then we assume
741                          *      there is nothing more to process so
742                          *      we just return null...
743                          * ----------------
744                          */
745                         if (TupIsNull(slot))
746                         {
747                                 result = NULL;
748                                 break;
749                         }
750                 }
751
752                 /* ----------------
753                  *              if we have a junk filter, then project a new
754                  *              tuple with the junk removed.
755                  *
756                  *              Store this new "clean" tuple in the place of the
757                  *              original tuple.
758                  *
759                  *              Also, extract all the junk ifnormation we need.
760                  * ----------------
761                  */
762                 if ((junkfilter = estate->es_junkFilter) != (JunkFilter *) NULL)
763                 {
764                         Datum           datum;
765
766 /*                      NameData        attrName; */
767                         HeapTuple       newTuple;
768                         bool            isNull;
769
770                         /* ---------------
771                          * extract the 'ctid' junk attribute.
772                          * ---------------
773                          */
774                         if (operation == CMD_UPDATE || operation == CMD_DELETE)
775                         {
776                                 if (!ExecGetJunkAttribute(junkfilter,
777                                                                                   slot,
778                                                                                   "ctid",
779                                                                                   &datum,
780                                                                                   &isNull))
781                                         elog(WARN, "ExecutePlan: NO (junk) `ctid' was found!");
782
783                                 if (isNull)
784                                         elog(WARN, "ExecutePlan: (junk) `ctid' is NULL!");
785
786                                 tupleid = (ItemPointer) DatumGetPointer(datum);
787                                 tuple_ctid = *tupleid;  /* make sure we don't free the
788                                                                                  * ctid!! */
789                                 tupleid = &tuple_ctid;
790                         }
791
792                         /* ---------------
793                          * Finally create a new "clean" tuple with all junk attributes
794                          * removed
795                          * ---------------
796                          */
797                         newTuple = ExecRemoveJunk(junkfilter, slot);
798
799                         slot = ExecStoreTuple(newTuple,         /* tuple to store */
800                                                                   slot, /* destination slot */
801                                                                   InvalidBuffer,                /* this tuple has no
802                                                                                                                  * buffer */
803                                                                   true);                /* tuple should be pfreed */
804                 }                                               /* if (junkfilter... */
805
806                 /* ----------------
807                  *              now that we have a tuple, do the appropriate thing
808                  *              with it.. either return it to the user, add
809                  *              it to a relation someplace, delete it from a
810                  *              relation, or modify some of it's attributes.
811                  * ----------------
812                  */
813
814                 switch (operation)
815                 {
816                         case CMD_SELECT:
817                                 ExecRetrieve(slot,              /* slot containing tuple */
818                                                          printfunc, /* print function */
819                                                          estate);       /* */
820                                 result = slot;
821                                 break;
822
823                         case CMD_INSERT:
824                                 ExecAppend(slot, tupleid, estate);
825                                 result = NULL;
826                                 break;
827
828                         case CMD_DELETE:
829                                 ExecDelete(slot, tupleid, estate);
830                                 result = NULL;
831                                 break;
832
833                         case CMD_UPDATE:
834                                 ExecReplace(slot, tupleid, estate, parseTree);
835                                 result = NULL;
836                                 break;
837
838                                 /*
839                                  * Total hack. I'm ignoring any accessor functions for
840                                  * Relation, RelationTupleForm, NameData. Assuming that
841                                  * NameData.data has offset 0.
842                                  */
843                         case CMD_NOTIFY:
844                                 {
845                                         RelationInfo *rInfo = estate->es_result_relation_info;
846                                         Relation        rDesc = rInfo->ri_RelationDesc;
847
848                                         Async_Notify(rDesc->rd_rel->relname.data);
849                                         result = NULL;
850                                         current_tuple_count = 0;
851                                         numberTuples = 1;
852                                         elog(DEBUG, "ExecNotify %s", &rDesc->rd_rel->relname);
853                                 }
854                                 break;
855
856                         default:
857                                 elog(DEBUG, "ExecutePlan: unknown operation in queryDesc");
858                                 result = NULL;
859                                 break;
860                 }
861                 /* ----------------
862                  *              check our tuple count.. if we've returned the
863                  *              proper number then return, else loop again and
864                  *              process more tuples..
865                  * ----------------
866                  */
867                 current_tuple_count += 1;
868                 if (numberTuples == current_tuple_count)
869                         break;
870         }
871
872         /* ----------------
873          *      here, result is either a slot containing a tuple in the case
874          *      of a RETRIEVE or NULL otherwise.
875          * ----------------
876          */
877         return result;
878 }
879
880 /* ----------------------------------------------------------------
881  *              ExecRetrieve
882  *
883  *              RETRIEVEs are easy.. we just pass the tuple to the appropriate
884  *              print function.  The only complexity is when we do a
885  *              "retrieve into", in which case we insert the tuple into
886  *              the appropriate relation (note: this is a newly created relation
887  *              so we don't need to worry about indices or locks.)
888  * ----------------------------------------------------------------
889  */
890 static void
891 ExecRetrieve(TupleTableSlot *slot,
892                          void (*printfunc) (),
893                          EState *estate)
894 {
895         HeapTuple       tuple;
896         TupleDesc       attrtype;
897
898         /* ----------------
899          *      get the heap tuple out of the tuple table slot
900          * ----------------
901          */
902         tuple = slot->val;
903         attrtype = slot->ttc_tupleDescriptor;
904
905         /* ----------------
906          *      insert the tuple into the "into relation"
907          * ----------------
908          */
909         if (estate->es_into_relation_descriptor != NULL)
910         {
911                 heap_insert(estate->es_into_relation_descriptor, tuple);
912                 IncrAppended();
913         }
914
915         /* ----------------
916          *      send the tuple to the front end (or the screen)
917          * ----------------
918          */
919         (*printfunc) (tuple, attrtype);
920         IncrRetrieved();
921         (estate->es_processed)++;
922 }
923
924 /* ----------------------------------------------------------------
925  *              ExecAppend
926  *
927  *              APPENDs are trickier.. we have to insert the tuple into
928  *              the base relation and insert appropriate tuples into the
929  *              index relations.
930  * ----------------------------------------------------------------
931  */
932
933 static void
934 ExecAppend(TupleTableSlot *slot,
935                    ItemPointer tupleid,
936                    EState *estate)
937 {
938         HeapTuple       tuple;
939         RelationInfo *resultRelationInfo;
940         Relation        resultRelationDesc;
941         int                     numIndices;
942         Oid                     newId;
943
944         /* ----------------
945          *      get the heap tuple out of the tuple table slot
946          * ----------------
947          */
948         tuple = slot->val;
949
950         /* ----------------
951          *      get information on the result relation
952          * ----------------
953          */
954         resultRelationInfo = estate->es_result_relation_info;
955         resultRelationDesc = resultRelationInfo->ri_RelationDesc;
956
957         /* ----------------
958          *      have to add code to preform unique checking here.
959          *      cim -12/1/89
960          * ----------------
961          */
962
963         /* BEFORE ROW INSERT Triggers */
964         if (resultRelationDesc->trigdesc &&
965         resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_INSERT] > 0)
966         {
967                 HeapTuple       newtuple;
968
969                 newtuple = ExecBRInsertTriggers(resultRelationDesc, tuple);
970
971                 if (newtuple == NULL)   /* "do nothing" */
972                         return;
973
974                 if (newtuple != tuple)  /* modified by Trigger(s) */
975                 {
976                         Assert(slot->ttc_shouldFree);
977                         pfree(tuple);
978                         slot->val = tuple = newtuple;
979                 }
980         }
981
982         /* ----------------
983          * Check the constraints of a tuple
984          * ----------------
985          */
986
987         if (resultRelationDesc->rd_att->constr)
988         {
989                 HeapTuple       newtuple;
990
991                 newtuple = ExecConstraints("ExecAppend", resultRelationDesc, tuple);
992
993                 if (newtuple != tuple)  /* modified by DEFAULT */
994                 {
995                         Assert(slot->ttc_shouldFree);
996                         pfree(tuple);
997                         slot->val = tuple = newtuple;
998                 }
999         }
1000
1001         /* ----------------
1002          *      insert the tuple
1003          * ----------------
1004          */
1005         newId = heap_insert(resultRelationDesc,         /* relation desc */
1006                                                 tuple); /* heap tuple */
1007         IncrAppended();
1008
1009         /* ----------------
1010          *      process indices
1011          *
1012          *      Note: heap_insert adds a new tuple to a relation.  As a side
1013          *      effect, the tupleid of the new tuple is placed in the new
1014          *      tuple's t_ctid field.
1015          * ----------------
1016          */
1017         numIndices = resultRelationInfo->ri_NumIndices;
1018         if (numIndices > 0)
1019         {
1020                 ExecInsertIndexTuples(slot, &(tuple->t_ctid), estate, false);
1021         }
1022         (estate->es_processed)++;
1023         estate->es_lastoid = newId;
1024
1025         /* AFTER ROW INSERT Triggers */
1026         if (resultRelationDesc->trigdesc &&
1027          resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_INSERT] > 0)
1028                 ExecARInsertTriggers(resultRelationDesc, tuple);
1029 }
1030
1031 /* ----------------------------------------------------------------
1032  *              ExecDelete
1033  *
1034  *              DELETE is like append, we delete the tuple and its
1035  *              index tuples.
1036  * ----------------------------------------------------------------
1037  */
1038 static void
1039 ExecDelete(TupleTableSlot *slot,
1040                    ItemPointer tupleid,
1041                    EState *estate)
1042 {
1043         RelationInfo *resultRelationInfo;
1044         Relation        resultRelationDesc;
1045
1046         /* ----------------
1047          *      get the result relation information
1048          * ----------------
1049          */
1050         resultRelationInfo = estate->es_result_relation_info;
1051         resultRelationDesc = resultRelationInfo->ri_RelationDesc;
1052
1053         /* BEFORE ROW DELETE Triggers */
1054         if (resultRelationDesc->trigdesc &&
1055         resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_DELETE] > 0)
1056         {
1057                 bool            dodelete;
1058
1059                 dodelete = ExecBRDeleteTriggers(resultRelationDesc, tupleid);
1060
1061                 if (!dodelete)                  /* "do nothing" */
1062                         return;
1063         }
1064
1065         /* ----------------
1066          *      delete the tuple
1067          * ----------------
1068          */
1069         if (heap_delete(resultRelationDesc, /* relation desc */
1070                                         tupleid))       /* item pointer to tuple */
1071                 return;
1072
1073         IncrDeleted();
1074         (estate->es_processed)++;
1075
1076         /* ----------------
1077          *      Note: Normally one would think that we have to
1078          *                delete index tuples associated with the
1079          *                heap tuple now..
1080          *
1081          *                ... but in POSTGRES, we have no need to do this
1082          *                because the vacuum daemon automatically
1083          *                opens an index scan and deletes index tuples
1084          *                when it finds deleted heap tuples. -cim 9/27/89
1085          * ----------------
1086          */
1087
1088         /* AFTER ROW DELETE Triggers */
1089         if (resultRelationDesc->trigdesc &&
1090          resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_DELETE] > 0)
1091                 ExecARDeleteTriggers(resultRelationDesc, tupleid);
1092
1093 }
1094
1095 /* ----------------------------------------------------------------
1096  *              ExecReplace
1097  *
1098  *              note: we can't run replace queries with transactions
1099  *              off because replaces are actually appends and our
1100  *              scan will mistakenly loop forever, replacing the tuple
1101  *              it just appended..      This should be fixed but until it
1102  *              is, we don't want to get stuck in an infinite loop
1103  *              which corrupts your database..
1104  * ----------------------------------------------------------------
1105  */
1106 static void
1107 ExecReplace(TupleTableSlot *slot,
1108                         ItemPointer tupleid,
1109                         EState *estate,
1110                         Query *parseTree)
1111 {
1112         HeapTuple       tuple;
1113         RelationInfo *resultRelationInfo;
1114         Relation        resultRelationDesc;
1115         int                     numIndices;
1116
1117         /* ----------------
1118          *      abort the operation if not running transactions
1119          * ----------------
1120          */
1121         if (IsBootstrapProcessingMode())
1122         {
1123                 elog(DEBUG, "ExecReplace: replace can't run without transactions");
1124                 return;
1125         }
1126
1127         /* ----------------
1128          *      get the heap tuple out of the tuple table slot
1129          * ----------------
1130          */
1131         tuple = slot->val;
1132
1133         /* ----------------
1134          *      get the result relation information
1135          * ----------------
1136          */
1137         resultRelationInfo = estate->es_result_relation_info;
1138         resultRelationDesc = resultRelationInfo->ri_RelationDesc;
1139
1140         /* ----------------
1141          *      have to add code to preform unique checking here.
1142          *      in the event of unique tuples, this becomes a deletion
1143          *      of the original tuple affected by the replace.
1144          *      cim -12/1/89
1145          * ----------------
1146          */
1147
1148         /* BEFORE ROW UPDATE Triggers */
1149         if (resultRelationDesc->trigdesc &&
1150         resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_UPDATE] > 0)
1151         {
1152                 HeapTuple       newtuple;
1153
1154                 newtuple = ExecBRUpdateTriggers(resultRelationDesc, tupleid, tuple);
1155
1156                 if (newtuple == NULL)   /* "do nothing" */
1157                         return;
1158
1159                 if (newtuple != tuple)  /* modified by Trigger(s) */
1160                 {
1161                         Assert(slot->ttc_shouldFree);
1162                         pfree(tuple);
1163                         slot->val = tuple = newtuple;
1164                 }
1165         }
1166
1167         /* ----------------
1168          * Check the constraints of a tuple
1169          * ----------------
1170          */
1171
1172         if (resultRelationDesc->rd_att->constr)
1173         {
1174                 HeapTuple       newtuple;
1175
1176                 newtuple = ExecConstraints("ExecReplace", resultRelationDesc, tuple);
1177
1178                 if (newtuple != tuple)  /* modified by DEFAULT */
1179                 {
1180                         Assert(slot->ttc_shouldFree);
1181                         pfree(tuple);
1182                         slot->val = tuple = newtuple;
1183                 }
1184         }
1185
1186         /* ----------------
1187          *      replace the heap tuple
1188          *
1189          * Don't want to continue if our heap_replace didn't actually
1190          * do a replace. This would be the case if heap_replace
1191          * detected a non-functional update. -kw 12/30/93
1192          * ----------------
1193          */
1194         if (heap_replace(resultRelationDesc,            /* relation desc */
1195                                          tupleid,       /* item ptr of tuple to replace */
1196                                          tuple))
1197         {                                                       /* replacement heap tuple */
1198                 return;
1199         }
1200
1201         IncrReplaced();
1202         (estate->es_processed)++;
1203
1204         /* ----------------
1205          *      Note: instead of having to update the old index tuples
1206          *                associated with the heap tuple, all we do is form
1207          *                and insert new index tuples..  This is because
1208          *                replaces are actually deletes and inserts and
1209          *                index tuple deletion is done automagically by
1210          *                the vaccuum deamon.. All we do is insert new
1211          *                index tuples.  -cim 9/27/89
1212          * ----------------
1213          */
1214
1215         /* ----------------
1216          *      process indices
1217          *
1218          *      heap_replace updates a tuple in the base relation by invalidating
1219          *      it and then appending a new tuple to the relation.      As a side
1220          *      effect, the tupleid of the new tuple is placed in the new
1221          *      tuple's t_ctid field.  So we now insert index tuples using
1222          *      the new tupleid stored there.
1223          * ----------------
1224          */
1225
1226         numIndices = resultRelationInfo->ri_NumIndices;
1227         if (numIndices > 0)
1228         {
1229                 ExecInsertIndexTuples(slot, &(tuple->t_ctid), estate, true);
1230         }
1231
1232         /* AFTER ROW UPDATE Triggers */
1233         if (resultRelationDesc->trigdesc &&
1234          resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_UPDATE] > 0)
1235                 ExecARUpdateTriggers(resultRelationDesc, tupleid, tuple);
1236 }
1237
1238 #if 0
1239 static HeapTuple
1240 ExecAttrDefault(Relation rel, HeapTuple tuple)
1241 {
1242         int                     ndef = rel->rd_att->constr->num_defval;
1243         AttrDefault *attrdef = rel->rd_att->constr->defval;
1244         ExprContext *econtext = makeNode(ExprContext);
1245         HeapTuple       newtuple;
1246         Node       *expr;
1247         bool            isnull;
1248         bool            isdone;
1249         Datum           val;
1250         Datum      *replValue = NULL;
1251         char       *replNull = NULL;
1252         char       *repl = NULL;
1253         int                     i;
1254
1255         econtext->ecxt_scantuple = NULL;        /* scan tuple slot */
1256         econtext->ecxt_innertuple = NULL;       /* inner tuple slot */
1257         econtext->ecxt_outertuple = NULL;       /* outer tuple slot */
1258         econtext->ecxt_relation = NULL;         /* relation */
1259         econtext->ecxt_relid = 0;       /* relid */
1260         econtext->ecxt_param_list_info = NULL;          /* param list info */
1261         econtext->ecxt_range_table = NULL;      /* range table */
1262         for (i = 0; i < ndef; i++)
1263         {
1264                 if (!heap_attisnull(tuple, attrdef[i].adnum))
1265                         continue;
1266                 expr = (Node *) stringToNode(attrdef[i].adbin);
1267
1268                 val = ExecEvalExpr(expr, econtext, &isnull, &isdone);
1269
1270                 pfree(expr);
1271
1272                 if (isnull)
1273                         continue;
1274
1275                 if (repl == NULL)
1276                 {
1277                         repl = (char *) palloc(rel->rd_att->natts * sizeof(char));
1278                         replNull = (char *) palloc(rel->rd_att->natts * sizeof(char));
1279                         replValue = (Datum *) palloc(rel->rd_att->natts * sizeof(Datum));
1280                         MemSet(repl, ' ', rel->rd_att->natts * sizeof(char));
1281                 }
1282
1283                 repl[attrdef[i].adnum - 1] = 'r';
1284                 replNull[attrdef[i].adnum - 1] = ' ';
1285                 replValue[attrdef[i].adnum - 1] = val;
1286
1287         }
1288
1289         pfree(econtext);
1290
1291         if (repl == NULL)
1292                 return (tuple);
1293
1294         newtuple = heap_modifytuple(tuple, InvalidBuffer, rel, replValue, replNull, repl);
1295
1296         pfree(repl);
1297         pfree(replNull);
1298         pfree(replValue);
1299
1300         return (newtuple);
1301
1302 }
1303 #endif
1304
1305 static char *
1306 ExecRelCheck(Relation rel, HeapTuple tuple)
1307 {
1308         int                     ncheck = rel->rd_att->constr->num_check;
1309         ConstrCheck *check = rel->rd_att->constr->check;
1310         ExprContext *econtext = makeNode(ExprContext);
1311         TupleTableSlot *slot = makeNode(TupleTableSlot);
1312         RangeTblEntry *rte = makeNode(RangeTblEntry);
1313         List       *rtlist;
1314         List       *qual;
1315         bool            res;
1316         int                     i;
1317
1318         slot->val = tuple;
1319         slot->ttc_shouldFree = false;
1320         slot->ttc_descIsNew = true;
1321         slot->ttc_tupleDescriptor = rel->rd_att;
1322         slot->ttc_buffer = InvalidBuffer;
1323         slot->ttc_whichplan = -1;
1324         rte->relname = nameout(&(rel->rd_rel->relname));
1325         rte->refname = rte->relname;
1326         rte->relid = rel->rd_id;
1327         rte->inh = false;
1328         rte->inFromCl = true;
1329         rtlist = lcons(rte, NIL);
1330         econtext->ecxt_scantuple = slot;        /* scan tuple slot */
1331         econtext->ecxt_innertuple = NULL;       /* inner tuple slot */
1332         econtext->ecxt_outertuple = NULL;       /* outer tuple slot */
1333         econtext->ecxt_relation = rel;          /* relation */
1334         econtext->ecxt_relid = 0;       /* relid */
1335         econtext->ecxt_param_list_info = NULL;          /* param list info */
1336         econtext->ecxt_range_table = rtlist;            /* range table */
1337
1338         for (i = 0; i < ncheck; i++)
1339         {
1340                 qual = (List *) stringToNode(check[i].ccbin);
1341
1342                 res = ExecQual(qual, econtext);
1343
1344                 pfree(qual);
1345
1346                 if (!res)
1347                         return (check[i].ccname);
1348         }
1349
1350         pfree(slot);
1351         pfree(rte->relname);
1352         pfree(rte);
1353         pfree(rtlist);
1354         pfree(econtext);
1355
1356         return ((char *) NULL);
1357
1358 }
1359
1360 HeapTuple
1361 ExecConstraints(char *caller, Relation rel, HeapTuple tuple)
1362 {
1363         HeapTuple       newtuple = tuple;
1364
1365         Assert(rel->rd_att->constr);
1366
1367 #if 0
1368         if (rel->rd_att->constr->num_defval > 0)
1369                 newtuple = tuple = ExecAttrDefault(rel, tuple);
1370 #endif
1371
1372         if (rel->rd_att->constr->has_not_null)
1373         {
1374                 int                     attrChk;
1375
1376                 for (attrChk = 1; attrChk <= rel->rd_att->natts; attrChk++)
1377                 {
1378                         if (rel->rd_att->attrs[attrChk - 1]->attnotnull && heap_attisnull(tuple, attrChk))
1379                                 elog(WARN, "%s: Fail to add null value in not null attribute %s",
1380                                   caller, rel->rd_att->attrs[attrChk - 1]->attname.data);
1381                 }
1382         }
1383
1384         if (rel->rd_att->constr->num_check > 0)
1385         {
1386                 char       *failed;
1387
1388                 if ((failed = ExecRelCheck(rel, tuple)) != NULL)
1389                         elog(WARN, "%s: rejected due to CHECK constraint %s", caller, failed);
1390         }
1391
1392         return (newtuple);
1393 }