]> granicus.if.org Git - postgresql/blob - src/backend/executor/execMain.c
Avoid duplicate ExecTypeFromTL() call in ExecInitJunkFilter() by passing
[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.98 1999/10/30 23:13:30 tgl Exp $
30  *
31  *-------------------------------------------------------------------------
32  */
33 #include "postgres.h"
34
35 #include "access/heapam.h"
36 #include "catalog/heap.h"
37 #include "commands/trigger.h"
38 #include "executor/execdebug.h"
39 #include "executor/execdefs.h"
40 #include "executor/executor.h"
41 #include "miscadmin.h"
42 #include "optimizer/var.h"
43 #include "parser/parsetree.h"
44 #include "utils/acl.h"
45 #include "utils/builtins.h"
46 #include "utils/syscache.h"
47
48 void ExecCheckPerms(CmdType operation, int resultRelation, List *rangeTable,
49                            Query *parseTree);
50
51
52 /* decls for local routines only used within this module */
53 static TupleDesc InitPlan(CmdType operation,
54                  Query *parseTree,
55                  Plan *plan,
56                  EState *estate);
57 static void EndPlan(Plan *plan,
58                 EState *estate);
59 static TupleTableSlot *ExecutePlan(EState *estate, Plan *plan,
60                         CmdType operation,
61                         int offsetTuples,
62                         int 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
75 TupleTableSlot *EvalPlanQual(EState *estate, Index rti, ItemPointer tid);
76 static TupleTableSlot *EvalPlanQualNext(EState *estate);
77
78
79 /* end of local decls */
80
81 /* ----------------------------------------------------------------
82  *              ExecutorStart
83  *
84  *              This routine must be called at the beginning of any execution of any
85  *              query plan
86  *
87  *              returns (AttrInfo*) which describes the attributes of the tuples to
88  *              be returned by the query.
89  *
90  * ----------------------------------------------------------------
91  */
92 TupleDesc
93 ExecutorStart(QueryDesc *queryDesc, EState *estate)
94 {
95         TupleDesc       result;
96
97         /* sanity checks */
98         Assert(queryDesc != NULL);
99
100         if (queryDesc->plantree->nParamExec > 0)
101         {
102                 estate->es_param_exec_vals = (ParamExecData *)
103                         palloc(queryDesc->plantree->nParamExec * sizeof(ParamExecData));
104                 memset(estate->es_param_exec_vals, 0, queryDesc->plantree->nParamExec * sizeof(ParamExecData));
105         }
106
107         /*
108          * Make our own private copy of the current queries snapshot data
109          */
110         if (QuerySnapshot == NULL)
111                 estate->es_snapshot = NULL;
112         else
113         {
114                 estate->es_snapshot = (Snapshot) palloc(sizeof(SnapshotData));
115                 memcpy(estate->es_snapshot, QuerySnapshot, sizeof(SnapshotData));
116                 if (estate->es_snapshot->xcnt > 0)
117                 {
118                         estate->es_snapshot->xip = (TransactionId *)
119                                 palloc(estate->es_snapshot->xcnt * sizeof(TransactionId));
120                         memcpy(estate->es_snapshot->xip, QuerySnapshot->xip,
121                                    estate->es_snapshot->xcnt * sizeof(TransactionId));
122                 }
123         }
124
125         /*
126          * Initialize the plan
127          */
128         result = InitPlan(queryDesc->operation,
129                                           queryDesc->parsetree,
130                                           queryDesc->plantree,
131                                           estate);
132
133         return result;
134 }
135
136 /* ----------------------------------------------------------------
137  *              ExecutorRun
138  *
139  *              This is the main routine of the executor module. It accepts
140  *              the query descriptor from the traffic cop and executes the
141  *              query plan.
142  *
143  *              ExecutorStart must have been called already.
144  *
145  *              the different features supported are:
146  *                       EXEC_RUN:      retrieve all tuples in the forward direction
147  *                       EXEC_FOR:      retrieve 'count' number of tuples in the forward dir
148  *                       EXEC_BACK: retrieve 'count' number of tuples in the backward dir
149  *                       EXEC_RETONE: return one tuple but don't 'retrieve' it
150  *                                                 used in postquel function processing
151  *
152  *
153  * ----------------------------------------------------------------
154  */
155 TupleTableSlot *
156 ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature,
157                         Node *limoffset, Node *limcount)
158 {
159         CmdType         operation;
160         Plan       *plan;
161         TupleTableSlot *result;
162         CommandDest dest;
163         DestReceiver *destfunc;
164         int                     offset = 0;
165         int                     count = 0;
166
167         /*
168          * sanity checks
169          */
170         Assert(queryDesc != NULL);
171
172         /*
173          * extract information from the query descriptor and the query
174          * feature.
175          */
176         operation = queryDesc->operation;
177         plan = queryDesc->plantree;
178         dest = queryDesc->dest;
179         destfunc = DestToFunction(dest);
180         estate->es_processed = 0;
181         estate->es_lastoid = InvalidOid;
182
183         /*
184          * FIXME: the dest setup function ought to be handed the tuple desc
185          * for the tuples to be output, but I'm not quite sure how to get that
186          * info at this point.  For now, passing NULL is OK because no
187          * existing dest setup function actually uses the pointer.
188          */
189         (*destfunc->setup) (destfunc, (TupleDesc) NULL);
190
191         /*
192          * if given get the offset of the LIMIT clause
193          */
194         if (limoffset != NULL)
195         {
196                 Const      *coffset;
197                 Param      *poffset;
198                 ParamListInfo paramLI;
199                 int                     i;
200
201                 switch (nodeTag(limoffset))
202                 {
203                         case T_Const:
204                                 coffset = (Const *) limoffset;
205                                 offset = (int) (coffset->constvalue);
206                                 break;
207
208                         case T_Param:
209                                 poffset = (Param *) limoffset;
210                                 paramLI = estate->es_param_list_info;
211
212                                 if (paramLI == NULL)
213                                         elog(ERROR, "parameter for limit offset not in executor state");
214                                 for (i = 0; paramLI[i].kind != PARAM_INVALID; i++)
215                                 {
216                                         if (paramLI[i].kind == PARAM_NUM && paramLI[i].id == poffset->paramid)
217                                                 break;
218                                 }
219                                 if (paramLI[i].kind == PARAM_INVALID)
220                                         elog(ERROR, "parameter for limit offset not in executor state");
221                                 if (paramLI[i].isnull)
222                                         elog(ERROR, "limit offset cannot be NULL value");
223                                 offset = (int) (paramLI[i].value);
224
225                                 break;
226
227                         default:
228                                 elog(ERROR, "unexpected node type %d as limit offset", nodeTag(limoffset));
229                 }
230
231                 if (offset < 0)
232                         elog(ERROR, "limit offset cannot be negative");
233         }
234
235         /*
236          * if given get the count of the LIMIT clause
237          */
238         if (limcount != NULL)
239         {
240                 Const      *ccount;
241                 Param      *pcount;
242                 ParamListInfo paramLI;
243                 int                     i;
244
245                 switch (nodeTag(limcount))
246                 {
247                         case T_Const:
248                                 ccount = (Const *) limcount;
249                                 count = (int) (ccount->constvalue);
250                                 break;
251
252                         case T_Param:
253                                 pcount = (Param *) limcount;
254                                 paramLI = estate->es_param_list_info;
255
256                                 if (paramLI == NULL)
257                                         elog(ERROR, "parameter for limit count not in executor state");
258                                 for (i = 0; paramLI[i].kind != PARAM_INVALID; i++)
259                                 {
260                                         if (paramLI[i].kind == PARAM_NUM && paramLI[i].id == pcount->paramid)
261                                                 break;
262                                 }
263                                 if (paramLI[i].kind == PARAM_INVALID)
264                                         elog(ERROR, "parameter for limit count not in executor state");
265                                 if (paramLI[i].isnull)
266                                         elog(ERROR, "limit count cannot be NULL value");
267                                 count = (int) (paramLI[i].value);
268
269                                 break;
270
271                         default:
272                                 elog(ERROR, "unexpected node type %d as limit count", nodeTag(limcount));
273                 }
274
275                 if (count < 0)
276                         elog(ERROR, "limit count cannot be negative");
277         }
278
279         switch (feature)
280         {
281
282                 case EXEC_RUN:
283                         result = ExecutePlan(estate,
284                                                                  plan,
285                                                                  operation,
286                                                                  offset,
287                                                                  count,
288                                                                  ForwardScanDirection,
289                                                                  destfunc);
290                         break;
291                 case EXEC_FOR:
292                         result = ExecutePlan(estate,
293                                                                  plan,
294                                                                  operation,
295                                                                  offset,
296                                                                  count,
297                                                                  ForwardScanDirection,
298                                                                  destfunc);
299                         break;
300
301                         /*
302                          * retrieve next n "backward" tuples
303                          */
304                 case EXEC_BACK:
305                         result = ExecutePlan(estate,
306                                                                  plan,
307                                                                  operation,
308                                                                  offset,
309                                                                  count,
310                                                                  BackwardScanDirection,
311                                                                  destfunc);
312                         break;
313
314                         /*
315                          * return one tuple but don't "retrieve" it. (this is used by
316                          * the rule manager..) -cim 9/14/89
317                          */
318                 case EXEC_RETONE:
319                         result = ExecutePlan(estate,
320                                                                  plan,
321                                                                  operation,
322                                                                  0,
323                                                                  ONE_TUPLE,
324                                                                  ForwardScanDirection,
325                                                                  destfunc);
326                         break;
327                 default:
328                         result = NULL;
329                         elog(DEBUG, "ExecutorRun: Unknown feature %d", feature);
330                         break;
331         }
332
333         (*destfunc->cleanup) (destfunc);
334
335         return result;
336 }
337
338 /* ----------------------------------------------------------------
339  *              ExecutorEnd
340  *
341  *              This routine must be called at the end of any execution of any
342  *              query plan
343  *
344  *              returns (AttrInfo*) which describes the attributes of the tuples to
345  *              be returned by the query.
346  *
347  * ----------------------------------------------------------------
348  */
349 void
350 ExecutorEnd(QueryDesc *queryDesc, EState *estate)
351 {
352         /* sanity checks */
353         Assert(queryDesc != NULL);
354
355         EndPlan(queryDesc->plantree, estate);
356
357         /* XXX - clean up some more from ExecutorStart() - er1p */
358         if (NULL == estate->es_snapshot)
359         {
360                 /* nothing to free */
361         }
362         else
363         {
364                 if (estate->es_snapshot->xcnt > 0)
365                         pfree(estate->es_snapshot->xip);
366                 pfree(estate->es_snapshot);
367         }
368
369         if (NULL == estate->es_param_exec_vals)
370         {
371                 /* nothing to free */
372         }
373         else
374         {
375                 pfree(estate->es_param_exec_vals);
376                 estate->es_param_exec_vals = NULL;
377         }
378 }
379
380 void
381 ExecCheckPerms(CmdType operation,
382                            int resultRelation,
383                            List *rangeTable,
384                            Query *parseTree)
385 {
386         int                     i = 1;
387         Oid                     relid;
388         HeapTuple       htup;
389         List       *lp;
390         List       *qvars,
391                            *tvars;
392         int32           ok = 1,
393                                 aclcheck_result = -1;
394         char       *opstr;
395         NameData        rname;
396         char       *userName;
397
398 #define CHECK(MODE)             pg_aclcheck(rname.data, userName, MODE)
399
400         userName = GetPgUserName();
401
402         foreach(lp, rangeTable)
403         {
404                 RangeTblEntry *rte = lfirst(lp);
405
406                 if (rte->skipAcl)
407                 {
408
409                         /*
410                          * This happens if the access to this table is due to a view
411                          * query rewriting - the rewrite handler checked the
412                          * permissions against the view owner, so we just skip this
413                          * entry.
414                          */
415                         continue;
416                 }
417
418                 relid = rte->relid;
419                 htup = SearchSysCacheTuple(RELOID,
420                                                                    ObjectIdGetDatum(relid),
421                                                                    0, 0, 0);
422                 if (!HeapTupleIsValid(htup))
423                         elog(ERROR, "ExecCheckPerms: bogus RT relid: %u", relid);
424                 StrNCpy(rname.data,
425                                 ((Form_pg_class) GETSTRUCT(htup))->relname.data,
426                                 NAMEDATALEN);
427                 if (i == resultRelation)
428                 {                                               /* this is the result relation */
429                         qvars = pull_varnos(parseTree->qual);
430                         tvars = pull_varnos((Node *) parseTree->targetList);
431                         if (intMember(resultRelation, qvars) ||
432                                 intMember(resultRelation, tvars))
433                         {
434                                 /* result relation is scanned */
435                                 ok = ((aclcheck_result = CHECK(ACL_RD)) == ACLCHECK_OK);
436                                 opstr = "read";
437                                 if (!ok)
438                                         break;
439                         }
440                         switch (operation)
441                         {
442                                 case CMD_INSERT:
443                                         ok = ((aclcheck_result = CHECK(ACL_AP)) == ACLCHECK_OK) ||
444                                                 ((aclcheck_result = CHECK(ACL_WR)) == ACLCHECK_OK);
445                                         opstr = "append";
446                                         break;
447                                 case CMD_DELETE:
448                                 case CMD_UPDATE:
449                                         ok = ((aclcheck_result = CHECK(ACL_WR)) == ACLCHECK_OK);
450                                         opstr = "write";
451                                         break;
452                                 default:
453                                         elog(ERROR, "ExecCheckPerms: bogus operation %d",
454                                                  operation);
455                         }
456                 }
457                 else
458                 {
459                         ok = ((aclcheck_result = CHECK(ACL_RD)) == ACLCHECK_OK);
460                         opstr = "read";
461                 }
462                 if (!ok)
463                         break;
464                 ++i;
465         }
466         if (!ok)
467                 elog(ERROR, "%s: %s", rname.data, aclcheck_error_strings[aclcheck_result]);
468
469         if (parseTree != NULL && parseTree->rowMark != NULL)
470         {
471                 foreach(lp, parseTree->rowMark)
472                 {
473                         RowMark    *rm = lfirst(lp);
474
475                         if (!(rm->info & ROW_ACL_FOR_UPDATE))
476                                 continue;
477
478                         relid = ((RangeTblEntry *) nth(rm->rti - 1, rangeTable))->relid;
479                         htup = SearchSysCacheTuple(RELOID,
480                                                                            ObjectIdGetDatum(relid),
481                                                                            0, 0, 0);
482                         if (!HeapTupleIsValid(htup))
483                                 elog(ERROR, "ExecCheckPerms: bogus RT relid: %u", relid);
484                         StrNCpy(rname.data,
485                                         ((Form_pg_class) GETSTRUCT(htup))->relname.data,
486                                         NAMEDATALEN);
487                         ok = ((aclcheck_result = CHECK(ACL_WR)) == ACLCHECK_OK);
488                         opstr = "write";
489                         if (!ok)
490                                 elog(ERROR, "%s: %s", rname.data, aclcheck_error_strings[aclcheck_result]);
491                 }
492         }
493 }
494
495 /* ===============================================================
496  * ===============================================================
497                                                  static routines follow
498  * ===============================================================
499  * ===============================================================
500  */
501
502 typedef struct execRowMark
503 {
504         Relation        relation;
505         Index           rti;
506         char            resname[32];
507 } execRowMark;
508
509 typedef struct evalPlanQual
510 {
511         Plan       *plan;
512         Index           rti;
513         EState          estate;
514         struct evalPlanQual *free;
515 } evalPlanQual;
516
517 /* ----------------------------------------------------------------
518  *              InitPlan
519  *
520  *              Initializes the query plan: open files, allocate storage
521  *              and start up the rule manager
522  * ----------------------------------------------------------------
523  */
524 static TupleDesc
525 InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
526 {
527         List       *rangeTable;
528         int                     resultRelation;
529         Relation        intoRelationDesc;
530         TupleDesc       tupType;
531         List       *targetList;
532
533         /*
534          * get information from query descriptor
535          */
536         rangeTable = parseTree->rtable;
537         resultRelation = parseTree->resultRelation;
538
539 #ifndef NO_SECURITY
540         ExecCheckPerms(operation, resultRelation, rangeTable, parseTree);
541 #endif
542
543         /*
544          * initialize the node's execution state
545          */
546         estate->es_range_table = rangeTable;
547
548         /*
549          * initialize the BaseId counter so node base_id's are assigned
550          * correctly.  Someday baseid's will have to be stored someplace other
551          * than estate because they should be unique per query planned.
552          */
553         estate->es_BaseId = 1;
554
555         /*
556          * initialize result relation stuff
557          */
558
559         if (resultRelation != 0 && operation != CMD_SELECT)
560         {
561
562                 /*
563                  * if we have a result relation, open it and initialize the result
564                  * relation info stuff.
565                  */
566                 RelationInfo *resultRelationInfo;
567                 Index           resultRelationIndex;
568                 RangeTblEntry *rtentry;
569                 Oid                     resultRelationOid;
570                 Relation        resultRelationDesc;
571
572                 resultRelationIndex = resultRelation;
573                 rtentry = rt_fetch(resultRelationIndex, rangeTable);
574                 resultRelationOid = rtentry->relid;
575                 resultRelationDesc = heap_open(resultRelationOid, RowExclusiveLock);
576
577                 if (resultRelationDesc->rd_rel->relkind == RELKIND_SEQUENCE)
578                         elog(ERROR, "You can't change sequence relation %s",
579                                  resultRelationDesc->rd_rel->relname.data);
580
581                 resultRelationInfo = makeNode(RelationInfo);
582                 resultRelationInfo->ri_RangeTableIndex = resultRelationIndex;
583                 resultRelationInfo->ri_RelationDesc = resultRelationDesc;
584                 resultRelationInfo->ri_NumIndices = 0;
585                 resultRelationInfo->ri_IndexRelationDescs = NULL;
586                 resultRelationInfo->ri_IndexRelationInfo = NULL;
587
588                 /*
589                  * open indices on result relation and save descriptors in the
590                  * result relation information..
591                  */
592                 if (operation != CMD_DELETE)
593                         ExecOpenIndices(resultRelationOid, resultRelationInfo);
594
595                 estate->es_result_relation_info = resultRelationInfo;
596         }
597         else
598         {
599
600                 /*
601                  * if no result relation, then set state appropriately
602                  */
603                 estate->es_result_relation_info = NULL;
604         }
605
606         /*
607          * Have to lock relations selected for update
608          */
609         estate->es_rowMark = NULL;
610         if (parseTree->rowMark != NULL)
611         {
612                 Relation        relation;
613                 Oid                     relid;
614                 RowMark    *rm;
615                 List       *l;
616                 execRowMark *erm;
617
618                 foreach(l, parseTree->rowMark)
619                 {
620                         rm = lfirst(l);
621                         relid = ((RangeTblEntry *) nth(rm->rti - 1, rangeTable))->relid;
622                         relation = heap_open(relid, RowShareLock);
623                         if (!(rm->info & ROW_MARK_FOR_UPDATE))
624                                 continue;
625                         erm = (execRowMark *) palloc(sizeof(execRowMark));
626                         erm->relation = relation;
627                         erm->rti = rm->rti;
628                         sprintf(erm->resname, "ctid%u", rm->rti);
629                         estate->es_rowMark = lappend(estate->es_rowMark, erm);
630                 }
631         }
632
633         /*
634          * initialize the executor "tuple" table.
635          */
636         {
637                 int                     nSlots = ExecCountSlotsNode(plan);
638                 TupleTable      tupleTable = ExecCreateTupleTable(nSlots + 10);         /* why add ten? - jolly */
639
640                 estate->es_tupleTable = tupleTable;
641         }
642
643         /*
644          * initialize the private state information for all the nodes in the
645          * query tree.  This opens files, allocates storage and leaves us
646          * ready to start processing tuples..
647          */
648         ExecInitNode(plan, estate, NULL);
649
650         /*
651          * get the tuple descriptor describing the type of tuples to return..
652          * (this is especially important if we are creating a relation with
653          * "retrieve into")
654          */
655         tupType = ExecGetTupType(plan);         /* tuple descriptor */
656         targetList = plan->targetlist;
657
658         /*
659          * Now that we have the target list, initialize the junk filter if needed.
660          * SELECT and INSERT queries need a filter if there are any junk attrs
661          * in the tlist.  UPDATE and DELETE always need one, since there's always
662          * a junk 'ctid' attribute present --- no need to look first.
663          */
664         {
665                 bool            junk_filter_needed = false;
666                 List       *tlist;
667
668                 switch (operation)
669                 {
670                         case CMD_SELECT:
671                         case CMD_INSERT:
672                                 foreach(tlist, targetList)
673                                 {
674                                         TargetEntry *tle = (TargetEntry *) lfirst(tlist);
675
676                                         if (tle->resdom->resjunk)
677                                         {
678                                                 junk_filter_needed = true;
679                                                 break;
680                                         }
681                                 }
682                                 break;
683                         case CMD_UPDATE:
684                         case CMD_DELETE:
685                                 junk_filter_needed = true;
686                                 break;
687                         default:
688                                 break;
689                 }
690
691                 if (junk_filter_needed)
692                 {
693                         JunkFilter *j = ExecInitJunkFilter(targetList, tupType);
694
695                         estate->es_junkFilter = j;
696
697                         if (operation == CMD_SELECT)
698                                 tupType = j->jf_cleanTupType;
699                 }
700                 else
701                         estate->es_junkFilter = NULL;
702         }
703
704         /*
705          * initialize the "into" relation
706          */
707         intoRelationDesc = (Relation) NULL;
708
709         if (operation == CMD_SELECT)
710         {
711                 char       *intoName;
712                 Oid                     intoRelationId;
713                 TupleDesc       tupdesc;
714
715                 if (!parseTree->isPortal)
716                 {
717
718                         /*
719                          * a select into table
720                          */
721                         if (parseTree->into != NULL)
722                         {
723
724                                 /*
725                                  * create the "into" relation
726                                  */
727                                 intoName = parseTree->into;
728
729                                 /*
730                                  * have to copy tupType to get rid of constraints
731                                  */
732                                 tupdesc = CreateTupleDescCopy(tupType);
733
734                                 intoRelationId = heap_create_with_catalog(intoName,
735                                                    tupdesc, RELKIND_RELATION, parseTree->isTemp);
736
737                                 FreeTupleDesc(tupdesc);
738
739                                 /*
740                                  * XXX rather than having to call setheapoverride(true)
741                                  * and then back to false, we should change the arguments
742                                  * to heap_open() instead..
743                                  */
744                                 setheapoverride(true);
745
746                                 intoRelationDesc = heap_open(intoRelationId,
747                                                                                          AccessExclusiveLock);
748
749                                 setheapoverride(false);
750                         }
751                 }
752         }
753
754         estate->es_into_relation_descriptor = intoRelationDesc;
755
756         estate->es_origPlan = plan;
757         estate->es_evalPlanQual = NULL;
758         estate->es_evTuple = NULL;
759         estate->es_useEvalPlan = false;
760
761         return tupType;
762 }
763
764 /* ----------------------------------------------------------------
765  *              EndPlan
766  *
767  *              Cleans up the query plan -- closes files and free up storages
768  * ----------------------------------------------------------------
769  */
770 static void
771 EndPlan(Plan *plan, EState *estate)
772 {
773         RelationInfo *resultRelationInfo;
774         Relation        intoRelationDesc;
775
776         /*
777          * get information from state
778          */
779         resultRelationInfo = estate->es_result_relation_info;
780         intoRelationDesc = estate->es_into_relation_descriptor;
781
782         /*
783          * shut down the query
784          */
785         ExecEndNode(plan, plan);
786
787         /*
788          * destroy the executor "tuple" table.
789          */
790         {
791                 TupleTable      tupleTable = (TupleTable) estate->es_tupleTable;
792
793                 ExecDestroyTupleTable(tupleTable, true);
794                 estate->es_tupleTable = NULL;
795         }
796
797         /*
798          * close the result relations if necessary,
799          * but hold locks on them until xact commit
800          */
801         if (resultRelationInfo != NULL)
802         {
803                 Relation        resultRelationDesc;
804
805                 resultRelationDesc = resultRelationInfo->ri_RelationDesc;
806                 heap_close(resultRelationDesc, NoLock);
807
808                 /*
809                  * close indices on the result relation
810                  */
811                 ExecCloseIndices(resultRelationInfo);
812         }
813
814         /*
815          * close the "into" relation if necessary
816          */
817         if (intoRelationDesc != NULL)
818                 heap_close(intoRelationDesc, NoLock);
819 }
820
821 /* ----------------------------------------------------------------
822  *              ExecutePlan
823  *
824  *              processes the query plan to retrieve 'tupleCount' tuples in the
825  *              direction specified.
826  *              Retrieves all tuples if tupleCount is 0
827  *
828  *              result is either a slot containing a tuple in the case
829  *              of a RETRIEVE or NULL otherwise.
830  *
831  * ----------------------------------------------------------------
832  */
833
834 /* the ctid attribute is a 'junk' attribute that is removed before the
835    user can see it*/
836
837 static TupleTableSlot *
838 ExecutePlan(EState *estate,
839                         Plan *plan,
840                         CmdType operation,
841                         int offsetTuples,
842                         int numberTuples,
843                         ScanDirection direction,
844                         DestReceiver *destfunc)
845 {
846         JunkFilter *junkfilter;
847         TupleTableSlot *slot;
848         ItemPointer tupleid = NULL;
849         ItemPointerData tuple_ctid;
850         int                     current_tuple_count;
851         TupleTableSlot *result;
852
853         /*
854          * initialize local variables
855          */
856         slot = NULL;
857         current_tuple_count = 0;
858         result = NULL;
859
860         /*
861          * Set the direction.
862          */
863         estate->es_direction = direction;
864
865         /*
866          * Loop until we've processed the proper number of tuples from the
867          * plan..
868          */
869
870         for (;;)
871         {
872
873                 /*
874                  * Execute the plan and obtain a tuple
875                  */
876                 /* at the top level, the parent of a plan (2nd arg) is itself */
877 lnext:  ;
878                 if (estate->es_useEvalPlan)
879                 {
880                         slot = EvalPlanQualNext(estate);
881                         if (TupIsNull(slot))
882                                 slot = ExecProcNode(plan, plan);
883                 }
884                 else
885                         slot = ExecProcNode(plan, plan);
886
887                 /*
888                  * if the tuple is null, then we assume there is nothing more to
889                  * process so we just return null...
890                  */
891                 if (TupIsNull(slot))
892                 {
893                         result = NULL;
894                         break;
895                 }
896
897                 /*
898                  * For now we completely execute the plan and skip result tuples
899                  * if requested by LIMIT offset. Finally we should try to do it in
900                  * deeper levels if possible (during index scan) - Jan
901                  */
902                 if (offsetTuples > 0)
903                 {
904                         --offsetTuples;
905                         continue;
906                 }
907
908                 /*
909                  * if we have a junk filter, then project a new tuple with the
910                  * junk removed.
911                  *
912                  * Store this new "clean" tuple in the place of the original tuple.
913                  *
914                  * Also, extract all the junk information we need.
915                  */
916                 if ((junkfilter = estate->es_junkFilter) != (JunkFilter *) NULL)
917                 {
918                         Datum           datum;
919                         HeapTuple       newTuple;
920                         bool            isNull;
921
922                         /*
923                          * extract the 'ctid' junk attribute.
924                          */
925                         if (operation == CMD_UPDATE || operation == CMD_DELETE)
926                         {
927                                 if (!ExecGetJunkAttribute(junkfilter,
928                                                                                   slot,
929                                                                                   "ctid",
930                                                                                   &datum,
931                                                                                   &isNull))
932                                         elog(ERROR, "ExecutePlan: NO (junk) `ctid' was found!");
933
934                                 if (isNull)
935                                         elog(ERROR, "ExecutePlan: (junk) `ctid' is NULL!");
936
937                                 tupleid = (ItemPointer) DatumGetPointer(datum);
938                                 tuple_ctid = *tupleid;  /* make sure we don't free the
939                                                                                  * ctid!! */
940                                 tupleid = &tuple_ctid;
941                         }
942                         else if (estate->es_rowMark != NULL)
943                         {
944                                 List       *l;
945                                 execRowMark *erm;
946                                 Buffer          buffer;
947                                 HeapTupleData tuple;
948                                 TupleTableSlot *newSlot;
949                                 int                     test;
950
951                 lmark:  ;
952                                 foreach(l, estate->es_rowMark)
953                                 {
954                                         erm = lfirst(l);
955                                         if (!ExecGetJunkAttribute(junkfilter,
956                                                                                           slot,
957                                                                                           erm->resname,
958                                                                                           &datum,
959                                                                                           &isNull))
960                                                 elog(ERROR, "ExecutePlan: NO (junk) `%s' was found!", erm->resname);
961
962                                         if (isNull)
963                                                 elog(ERROR, "ExecutePlan: (junk) `%s' is NULL!", erm->resname);
964
965                                         tuple.t_self = *((ItemPointer) DatumGetPointer(datum));
966                                         test = heap_mark4update(erm->relation, &tuple, &buffer);
967                                         ReleaseBuffer(buffer);
968                                         switch (test)
969                                         {
970                                                 case HeapTupleSelfUpdated:
971                                                 case HeapTupleMayBeUpdated:
972                                                         break;
973
974                                                 case HeapTupleUpdated:
975                                                         if (XactIsoLevel == XACT_SERIALIZABLE)
976                                                         {
977                                                                 elog(ERROR, "Can't serialize access due to concurrent update");
978                                                                 return (NULL);
979                                                         }
980                                                         else if (!(ItemPointerEquals(&(tuple.t_self),
981                                                                   (ItemPointer) DatumGetPointer(datum))))
982                                                         {
983                                                                 newSlot = EvalPlanQual(estate, erm->rti, &(tuple.t_self));
984                                                                 if (!(TupIsNull(newSlot)))
985                                                                 {
986                                                                         slot = newSlot;
987                                                                         estate->es_useEvalPlan = true;
988                                                                         goto lmark;
989                                                                 }
990                                                         }
991
992                                                         /*
993                                                          * if tuple was deleted or PlanQual failed for
994                                                          * updated tuple - we have not return this
995                                                          * tuple!
996                                                          */
997                                                         goto lnext;
998
999                                                 default:
1000                                                         elog(ERROR, "Unknown status %u from heap_mark4update", test);
1001                                                         return (NULL);
1002                                         }
1003                                 }
1004                         }
1005
1006                         /*
1007                          * Finally create a new "clean" tuple with all junk attributes
1008                          * removed
1009                          */
1010                         newTuple = ExecRemoveJunk(junkfilter, slot);
1011
1012                         slot = ExecStoreTuple(newTuple,         /* tuple to store */
1013                                                                   slot, /* destination slot */
1014                                                                   InvalidBuffer,                /* this tuple has no
1015                                                                                                                  * buffer */
1016                                                                   true);                /* tuple should be pfreed */
1017                 }                                               /* if (junkfilter... */
1018
1019                 /*
1020                  * now that we have a tuple, do the appropriate thing with it..
1021                  * either return it to the user, add it to a relation someplace,
1022                  * delete it from a relation, or modify some of it's attributes.
1023                  */
1024
1025                 switch (operation)
1026                 {
1027                         case CMD_SELECT:
1028                                 ExecRetrieve(slot,              /* slot containing tuple */
1029                                                          destfunc,      /* destination's tuple-receiver
1030                                                                                  * obj */
1031                                                          estate);       /* */
1032                                 result = slot;
1033                                 break;
1034
1035                         case CMD_INSERT:
1036                                 ExecAppend(slot, tupleid, estate);
1037                                 result = NULL;
1038                                 break;
1039
1040                         case CMD_DELETE:
1041                                 ExecDelete(slot, tupleid, estate);
1042                                 result = NULL;
1043                                 break;
1044
1045                         case CMD_UPDATE:
1046                                 ExecReplace(slot, tupleid, estate);
1047                                 result = NULL;
1048                                 break;
1049
1050                         default:
1051                                 elog(DEBUG, "ExecutePlan: unknown operation in queryDesc");
1052                                 result = NULL;
1053                                 break;
1054                 }
1055
1056                 /*
1057                  * check our tuple count.. if we've returned the proper number
1058                  * then return, else loop again and process more tuples..
1059                  */
1060                 current_tuple_count += 1;
1061                 if (numberTuples == current_tuple_count)
1062                         break;
1063         }
1064
1065         /*
1066          * here, result is either a slot containing a tuple in the case of a
1067          * RETRIEVE or NULL otherwise.
1068          */
1069         return result;
1070 }
1071
1072 /* ----------------------------------------------------------------
1073  *              ExecRetrieve
1074  *
1075  *              RETRIEVEs are easy.. we just pass the tuple to the appropriate
1076  *              print function.  The only complexity is when we do a
1077  *              "retrieve into", in which case we insert the tuple into
1078  *              the appropriate relation (note: this is a newly created relation
1079  *              so we don't need to worry about indices or locks.)
1080  * ----------------------------------------------------------------
1081  */
1082 static void
1083 ExecRetrieve(TupleTableSlot *slot,
1084                          DestReceiver *destfunc,
1085                          EState *estate)
1086 {
1087         HeapTuple       tuple;
1088         TupleDesc       attrtype;
1089
1090         /*
1091          * get the heap tuple out of the tuple table slot
1092          */
1093         tuple = slot->val;
1094         attrtype = slot->ttc_tupleDescriptor;
1095
1096         /*
1097          * insert the tuple into the "into relation"
1098          */
1099         if (estate->es_into_relation_descriptor != NULL)
1100         {
1101                 heap_insert(estate->es_into_relation_descriptor, tuple);
1102                 IncrAppended();
1103         }
1104
1105         /*
1106          * send the tuple to the front end (or the screen)
1107          */
1108         (*destfunc->receiveTuple) (tuple, attrtype, destfunc);
1109         IncrRetrieved();
1110         (estate->es_processed)++;
1111 }
1112
1113 /* ----------------------------------------------------------------
1114  *              ExecAppend
1115  *
1116  *              APPENDs are trickier.. we have to insert the tuple into
1117  *              the base relation and insert appropriate tuples into the
1118  *              index relations.
1119  * ----------------------------------------------------------------
1120  */
1121
1122 static void
1123 ExecAppend(TupleTableSlot *slot,
1124                    ItemPointer tupleid,
1125                    EState *estate)
1126 {
1127         HeapTuple       tuple;
1128         RelationInfo *resultRelationInfo;
1129         Relation        resultRelationDesc;
1130         int                     numIndices;
1131         Oid                     newId;
1132
1133         /*
1134          * get the heap tuple out of the tuple table slot
1135          */
1136         tuple = slot->val;
1137
1138         /*
1139          * get information on the result relation
1140          */
1141         resultRelationInfo = estate->es_result_relation_info;
1142         resultRelationDesc = resultRelationInfo->ri_RelationDesc;
1143
1144         /*
1145          * have to add code to preform unique checking here. cim -12/1/89
1146          */
1147
1148         /* BEFORE ROW INSERT Triggers */
1149         if (resultRelationDesc->trigdesc &&
1150         resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_INSERT] > 0)
1151         {
1152                 HeapTuple       newtuple;
1153
1154                 newtuple = ExecBRInsertTriggers(resultRelationDesc, 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         if (resultRelationDesc->rd_att->constr)
1172                 ExecConstraints("ExecAppend", resultRelationDesc, tuple, estate);
1173
1174         /*
1175          * insert the tuple
1176          */
1177         newId = heap_insert(resultRelationDesc,         /* relation desc */
1178                                                 tuple); /* heap tuple */
1179         IncrAppended();
1180
1181         /*
1182          * process indices
1183          *
1184          * Note: heap_insert adds a new tuple to a relation.  As a side effect,
1185          * the tupleid of the new tuple is placed in the new tuple's t_ctid
1186          * field.
1187          */
1188         numIndices = resultRelationInfo->ri_NumIndices;
1189         if (numIndices > 0)
1190                 ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false);
1191         (estate->es_processed)++;
1192         estate->es_lastoid = newId;
1193
1194         /* AFTER ROW INSERT Triggers */
1195         if (resultRelationDesc->trigdesc)
1196                 ExecARInsertTriggers(resultRelationDesc, tuple);
1197 }
1198
1199 /* ----------------------------------------------------------------
1200  *              ExecDelete
1201  *
1202  *              DELETE is like append, we delete the tuple and its
1203  *              index tuples.
1204  * ----------------------------------------------------------------
1205  */
1206 static void
1207 ExecDelete(TupleTableSlot *slot,
1208                    ItemPointer tupleid,
1209                    EState *estate)
1210 {
1211         RelationInfo *resultRelationInfo;
1212         Relation        resultRelationDesc;
1213         ItemPointerData ctid;
1214         int                     result;
1215
1216         /*
1217          * get the result relation information
1218          */
1219         resultRelationInfo = estate->es_result_relation_info;
1220         resultRelationDesc = resultRelationInfo->ri_RelationDesc;
1221
1222         /* BEFORE ROW DELETE Triggers */
1223         if (resultRelationDesc->trigdesc &&
1224         resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_DELETE] > 0)
1225         {
1226                 bool            dodelete;
1227
1228                 dodelete = ExecBRDeleteTriggers(estate, tupleid);
1229
1230                 if (!dodelete)                  /* "do nothing" */
1231                         return;
1232         }
1233
1234         /*
1235          * delete the tuple
1236          */
1237 ldelete:;
1238         result = heap_delete(resultRelationDesc, tupleid, &ctid);
1239         switch (result)
1240         {
1241                 case HeapTupleSelfUpdated:
1242                         return;
1243
1244                 case HeapTupleMayBeUpdated:
1245                         break;
1246
1247                 case HeapTupleUpdated:
1248                         if (XactIsoLevel == XACT_SERIALIZABLE)
1249                                 elog(ERROR, "Can't serialize access due to concurrent update");
1250                         else if (!(ItemPointerEquals(tupleid, &ctid)))
1251                         {
1252                                 TupleTableSlot *epqslot = EvalPlanQual(estate,
1253                                                   resultRelationInfo->ri_RangeTableIndex, &ctid);
1254
1255                                 if (!TupIsNull(epqslot))
1256                                 {
1257                                         *tupleid = ctid;
1258                                         goto ldelete;
1259                                 }
1260                         }
1261                         return;
1262
1263                 default:
1264                         elog(ERROR, "Unknown status %u from heap_delete", result);
1265                         return;
1266         }
1267
1268         IncrDeleted();
1269         (estate->es_processed)++;
1270
1271         /*
1272          * Note: Normally one would think that we have to delete index tuples
1273          * associated with the heap tuple now..
1274          *
1275          * ... but in POSTGRES, we have no need to do this because the vacuum
1276          * daemon automatically opens an index scan and deletes index tuples
1277          * when it finds deleted heap tuples. -cim 9/27/89
1278          */
1279
1280         /* AFTER ROW DELETE Triggers */
1281         if (resultRelationDesc->trigdesc)
1282                 ExecARDeleteTriggers(estate, tupleid);
1283
1284 }
1285
1286 /* ----------------------------------------------------------------
1287  *              ExecReplace
1288  *
1289  *              note: we can't run replace queries with transactions
1290  *              off because replaces are actually appends and our
1291  *              scan will mistakenly loop forever, replacing the tuple
1292  *              it just appended..      This should be fixed but until it
1293  *              is, we don't want to get stuck in an infinite loop
1294  *              which corrupts your database..
1295  * ----------------------------------------------------------------
1296  */
1297 static void
1298 ExecReplace(TupleTableSlot *slot,
1299                         ItemPointer tupleid,
1300                         EState *estate)
1301 {
1302         HeapTuple       tuple;
1303         RelationInfo *resultRelationInfo;
1304         Relation        resultRelationDesc;
1305         ItemPointerData ctid;
1306         int                     result;
1307         int                     numIndices;
1308
1309         /*
1310          * abort the operation if not running transactions
1311          */
1312         if (IsBootstrapProcessingMode())
1313         {
1314                 elog(DEBUG, "ExecReplace: replace can't run without transactions");
1315                 return;
1316         }
1317
1318         /*
1319          * get the heap tuple out of the tuple table slot
1320          */
1321         tuple = slot->val;
1322
1323         /*
1324          * get the result relation information
1325          */
1326         resultRelationInfo = estate->es_result_relation_info;
1327         resultRelationDesc = resultRelationInfo->ri_RelationDesc;
1328
1329         /*
1330          * have to add code to preform unique checking here. in the event of
1331          * unique tuples, this becomes a deletion of the original tuple
1332          * affected by the replace. cim -12/1/89
1333          */
1334
1335         /* BEFORE ROW UPDATE Triggers */
1336         if (resultRelationDesc->trigdesc &&
1337         resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_UPDATE] > 0)
1338         {
1339                 HeapTuple       newtuple;
1340
1341                 newtuple = ExecBRUpdateTriggers(estate, tupleid, tuple);
1342
1343                 if (newtuple == NULL)   /* "do nothing" */
1344                         return;
1345
1346                 if (newtuple != tuple)  /* modified by Trigger(s) */
1347                 {
1348                         Assert(slot->ttc_shouldFree);
1349                         pfree(tuple);
1350                         slot->val = tuple = newtuple;
1351                 }
1352         }
1353
1354         /*
1355          * Check the constraints of a tuple
1356          */
1357
1358         if (resultRelationDesc->rd_att->constr)
1359                 ExecConstraints("ExecReplace", resultRelationDesc, tuple, estate);
1360
1361         /*
1362          * replace the heap tuple
1363          */
1364 lreplace:;
1365         result = heap_replace(resultRelationDesc, tupleid, tuple, &ctid);
1366         switch (result)
1367         {
1368                 case HeapTupleSelfUpdated:
1369                         return;
1370
1371                 case HeapTupleMayBeUpdated:
1372                         break;
1373
1374                 case HeapTupleUpdated:
1375                         if (XactIsoLevel == XACT_SERIALIZABLE)
1376                                 elog(ERROR, "Can't serialize access due to concurrent update");
1377                         else if (!(ItemPointerEquals(tupleid, &ctid)))
1378                         {
1379                                 TupleTableSlot *epqslot = EvalPlanQual(estate,
1380                                                   resultRelationInfo->ri_RangeTableIndex, &ctid);
1381
1382                                 if (!TupIsNull(epqslot))
1383                                 {
1384                                         *tupleid = ctid;
1385                                         tuple = ExecRemoveJunk(estate->es_junkFilter, epqslot);
1386                                         slot = ExecStoreTuple(tuple, slot, InvalidBuffer, true);
1387                                         goto lreplace;
1388                                 }
1389                         }
1390                         return;
1391
1392                 default:
1393                         elog(ERROR, "Unknown status %u from heap_replace", result);
1394                         return;
1395         }
1396
1397         IncrReplaced();
1398         (estate->es_processed)++;
1399
1400         /*
1401          * Note: instead of having to update the old index tuples associated
1402          * with the heap tuple, all we do is form and insert new index
1403          * tuples..  This is because replaces are actually deletes and inserts
1404          * and index tuple deletion is done automagically by the vaccuum
1405          * deamon.. All we do is insert new index tuples.  -cim 9/27/89
1406          */
1407
1408         /*
1409          * process indices
1410          *
1411          * heap_replace updates a tuple in the base relation by invalidating it
1412          * and then appending a new tuple to the relation.      As a side effect,
1413          * the tupleid of the new tuple is placed in the new tuple's t_ctid
1414          * field.  So we now insert index tuples using the new tupleid stored
1415          * there.
1416          */
1417
1418         numIndices = resultRelationInfo->ri_NumIndices;
1419         if (numIndices > 0)
1420                 ExecInsertIndexTuples(slot, &(tuple->t_self), estate, true);
1421
1422         /* AFTER ROW UPDATE Triggers */
1423         if (resultRelationDesc->trigdesc)
1424                 ExecARUpdateTriggers(estate, tupleid, tuple);
1425 }
1426
1427 #ifdef NOT_USED
1428 static HeapTuple
1429 ExecAttrDefault(Relation rel, HeapTuple tuple)
1430 {
1431         int                     ndef = rel->rd_att->constr->num_defval;
1432         AttrDefault *attrdef = rel->rd_att->constr->defval;
1433         ExprContext *econtext = makeNode(ExprContext);
1434         HeapTuple       newtuple;
1435         Node       *expr;
1436         bool            isnull;
1437         bool            isdone;
1438         Datum           val;
1439         Datum      *replValue = NULL;
1440         char       *replNull = NULL;
1441         char       *repl = NULL;
1442         int                     i;
1443
1444         econtext->ecxt_scantuple = NULL;        /* scan tuple slot */
1445         econtext->ecxt_innertuple = NULL;       /* inner tuple slot */
1446         econtext->ecxt_outertuple = NULL;       /* outer tuple slot */
1447         econtext->ecxt_relation = NULL;         /* relation */
1448         econtext->ecxt_relid = 0;       /* relid */
1449         econtext->ecxt_param_list_info = NULL;          /* param list info */
1450         econtext->ecxt_param_exec_vals = NULL;          /* exec param values */
1451         econtext->ecxt_range_table = NULL;      /* range table */
1452         for (i = 0; i < ndef; i++)
1453         {
1454                 if (!heap_attisnull(tuple, attrdef[i].adnum))
1455                         continue;
1456                 expr = (Node *) stringToNode(attrdef[i].adbin);
1457
1458                 val = ExecEvalExpr(expr, econtext, &isnull, &isdone);
1459
1460                 pfree(expr);
1461
1462                 if (isnull)
1463                         continue;
1464
1465                 if (repl == NULL)
1466                 {
1467                         repl = (char *) palloc(rel->rd_att->natts * sizeof(char));
1468                         replNull = (char *) palloc(rel->rd_att->natts * sizeof(char));
1469                         replValue = (Datum *) palloc(rel->rd_att->natts * sizeof(Datum));
1470                         MemSet(repl, ' ', rel->rd_att->natts * sizeof(char));
1471                 }
1472
1473                 repl[attrdef[i].adnum - 1] = 'r';
1474                 replNull[attrdef[i].adnum - 1] = ' ';
1475                 replValue[attrdef[i].adnum - 1] = val;
1476
1477         }
1478
1479         pfree(econtext);
1480
1481         if (repl == NULL)
1482                 return tuple;
1483
1484         newtuple = heap_modifytuple(tuple, rel, replValue, replNull, repl);
1485
1486         pfree(repl);
1487         pfree(tuple);
1488         pfree(replNull);
1489         pfree(replValue);
1490
1491         return newtuple;
1492
1493 }
1494
1495 #endif
1496
1497 static char *
1498 ExecRelCheck(Relation rel, HeapTuple tuple, EState *estate)
1499 {
1500         int                     ncheck = rel->rd_att->constr->num_check;
1501         ConstrCheck *check = rel->rd_att->constr->check;
1502         ExprContext *econtext = makeNode(ExprContext);
1503         TupleTableSlot *slot = makeNode(TupleTableSlot);
1504         RangeTblEntry *rte = makeNode(RangeTblEntry);
1505         List       *rtlist;
1506         List       *qual;
1507         bool            res;
1508         int                     i;
1509
1510         slot->val = tuple;
1511         slot->ttc_shouldFree = false;
1512         slot->ttc_descIsNew = true;
1513         slot->ttc_tupleDescriptor = rel->rd_att;
1514         slot->ttc_buffer = InvalidBuffer;
1515         slot->ttc_whichplan = -1;
1516         rte->relname = nameout(&(rel->rd_rel->relname));
1517         rte->refname = rte->relname;
1518         rte->relid = RelationGetRelid(rel);
1519         /* inh, inFromCl, inJoinSet, skipAcl won't be used, leave them zero */
1520         rtlist = lcons(rte, NIL);
1521         econtext->ecxt_scantuple = slot;        /* scan tuple slot */
1522         econtext->ecxt_innertuple = NULL;       /* inner tuple slot */
1523         econtext->ecxt_outertuple = NULL;       /* outer tuple slot */
1524         econtext->ecxt_relation = rel;          /* relation */
1525         econtext->ecxt_relid = 0;       /* relid */
1526         econtext->ecxt_param_list_info = NULL;          /* param list info */
1527         econtext->ecxt_param_exec_vals = NULL;          /* exec param values */
1528         econtext->ecxt_range_table = rtlist;            /* range table */
1529
1530         if (estate->es_result_relation_constraints == NULL)
1531         {
1532                 estate->es_result_relation_constraints =
1533                         (List **) palloc(ncheck * sizeof(List *));
1534
1535                 for (i = 0; i < ncheck; i++)
1536                 {
1537                         qual = (List *) stringToNode(check[i].ccbin);
1538                         estate->es_result_relation_constraints[i] = qual;
1539                 }
1540         }
1541
1542         for (i = 0; i < ncheck; i++)
1543         {
1544                 qual = estate->es_result_relation_constraints[i];
1545
1546                 res = ExecQual(qual, econtext);
1547
1548                 if (!res)
1549                         return check[i].ccname;
1550         }
1551
1552         pfree(slot);
1553         pfree(rte->relname);
1554         pfree(rte);
1555         pfree(rtlist);
1556         pfree(econtext);
1557
1558         return (char *) NULL;
1559
1560 }
1561
1562 void
1563 ExecConstraints(char *caller, Relation rel, HeapTuple tuple, EState *estate)
1564 {
1565
1566         Assert(rel->rd_att->constr);
1567
1568         if (rel->rd_att->constr->has_not_null)
1569         {
1570                 int                     attrChk;
1571
1572                 for (attrChk = 1; attrChk <= rel->rd_att->natts; attrChk++)
1573                 {
1574                         if (rel->rd_att->attrs[attrChk - 1]->attnotnull && heap_attisnull(tuple, attrChk))
1575                                 elog(ERROR, "%s: Fail to add null value in not null attribute %s",
1576                                   caller, rel->rd_att->attrs[attrChk - 1]->attname.data);
1577                 }
1578         }
1579
1580         if (rel->rd_att->constr->num_check > 0)
1581         {
1582                 char       *failed;
1583
1584                 if ((failed = ExecRelCheck(rel, tuple, estate)) != NULL)
1585                         elog(ERROR, "%s: rejected due to CHECK constraint %s", caller, failed);
1586         }
1587
1588         return;
1589 }
1590
1591 TupleTableSlot *
1592 EvalPlanQual(EState *estate, Index rti, ItemPointer tid)
1593 {
1594         evalPlanQual *epq = (evalPlanQual *) estate->es_evalPlanQual;
1595         evalPlanQual *oldepq;
1596         EState     *epqstate = NULL;
1597         Relation        relation;
1598         Buffer          buffer;
1599         HeapTupleData tuple;
1600         bool            endNode = true;
1601
1602         Assert(rti != 0);
1603
1604         if (epq != NULL && epq->rti == 0)
1605         {
1606                 Assert(!(estate->es_useEvalPlan) &&
1607                            epq->estate.es_evalPlanQual == NULL);
1608                 epq->rti = rti;
1609                 endNode = false;
1610         }
1611
1612         /*
1613          * If this is request for another RTE - Ra, - then we have to check
1614          * wasn't PlanQual requested for Ra already and if so then Ra' row was
1615          * updated again and we have to re-start old execution for Ra and
1616          * forget all what we done after Ra was suspended. Cool? -:))
1617          */
1618         if (epq != NULL && epq->rti != rti &&
1619                 epq->estate.es_evTuple[rti - 1] != NULL)
1620         {
1621                 do
1622                 {
1623                         /* pop previous PlanQual from the stack */
1624                         epqstate = &(epq->estate);
1625                         oldepq = (evalPlanQual *) epqstate->es_evalPlanQual;
1626                         Assert(oldepq->rti != 0);
1627                         /* stop execution */
1628                         ExecEndNode(epq->plan, epq->plan);
1629                     epqstate->es_tupleTable->next = 0;
1630                         pfree(epqstate->es_evTuple[epq->rti - 1]);
1631                         epqstate->es_evTuple[epq->rti - 1] = NULL;
1632                         /* push current PQ to freePQ stack */
1633                         oldepq->free = epq;
1634                         epq = oldepq;
1635                 } while (epq->rti != rti);
1636                 estate->es_evalPlanQual = (Pointer) epq;
1637         }
1638
1639         /*
1640          * If we are requested for another RTE then we have to suspend
1641          * execution of current PlanQual and start execution for new one.
1642          */
1643         if (epq == NULL || epq->rti != rti)
1644         {
1645                 /* try to reuse plan used previously */
1646                 evalPlanQual *newepq = (epq != NULL) ? epq->free : NULL;
1647
1648                 if (newepq == NULL)             /* first call or freePQ stack is empty */
1649                 {
1650                         newepq = (evalPlanQual *) palloc(sizeof(evalPlanQual));
1651                         /* Init EState */
1652                         epqstate = &(newepq->estate);
1653                         memset(epqstate, 0, sizeof(EState));
1654                         epqstate->type = T_EState;
1655                         epqstate->es_direction = ForwardScanDirection;
1656                         epqstate->es_snapshot = estate->es_snapshot;
1657                         epqstate->es_range_table = estate->es_range_table;
1658                         epqstate->es_param_list_info = estate->es_param_list_info;
1659                         if (estate->es_origPlan->nParamExec > 0)
1660                                 epqstate->es_param_exec_vals = (ParamExecData *)
1661                                         palloc(estate->es_origPlan->nParamExec *
1662                                                    sizeof(ParamExecData));
1663                         epqstate->es_tupleTable =
1664                                 ExecCreateTupleTable(estate->es_tupleTable->size);
1665                         /* ... rest */
1666                         newepq->plan = copyObject(estate->es_origPlan);
1667                         newepq->free = NULL;
1668                         epqstate->es_evTupleNull = (bool *)
1669                                 palloc(length(estate->es_range_table) * sizeof(bool));
1670                         if (epq == NULL)        /* first call */
1671                         {
1672                                 epqstate->es_evTuple = (HeapTuple *)
1673                                         palloc(length(estate->es_range_table) * sizeof(HeapTuple));
1674                                 memset(epqstate->es_evTuple, 0,
1675                                          length(estate->es_range_table) * sizeof(HeapTuple));
1676                         }
1677                         else
1678                                 epqstate->es_evTuple = epq->estate.es_evTuple;
1679                 }
1680                 else
1681                         epqstate = &(newepq->estate);
1682                 /* push current PQ to the stack */
1683                 epqstate->es_evalPlanQual = (Pointer) epq;
1684                 epq = newepq;
1685                 estate->es_evalPlanQual = (Pointer) epq;
1686                 epq->rti = rti;
1687                 endNode = false;
1688         }
1689
1690         epqstate = &(epq->estate);
1691
1692         /*
1693          * Ok - we're requested for the same RTE (-:)). I'm not sure about
1694          * ability to use ExecReScan instead of ExecInitNode, so...
1695          */
1696         if (endNode)
1697         {
1698                 ExecEndNode(epq->plan, epq->plan);
1699             epqstate->es_tupleTable->next = 0;
1700         }
1701
1702         /* free old RTE' tuple */
1703         if (epqstate->es_evTuple[epq->rti - 1] != NULL)
1704         {
1705                 pfree(epqstate->es_evTuple[epq->rti - 1]);
1706                 epqstate->es_evTuple[epq->rti - 1] = NULL;
1707         }
1708
1709         /* ** fetch tid tuple ** */
1710         if (estate->es_result_relation_info != NULL &&
1711                 estate->es_result_relation_info->ri_RangeTableIndex == rti)
1712                 relation = estate->es_result_relation_info->ri_RelationDesc;
1713         else
1714         {
1715                 List       *l;
1716
1717                 foreach(l, estate->es_rowMark)
1718                 {
1719                         if (((execRowMark *) lfirst(l))->rti == rti)
1720                                 break;
1721                 }
1722                 relation = ((execRowMark *) lfirst(l))->relation;
1723         }
1724         tuple.t_self = *tid;
1725         for (;;)
1726         {
1727                 heap_fetch(relation, SnapshotDirty, &tuple, &buffer);
1728                 if (tuple.t_data != NULL)
1729                 {
1730                         TransactionId xwait = SnapshotDirty->xmax;
1731
1732                         if (TransactionIdIsValid(SnapshotDirty->xmin))
1733                         {
1734                                 elog(NOTICE, "EvalPlanQual: t_xmin is uncommitted ?!");
1735                                 Assert(!TransactionIdIsValid(SnapshotDirty->xmin));
1736                                 elog(ERROR, "Aborting this transaction");
1737                         }
1738
1739                         /*
1740                          * If tuple is being updated by other transaction then we have
1741                          * to wait for its commit/abort.
1742                          */
1743                         if (TransactionIdIsValid(xwait))
1744                         {
1745                                 ReleaseBuffer(buffer);
1746                                 XactLockTableWait(xwait);
1747                                 continue;
1748                         }
1749
1750                         /*
1751                          * Nice! We got tuple - now copy it.
1752                          */
1753                         if (epqstate->es_evTuple[epq->rti - 1] != NULL)
1754                                 pfree(epqstate->es_evTuple[epq->rti - 1]);
1755                         epqstate->es_evTuple[epq->rti - 1] = heap_copytuple(&tuple);
1756                         ReleaseBuffer(buffer);
1757                         break;
1758                 }
1759
1760                 /*
1761                  * Ops! Invalid tuple. Have to check is it updated or deleted.
1762                  * Note that it's possible to get invalid SnapshotDirty->tid if
1763                  * tuple updated by this transaction. Have we to check this ?
1764                  */
1765                 if (ItemPointerIsValid(&(SnapshotDirty->tid)) &&
1766                         !(ItemPointerEquals(&(tuple.t_self), &(SnapshotDirty->tid))))
1767                 {
1768                         tuple.t_self = SnapshotDirty->tid;      /* updated ... */
1769                         continue;
1770                 }
1771
1772                 /*
1773                  * Deleted or updated by this transaction. Do not (re-)start
1774                  * execution of this PQ. Continue previous PQ.
1775                  */
1776                 oldepq = (evalPlanQual *) epqstate->es_evalPlanQual;
1777                 if (oldepq != NULL)
1778                 {
1779                         Assert(oldepq->rti != 0);
1780                         /* push current PQ to freePQ stack */
1781                         oldepq->free = epq;
1782                         epq = oldepq;
1783                         epqstate = &(epq->estate);
1784                         estate->es_evalPlanQual = (Pointer) epq;
1785                 }
1786                 else
1787                 {                                                                       
1788                         epq->rti = 0;                                   /* this is the first (oldest) */
1789                         estate->es_useEvalPlan = false; /* PQ - mark as free and      */
1790                         return (NULL);                                  /* continue Query execution   */
1791                 }
1792         }
1793
1794         if (estate->es_origPlan->nParamExec > 0)
1795                 memset(epqstate->es_param_exec_vals, 0,
1796                            estate->es_origPlan->nParamExec * sizeof(ParamExecData));
1797         memset(epqstate->es_evTupleNull, false,
1798                    length(estate->es_range_table) * sizeof(bool));
1799     Assert(epqstate->es_tupleTable->next == 0);
1800         ExecInitNode(epq->plan, epqstate, NULL);
1801
1802         /*
1803          * For UPDATE/DELETE we have to return tid of actual row we're
1804          * executing PQ for.
1805          */
1806         *tid = tuple.t_self;
1807
1808         return (EvalPlanQualNext(estate));
1809 }
1810
1811 static TupleTableSlot *
1812 EvalPlanQualNext(EState *estate)
1813 {
1814         evalPlanQual *epq = (evalPlanQual *) estate->es_evalPlanQual;
1815         EState     *epqstate = &(epq->estate);
1816         evalPlanQual *oldepq;
1817         TupleTableSlot *slot;
1818
1819         Assert(epq->rti != 0);
1820
1821 lpqnext:;
1822         slot = ExecProcNode(epq->plan, epq->plan);
1823
1824         /*
1825          * No more tuples for this PQ. Continue previous one.
1826          */
1827         if (TupIsNull(slot))
1828         {
1829                 ExecEndNode(epq->plan, epq->plan);
1830             epqstate->es_tupleTable->next = 0;
1831                 pfree(epqstate->es_evTuple[epq->rti - 1]);
1832                 epqstate->es_evTuple[epq->rti - 1] = NULL;
1833                 /* pop old PQ from the stack */
1834                 oldepq = (evalPlanQual *) epqstate->es_evalPlanQual;
1835                 if (oldepq == (evalPlanQual *) NULL)
1836                 {
1837                         epq->rti = 0;                                   /* this is the first (oldest) */
1838                         estate->es_useEvalPlan = false; /* PQ - mark as free and          */
1839                         return (NULL);                                  /* continue Query execution   */
1840                 }
1841                 Assert(oldepq->rti != 0);
1842                 /* push current PQ to freePQ stack */
1843                 oldepq->free = epq;
1844                 epq = oldepq;
1845                 epqstate = &(epq->estate);
1846                 estate->es_evalPlanQual = (Pointer) epq;
1847                 goto lpqnext;
1848         }
1849
1850         return (slot);
1851 }