]> granicus.if.org Git - postgresql/blob - src/backend/executor/execQual.c
Fix comments that were mis-wrapped, for Tom Lane.
[postgresql] / src / backend / executor / execQual.c
1 /*-------------------------------------------------------------------------
2  *
3  * execQual.c
4  *        Routines to evaluate qualification and targetlist expressions
5  *
6  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.85 2001/03/23 04:49:53 momjian Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 /*
16  *       INTERFACE ROUTINES
17  *              ExecEvalExpr    - evaluate an expression and return a datum
18  *              ExecEvalExprSwitchContext - same, but switch into eval memory context
19  *              ExecQual                - return true/false if qualification is satisfied
20  *              ExecProject             - form a new tuple by projecting the given tuple
21  *
22  *       NOTES
23  *              ExecEvalExpr() and ExecEvalVar() are hotspots.  making these faster
24  *              will speed up the entire system.  Unfortunately they are currently
25  *              implemented recursively.  Eliminating the recursion is bound to
26  *              improve the speed of the executor.
27  *
28  *              ExecProject() is used to make tuple projections.  Rather then
29  *              trying to speed it up, the execution plan should be pre-processed
30  *              to facilitate attribute sharing between nodes wherever possible,
31  *              instead of doing needless copying.      -cim 5/31/91
32  *
33  */
34
35 #include "postgres.h"
36
37 #include "access/heapam.h"
38 #include "executor/execFlatten.h"
39 #include "executor/execdebug.h"
40 #include "executor/functions.h"
41 #include "executor/nodeSubplan.h"
42 #include "utils/array.h"
43 #include "utils/builtins.h"
44 #include "utils/fcache.h"
45
46
47 /* static function decls */
48 static Datum ExecEvalAggref(Aggref *aggref, ExprContext *econtext,
49                            bool *isNull);
50 static Datum ExecEvalArrayRef(ArrayRef *arrayRef, ExprContext *econtext,
51                                  bool *isNull, ExprDoneCond *isDone);
52 static Datum ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull);
53 static Datum ExecEvalOper(Expr *opClause, ExprContext *econtext,
54                          bool *isNull, ExprDoneCond *isDone);
55 static Datum ExecEvalFunc(Expr *funcClause, ExprContext *econtext,
56                          bool *isNull, ExprDoneCond *isDone);
57 static ExprDoneCond ExecEvalFuncArgs(FunctionCachePtr fcache,
58                                  List *argList,
59                                  ExprContext *econtext);
60 static Datum ExecEvalNot(Expr *notclause, ExprContext *econtext, bool *isNull);
61 static Datum ExecEvalAnd(Expr *andExpr, ExprContext *econtext, bool *isNull);
62 static Datum ExecEvalOr(Expr *orExpr, ExprContext *econtext, bool *isNull);
63 static Datum ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext,
64                          bool *isNull, ExprDoneCond *isDone);
65
66
67 /*----------
68  *        ExecEvalArrayRef
69  *
70  *         This function takes an ArrayRef and returns the extracted Datum
71  *         if it's a simple reference, or the modified array value if it's
72  *         an array assignment (i.e., array element or slice insertion).
73  *
74  * NOTE: if we get a NULL result from a subexpression, we return NULL when
75  * it's an array reference, or the unmodified source array when it's an
76  * array assignment.  This may seem peculiar, but if we return NULL (as was
77  * done in versions up through 7.0) then an assignment like
78  *                      UPDATE table SET arrayfield[4] = NULL
79  * will result in setting the whole array to NULL, which is certainly not
80  * very desirable.      By returning the source array we make the assignment
81  * into a no-op, instead.  (Eventually we need to redesign arrays so that
82  * individual elements can be NULL, but for now, let's try to protect users
83  * from shooting themselves in the foot.)
84  *
85  * NOTE: we deliberately refrain from applying DatumGetArrayTypeP() here,
86  * even though that might seem natural, because this code needs to support
87  * both varlena arrays and fixed-length array types.  DatumGetArrayTypeP()
88  * only works for the varlena kind.  The routines we call in arrayfuncs.c
89  * have to know the difference (that's what they need refattrlength for).
90  *----------
91  */
92 static Datum
93 ExecEvalArrayRef(ArrayRef *arrayRef,
94                                  ExprContext *econtext,
95                                  bool *isNull,
96                                  ExprDoneCond *isDone)
97 {
98         ArrayType  *array_source;
99         ArrayType  *resultArray;
100         bool            isAssignment = (arrayRef->refassgnexpr != NULL);
101         List       *elt;
102         int                     i = 0,
103                                 j = 0;
104         IntArray        upper,
105                                 lower;
106         int                *lIndex;
107
108         if (arrayRef->refexpr != NULL)
109         {
110                 array_source = (ArrayType *)
111                         DatumGetPointer(ExecEvalExpr(arrayRef->refexpr,
112                                                                                  econtext,
113                                                                                  isNull,
114                                                                                  isDone));
115
116                 /*
117                  * If refexpr yields NULL, result is always NULL, for now anyway.
118                  * (This means you cannot assign to an element or slice of an
119                  * array that's NULL; it'll just stay NULL.)
120                  */
121                 if (*isNull)
122                         return (Datum) NULL;
123         }
124         else
125         {
126
127                 /*
128                  * Empty refexpr indicates we are doing an INSERT into an array
129                  * column. For now, we just take the refassgnexpr (which the
130                  * parser will have ensured is an array value) and return it
131                  * as-is, ignoring any subscripts that may have been supplied in
132                  * the INSERT column list. This is a kluge, but it's not real
133                  * clear what the semantics ought to be...
134                  */
135                 array_source = NULL;
136         }
137
138         foreach(elt, arrayRef->refupperindexpr)
139         {
140                 if (i >= MAXDIM)
141                         elog(ERROR, "ExecEvalArrayRef: can only handle %d dimensions",
142                                  MAXDIM);
143
144                 upper.indx[i++] = DatumGetInt32(ExecEvalExpr((Node *) lfirst(elt),
145                                                                                                          econtext,
146                                                                                                          isNull,
147                                                                                                          NULL));
148                 /* If any index expr yields NULL, result is NULL or source array */
149                 if (*isNull)
150                 {
151                         if (!isAssignment || array_source == NULL)
152                                 return (Datum) NULL;
153                         *isNull = false;
154                         return PointerGetDatum(array_source);
155                 }
156         }
157
158         if (arrayRef->reflowerindexpr != NIL)
159         {
160                 foreach(elt, arrayRef->reflowerindexpr)
161                 {
162                         if (j >= MAXDIM)
163                                 elog(ERROR, "ExecEvalArrayRef: can only handle %d dimensions",
164                                          MAXDIM);
165
166                         lower.indx[j++] = DatumGetInt32(ExecEvalExpr((Node *) lfirst(elt),
167                                                                                                                  econtext,
168                                                                                                                  isNull,
169                                                                                                                  NULL));
170
171                         /*
172                          * If any index expr yields NULL, result is NULL or source
173                          * array
174                          */
175                         if (*isNull)
176                         {
177                                 if (!isAssignment || array_source == NULL)
178                                         return (Datum) NULL;
179                                 *isNull = false;
180                                 return PointerGetDatum(array_source);
181                         }
182                 }
183                 if (i != j)
184                         elog(ERROR,
185                                  "ExecEvalArrayRef: upper and lower indices mismatch");
186                 lIndex = lower.indx;
187         }
188         else
189                 lIndex = NULL;
190
191         if (isAssignment)
192         {
193                 Datum           sourceData = ExecEvalExpr(arrayRef->refassgnexpr,
194                                                                                           econtext,
195                                                                                           isNull,
196                                                                                           NULL);
197
198                 /*
199                  * For now, can't cope with inserting NULL into an array, so make
200                  * it a no-op per discussion above...
201                  */
202                 if (*isNull)
203                 {
204                         if (array_source == NULL)
205                                 return (Datum) NULL;
206                         *isNull = false;
207                         return PointerGetDatum(array_source);
208                 }
209
210                 if (array_source == NULL)
211                         return sourceData;      /* XXX do something else? */
212
213                 if (lIndex == NULL)
214                         resultArray = array_set(array_source, i,
215                                                                         upper.indx,
216                                                                         sourceData,
217                                                                         arrayRef->refelembyval,
218                                                                         arrayRef->refelemlength,
219                                                                         arrayRef->refattrlength,
220                                                                         isNull);
221                 else
222                         resultArray = array_set_slice(array_source, i,
223                                                                                   upper.indx, lower.indx,
224                                                            (ArrayType *) DatumGetPointer(sourceData),
225                                                                                   arrayRef->refelembyval,
226                                                                                   arrayRef->refelemlength,
227                                                                                   arrayRef->refattrlength,
228                                                                                   isNull);
229                 return PointerGetDatum(resultArray);
230         }
231
232         if (lIndex == NULL)
233                 return array_ref(array_source, i,
234                                                  upper.indx,
235                                                  arrayRef->refelembyval,
236                                                  arrayRef->refelemlength,
237                                                  arrayRef->refattrlength,
238                                                  isNull);
239         else
240         {
241                 resultArray = array_get_slice(array_source, i,
242                                                                           upper.indx, lower.indx,
243                                                                           arrayRef->refelembyval,
244                                                                           arrayRef->refelemlength,
245                                                                           arrayRef->refattrlength,
246                                                                           isNull);
247                 return PointerGetDatum(resultArray);
248         }
249 }
250
251
252 /* ----------------------------------------------------------------
253  *              ExecEvalAggref
254  *
255  *              Returns a Datum whose value is the value of the precomputed
256  *              aggregate found in the given expression context.
257  * ----------------------------------------------------------------
258  */
259 static Datum
260 ExecEvalAggref(Aggref *aggref, ExprContext *econtext, bool *isNull)
261 {
262         if (econtext->ecxt_aggvalues == NULL)           /* safety check */
263                 elog(ERROR, "ExecEvalAggref: no aggregates in this expression context");
264
265         *isNull = econtext->ecxt_aggnulls[aggref->aggno];
266         return econtext->ecxt_aggvalues[aggref->aggno];
267 }
268
269 /* ----------------------------------------------------------------
270  *              ExecEvalVar
271  *
272  *              Returns a Datum whose value is the value of a range
273  *              variable with respect to given expression context.
274  *
275  *
276  *              As an entry condition, we expect that the datatype the
277  *              plan expects to get (as told by our "variable" argument) is in
278  *              fact the datatype of the attribute the plan says to fetch (as
279  *              seen in the current context, identified by our "econtext"
280  *              argument).
281  *
282  *              If we fetch a Type A attribute and Caller treats it as if it
283  *              were Type B, there will be undefined results (e.g. crash).
284  *              One way these might mismatch now is that we're accessing a
285  *              catalog class and the type information in the pg_attribute
286  *              class does not match the hardcoded pg_attribute information
287  *              (in pg_attribute.h) for the class in question.
288  *
289  *              We have an Assert to make sure this entry condition is met.
290  *
291  * ---------------------------------------------------------------- */
292 static Datum
293 ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull)
294 {
295         Datum           result;
296         TupleTableSlot *slot;
297         AttrNumber      attnum;
298         HeapTuple       heapTuple;
299         TupleDesc       tuple_type;
300
301         /*
302          * get the slot we want
303          */
304         switch (variable->varno)
305         {
306                 case INNER:                             /* get the tuple from the inner node */
307                         slot = econtext->ecxt_innertuple;
308                         break;
309
310                 case OUTER:                             /* get the tuple from the outer node */
311                         slot = econtext->ecxt_outertuple;
312                         break;
313
314                 default:                                /* get the tuple from the relation being
315                                                                  * scanned */
316                         slot = econtext->ecxt_scantuple;
317                         break;
318         }
319
320         /*
321          * extract tuple information from the slot
322          */
323         heapTuple = slot->val;
324         tuple_type = slot->ttc_tupleDescriptor;
325
326         attnum = variable->varattno;
327
328         /* (See prolog for explanation of this Assert) */
329         Assert(attnum <= 0 ||
330                    (attnum - 1 <= tuple_type->natts - 1 &&
331                         tuple_type->attrs[attnum - 1] != NULL &&
332                   variable->vartype == tuple_type->attrs[attnum - 1]->atttypid));
333
334         /*
335          * If the attribute number is invalid, then we are supposed to return
336          * the entire tuple, we give back a whole slot so that callers know
337          * what the tuple looks like.  XXX why copy?  Couldn't we just give
338          * back the existing slot?
339          */
340         if (attnum == InvalidAttrNumber)
341         {
342                 TupleTableSlot *tempSlot = MakeTupleTableSlot();
343                 TupleDesc       td;
344                 HeapTuple       tup;
345
346                 tup = heap_copytuple(heapTuple);
347                 td = CreateTupleDescCopy(tuple_type);
348
349                 ExecSetSlotDescriptor(tempSlot, td, true);
350                 ExecStoreTuple(tup, tempSlot, InvalidBuffer, true);
351                 return PointerGetDatum(tempSlot);
352         }
353
354         result = heap_getattr(heapTuple,        /* tuple containing attribute */
355                                                   attnum,               /* attribute number of desired
356                                                                                  * attribute */
357                                                   tuple_type,   /* tuple descriptor of tuple */
358                                                   isNull);              /* return: is attribute null? */
359
360         return result;
361 }
362
363 /* ----------------------------------------------------------------
364  *              ExecEvalParam
365  *
366  *              Returns the value of a parameter.  A param node contains
367  *              something like ($.name) and the expression context contains
368  *              the current parameter bindings (name = "sam") (age = 34)...
369  *              so our job is to replace the param node with the datum
370  *              containing the appropriate information ("sam").
371  *
372  *              Q: if we have a parameter ($.foo) without a binding, i.e.
373  *                 there is no (foo = xxx) in the parameter list info,
374  *                 is this a fatal error or should this be a "not available"
375  *                 (in which case we shoud return a Const node with the
376  *                      isnull flag) ?  -cim 10/13/89
377  *
378  *              Minor modification: Param nodes now have an extra field,
379  *              `paramkind' which specifies the type of parameter
380  *              (see params.h). So while searching the paramList for
381  *              a paramname/value pair, we have also to check for `kind'.
382  *
383  *              NOTE: The last entry in `paramList' is always an
384  *              entry with kind == PARAM_INVALID.
385  * ----------------------------------------------------------------
386  */
387 Datum
388 ExecEvalParam(Param *expression, ExprContext *econtext, bool *isNull)
389 {
390         char       *thisParameterName;
391         int                     thisParameterKind = expression->paramkind;
392         AttrNumber      thisParameterId = expression->paramid;
393         int                     matchFound;
394         ParamListInfo paramList;
395
396         if (thisParameterKind == PARAM_EXEC)
397         {
398                 ParamExecData *prm;
399
400                 prm = &(econtext->ecxt_param_exec_vals[thisParameterId]);
401                 if (prm->execPlan != NULL)
402                 {
403                         ExecSetParamPlan(prm->execPlan, econtext);
404                         /* ExecSetParamPlan should have processed this param... */
405                         Assert(prm->execPlan == NULL);
406                 }
407                 *isNull = prm->isnull;
408                 return prm->value;
409         }
410
411         thisParameterName = expression->paramname;
412         paramList = econtext->ecxt_param_list_info;
413
414         *isNull = false;
415
416         /*
417          * search the list with the parameter info to find a matching name. An
418          * entry with an InvalidName denotes the last element in the array.
419          */
420         matchFound = 0;
421         if (paramList != NULL)
422         {
423
424                 /*
425                  * search for an entry in 'paramList' that matches the
426                  * `expression'.
427                  */
428                 while (paramList->kind != PARAM_INVALID && !matchFound)
429                 {
430                         switch (thisParameterKind)
431                         {
432                                 case PARAM_NAMED:
433                                         if (thisParameterKind == paramList->kind &&
434                                                 strcmp(paramList->name, thisParameterName) == 0)
435                                                 matchFound = 1;
436                                         break;
437                                 case PARAM_NUM:
438                                         if (thisParameterKind == paramList->kind &&
439                                                 paramList->id == thisParameterId)
440                                                 matchFound = 1;
441                                         break;
442                                 case PARAM_OLD:
443                                 case PARAM_NEW:
444                                         if (thisParameterKind == paramList->kind &&
445                                                 paramList->id == thisParameterId)
446                                         {
447                                                 matchFound = 1;
448
449                                                 /*
450                                                  * sanity check
451                                                  */
452                                                 if (strcmp(paramList->name, thisParameterName) != 0)
453                                                 {
454                                                         elog(ERROR,
455                                                                  "ExecEvalParam: new/old params with same id & diff names");
456                                                 }
457                                         }
458                                         break;
459                                 default:
460
461                                         /*
462                                          * oops! this is not supposed to happen!
463                                          */
464                                         elog(ERROR, "ExecEvalParam: invalid paramkind %d",
465                                                  thisParameterKind);
466                         }
467                         if (!matchFound)
468                                 paramList++;
469                 }                                               /* while */
470         }                                                       /* if */
471
472         if (!matchFound)
473         {
474
475                 /*
476                  * ooops! we couldn't find this parameter in the parameter list.
477                  * Signal an error
478                  */
479                 elog(ERROR, "ExecEvalParam: Unknown value for parameter %s",
480                          thisParameterName);
481         }
482
483         /*
484          * return the value.
485          */
486         *isNull = paramList->isnull;
487         return paramList->value;
488 }
489
490
491 /* ----------------------------------------------------------------
492  *              ExecEvalOper / ExecEvalFunc support routines
493  * ----------------------------------------------------------------
494  */
495
496 /*
497  *              GetAttributeByName
498  *              GetAttributeByNum
499  *
500  *              These are functions which return the value of the
501  *              named attribute out of the tuple from the arg slot.  User defined
502  *              C functions which take a tuple as an argument are expected
503  *              to use this.  Ex: overpaid(EMP) might call GetAttributeByNum().
504  */
505 Datum
506 GetAttributeByNum(TupleTableSlot *slot,
507                                   AttrNumber attrno,
508                                   bool *isNull)
509 {
510         Datum           retval;
511
512         if (!AttributeNumberIsValid(attrno))
513                 elog(ERROR, "GetAttributeByNum: Invalid attribute number");
514
515         if (!AttrNumberIsForUserDefinedAttr(attrno))
516                 elog(ERROR, "GetAttributeByNum: cannot access system attributes here");
517
518         if (isNull == (bool *) NULL)
519                 elog(ERROR, "GetAttributeByNum: a NULL isNull flag was passed");
520
521         if (TupIsNull(slot))
522         {
523                 *isNull = true;
524                 return (Datum) 0;
525         }
526
527         retval = heap_getattr(slot->val,
528                                                   attrno,
529                                                   slot->ttc_tupleDescriptor,
530                                                   isNull);
531         if (*isNull)
532                 return (Datum) 0;
533
534         return retval;
535 }
536
537 Datum
538 GetAttributeByName(TupleTableSlot *slot, char *attname, bool *isNull)
539 {
540         AttrNumber      attrno;
541         TupleDesc       tupdesc;
542         Datum           retval;
543         int                     natts;
544         int                     i;
545
546         if (attname == NULL)
547                 elog(ERROR, "GetAttributeByName: Invalid attribute name");
548
549         if (isNull == (bool *) NULL)
550                 elog(ERROR, "GetAttributeByName: a NULL isNull flag was passed");
551
552         if (TupIsNull(slot))
553         {
554                 *isNull = true;
555                 return (Datum) 0;
556         }
557
558         tupdesc = slot->ttc_tupleDescriptor;
559         natts = slot->val->t_data->t_natts;
560
561         attrno = InvalidAttrNumber;
562         for (i = 0; i < tupdesc->natts; i++)
563         {
564                 if (namestrcmp(&(tupdesc->attrs[i]->attname), attname) == 0)
565                 {
566                         attrno = tupdesc->attrs[i]->attnum;
567                         break;
568                 }
569         }
570
571         if (attrno == InvalidAttrNumber)
572                 elog(ERROR, "GetAttributeByName: attribute %s not found", attname);
573
574         retval = heap_getattr(slot->val,
575                                                   attrno,
576                                                   tupdesc,
577                                                   isNull);
578         if (*isNull)
579                 return (Datum) 0;
580
581         return retval;
582 }
583
584 /*
585  * Evaluate arguments for a function.
586  */
587 static ExprDoneCond
588 ExecEvalFuncArgs(FunctionCachePtr fcache,
589                                  List *argList,
590                                  ExprContext *econtext)
591 {
592         ExprDoneCond argIsDone;
593         int                     i;
594         List       *arg;
595
596         argIsDone = ExprSingleResult;           /* default assumption */
597
598         i = 0;
599         foreach(arg, argList)
600         {
601                 ExprDoneCond thisArgIsDone;
602
603                 fcache->fcinfo.arg[i] = ExecEvalExpr((Node *) lfirst(arg),
604                                                                                          econtext,
605                                                                                          &fcache->fcinfo.argnull[i],
606                                                                                          &thisArgIsDone);
607
608                 if (thisArgIsDone != ExprSingleResult)
609                 {
610
611                         /*
612                          * We allow only one argument to have a set value; we'd need
613                          * much more complexity to keep track of multiple set
614                          * arguments (cf. ExecTargetList) and it doesn't seem worth
615                          * it.
616                          */
617                         if (argIsDone != ExprSingleResult)
618                                 elog(ERROR, "Functions and operators can take only one set argument");
619                         fcache->hasSetArg = true;
620                         argIsDone = thisArgIsDone;
621                 }
622                 i++;
623         }
624
625         return argIsDone;
626 }
627
628 /*
629  *              ExecMakeFunctionResult
630  *
631  * Evaluate the arguments to a function and then the function itself.
632  *
633  * NOTE: econtext is used only for evaluating the argument expressions;
634  * it is not passed to the function itself.
635  */
636 Datum
637 ExecMakeFunctionResult(FunctionCachePtr fcache,
638                                            List *arguments,
639                                            ExprContext *econtext,
640                                            bool *isNull,
641                                            ExprDoneCond *isDone)
642 {
643         Datum           result;
644         ExprDoneCond argDone;
645         int                     i;
646
647         /*
648          * arguments is a list of expressions to evaluate before passing to
649          * the function manager.  We skip the evaluation if it was already
650          * done in the previous call (ie, we are continuing the evaluation of
651          * a set-valued function).      Otherwise, collect the current argument
652          * values into fcache->fcinfo.
653          */
654         if (fcache->fcinfo.nargs > 0 && !fcache->argsValid)
655         {
656                 argDone = ExecEvalFuncArgs(fcache, arguments, econtext);
657                 if (argDone == ExprEndResult)
658                 {
659                         /* input is an empty set, so return an empty set. */
660                         *isNull = true;
661                         if (isDone)
662                                 *isDone = ExprEndResult;
663                         else
664                                 elog(ERROR, "Set-valued function called in context that cannot accept a set");
665                         return (Datum) 0;
666                 }
667         }
668
669         /*
670          * now return the value gotten by calling the function manager,
671          * passing the function the evaluated parameter values.
672          */
673         if (fcache->func.fn_retset || fcache->hasSetArg)
674         {
675
676                 /*
677                  * We need to return a set result.      Complain if caller not ready
678                  * to accept one.
679                  */
680                 if (isDone == NULL)
681                         elog(ERROR, "Set-valued function called in context that cannot accept a set");
682
683                 /*
684                  * This loop handles the situation where we have both a set
685                  * argument and a set-valued function.  Once we have exhausted the
686                  * function's value(s) for a particular argument value, we have to
687                  * get the next argument value and start the function over again.
688                  * We might have to do it more than once, if the function produces
689                  * an empty result set for a particular input value.
690                  */
691                 for (;;)
692                 {
693
694                         /*
695                          * If function is strict, and there are any NULL arguments,
696                          * skip calling the function (at least for this set of args).
697                          */
698                         bool            callit = true;
699
700                         if (fcache->func.fn_strict)
701                         {
702                                 for (i = 0; i < fcache->fcinfo.nargs; i++)
703                                 {
704                                         if (fcache->fcinfo.argnull[i])
705                                         {
706                                                 callit = false;
707                                                 break;
708                                         }
709                                 }
710                         }
711
712                         if (callit)
713                         {
714                                 fcache->fcinfo.isnull = false;
715                                 fcache->rsinfo.isDone = ExprSingleResult;
716                                 result = FunctionCallInvoke(&fcache->fcinfo);
717                                 *isNull = fcache->fcinfo.isnull;
718                                 *isDone = fcache->rsinfo.isDone;
719                         }
720                         else
721                         {
722                                 result = (Datum) 0;
723                                 *isNull = true;
724                                 *isDone = ExprEndResult;
725                         }
726
727                         if (*isDone != ExprEndResult)
728                         {
729
730                                 /*
731                                  * Got a result from current argument.  If function itself
732                                  * returns set, flag that we want to reuse current
733                                  * argument values on next call.
734                                  */
735                                 if (fcache->func.fn_retset)
736                                         fcache->argsValid = true;
737
738                                 /*
739                                  * Make sure we say we are returning a set, even if the
740                                  * function itself doesn't return sets.
741                                  */
742                                 *isDone = ExprMultipleResult;
743                                 break;
744                         }
745
746                         /* Else, done with this argument */
747                         fcache->argsValid = false;
748
749                         if (!fcache->hasSetArg)
750                                 break;                  /* input not a set, so done */
751
752                         /* Re-eval args to get the next element of the input set */
753                         argDone = ExecEvalFuncArgs(fcache, arguments, econtext);
754
755                         if (argDone != ExprMultipleResult)
756                         {
757
758                                 /*
759                                  * End of arguments, so reset the hasSetArg flag and say
760                                  * "Done"
761                                  */
762                                 fcache->hasSetArg = false;
763                                 *isNull = true;
764                                 *isDone = ExprEndResult;
765                                 result = (Datum) 0;
766                                 break;
767                         }
768
769                         /*
770                          * If we reach here, loop around to run the function on the
771                          * new argument.
772                          */
773                 }
774         }
775         else
776         {
777
778                 /*
779                  * Non-set case: much easier.
780                  *
781                  * If function is strict, and there are any NULL arguments, skip
782                  * calling the function and return NULL.
783                  */
784                 if (fcache->func.fn_strict)
785                 {
786                         for (i = 0; i < fcache->fcinfo.nargs; i++)
787                         {
788                                 if (fcache->fcinfo.argnull[i])
789                                 {
790                                         *isNull = true;
791                                         return (Datum) 0;
792                                 }
793                         }
794                 }
795                 fcache->fcinfo.isnull = false;
796                 result = FunctionCallInvoke(&fcache->fcinfo);
797                 *isNull = fcache->fcinfo.isnull;
798         }
799
800         return result;
801 }
802
803
804 /* ----------------------------------------------------------------
805  *              ExecEvalOper
806  *              ExecEvalFunc
807  *
808  *              Evaluate the functional result of a list of arguments by calling the
809  *              function manager.
810  * ----------------------------------------------------------------
811  */
812
813 /* ----------------------------------------------------------------
814  *              ExecEvalOper
815  * ----------------------------------------------------------------
816  */
817 static Datum
818 ExecEvalOper(Expr *opClause,
819                          ExprContext *econtext,
820                          bool *isNull,
821                          ExprDoneCond *isDone)
822 {
823         Oper       *op;
824         List       *argList;
825         FunctionCachePtr fcache;
826
827         /*
828          * we extract the oid of the function associated with the op and then
829          * pass the work onto ExecMakeFunctionResult which evaluates the
830          * arguments and returns the result of calling the function on the
831          * evaluated arguments.
832          */
833         op = (Oper *) opClause->oper;
834         argList = opClause->args;
835
836         /*
837          * get the fcache from the Oper node. If it is NULL, then initialize
838          * it
839          */
840         fcache = op->op_fcache;
841         if (fcache == NULL)
842         {
843                 fcache = init_fcache(op->opid, length(argList),
844                                                          econtext->ecxt_per_query_memory);
845                 op->op_fcache = fcache;
846         }
847
848         return ExecMakeFunctionResult(fcache, argList, econtext,
849                                                                   isNull, isDone);
850 }
851
852 /* ----------------------------------------------------------------
853  *              ExecEvalFunc
854  * ----------------------------------------------------------------
855  */
856
857 static Datum
858 ExecEvalFunc(Expr *funcClause,
859                          ExprContext *econtext,
860                          bool *isNull,
861                          ExprDoneCond *isDone)
862 {
863         Func       *func;
864         List       *argList;
865         FunctionCachePtr fcache;
866
867         /*
868          * we extract the oid of the function associated with the func node
869          * and then pass the work onto ExecMakeFunctionResult which evaluates
870          * the arguments and returns the result of calling the function on the
871          * evaluated arguments.
872          *
873          * this is nearly identical to the ExecEvalOper code.
874          */
875         func = (Func *) funcClause->oper;
876         argList = funcClause->args;
877
878         /*
879          * get the fcache from the Func node. If it is NULL, then initialize
880          * it
881          */
882         fcache = func->func_fcache;
883         if (fcache == NULL)
884         {
885                 fcache = init_fcache(func->funcid, length(argList),
886                                                          econtext->ecxt_per_query_memory);
887                 func->func_fcache = fcache;
888         }
889
890         return ExecMakeFunctionResult(fcache, argList, econtext,
891                                                                   isNull, isDone);
892 }
893
894 /* ----------------------------------------------------------------
895  *              ExecEvalNot
896  *              ExecEvalOr
897  *              ExecEvalAnd
898  *
899  *              Evaluate boolean expressions.  Evaluation of 'or' is
900  *              short-circuited when the first true (or null) value is found.
901  *
902  *              The query planner reformulates clause expressions in the
903  *              qualification to conjunctive normal form.  If we ever get
904  *              an AND to evaluate, we can be sure that it's not a top-level
905  *              clause in the qualification, but appears lower (as a function
906  *              argument, for example), or in the target list.  Not that you
907  *              need to know this, mind you...
908  * ----------------------------------------------------------------
909  */
910 static Datum
911 ExecEvalNot(Expr *notclause, ExprContext *econtext, bool *isNull)
912 {
913         Node       *clause;
914         Datum           expr_value;
915
916         clause = lfirst(notclause->args);
917
918         expr_value = ExecEvalExpr(clause, econtext, isNull, NULL);
919
920         /*
921          * if the expression evaluates to null, then we just cascade the null
922          * back to whoever called us.
923          */
924         if (*isNull)
925                 return expr_value;
926
927         /*
928          * evaluation of 'not' is simple.. expr is false, then return 'true'
929          * and vice versa.
930          */
931         return BoolGetDatum(!DatumGetBool(expr_value));
932 }
933
934 /* ----------------------------------------------------------------
935  *              ExecEvalOr
936  * ----------------------------------------------------------------
937  */
938 static Datum
939 ExecEvalOr(Expr *orExpr, ExprContext *econtext, bool *isNull)
940 {
941         List       *clauses;
942         List       *clause;
943         bool            AnyNull;
944         Datum           clause_value;
945
946         clauses = orExpr->args;
947         AnyNull = false;
948
949         /*
950          * If any of the clauses is TRUE, the OR result is TRUE regardless of
951          * the states of the rest of the clauses, so we can stop evaluating
952          * and return TRUE immediately.  If none are TRUE and one or more is
953          * NULL, we return NULL; otherwise we return FALSE.  This makes sense
954          * when you interpret NULL as "don't know": if we have a TRUE then the
955          * OR is TRUE even if we aren't sure about some of the other inputs.
956          * If all the known inputs are FALSE, but we have one or more "don't
957          * knows", then we have to report that we "don't know" what the OR's
958          * result should be --- perhaps one of the "don't knows" would have
959          * been TRUE if we'd known its value.  Only when all the inputs are
960          * known to be FALSE can we state confidently that the OR's result is
961          * FALSE.
962          */
963         foreach(clause, clauses)
964         {
965                 clause_value = ExecEvalExpr((Node *) lfirst(clause),
966                                                                         econtext, isNull, NULL);
967
968                 /*
969                  * if we have a non-null true result, then return it.
970                  */
971                 if (*isNull)
972                         AnyNull = true;         /* remember we got a null */
973                 else if (DatumGetBool(clause_value))
974                         return clause_value;
975         }
976
977         /* AnyNull is true if at least one clause evaluated to NULL */
978         *isNull = AnyNull;
979         return BoolGetDatum(false);
980 }
981
982 /* ----------------------------------------------------------------
983  *              ExecEvalAnd
984  * ----------------------------------------------------------------
985  */
986 static Datum
987 ExecEvalAnd(Expr *andExpr, ExprContext *econtext, bool *isNull)
988 {
989         List       *clauses;
990         List       *clause;
991         bool            AnyNull;
992         Datum           clause_value;
993
994         clauses = andExpr->args;
995         AnyNull = false;
996
997         /*
998          * If any of the clauses is FALSE, the AND result is FALSE regardless
999          * of the states of the rest of the clauses, so we can stop evaluating
1000          * and return FALSE immediately.  If none are FALSE and one or more is
1001          * NULL, we return NULL; otherwise we return TRUE.      This makes sense
1002          * when you interpret NULL as "don't know", using the same sort of
1003          * reasoning as for OR, above.
1004          */
1005         foreach(clause, clauses)
1006         {
1007                 clause_value = ExecEvalExpr((Node *) lfirst(clause),
1008                                                                         econtext, isNull, NULL);
1009
1010                 /*
1011                  * if we have a non-null false result, then return it.
1012                  */
1013                 if (*isNull)
1014                         AnyNull = true;         /* remember we got a null */
1015                 else if (!DatumGetBool(clause_value))
1016                         return clause_value;
1017         }
1018
1019         /* AnyNull is true if at least one clause evaluated to NULL */
1020         *isNull = AnyNull;
1021         return BoolGetDatum(!AnyNull);
1022 }
1023
1024 /* ----------------------------------------------------------------
1025  *              ExecEvalCase
1026  *
1027  *              Evaluate a CASE clause. Will have boolean expressions
1028  *              inside the WHEN clauses, and will have expressions
1029  *              for results.
1030  *              - thomas 1998-11-09
1031  * ----------------------------------------------------------------
1032  */
1033 static Datum
1034 ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext,
1035                          bool *isNull, ExprDoneCond *isDone)
1036 {
1037         List       *clauses;
1038         List       *clause;
1039         Datum           clause_value;
1040
1041         clauses = caseExpr->args;
1042
1043         /*
1044          * we evaluate each of the WHEN clauses in turn, as soon as one is
1045          * true we return the corresponding result. If none are true then we
1046          * return the value of the default clause, or NULL if there is none.
1047          */
1048         foreach(clause, clauses)
1049         {
1050                 CaseWhen   *wclause = lfirst(clause);
1051
1052                 clause_value = ExecEvalExpr(wclause->expr,
1053                                                                         econtext,
1054                                                                         isNull,
1055                                                                         NULL);
1056
1057                 /*
1058                  * if we have a true test, then we return the result, since the
1059                  * case statement is satisfied.  A NULL result from the test is
1060                  * not considered true.
1061                  */
1062                 if (DatumGetBool(clause_value) && !*isNull)
1063                 {
1064                         return ExecEvalExpr(wclause->result,
1065                                                                 econtext,
1066                                                                 isNull,
1067                                                                 isDone);
1068                 }
1069         }
1070
1071         if (caseExpr->defresult)
1072         {
1073                 return ExecEvalExpr(caseExpr->defresult,
1074                                                         econtext,
1075                                                         isNull,
1076                                                         isDone);
1077         }
1078
1079         *isNull = true;
1080         return (Datum) 0;
1081 }
1082
1083 /* ----------------------------------------------------------------
1084  *              ExecEvalFieldSelect
1085  *
1086  *              Evaluate a FieldSelect node.
1087  * ----------------------------------------------------------------
1088  */
1089 static Datum
1090 ExecEvalFieldSelect(FieldSelect *fselect,
1091                                         ExprContext *econtext,
1092                                         bool *isNull,
1093                                         ExprDoneCond *isDone)
1094 {
1095         Datum           result;
1096         TupleTableSlot *resSlot;
1097
1098         result = ExecEvalExpr(fselect->arg, econtext, isNull, isDone);
1099         if (*isNull)
1100                 return result;
1101         resSlot = (TupleTableSlot *) DatumGetPointer(result);
1102         Assert(resSlot != NULL && IsA(resSlot, TupleTableSlot));
1103         result = heap_getattr(resSlot->val,
1104                                                   fselect->fieldnum,
1105                                                   resSlot->ttc_tupleDescriptor,
1106                                                   isNull);
1107         return result;
1108 }
1109
1110 /* ----------------------------------------------------------------
1111  *              ExecEvalExpr
1112  *
1113  *              Recursively evaluate a targetlist or qualification expression.
1114  *
1115  * Inputs:
1116  *              expression: the expression tree to evaluate
1117  *              econtext: evaluation context information
1118  *
1119  * Outputs:
1120  *              return value: Datum value of result
1121  *              *isNull: set to TRUE if result is NULL (actual return value is
1122  *                               meaningless if so); set to FALSE if non-null result
1123  *              *isDone: set to indicator of set-result status
1124  *
1125  * A caller that can only accept a singleton (non-set) result should pass
1126  * NULL for isDone; if the expression computes a set result then an elog()
1127  * error will be reported.      If the caller does pass an isDone pointer then
1128  * *isDone is set to one of these three states:
1129  *              ExprSingleResult                singleton result (not a set)
1130  *              ExprMultipleResult              return value is one element of a set
1131  *              ExprEndResult                   there are no more elements in the set
1132  * When ExprMultipleResult is returned, the caller should invoke
1133  * ExecEvalExpr() repeatedly until ExprEndResult is returned.  ExprEndResult
1134  * is returned after the last real set element.  For convenience isNull will
1135  * always be set TRUE when ExprEndResult is returned, but this should not be
1136  * taken as indicating a NULL element of the set.  Note that these return
1137  * conventions allow us to distinguish among a singleton NULL, a NULL element
1138  * of a set, and an empty set.
1139  *
1140  * The caller should already have switched into the temporary memory
1141  * context econtext->ecxt_per_tuple_memory.  The convenience entry point
1142  * ExecEvalExprSwitchContext() is provided for callers who don't prefer to
1143  * do the switch in an outer loop.      We do not do the switch here because
1144  * it'd be a waste of cycles during recursive entries to ExecEvalExpr().
1145  *
1146  * This routine is an inner loop routine and must be as fast as possible.
1147  * ----------------------------------------------------------------
1148  */
1149 Datum
1150 ExecEvalExpr(Node *expression,
1151                          ExprContext *econtext,
1152                          bool *isNull,
1153                          ExprDoneCond *isDone)
1154 {
1155         Datum           retDatum;
1156
1157         /* Set default values for result flags: non-null, not a set result */
1158         *isNull = false;
1159         if (isDone)
1160                 *isDone = ExprSingleResult;
1161
1162         /* Is this still necessary?  Doubtful... */
1163         if (expression == NULL)
1164         {
1165                 *isNull = true;
1166                 return (Datum) 0;
1167         }
1168
1169         /*
1170          * here we dispatch the work to the appropriate type of function given
1171          * the type of our expression.
1172          */
1173         switch (nodeTag(expression))
1174         {
1175                 case T_Var:
1176                         retDatum = ExecEvalVar((Var *) expression, econtext, isNull);
1177                         break;
1178                 case T_Const:
1179                         {
1180                                 Const      *con = (Const *) expression;
1181
1182                                 retDatum = con->constvalue;
1183                                 *isNull = con->constisnull;
1184                                 break;
1185                         }
1186                 case T_Param:
1187                         retDatum = ExecEvalParam((Param *) expression, econtext, isNull);
1188                         break;
1189                 case T_Iter:
1190                         retDatum = ExecEvalIter((Iter *) expression,
1191                                                                         econtext,
1192                                                                         isNull,
1193                                                                         isDone);
1194                         break;
1195                 case T_Aggref:
1196                         retDatum = ExecEvalAggref((Aggref *) expression, econtext, isNull);
1197                         break;
1198                 case T_ArrayRef:
1199                         retDatum = ExecEvalArrayRef((ArrayRef *) expression,
1200                                                                                 econtext,
1201                                                                                 isNull,
1202                                                                                 isDone);
1203                         break;
1204                 case T_Expr:
1205                         {
1206                                 Expr       *expr = (Expr *) expression;
1207
1208                                 switch (expr->opType)
1209                                 {
1210                                         case OP_EXPR:
1211                                                 retDatum = ExecEvalOper(expr, econtext,
1212                                                                                                 isNull, isDone);
1213                                                 break;
1214                                         case FUNC_EXPR:
1215                                                 retDatum = ExecEvalFunc(expr, econtext,
1216                                                                                                 isNull, isDone);
1217                                                 break;
1218                                         case OR_EXPR:
1219                                                 retDatum = ExecEvalOr(expr, econtext, isNull);
1220                                                 break;
1221                                         case AND_EXPR:
1222                                                 retDatum = ExecEvalAnd(expr, econtext, isNull);
1223                                                 break;
1224                                         case NOT_EXPR:
1225                                                 retDatum = ExecEvalNot(expr, econtext, isNull);
1226                                                 break;
1227                                         case SUBPLAN_EXPR:
1228                                                 retDatum = ExecSubPlan((SubPlan *) expr->oper,
1229                                                                                            expr->args, econtext,
1230                                                                                            isNull);
1231                                                 break;
1232                                         default:
1233                                                 elog(ERROR, "ExecEvalExpr: unknown expression type %d",
1234                                                          expr->opType);
1235                                                 retDatum = 0;   /* keep compiler quiet */
1236                                                 break;
1237                                 }
1238                                 break;
1239                         }
1240                 case T_FieldSelect:
1241                         retDatum = ExecEvalFieldSelect((FieldSelect *) expression,
1242                                                                                    econtext,
1243                                                                                    isNull,
1244                                                                                    isDone);
1245                         break;
1246                 case T_RelabelType:
1247                         retDatum = ExecEvalExpr(((RelabelType *) expression)->arg,
1248                                                                         econtext,
1249                                                                         isNull,
1250                                                                         isDone);
1251                         break;
1252                 case T_CaseExpr:
1253                         retDatum = ExecEvalCase((CaseExpr *) expression,
1254                                                                         econtext,
1255                                                                         isNull,
1256                                                                         isDone);
1257                         break;
1258
1259                 default:
1260                         elog(ERROR, "ExecEvalExpr: unknown expression type %d",
1261                                  nodeTag(expression));
1262                         retDatum = 0;           /* keep compiler quiet */
1263                         break;
1264         }
1265
1266         return retDatum;
1267 }       /* ExecEvalExpr() */
1268
1269
1270 /*
1271  * Same as above, but get into the right allocation context explicitly.
1272  */
1273 Datum
1274 ExecEvalExprSwitchContext(Node *expression,
1275                                                   ExprContext *econtext,
1276                                                   bool *isNull,
1277                                                   ExprDoneCond *isDone)
1278 {
1279         Datum           retDatum;
1280         MemoryContext oldContext;
1281
1282         oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
1283         retDatum = ExecEvalExpr(expression, econtext, isNull, isDone);
1284         MemoryContextSwitchTo(oldContext);
1285         return retDatum;
1286 }
1287
1288
1289 /* ----------------------------------------------------------------
1290  *                                       ExecQual / ExecTargetList / ExecProject
1291  * ----------------------------------------------------------------
1292  */
1293
1294 /* ----------------------------------------------------------------
1295  *              ExecQual
1296  *
1297  *              Evaluates a conjunctive boolean expression (qual list) and
1298  *              returns true iff none of the subexpressions are false.
1299  *              (We also return true if the list is empty.)
1300  *
1301  *      If some of the subexpressions yield NULL but none yield FALSE,
1302  *      then the result of the conjunction is NULL (ie, unknown)
1303  *      according to three-valued boolean logic.  In this case,
1304  *      we return the value specified by the "resultForNull" parameter.
1305  *
1306  *      Callers evaluating WHERE clauses should pass resultForNull=FALSE,
1307  *      since SQL specifies that tuples with null WHERE results do not
1308  *      get selected.  On the other hand, callers evaluating constraint
1309  *      conditions should pass resultForNull=TRUE, since SQL also specifies
1310  *      that NULL constraint conditions are not failures.
1311  *
1312  *      NOTE: it would not be correct to use this routine to evaluate an
1313  *      AND subclause of a boolean expression; for that purpose, a NULL
1314  *      result must be returned as NULL so that it can be properly treated
1315  *      in the next higher operator (cf. ExecEvalAnd and ExecEvalOr).
1316  *      This routine is only used in contexts where a complete expression
1317  *      is being evaluated and we know that NULL can be treated the same
1318  *      as one boolean result or the other.
1319  *
1320  * ----------------------------------------------------------------
1321  */
1322 bool
1323 ExecQual(List *qual, ExprContext *econtext, bool resultForNull)
1324 {
1325         bool            result;
1326         MemoryContext oldContext;
1327         List       *qlist;
1328
1329         /*
1330          * debugging stuff
1331          */
1332         EV_printf("ExecQual: qual is ");
1333         EV_nodeDisplay(qual);
1334         EV_printf("\n");
1335
1336         IncrProcessed();
1337
1338         /*
1339          * Run in short-lived per-tuple context while computing expressions.
1340          */
1341         oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
1342
1343         /*
1344          * Evaluate the qual conditions one at a time.  If we find a FALSE
1345          * result, we can stop evaluating and return FALSE --- the AND result
1346          * must be FALSE.  Also, if we find a NULL result when resultForNull
1347          * is FALSE, we can stop and return FALSE --- the AND result must be
1348          * FALSE or NULL in that case, and the caller doesn't care which.
1349          *
1350          * If we get to the end of the list, we can return TRUE.  This will
1351          * happen when the AND result is indeed TRUE, or when the AND result
1352          * is NULL (one or more NULL subresult, with all the rest TRUE) and
1353          * the caller has specified resultForNull = TRUE.
1354          */
1355         result = true;
1356
1357         foreach(qlist, qual)
1358         {
1359                 Node       *clause = (Node *) lfirst(qlist);
1360                 Datum           expr_value;
1361                 bool            isNull;
1362
1363                 expr_value = ExecEvalExpr(clause, econtext, &isNull, NULL);
1364
1365                 if (isNull)
1366                 {
1367                         if (resultForNull == false)
1368                         {
1369                                 result = false; /* treat NULL as FALSE */
1370                                 break;
1371                         }
1372                 }
1373                 else
1374                 {
1375                         if (!DatumGetBool(expr_value))
1376                         {
1377                                 result = false; /* definitely FALSE */
1378                                 break;
1379                         }
1380                 }
1381         }
1382
1383         MemoryContextSwitchTo(oldContext);
1384
1385         return result;
1386 }
1387
1388 /*
1389  * Number of items in a tlist (including any resjunk items!)
1390  */
1391 int
1392 ExecTargetListLength(List *targetlist)
1393 {
1394         int                     len = 0;
1395         List       *tl;
1396
1397         foreach(tl, targetlist)
1398         {
1399                 TargetEntry *curTle = (TargetEntry *) lfirst(tl);
1400
1401                 if (curTle->resdom != NULL)
1402                         len++;
1403                 else
1404                         len += curTle->fjoin->fj_nNodes;
1405         }
1406         return len;
1407 }
1408
1409 /*
1410  * Number of items in a tlist, not including any resjunk items
1411  */
1412 int
1413 ExecCleanTargetListLength(List *targetlist)
1414 {
1415         int                     len = 0;
1416         List       *tl;
1417
1418         foreach(tl, targetlist)
1419         {
1420                 TargetEntry *curTle = (TargetEntry *) lfirst(tl);
1421
1422                 if (curTle->resdom != NULL)
1423                 {
1424                         if (!curTle->resdom->resjunk)
1425                                 len++;
1426                 }
1427                 else
1428                         len += curTle->fjoin->fj_nNodes;
1429         }
1430         return len;
1431 }
1432
1433 /* ----------------------------------------------------------------
1434  *              ExecTargetList
1435  *
1436  *              Evaluates a targetlist with respect to the current
1437  *              expression context and return a tuple.
1438  *
1439  * As with ExecEvalExpr, the caller should pass isDone = NULL if not
1440  * prepared to deal with sets of result tuples.  Otherwise, a return
1441  * of *isDone = ExprMultipleResult signifies a set element, and a return
1442  * of *isDone = ExprEndResult signifies end of the set of tuple.
1443  * ----------------------------------------------------------------
1444  */
1445 static HeapTuple
1446 ExecTargetList(List *targetlist,
1447                            int nodomains,
1448                            TupleDesc targettype,
1449                            Datum *values,
1450                            ExprContext *econtext,
1451                            ExprDoneCond *isDone)
1452 {
1453         MemoryContext oldContext;
1454
1455 #define NPREALLOCDOMAINS 64
1456         char            nullsArray[NPREALLOCDOMAINS];
1457         bool            fjIsNullArray[NPREALLOCDOMAINS];
1458         ExprDoneCond itemIsDoneArray[NPREALLOCDOMAINS];
1459         char       *nulls;
1460         bool       *fjIsNull;
1461         ExprDoneCond *itemIsDone;
1462         List       *tl;
1463         TargetEntry *tle;
1464         AttrNumber      resind;
1465         HeapTuple       newTuple;
1466         bool            isNull;
1467         bool            haveDoneSets;
1468         static struct tupleDesc NullTupleDesc;          /* we assume this inits to
1469                                                                                                  * zeroes */
1470
1471         /*
1472          * debugging stuff
1473          */
1474         EV_printf("ExecTargetList: tl is ");
1475         EV_nodeDisplay(targetlist);
1476         EV_printf("\n");
1477
1478         /*
1479          * Run in short-lived per-tuple context while computing expressions.
1480          */
1481         oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
1482
1483         /*
1484          * There used to be some klugy and demonstrably broken code here that
1485          * special-cased the situation where targetlist == NIL.  Now we just
1486          * fall through and return an empty-but-valid tuple.  We do, however,
1487          * have to cope with the possibility that targettype is NULL ---
1488          * heap_formtuple won't like that, so pass a dummy descriptor with
1489          * natts = 0 to deal with it.
1490          */
1491         if (targettype == NULL)
1492                 targettype = &NullTupleDesc;
1493
1494         /*
1495          * allocate an array of char's to hold the "null" information only if
1496          * we have a really large targetlist.  otherwise we use the stack.
1497          *
1498          * We also allocate a bool array that is used to hold fjoin result state,
1499          * and another array that holds the isDone status for each targetlist
1500          * item. The isDone status is needed so that we can iterate,
1501          * generating multiple tuples, when one or more tlist items return
1502          * sets.  (We expect the caller to call us again if we return:
1503          *
1504          *      isDone = ExprMultipleResult.)
1505          */
1506         if (nodomains > NPREALLOCDOMAINS)
1507         {
1508                 nulls = (char *) palloc(nodomains * sizeof(char));
1509                 fjIsNull = (bool *) palloc(nodomains * sizeof(bool));
1510                 itemIsDone = (ExprDoneCond *) palloc(nodomains * sizeof(ExprDoneCond));
1511         }
1512         else
1513         {
1514                 nulls = nullsArray;
1515                 fjIsNull = fjIsNullArray;
1516                 itemIsDone = itemIsDoneArray;
1517         }
1518
1519         /*
1520          * evaluate all the expressions in the target list
1521          */
1522
1523         if (isDone)
1524                 *isDone = ExprSingleResult;             /* until proven otherwise */
1525
1526         haveDoneSets = false;           /* any exhausted set exprs in tlist? */
1527
1528         foreach(tl, targetlist)
1529         {
1530                 tle = lfirst(tl);
1531
1532                 if (tle->resdom != NULL)
1533                 {
1534                         resind = tle->resdom->resno - 1;
1535
1536                         values[resind] = ExecEvalExpr(tle->expr,
1537                                                                                   econtext,
1538                                                                                   &isNull,
1539                                                                                   &itemIsDone[resind]);
1540                         nulls[resind] = isNull ? 'n' : ' ';
1541
1542                         if (itemIsDone[resind] != ExprSingleResult)
1543                         {
1544                                 /* We have a set-valued expression in the tlist */
1545                                 if (isDone == NULL)
1546                                         elog(ERROR, "Set-valued function called in context that cannot accept a set");
1547                                 if (itemIsDone[resind] == ExprMultipleResult)
1548                                 {
1549                                         /* we have undone sets in the tlist, set flag */
1550                                         *isDone = ExprMultipleResult;
1551                                 }
1552                                 else
1553                                 {
1554                                         /* we have done sets in the tlist, set flag for that */
1555                                         haveDoneSets = true;
1556                                 }
1557                         }
1558                 }
1559                 else
1560                 {
1561 #ifdef SETS_FIXED
1562                         int                     curNode;
1563                         Resdom     *fjRes;
1564                         List       *fjTlist = (List *) tle->expr;
1565                         Fjoin      *fjNode = tle->fjoin;
1566                         int                     nNodes = fjNode->fj_nNodes;
1567                         DatumPtr        results = fjNode->fj_results;
1568
1569                         ExecEvalFjoin(tle, econtext, fjIsNull, isDone);
1570
1571                         /*
1572                          * XXX this is wrong, but since fjoin code is completely
1573                          * broken anyway, I'm not going to worry about it now --- tgl
1574                          * 8/23/00
1575                          */
1576                         if (isDone && *isDone == ExprEndResult)
1577                         {
1578                                 MemoryContextSwitchTo(oldContext);
1579                                 newTuple = NULL;
1580                                 goto exit;
1581                         }
1582
1583                         /*
1584                          * get the result from the inner node
1585                          */
1586                         fjRes = (Resdom *) fjNode->fj_innerNode;
1587                         resind = fjRes->resno - 1;
1588                         values[resind] = results[0];
1589                         nulls[resind] = fjIsNull[0] ? 'n' : ' ';
1590
1591                         /*
1592                          * Get results from all of the outer nodes
1593                          */
1594                         for (curNode = 1;
1595                                  curNode < nNodes;
1596                                  curNode++, fjTlist = lnext(fjTlist))
1597                         {
1598                                 Node       *outernode = lfirst(fjTlist);
1599
1600                                 fjRes = (Resdom *) outernode->iterexpr;
1601                                 resind = fjRes->resno - 1;
1602                                 values[resind] = results[curNode];
1603                                 nulls[resind] = fjIsNull[curNode] ? 'n' : ' ';
1604                         }
1605 #else
1606                         elog(ERROR, "ExecTargetList: fjoin nodes not currently supported");
1607 #endif
1608                 }
1609         }
1610
1611         if (haveDoneSets)
1612         {
1613
1614                 /*
1615                  * note: can't get here unless we verified isDone != NULL
1616                  */
1617                 if (*isDone == ExprSingleResult)
1618                 {
1619
1620                         /*
1621                          * all sets are done, so report that tlist expansion is
1622                          * complete.
1623                          */
1624                         *isDone = ExprEndResult;
1625                         MemoryContextSwitchTo(oldContext);
1626                         newTuple = NULL;
1627                         goto exit;
1628                 }
1629                 else
1630                 {
1631
1632                         /*
1633                          * We have some done and some undone sets.      Restart the done
1634                          * ones so that we can deliver a tuple (if possible).
1635                          */
1636                         foreach(tl, targetlist)
1637                         {
1638                                 tle = lfirst(tl);
1639
1640                                 if (tle->resdom != NULL)
1641                                 {
1642                                         resind = tle->resdom->resno - 1;
1643
1644                                         if (itemIsDone[resind] == ExprEndResult)
1645                                         {
1646                                                 values[resind] = ExecEvalExpr(tle->expr,
1647                                                                                                           econtext,
1648                                                                                                           &isNull,
1649                                                                                                         &itemIsDone[resind]);
1650                                                 nulls[resind] = isNull ? 'n' : ' ';
1651
1652                                                 if (itemIsDone[resind] == ExprEndResult)
1653                                                 {
1654
1655                                                         /*
1656                                                          * Oh dear, this item is returning an empty
1657                                                          * set. Guess we can't make a tuple after all.
1658                                                          */
1659                                                         *isDone = ExprEndResult;
1660                                                         break;
1661                                                 }
1662                                         }
1663                                 }
1664                         }
1665
1666                         /*
1667                          * If we cannot make a tuple because some sets are empty, we
1668                          * still have to cycle the nonempty sets to completion, else
1669                          * resources will not be released from subplans etc.
1670                          */
1671                         if (*isDone == ExprEndResult)
1672                         {
1673                                 foreach(tl, targetlist)
1674                                 {
1675                                         tle = lfirst(tl);
1676
1677                                         if (tle->resdom != NULL)
1678                                         {
1679                                                 resind = tle->resdom->resno - 1;
1680
1681                                                 while (itemIsDone[resind] == ExprMultipleResult)
1682                                                 {
1683                                                         (void) ExecEvalExpr(tle->expr,
1684                                                                                                 econtext,
1685                                                                                                 &isNull,
1686                                                                                                 &itemIsDone[resind]);
1687                                                 }
1688                                         }
1689                                 }
1690
1691                                 MemoryContextSwitchTo(oldContext);
1692                                 newTuple = NULL;
1693                                 goto exit;
1694                         }
1695                 }
1696         }
1697
1698         /*
1699          * form the new result tuple (in the caller's memory context!)
1700          */
1701         MemoryContextSwitchTo(oldContext);
1702
1703         newTuple = (HeapTuple) heap_formtuple(targettype, values, nulls);
1704
1705 exit:
1706
1707         /*
1708          * free the status arrays if we palloc'd them
1709          */
1710         if (nodomains > NPREALLOCDOMAINS)
1711         {
1712                 pfree(nulls);
1713                 pfree(fjIsNull);
1714                 pfree(itemIsDone);
1715         }
1716
1717         return newTuple;
1718 }
1719
1720 /* ----------------------------------------------------------------
1721  *              ExecProject
1722  *
1723  *              projects a tuple based on projection info and stores
1724  *              it in the specified tuple table slot.
1725  *
1726  *              Note: someday soon the executor can be extended to eliminate
1727  *                        redundant projections by storing pointers to datums
1728  *                        in the tuple table and then passing these around when
1729  *                        possible.  this should make things much quicker.
1730  *                        -cim 6/3/91
1731  * ----------------------------------------------------------------
1732  */
1733 TupleTableSlot *
1734 ExecProject(ProjectionInfo *projInfo, ExprDoneCond *isDone)
1735 {
1736         TupleTableSlot *slot;
1737         List       *targetlist;
1738         int                     len;
1739         TupleDesc       tupType;
1740         Datum      *tupValue;
1741         ExprContext *econtext;
1742         HeapTuple       newTuple;
1743
1744         /*
1745          * sanity checks
1746          */
1747         if (projInfo == NULL)
1748                 return (TupleTableSlot *) NULL;
1749
1750         /*
1751          * get the projection info we want
1752          */
1753         slot = projInfo->pi_slot;
1754         targetlist = projInfo->pi_targetlist;
1755         len = projInfo->pi_len;
1756         tupType = slot->ttc_tupleDescriptor;
1757
1758         tupValue = projInfo->pi_tupValue;
1759         econtext = projInfo->pi_exprContext;
1760
1761         /*
1762          * form a new result tuple (if possible --- result can be NULL)
1763          */
1764         newTuple = ExecTargetList(targetlist,
1765                                                           len,
1766                                                           tupType,
1767                                                           tupValue,
1768                                                           econtext,
1769                                                           isDone);
1770
1771         /*
1772          * store the tuple in the projection slot and return the slot.
1773          */
1774         return ExecStoreTuple(newTuple,         /* tuple to store */
1775                                                   slot, /* slot to store in */
1776                                                   InvalidBuffer,                /* tuple has no buffer */
1777                                                   true);
1778 }