]> granicus.if.org Git - postgresql/blob - src/backend/executor/execQual.c
Fix ExecMakeTableFunctionResult() to work with generic expressions as
[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-2002, 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.112 2002/12/01 20:27:32 tgl 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 "catalog/pg_type.h"
39 #include "executor/execdebug.h"
40 #include "executor/functions.h"
41 #include "executor/nodeSubplan.h"
42 #include "miscadmin.h"
43 #include "parser/parse_expr.h"
44 #include "utils/array.h"
45 #include "utils/builtins.h"
46 #include "utils/fcache.h"
47 #include "utils/lsyscache.h"
48
49
50 /* static function decls */
51 static Datum ExecEvalAggref(Aggref *aggref, ExprContext *econtext,
52                            bool *isNull);
53 static Datum ExecEvalArrayRef(ArrayRef *arrayRef, ExprContext *econtext,
54                                  bool *isNull, ExprDoneCond *isDone);
55 static Datum ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull);
56 static Datum ExecEvalOper(Expr *opClause, ExprContext *econtext,
57                          bool *isNull, ExprDoneCond *isDone);
58 static Datum ExecEvalDistinct(Expr *opClause, ExprContext *econtext,
59                                  bool *isNull, ExprDoneCond *isDone);
60 static Datum ExecEvalFunc(Expr *funcClause, ExprContext *econtext,
61                          bool *isNull, ExprDoneCond *isDone);
62 static ExprDoneCond ExecEvalFuncArgs(FunctionCallInfo fcinfo,
63                                  List *argList, ExprContext *econtext);
64 static Datum ExecEvalNot(Expr *notclause, ExprContext *econtext, bool *isNull);
65 static Datum ExecEvalAnd(Expr *andExpr, ExprContext *econtext, bool *isNull);
66 static Datum ExecEvalOr(Expr *orExpr, ExprContext *econtext, bool *isNull);
67 static Datum ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext,
68                          bool *isNull, ExprDoneCond *isDone);
69 static Datum ExecEvalNullTest(NullTest *ntest, ExprContext *econtext,
70                                  bool *isNull, ExprDoneCond *isDone);
71 static Datum ExecEvalBooleanTest(BooleanTest *btest, ExprContext *econtext,
72                                         bool *isNull, ExprDoneCond *isDone);
73 static Datum ExecEvalConstraintTest(ConstraintTest *constraint,
74                                            ExprContext *econtext,
75                                            bool *isNull, ExprDoneCond *isDone);
76 static Datum ExecEvalConstraintTestValue(ConstraintTestValue *conVal,
77                                            ExprContext *econtext,
78                                            bool *isNull, ExprDoneCond *isDone);
79
80
81 /*----------
82  *        ExecEvalArrayRef
83  *
84  *         This function takes an ArrayRef and returns the extracted Datum
85  *         if it's a simple reference, or the modified array value if it's
86  *         an array assignment (i.e., array element or slice insertion).
87  *
88  * NOTE: if we get a NULL result from a subexpression, we return NULL when
89  * it's an array reference, or the unmodified source array when it's an
90  * array assignment.  This may seem peculiar, but if we return NULL (as was
91  * done in versions up through 7.0) then an assignment like
92  *                      UPDATE table SET arrayfield[4] = NULL
93  * will result in setting the whole array to NULL, which is certainly not
94  * very desirable.      By returning the source array we make the assignment
95  * into a no-op, instead.  (Eventually we need to redesign arrays so that
96  * individual elements can be NULL, but for now, let's try to protect users
97  * from shooting themselves in the foot.)
98  *
99  * NOTE: we deliberately refrain from applying DatumGetArrayTypeP() here,
100  * even though that might seem natural, because this code needs to support
101  * both varlena arrays and fixed-length array types.  DatumGetArrayTypeP()
102  * only works for the varlena kind.  The routines we call in arrayfuncs.c
103  * have to know the difference (that's what they need refattrlength for).
104  *----------
105  */
106 static Datum
107 ExecEvalArrayRef(ArrayRef *arrayRef,
108                                  ExprContext *econtext,
109                                  bool *isNull,
110                                  ExprDoneCond *isDone)
111 {
112         ArrayType  *array_source;
113         ArrayType  *resultArray;
114         bool            isAssignment = (arrayRef->refassgnexpr != NULL);
115         List       *elt;
116         int                     i = 0,
117                                 j = 0;
118         IntArray        upper,
119                                 lower;
120         int                *lIndex;
121
122         if (arrayRef->refexpr != NULL)
123         {
124                 array_source = (ArrayType *)
125                         DatumGetPointer(ExecEvalExpr(arrayRef->refexpr,
126                                                                                  econtext,
127                                                                                  isNull,
128                                                                                  isDone));
129
130                 /*
131                  * If refexpr yields NULL, result is always NULL, for now anyway.
132                  * (This means you cannot assign to an element or slice of an
133                  * array that's NULL; it'll just stay NULL.)
134                  */
135                 if (*isNull)
136                         return (Datum) NULL;
137         }
138         else
139         {
140                 /*
141                  * Empty refexpr indicates we are doing an INSERT into an array
142                  * column. For now, we just take the refassgnexpr (which the
143                  * parser will have ensured is an array value) and return it
144                  * as-is, ignoring any subscripts that may have been supplied in
145                  * the INSERT column list. This is a kluge, but it's not real
146                  * clear what the semantics ought to be...
147                  */
148                 array_source = NULL;
149         }
150
151         foreach(elt, arrayRef->refupperindexpr)
152         {
153                 if (i >= MAXDIM)
154                         elog(ERROR, "ExecEvalArrayRef: can only handle %d dimensions",
155                                  MAXDIM);
156
157                 upper.indx[i++] = DatumGetInt32(ExecEvalExpr((Node *) lfirst(elt),
158                                                                                                          econtext,
159                                                                                                          isNull,
160                                                                                                          NULL));
161                 /* If any index expr yields NULL, result is NULL or source array */
162                 if (*isNull)
163                 {
164                         if (!isAssignment || array_source == NULL)
165                                 return (Datum) NULL;
166                         *isNull = false;
167                         return PointerGetDatum(array_source);
168                 }
169         }
170
171         if (arrayRef->reflowerindexpr != NIL)
172         {
173                 foreach(elt, arrayRef->reflowerindexpr)
174                 {
175                         if (j >= MAXDIM)
176                                 elog(ERROR, "ExecEvalArrayRef: can only handle %d dimensions",
177                                          MAXDIM);
178
179                         lower.indx[j++] = DatumGetInt32(ExecEvalExpr((Node *) lfirst(elt),
180                                                                                                                  econtext,
181                                                                                                                  isNull,
182                                                                                                                  NULL));
183
184                         /*
185                          * If any index expr yields NULL, result is NULL or source
186                          * array
187                          */
188                         if (*isNull)
189                         {
190                                 if (!isAssignment || array_source == NULL)
191                                         return (Datum) NULL;
192                                 *isNull = false;
193                                 return PointerGetDatum(array_source);
194                         }
195                 }
196                 if (i != j)
197                         elog(ERROR,
198                                  "ExecEvalArrayRef: upper and lower indices mismatch");
199                 lIndex = lower.indx;
200         }
201         else
202                 lIndex = NULL;
203
204         if (isAssignment)
205         {
206                 Datum           sourceData = ExecEvalExpr(arrayRef->refassgnexpr,
207                                                                                           econtext,
208                                                                                           isNull,
209                                                                                           NULL);
210
211                 /*
212                  * For now, can't cope with inserting NULL into an array, so make
213                  * it a no-op per discussion above...
214                  */
215                 if (*isNull)
216                 {
217                         if (array_source == NULL)
218                                 return (Datum) NULL;
219                         *isNull = false;
220                         return PointerGetDatum(array_source);
221                 }
222
223                 if (array_source == NULL)
224                         return sourceData;      /* XXX do something else? */
225
226                 if (lIndex == NULL)
227                         resultArray = array_set(array_source, i,
228                                                                         upper.indx,
229                                                                         sourceData,
230                                                                         arrayRef->refattrlength,
231                                                                         arrayRef->refelemlength,
232                                                                         arrayRef->refelembyval,
233                                                                         arrayRef->refelemalign,
234                                                                         isNull);
235                 else
236                         resultArray = array_set_slice(array_source, i,
237                                                                                   upper.indx, lower.indx,
238                                                            (ArrayType *) DatumGetPointer(sourceData),
239                                                                                   arrayRef->refattrlength,
240                                                                                   arrayRef->refelemlength,
241                                                                                   arrayRef->refelembyval,
242                                                                                   arrayRef->refelemalign,
243                                                                                   isNull);
244                 return PointerGetDatum(resultArray);
245         }
246
247         if (lIndex == NULL)
248                 return array_ref(array_source, i, upper.indx,
249                                                  arrayRef->refattrlength,
250                                                  arrayRef->refelemlength,
251                                                  arrayRef->refelembyval,
252                                                  arrayRef->refelemalign,
253                                                  isNull);
254         else
255         {
256                 resultArray = array_get_slice(array_source, i,
257                                                                           upper.indx, lower.indx,
258                                                                           arrayRef->refattrlength,
259                                                                           arrayRef->refelemlength,
260                                                                           arrayRef->refelembyval,
261                                                                           arrayRef->refelemalign,
262                                                                           isNull);
263                 return PointerGetDatum(resultArray);
264         }
265 }
266
267
268 /* ----------------------------------------------------------------
269  *              ExecEvalAggref
270  *
271  *              Returns a Datum whose value is the value of the precomputed
272  *              aggregate found in the given expression context.
273  * ----------------------------------------------------------------
274  */
275 static Datum
276 ExecEvalAggref(Aggref *aggref, ExprContext *econtext, bool *isNull)
277 {
278         if (econtext->ecxt_aggvalues == NULL)           /* safety check */
279                 elog(ERROR, "ExecEvalAggref: no aggregates in this expression context");
280
281         *isNull = econtext->ecxt_aggnulls[aggref->aggno];
282         return econtext->ecxt_aggvalues[aggref->aggno];
283 }
284
285 /* ----------------------------------------------------------------
286  *              ExecEvalVar
287  *
288  *              Returns a Datum whose value is the value of a range
289  *              variable with respect to given expression context.
290  *
291  *
292  *              As an entry condition, we expect that the datatype the
293  *              plan expects to get (as told by our "variable" argument) is in
294  *              fact the datatype of the attribute the plan says to fetch (as
295  *              seen in the current context, identified by our "econtext"
296  *              argument).
297  *
298  *              If we fetch a Type A attribute and Caller treats it as if it
299  *              were Type B, there will be undefined results (e.g. crash).
300  *              One way these might mismatch now is that we're accessing a
301  *              catalog class and the type information in the pg_attribute
302  *              class does not match the hardcoded pg_attribute information
303  *              (in pg_attribute.h) for the class in question.
304  *
305  *              We have an Assert to make sure this entry condition is met.
306  *
307  * ---------------------------------------------------------------- */
308 static Datum
309 ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull)
310 {
311         Datum           result;
312         TupleTableSlot *slot;
313         AttrNumber      attnum;
314         HeapTuple       heapTuple;
315         TupleDesc       tuple_type;
316
317         /*
318          * get the slot we want
319          */
320         switch (variable->varno)
321         {
322                 case INNER:                             /* get the tuple from the inner node */
323                         slot = econtext->ecxt_innertuple;
324                         break;
325
326                 case OUTER:                             /* get the tuple from the outer node */
327                         slot = econtext->ecxt_outertuple;
328                         break;
329
330                 default:                                /* get the tuple from the relation being
331                                                                  * scanned */
332                         slot = econtext->ecxt_scantuple;
333                         break;
334         }
335
336         /*
337          * extract tuple information from the slot
338          */
339         heapTuple = slot->val;
340         tuple_type = slot->ttc_tupleDescriptor;
341
342         attnum = variable->varattno;
343
344         /* (See prolog for explanation of this Assert) */
345         Assert(attnum <= 0 ||
346                    (attnum - 1 <= tuple_type->natts - 1 &&
347                         tuple_type->attrs[attnum - 1] != NULL &&
348                   variable->vartype == tuple_type->attrs[attnum - 1]->atttypid));
349
350         /*
351          * If the attribute number is invalid, then we are supposed to return
352          * the entire tuple; we give back a whole slot so that callers know
353          * what the tuple looks like.
354          *
355          * XXX this is a horrid crock: since the pointer to the slot might live
356          * longer than the current evaluation context, we are forced to copy
357          * the tuple and slot into a long-lived context --- we use
358          * TransactionCommandContext which should be safe enough.  This
359          * represents a serious memory leak if many such tuples are processed
360          * in one command, however.  We ought to redesign the representation
361          * of whole-tuple datums so that this is not necessary.
362          *
363          * We assume it's OK to point to the existing tupleDescriptor, rather
364          * than copy that too.
365          */
366         if (attnum == InvalidAttrNumber)
367         {
368                 MemoryContext oldContext;
369                 TupleTableSlot *tempSlot;
370                 HeapTuple       tup;
371
372                 oldContext = MemoryContextSwitchTo(TransactionCommandContext);
373                 tempSlot = MakeTupleTableSlot();
374                 tup = heap_copytuple(heapTuple);
375                 ExecStoreTuple(tup, tempSlot, InvalidBuffer, true);
376                 ExecSetSlotDescriptor(tempSlot, tuple_type, false);
377                 MemoryContextSwitchTo(oldContext);
378                 return PointerGetDatum(tempSlot);
379         }
380
381         result = heap_getattr(heapTuple,        /* tuple containing attribute */
382                                                   attnum,               /* attribute number of desired
383                                                                                  * attribute */
384                                                   tuple_type,   /* tuple descriptor of tuple */
385                                                   isNull);              /* return: is attribute null? */
386
387         return result;
388 }
389
390 /* ----------------------------------------------------------------
391  *              ExecEvalParam
392  *
393  *              Returns the value of a parameter.  A param node contains
394  *              something like ($.name) and the expression context contains
395  *              the current parameter bindings (name = "sam") (age = 34)...
396  *              so our job is to find and return the appropriate datum ("sam").
397  *
398  *              Q: if we have a parameter ($.foo) without a binding, i.e.
399  *                 there is no (foo = xxx) in the parameter list info,
400  *                 is this a fatal error or should this be a "not available"
401  *                 (in which case we could return NULL)?        -cim 10/13/89
402  * ----------------------------------------------------------------
403  */
404 Datum
405 ExecEvalParam(Param *expression, ExprContext *econtext, bool *isNull)
406 {
407         int                     thisParamKind = expression->paramkind;
408         AttrNumber      thisParamId = expression->paramid;
409
410         if (thisParamKind == PARAM_EXEC)
411         {
412                 /*
413                  * PARAM_EXEC params (internal executor parameters) are stored in
414                  * the ecxt_param_exec_vals array, and can be accessed by array index.
415                  */
416                 ParamExecData *prm;
417
418                 prm = &(econtext->ecxt_param_exec_vals[thisParamId]);
419                 if (prm->execPlan != NULL)
420                 {
421                         /* Parameter not evaluated yet, so go do it */
422                         ExecSetParamPlan(prm->execPlan, econtext);
423                         /* ExecSetParamPlan should have processed this param... */
424                         Assert(prm->execPlan == NULL);
425                 }
426                 *isNull = prm->isnull;
427                 return prm->value;
428         }
429         else
430         {
431                 /*
432                  * All other parameter types must be sought in ecxt_param_list_info.
433                  * NOTE: The last entry in the param array is always an
434                  * entry with kind == PARAM_INVALID.
435                  */
436                 ParamListInfo paramList = econtext->ecxt_param_list_info;
437                 char       *thisParamName = expression->paramname;
438                 bool            matchFound = false;
439
440                 if (paramList != NULL)
441                 {
442                         while (paramList->kind != PARAM_INVALID && !matchFound)
443                         {
444                                 if (thisParamKind == paramList->kind)
445                                 {
446                                         switch (thisParamKind)
447                                         {
448                                                 case PARAM_NAMED:
449                                                         if (strcmp(paramList->name, thisParamName) == 0)
450                                                                 matchFound = true;
451                                                         break;
452                                                 case PARAM_NUM:
453                                                         if (paramList->id == thisParamId)
454                                                                 matchFound = true;
455                                                         break;
456                                                 default:
457                                                         elog(ERROR, "ExecEvalParam: invalid paramkind %d",
458                                                                  thisParamKind);
459                                         }
460                                 }
461                                 if (!matchFound)
462                                         paramList++;
463                         } /* while */
464                 } /* if */
465
466                 if (!matchFound)
467                 {
468                         if (thisParamKind == PARAM_NAMED)
469                                 elog(ERROR, "ExecEvalParam: Unknown value for parameter %s",
470                                          thisParamName);
471                         else
472                                 elog(ERROR, "ExecEvalParam: Unknown value for parameter %d",
473                                          thisParamId);
474                 }
475
476                 *isNull = paramList->isnull;
477                 return paramList->value;
478         }
479 }
480
481
482 /* ----------------------------------------------------------------
483  *              ExecEvalOper / ExecEvalFunc support routines
484  * ----------------------------------------------------------------
485  */
486
487 /*
488  *              GetAttributeByName
489  *              GetAttributeByNum
490  *
491  *              These are functions which return the value of the
492  *              named attribute out of the tuple from the arg slot.  User defined
493  *              C functions which take a tuple as an argument are expected
494  *              to use this.  Ex: overpaid(EMP) might call GetAttributeByNum().
495  */
496 Datum
497 GetAttributeByNum(TupleTableSlot *slot,
498                                   AttrNumber attrno,
499                                   bool *isNull)
500 {
501         Datum           retval;
502
503         if (!AttributeNumberIsValid(attrno))
504                 elog(ERROR, "GetAttributeByNum: Invalid attribute number");
505
506         if (!AttrNumberIsForUserDefinedAttr(attrno))
507                 elog(ERROR, "GetAttributeByNum: cannot access system attributes here");
508
509         if (isNull == (bool *) NULL)
510                 elog(ERROR, "GetAttributeByNum: a NULL isNull flag was passed");
511
512         if (TupIsNull(slot))
513         {
514                 *isNull = true;
515                 return (Datum) 0;
516         }
517
518         retval = heap_getattr(slot->val,
519                                                   attrno,
520                                                   slot->ttc_tupleDescriptor,
521                                                   isNull);
522         if (*isNull)
523                 return (Datum) 0;
524
525         return retval;
526 }
527
528 Datum
529 GetAttributeByName(TupleTableSlot *slot, char *attname, bool *isNull)
530 {
531         AttrNumber      attrno;
532         TupleDesc       tupdesc;
533         Datum           retval;
534         int                     natts;
535         int                     i;
536
537         if (attname == NULL)
538                 elog(ERROR, "GetAttributeByName: Invalid attribute name");
539
540         if (isNull == (bool *) NULL)
541                 elog(ERROR, "GetAttributeByName: a NULL isNull flag was passed");
542
543         if (TupIsNull(slot))
544         {
545                 *isNull = true;
546                 return (Datum) 0;
547         }
548
549         tupdesc = slot->ttc_tupleDescriptor;
550         natts = slot->val->t_data->t_natts;
551
552         attrno = InvalidAttrNumber;
553         for (i = 0; i < tupdesc->natts; i++)
554         {
555                 if (namestrcmp(&(tupdesc->attrs[i]->attname), attname) == 0)
556                 {
557                         attrno = tupdesc->attrs[i]->attnum;
558                         break;
559                 }
560         }
561
562         if (attrno == InvalidAttrNumber)
563                 elog(ERROR, "GetAttributeByName: attribute %s not found", attname);
564
565         retval = heap_getattr(slot->val,
566                                                   attrno,
567                                                   tupdesc,
568                                                   isNull);
569         if (*isNull)
570                 return (Datum) 0;
571
572         return retval;
573 }
574
575 /*
576  * Evaluate arguments for a function.
577  */
578 static ExprDoneCond
579 ExecEvalFuncArgs(FunctionCallInfo fcinfo,
580                                  List *argList,
581                                  ExprContext *econtext)
582 {
583         ExprDoneCond argIsDone;
584         int                     i;
585         List       *arg;
586
587         argIsDone = ExprSingleResult;           /* default assumption */
588
589         i = 0;
590         foreach(arg, argList)
591         {
592                 ExprDoneCond thisArgIsDone;
593
594                 fcinfo->arg[i] = ExecEvalExpr((Node *) lfirst(arg),
595                                                                           econtext,
596                                                                           &fcinfo->argnull[i],
597                                                                           &thisArgIsDone);
598
599                 if (thisArgIsDone != ExprSingleResult)
600                 {
601                         /*
602                          * We allow only one argument to have a set value; we'd need
603                          * much more complexity to keep track of multiple set
604                          * arguments (cf. ExecTargetList) and it doesn't seem worth
605                          * it.
606                          */
607                         if (argIsDone != ExprSingleResult)
608                                 elog(ERROR, "Functions and operators can take only one set argument");
609                         argIsDone = thisArgIsDone;
610                 }
611                 i++;
612         }
613
614         fcinfo->nargs = i;
615
616         return argIsDone;
617 }
618
619 /*
620  *              ExecMakeFunctionResult
621  *
622  * Evaluate the arguments to a function and then the function itself.
623  */
624 Datum
625 ExecMakeFunctionResult(FunctionCachePtr fcache,
626                                            List *arguments,
627                                            ExprContext *econtext,
628                                            bool *isNull,
629                                            ExprDoneCond *isDone)
630 {
631         Datum           result;
632         FunctionCallInfoData fcinfo;
633         ReturnSetInfo rsinfo;           /* for functions returning sets */
634         ExprDoneCond argDone;
635         bool            hasSetArg;
636         int                     i;
637
638         /*
639          * arguments is a list of expressions to evaluate before passing to
640          * the function manager.  We skip the evaluation if it was already
641          * done in the previous call (ie, we are continuing the evaluation of
642          * a set-valued function).      Otherwise, collect the current argument
643          * values into fcinfo.
644          */
645         if (!fcache->setArgsValid)
646         {
647                 /* Need to prep callinfo structure */
648                 MemSet(&fcinfo, 0, sizeof(fcinfo));
649                 fcinfo.flinfo = &(fcache->func);
650                 argDone = ExecEvalFuncArgs(&fcinfo, arguments, econtext);
651                 if (argDone == ExprEndResult)
652                 {
653                         /* input is an empty set, so return an empty set. */
654                         *isNull = true;
655                         if (isDone)
656                                 *isDone = ExprEndResult;
657                         else
658                                 elog(ERROR, "Set-valued function called in context that cannot accept a set");
659                         return (Datum) 0;
660                 }
661                 hasSetArg = (argDone != ExprSingleResult);
662         }
663         else
664         {
665                 /* Copy callinfo from previous evaluation */
666                 memcpy(&fcinfo, &fcache->setArgs, sizeof(fcinfo));
667                 hasSetArg = fcache->setHasSetArg;
668                 /* Reset flag (we may set it again below) */
669                 fcache->setArgsValid = false;
670         }
671
672         /*
673          * If function returns set, prepare a resultinfo node for
674          * communication
675          */
676         if (fcache->func.fn_retset)
677         {
678                 fcinfo.resultinfo = (Node *) &rsinfo;
679                 rsinfo.type = T_ReturnSetInfo;
680                 rsinfo.econtext = econtext;
681                 rsinfo.expectedDesc = NULL;
682                 rsinfo.allowedModes = (int) SFRM_ValuePerCall;
683                 rsinfo.returnMode = SFRM_ValuePerCall;
684                 /* isDone is filled below */
685                 rsinfo.setResult = NULL;
686                 rsinfo.setDesc = NULL;
687         }
688
689         /*
690          * now return the value gotten by calling the function manager,
691          * passing the function the evaluated parameter values.
692          */
693         if (fcache->func.fn_retset || hasSetArg)
694         {
695                 /*
696                  * We need to return a set result.      Complain if caller not ready
697                  * to accept one.
698                  */
699                 if (isDone == NULL)
700                         elog(ERROR, "Set-valued function called in context that cannot accept a set");
701
702                 /*
703                  * This loop handles the situation where we have both a set
704                  * argument and a set-valued function.  Once we have exhausted the
705                  * function's value(s) for a particular argument value, we have to
706                  * get the next argument value and start the function over again.
707                  * We might have to do it more than once, if the function produces
708                  * an empty result set for a particular input value.
709                  */
710                 for (;;)
711                 {
712                         /*
713                          * If function is strict, and there are any NULL arguments,
714                          * skip calling the function (at least for this set of args).
715                          */
716                         bool            callit = true;
717
718                         if (fcache->func.fn_strict)
719                         {
720                                 for (i = 0; i < fcinfo.nargs; i++)
721                                 {
722                                         if (fcinfo.argnull[i])
723                                         {
724                                                 callit = false;
725                                                 break;
726                                         }
727                                 }
728                         }
729
730                         if (callit)
731                         {
732                                 fcinfo.isnull = false;
733                                 rsinfo.isDone = ExprSingleResult;
734                                 result = FunctionCallInvoke(&fcinfo);
735                                 *isNull = fcinfo.isnull;
736                                 *isDone = rsinfo.isDone;
737                         }
738                         else
739                         {
740                                 result = (Datum) 0;
741                                 *isNull = true;
742                                 *isDone = ExprEndResult;
743                         }
744
745                         if (*isDone != ExprEndResult)
746                         {
747                                 /*
748                                  * Got a result from current argument.  If function itself
749                                  * returns set, save the current argument values to re-use
750                                  * on the next call.
751                                  */
752                                 if (fcache->func.fn_retset)
753                                 {
754                                         memcpy(&fcache->setArgs, &fcinfo, sizeof(fcinfo));
755                                         fcache->setHasSetArg = hasSetArg;
756                                         fcache->setArgsValid = true;
757                                 }
758
759                                 /*
760                                  * Make sure we say we are returning a set, even if the
761                                  * function itself doesn't return sets.
762                                  */
763                                 *isDone = ExprMultipleResult;
764                                 break;
765                         }
766
767                         /* Else, done with this argument */
768                         if (!hasSetArg)
769                                 break;                  /* input not a set, so done */
770
771                         /* Re-eval args to get the next element of the input set */
772                         argDone = ExecEvalFuncArgs(&fcinfo, arguments, econtext);
773
774                         if (argDone != ExprMultipleResult)
775                         {
776                                 /* End of argument set, so we're done. */
777                                 *isNull = true;
778                                 *isDone = ExprEndResult;
779                                 result = (Datum) 0;
780                                 break;
781                         }
782
783                         /*
784                          * If we reach here, loop around to run the function on the
785                          * new argument.
786                          */
787                 }
788         }
789         else
790         {
791                 /*
792                  * Non-set case: much easier.
793                  *
794                  * If function is strict, and there are any NULL arguments, skip
795                  * calling the function and return NULL.
796                  */
797                 if (fcache->func.fn_strict)
798                 {
799                         for (i = 0; i < fcinfo.nargs; i++)
800                         {
801                                 if (fcinfo.argnull[i])
802                                 {
803                                         *isNull = true;
804                                         return (Datum) 0;
805                                 }
806                         }
807                 }
808                 fcinfo.isnull = false;
809                 result = FunctionCallInvoke(&fcinfo);
810                 *isNull = fcinfo.isnull;
811         }
812
813         return result;
814 }
815
816
817 /*
818  *              ExecMakeTableFunctionResult
819  *
820  * Evaluate a table function, producing a materialized result in a Tuplestore
821  * object.      (If function returns an empty set, we just return NULL instead.)
822  */
823 Tuplestorestate *
824 ExecMakeTableFunctionResult(Node *funcexpr,
825                                                         ExprContext *econtext,
826                                                         TupleDesc expectedDesc,
827                                                         TupleDesc *returnDesc)
828 {
829         Tuplestorestate *tupstore = NULL;
830         TupleDesc       tupdesc = NULL;
831         Oid                     funcrettype;
832         FunctionCallInfoData fcinfo;
833         ReturnSetInfo rsinfo;
834         MemoryContext callerContext;
835         MemoryContext oldcontext;
836         TupleTableSlot *slot;
837         bool            direct_function_call;
838         bool            first_time = true;
839         bool            returnsTuple = false;
840
841         /*
842          * Normally the passed expression tree will be a FUNC_EXPR, since the
843          * grammar only allows a function call at the top level of a table
844          * function reference.  However, if the function doesn't return set then
845          * the planner might have replaced the function call via constant-folding
846          * or inlining.  So if we see any other kind of expression node, execute
847          * it via the general ExecEvalExpr() code; the only difference is that
848          * we don't get a chance to pass a special ReturnSetInfo to any functions
849          * buried in the expression.
850          */
851         if (funcexpr &&
852                 IsA(funcexpr, Expr) &&
853                 ((Expr *) funcexpr)->opType == FUNC_EXPR)
854         {
855                 Func       *func;
856                 List       *argList;
857                 FunctionCachePtr fcache;
858                 ExprDoneCond argDone;
859
860                 /*
861                  * This path is similar to ExecMakeFunctionResult.
862                  */
863                 direct_function_call = true;
864
865                 funcrettype = ((Expr *) funcexpr)->typeOid;
866                 func = (Func *) ((Expr *) funcexpr)->oper;
867                 argList = ((Expr *) funcexpr)->args;
868
869                 /*
870                  * get the fcache from the Func node. If it is NULL, then initialize
871                  * it
872                  */
873                 fcache = func->func_fcache;
874                 if (fcache == NULL)
875                 {
876                         fcache = init_fcache(func->funcid, length(argList),
877                                                                  econtext->ecxt_per_query_memory);
878                         func->func_fcache = fcache;
879                 }
880
881                 /*
882                  * Evaluate the function's argument list.
883                  *
884                  * Note: ideally, we'd do this in the per-tuple context, but then the
885                  * argument values would disappear when we reset the context in the
886                  * inner loop.  So do it in caller context.  Perhaps we should make a
887                  * separate context just to hold the evaluated arguments?
888                  */
889                 MemSet(&fcinfo, 0, sizeof(fcinfo));
890                 fcinfo.flinfo = &(fcache->func);
891                 argDone = ExecEvalFuncArgs(&fcinfo, argList, econtext);
892                 /* We don't allow sets in the arguments of the table function */
893                 if (argDone != ExprSingleResult)
894                         elog(ERROR, "Set-valued function called in context that cannot accept a set");
895
896                 /*
897                  * If function is strict, and there are any NULL arguments, skip
898                  * calling the function and return NULL (actually an empty set).
899                  */
900                 if (fcache->func.fn_strict)
901                 {
902                         int                     i;
903
904                         for (i = 0; i < fcinfo.nargs; i++)
905                         {
906                                 if (fcinfo.argnull[i])
907                                 {
908                                         *returnDesc = NULL;
909                                         return NULL;
910                                 }
911                         }
912                 }
913         }
914         else
915         {
916                 /* Treat funcexpr as a generic expression */
917                 direct_function_call = false;
918                 funcrettype = exprType(funcexpr);
919         }
920
921         /*
922          * Prepare a resultinfo node for communication.  We always do this
923          * even if not expecting a set result, so that we can pass
924          * expectedDesc.  In the generic-expression case, the expression
925          * doesn't actually get to see the resultinfo, but set it up anyway
926          * because we use some of the fields as our own state variables.
927          */
928         fcinfo.resultinfo = (Node *) &rsinfo;
929         rsinfo.type = T_ReturnSetInfo;
930         rsinfo.econtext = econtext;
931         rsinfo.expectedDesc = expectedDesc;
932         rsinfo.allowedModes = (int) (SFRM_ValuePerCall | SFRM_Materialize);
933         rsinfo.returnMode = SFRM_ValuePerCall;
934         /* isDone is filled below */
935         rsinfo.setResult = NULL;
936         rsinfo.setDesc = NULL;
937
938         /*
939          * Switch to short-lived context for calling the function or expression.
940          */
941         callerContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
942
943         /*
944          * Loop to handle the ValuePerCall protocol (which is also the same
945          * behavior needed in the generic ExecEvalExpr path).
946          */
947         for (;;)
948         {
949                 Datum           result;
950                 HeapTuple       tuple;
951
952                 /*
953                  * reset per-tuple memory context before each call of the
954                  * function or expression. This cleans up any local memory the
955                  * function may leak when called.
956                  */
957                 ResetExprContext(econtext);
958
959                 /* Call the function or expression one time */
960                 if (direct_function_call)
961                 {
962                         fcinfo.isnull = false;
963                         rsinfo.isDone = ExprSingleResult;
964                         result = FunctionCallInvoke(&fcinfo);
965                 }
966                 else
967                 {
968                         result = ExecEvalExpr(funcexpr, econtext,
969                                                                   &fcinfo.isnull, &rsinfo.isDone);
970                 }
971
972                 /* Which protocol does function want to use? */
973                 if (rsinfo.returnMode == SFRM_ValuePerCall)
974                 {
975                         /*
976                          * Check for end of result set.
977                          *
978                          * Note: if function returns an empty set, we don't build a
979                          * tupdesc or tuplestore (since we can't get a tupdesc in the
980                          * function-returning-tuple case)
981                          */
982                         if (rsinfo.isDone == ExprEndResult)
983                                 break;
984
985                         /*
986                          * If first time through, build tupdesc and tuplestore for
987                          * result
988                          */
989                         if (first_time)
990                         {
991                                 oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
992                                 if (funcrettype == RECORDOID ||
993                                         get_typtype(funcrettype) == 'c')
994                                 {
995                                         /*
996                                          * Composite type, so function should have returned a
997                                          * TupleTableSlot; use its descriptor
998                                          */
999                                         slot = (TupleTableSlot *) DatumGetPointer(result);
1000                                         if (fcinfo.isnull ||
1001                                                 !slot ||
1002                                                 !IsA(slot, TupleTableSlot) ||
1003                                                 !slot->ttc_tupleDescriptor)
1004                                                 elog(ERROR, "ExecMakeTableFunctionResult: Invalid result from function returning tuple");
1005                                         tupdesc = CreateTupleDescCopy(slot->ttc_tupleDescriptor);
1006                                         returnsTuple = true;
1007                                 }
1008                                 else
1009                                 {
1010                                         /*
1011                                          * Scalar type, so make a single-column descriptor
1012                                          */
1013                                         tupdesc = CreateTemplateTupleDesc(1, false);
1014                                         TupleDescInitEntry(tupdesc,
1015                                                                            (AttrNumber) 1,
1016                                                                            "column",
1017                                                                            funcrettype,
1018                                                                            -1,
1019                                                                            0,
1020                                                                            false);
1021                                 }
1022                                 tupstore = tuplestore_begin_heap(true,  /* randomAccess */
1023                                                                                                  SortMem);
1024                                 MemoryContextSwitchTo(oldcontext);
1025                                 rsinfo.setResult = tupstore;
1026                                 rsinfo.setDesc = tupdesc;
1027                         }
1028
1029                         /*
1030                          * Store current resultset item.
1031                          */
1032                         if (returnsTuple)
1033                         {
1034                                 slot = (TupleTableSlot *) DatumGetPointer(result);
1035                                 if (fcinfo.isnull ||
1036                                         !slot ||
1037                                         !IsA(slot, TupleTableSlot) ||
1038                                         TupIsNull(slot))
1039                                         elog(ERROR, "ExecMakeTableFunctionResult: Invalid result from function returning tuple");
1040                                 tuple = slot->val;
1041                         }
1042                         else
1043                         {
1044                                 char            nullflag;
1045
1046                                 nullflag = fcinfo.isnull ? 'n' : ' ';
1047                                 tuple = heap_formtuple(tupdesc, &result, &nullflag);
1048                         }
1049
1050                         oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
1051                         tuplestore_puttuple(tupstore, tuple);
1052                         MemoryContextSwitchTo(oldcontext);
1053
1054                         /*
1055                          * Are we done?
1056                          */
1057                         if (rsinfo.isDone != ExprMultipleResult)
1058                                 break;
1059                 }
1060                 else if (rsinfo.returnMode == SFRM_Materialize)
1061                 {
1062                         /* check we're on the same page as the function author */
1063                         if (!first_time || rsinfo.isDone != ExprSingleResult)
1064                                 elog(ERROR, "ExecMakeTableFunctionResult: Materialize-mode protocol not followed");
1065                         /* Done evaluating the set result */
1066                         break;
1067                 }
1068                 else
1069                         elog(ERROR, "ExecMakeTableFunctionResult: unknown returnMode %d",
1070                                  (int) rsinfo.returnMode);
1071
1072                 first_time = false;
1073         }
1074
1075         /* If we have a locally-created tupstore, close it up */
1076         if (tupstore)
1077         {
1078                 MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
1079                 tuplestore_donestoring(tupstore);
1080         }
1081
1082         MemoryContextSwitchTo(callerContext);
1083
1084         /* The returned pointers are those in rsinfo */
1085         *returnDesc = rsinfo.setDesc;
1086         return rsinfo.setResult;
1087 }
1088
1089
1090 /* ----------------------------------------------------------------
1091  *              ExecEvalOper
1092  *              ExecEvalFunc
1093  *              ExecEvalDistinct
1094  *
1095  *              Evaluate the functional result of a list of arguments by calling the
1096  *              function manager.
1097  * ----------------------------------------------------------------
1098  */
1099
1100 /* ----------------------------------------------------------------
1101  *              ExecEvalOper
1102  * ----------------------------------------------------------------
1103  */
1104 static Datum
1105 ExecEvalOper(Expr *opClause,
1106                          ExprContext *econtext,
1107                          bool *isNull,
1108                          ExprDoneCond *isDone)
1109 {
1110         Oper       *op;
1111         List       *argList;
1112         FunctionCachePtr fcache;
1113
1114         /*
1115          * we extract the oid of the function associated with the op and then
1116          * pass the work onto ExecMakeFunctionResult which evaluates the
1117          * arguments and returns the result of calling the function on the
1118          * evaluated arguments.
1119          */
1120         op = (Oper *) opClause->oper;
1121         argList = opClause->args;
1122
1123         /*
1124          * get the fcache from the Oper node. If it is NULL, then initialize
1125          * it
1126          */
1127         fcache = op->op_fcache;
1128         if (fcache == NULL)
1129         {
1130                 fcache = init_fcache(op->opid, length(argList),
1131                                                          econtext->ecxt_per_query_memory);
1132                 op->op_fcache = fcache;
1133         }
1134
1135         return ExecMakeFunctionResult(fcache, argList, econtext,
1136                                                                   isNull, isDone);
1137 }
1138
1139 /* ----------------------------------------------------------------
1140  *              ExecEvalFunc
1141  * ----------------------------------------------------------------
1142  */
1143
1144 static Datum
1145 ExecEvalFunc(Expr *funcClause,
1146                          ExprContext *econtext,
1147                          bool *isNull,
1148                          ExprDoneCond *isDone)
1149 {
1150         Func       *func;
1151         List       *argList;
1152         FunctionCachePtr fcache;
1153
1154         /*
1155          * we extract the oid of the function associated with the func node
1156          * and then pass the work onto ExecMakeFunctionResult which evaluates
1157          * the arguments and returns the result of calling the function on the
1158          * evaluated arguments.
1159          *
1160          * this is nearly identical to the ExecEvalOper code.
1161          */
1162         func = (Func *) funcClause->oper;
1163         argList = funcClause->args;
1164
1165         /*
1166          * get the fcache from the Func node. If it is NULL, then initialize
1167          * it
1168          */
1169         fcache = func->func_fcache;
1170         if (fcache == NULL)
1171         {
1172                 fcache = init_fcache(func->funcid, length(argList),
1173                                                          econtext->ecxt_per_query_memory);
1174                 func->func_fcache = fcache;
1175         }
1176
1177         return ExecMakeFunctionResult(fcache, argList, econtext,
1178                                                                   isNull, isDone);
1179 }
1180
1181 /* ----------------------------------------------------------------
1182  *              ExecEvalDistinct
1183  *
1184  * IS DISTINCT FROM must evaluate arguments to determine whether
1185  * they are NULL; if either is NULL then the result is already
1186  * known. If neither is NULL, then proceed to evaluate the
1187  * function. Note that this is *always* derived from the equals
1188  * operator, but since we need special processing of the arguments
1189  * we can not simply reuse ExecEvalOper() or ExecEvalFunc().
1190  * ----------------------------------------------------------------
1191  */
1192 static Datum
1193 ExecEvalDistinct(Expr *opClause,
1194                                  ExprContext *econtext,
1195                                  bool *isNull,
1196                                  ExprDoneCond *isDone)
1197 {
1198         Datum           result;
1199         FunctionCachePtr fcache;
1200         FunctionCallInfoData fcinfo;
1201         ExprDoneCond argDone;
1202         Oper       *op;
1203         List       *argList;
1204
1205         /*
1206          * extract info from opClause
1207          */
1208         op = (Oper *) opClause->oper;
1209         argList = opClause->args;
1210
1211         /*
1212          * get the fcache from the Oper node. If it is NULL, then initialize
1213          * it
1214          */
1215         fcache = op->op_fcache;
1216         if (fcache == NULL)
1217         {
1218                 fcache = init_fcache(op->opid, length(argList),
1219                                                          econtext->ecxt_per_query_memory);
1220                 op->op_fcache = fcache;
1221         }
1222         Assert(!fcache->func.fn_retset);
1223
1224         /* Need to prep callinfo structure */
1225         MemSet(&fcinfo, 0, sizeof(fcinfo));
1226         fcinfo.flinfo = &(fcache->func);
1227         argDone = ExecEvalFuncArgs(&fcinfo, argList, econtext);
1228         if (argDone != ExprSingleResult)
1229                 elog(ERROR, "IS DISTINCT FROM does not support set arguments");
1230         Assert(fcinfo.nargs == 2);
1231
1232         if (fcinfo.argnull[0] && fcinfo.argnull[1])
1233         {
1234                 /* Both NULL? Then is not distinct... */
1235                 result = BoolGetDatum(FALSE);
1236         }
1237         else if (fcinfo.argnull[0] || fcinfo.argnull[1])
1238         {
1239                 /* Only one is NULL? Then is distinct... */
1240                 result = BoolGetDatum(TRUE);
1241         }
1242         else
1243         {
1244                 fcinfo.isnull = false;
1245                 result = FunctionCallInvoke(&fcinfo);
1246                 *isNull = fcinfo.isnull;
1247                 /* Must invert result of "=" */
1248                 result = BoolGetDatum(!DatumGetBool(result));
1249         }
1250
1251         return result;
1252 }
1253
1254 /* ----------------------------------------------------------------
1255  *              ExecEvalNot
1256  *              ExecEvalOr
1257  *              ExecEvalAnd
1258  *
1259  *              Evaluate boolean expressions.  Evaluation of 'or' is
1260  *              short-circuited when the first true (or null) value is found.
1261  *
1262  *              The query planner reformulates clause expressions in the
1263  *              qualification to conjunctive normal form.  If we ever get
1264  *              an AND to evaluate, we can be sure that it's not a top-level
1265  *              clause in the qualification, but appears lower (as a function
1266  *              argument, for example), or in the target list.  Not that you
1267  *              need to know this, mind you...
1268  * ----------------------------------------------------------------
1269  */
1270 static Datum
1271 ExecEvalNot(Expr *notclause, ExprContext *econtext, bool *isNull)
1272 {
1273         Node       *clause;
1274         Datum           expr_value;
1275
1276         clause = lfirst(notclause->args);
1277
1278         expr_value = ExecEvalExpr(clause, econtext, isNull, NULL);
1279
1280         /*
1281          * if the expression evaluates to null, then we just cascade the null
1282          * back to whoever called us.
1283          */
1284         if (*isNull)
1285                 return expr_value;
1286
1287         /*
1288          * evaluation of 'not' is simple.. expr is false, then return 'true'
1289          * and vice versa.
1290          */
1291         return BoolGetDatum(!DatumGetBool(expr_value));
1292 }
1293
1294 /* ----------------------------------------------------------------
1295  *              ExecEvalOr
1296  * ----------------------------------------------------------------
1297  */
1298 static Datum
1299 ExecEvalOr(Expr *orExpr, ExprContext *econtext, bool *isNull)
1300 {
1301         List       *clauses;
1302         List       *clause;
1303         bool            AnyNull;
1304         Datum           clause_value;
1305
1306         clauses = orExpr->args;
1307         AnyNull = false;
1308
1309         /*
1310          * If any of the clauses is TRUE, the OR result is TRUE regardless of
1311          * the states of the rest of the clauses, so we can stop evaluating
1312          * and return TRUE immediately.  If none are TRUE and one or more is
1313          * NULL, we return NULL; otherwise we return FALSE.  This makes sense
1314          * when you interpret NULL as "don't know": if we have a TRUE then the
1315          * OR is TRUE even if we aren't sure about some of the other inputs.
1316          * If all the known inputs are FALSE, but we have one or more "don't
1317          * knows", then we have to report that we "don't know" what the OR's
1318          * result should be --- perhaps one of the "don't knows" would have
1319          * been TRUE if we'd known its value.  Only when all the inputs are
1320          * known to be FALSE can we state confidently that the OR's result is
1321          * FALSE.
1322          */
1323         foreach(clause, clauses)
1324         {
1325                 clause_value = ExecEvalExpr((Node *) lfirst(clause),
1326                                                                         econtext, isNull, NULL);
1327
1328                 /*
1329                  * if we have a non-null true result, then return it.
1330                  */
1331                 if (*isNull)
1332                         AnyNull = true;         /* remember we got a null */
1333                 else if (DatumGetBool(clause_value))
1334                         return clause_value;
1335         }
1336
1337         /* AnyNull is true if at least one clause evaluated to NULL */
1338         *isNull = AnyNull;
1339         return BoolGetDatum(false);
1340 }
1341
1342 /* ----------------------------------------------------------------
1343  *              ExecEvalAnd
1344  * ----------------------------------------------------------------
1345  */
1346 static Datum
1347 ExecEvalAnd(Expr *andExpr, ExprContext *econtext, bool *isNull)
1348 {
1349         List       *clauses;
1350         List       *clause;
1351         bool            AnyNull;
1352         Datum           clause_value;
1353
1354         clauses = andExpr->args;
1355         AnyNull = false;
1356
1357         /*
1358          * If any of the clauses is FALSE, the AND result is FALSE regardless
1359          * of the states of the rest of the clauses, so we can stop evaluating
1360          * and return FALSE immediately.  If none are FALSE and one or more is
1361          * NULL, we return NULL; otherwise we return TRUE.      This makes sense
1362          * when you interpret NULL as "don't know", using the same sort of
1363          * reasoning as for OR, above.
1364          */
1365         foreach(clause, clauses)
1366         {
1367                 clause_value = ExecEvalExpr((Node *) lfirst(clause),
1368                                                                         econtext, isNull, NULL);
1369
1370                 /*
1371                  * if we have a non-null false result, then return it.
1372                  */
1373                 if (*isNull)
1374                         AnyNull = true;         /* remember we got a null */
1375                 else if (!DatumGetBool(clause_value))
1376                         return clause_value;
1377         }
1378
1379         /* AnyNull is true if at least one clause evaluated to NULL */
1380         *isNull = AnyNull;
1381         return BoolGetDatum(!AnyNull);
1382 }
1383
1384 /* ----------------------------------------------------------------
1385  *              ExecEvalCase
1386  *
1387  *              Evaluate a CASE clause. Will have boolean expressions
1388  *              inside the WHEN clauses, and will have expressions
1389  *              for results.
1390  *              - thomas 1998-11-09
1391  * ----------------------------------------------------------------
1392  */
1393 static Datum
1394 ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext,
1395                          bool *isNull, ExprDoneCond *isDone)
1396 {
1397         List       *clauses;
1398         List       *clause;
1399         Datum           clause_value;
1400
1401         clauses = caseExpr->args;
1402
1403         /*
1404          * we evaluate each of the WHEN clauses in turn, as soon as one is
1405          * true we return the corresponding result. If none are true then we
1406          * return the value of the default clause, or NULL if there is none.
1407          */
1408         foreach(clause, clauses)
1409         {
1410                 CaseWhen   *wclause = lfirst(clause);
1411
1412                 clause_value = ExecEvalExpr(wclause->expr,
1413                                                                         econtext,
1414                                                                         isNull,
1415                                                                         NULL);
1416
1417                 /*
1418                  * if we have a true test, then we return the result, since the
1419                  * case statement is satisfied.  A NULL result from the test is
1420                  * not considered true.
1421                  */
1422                 if (DatumGetBool(clause_value) && !*isNull)
1423                 {
1424                         return ExecEvalExpr(wclause->result,
1425                                                                 econtext,
1426                                                                 isNull,
1427                                                                 isDone);
1428                 }
1429         }
1430
1431         if (caseExpr->defresult)
1432         {
1433                 return ExecEvalExpr(caseExpr->defresult,
1434                                                         econtext,
1435                                                         isNull,
1436                                                         isDone);
1437         }
1438
1439         *isNull = true;
1440         return (Datum) 0;
1441 }
1442
1443 /* ----------------------------------------------------------------
1444  *              ExecEvalNullTest
1445  *
1446  *              Evaluate a NullTest node.
1447  * ----------------------------------------------------------------
1448  */
1449 static Datum
1450 ExecEvalNullTest(NullTest *ntest,
1451                                  ExprContext *econtext,
1452                                  bool *isNull,
1453                                  ExprDoneCond *isDone)
1454 {
1455         Datum           result;
1456
1457         result = ExecEvalExpr(ntest->arg, econtext, isNull, isDone);
1458         switch (ntest->nulltesttype)
1459         {
1460                 case IS_NULL:
1461                         if (*isNull)
1462                         {
1463                                 *isNull = false;
1464                                 return BoolGetDatum(true);
1465                         }
1466                         else
1467                                 return BoolGetDatum(false);
1468                 case IS_NOT_NULL:
1469                         if (*isNull)
1470                         {
1471                                 *isNull = false;
1472                                 return BoolGetDatum(false);
1473                         }
1474                         else
1475                                 return BoolGetDatum(true);
1476                 default:
1477                         elog(ERROR, "ExecEvalNullTest: unexpected nulltesttype %d",
1478                                  (int) ntest->nulltesttype);
1479                         return (Datum) 0;       /* keep compiler quiet */
1480         }
1481 }
1482
1483 /* ----------------------------------------------------------------
1484  *              ExecEvalBooleanTest
1485  *
1486  *              Evaluate a BooleanTest node.
1487  * ----------------------------------------------------------------
1488  */
1489 static Datum
1490 ExecEvalBooleanTest(BooleanTest *btest,
1491                                         ExprContext *econtext,
1492                                         bool *isNull,
1493                                         ExprDoneCond *isDone)
1494 {
1495         Datum           result;
1496
1497         result = ExecEvalExpr(btest->arg, econtext, isNull, isDone);
1498         switch (btest->booltesttype)
1499         {
1500                 case IS_TRUE:
1501                         if (*isNull)
1502                         {
1503                                 *isNull = false;
1504                                 return BoolGetDatum(false);
1505                         }
1506                         else if (DatumGetBool(result))
1507                                 return BoolGetDatum(true);
1508                         else
1509                                 return BoolGetDatum(false);
1510                 case IS_NOT_TRUE:
1511                         if (*isNull)
1512                         {
1513                                 *isNull = false;
1514                                 return BoolGetDatum(true);
1515                         }
1516                         else if (DatumGetBool(result))
1517                                 return BoolGetDatum(false);
1518                         else
1519                                 return BoolGetDatum(true);
1520                 case IS_FALSE:
1521                         if (*isNull)
1522                         {
1523                                 *isNull = false;
1524                                 return BoolGetDatum(false);
1525                         }
1526                         else if (DatumGetBool(result))
1527                                 return BoolGetDatum(false);
1528                         else
1529                                 return BoolGetDatum(true);
1530                 case IS_NOT_FALSE:
1531                         if (*isNull)
1532                         {
1533                                 *isNull = false;
1534                                 return BoolGetDatum(true);
1535                         }
1536                         else if (DatumGetBool(result))
1537                                 return BoolGetDatum(true);
1538                         else
1539                                 return BoolGetDatum(false);
1540                 case IS_UNKNOWN:
1541                         if (*isNull)
1542                         {
1543                                 *isNull = false;
1544                                 return BoolGetDatum(true);
1545                         }
1546                         else
1547                                 return BoolGetDatum(false);
1548                 case IS_NOT_UNKNOWN:
1549                         if (*isNull)
1550                         {
1551                                 *isNull = false;
1552                                 return BoolGetDatum(false);
1553                         }
1554                         else
1555                                 return BoolGetDatum(true);
1556                 default:
1557                         elog(ERROR, "ExecEvalBooleanTest: unexpected booltesttype %d",
1558                                  (int) btest->booltesttype);
1559                         return (Datum) 0;       /* keep compiler quiet */
1560         }
1561 }
1562
1563 /*
1564  * ExecEvalConstraintTestValue
1565  *
1566  * Return the value stored by constraintTest.
1567  */
1568 static Datum
1569 ExecEvalConstraintTestValue(ConstraintTestValue *conVal, ExprContext *econtext,
1570                                                         bool *isNull, ExprDoneCond *isDone)
1571 {
1572         /*
1573          * If the Datum hasn't been set, then it's ExecEvalConstraintTest
1574          * hasn't been called.
1575          */
1576         *isNull = econtext->domainValue_isNull;
1577         return econtext->domainValue_datum;
1578 }
1579
1580 /*
1581  * ExecEvalConstraintTest
1582  *
1583  * Test the constraint against the data provided.  If the data fits
1584  * within the constraint specifications, pass it through (return the
1585  * datum) otherwise throw an error.
1586  */
1587 static Datum
1588 ExecEvalConstraintTest(ConstraintTest *constraint, ExprContext *econtext,
1589                                            bool *isNull, ExprDoneCond *isDone)
1590 {
1591         Datum           result;
1592
1593         result = ExecEvalExpr(constraint->arg, econtext, isNull, isDone);
1594
1595         switch (constraint->testtype)
1596         {
1597                 case CONSTR_TEST_NOTNULL:
1598                         if (*isNull)
1599                                 elog(ERROR, "Domain %s does not allow NULL values",
1600                                          constraint->domname);
1601                         break;
1602                 case CONSTR_TEST_CHECK:
1603                         {
1604                                 Datum   conResult;
1605
1606                                 /* Var with attnum == UnassignedAttrNum uses the result */
1607                                 econtext->domainValue_datum = result;
1608                                 econtext->domainValue_isNull = *isNull;
1609
1610                                 conResult = ExecEvalExpr(constraint->check_expr, econtext, isNull, isDone);
1611
1612                                 if (!DatumGetBool(conResult))
1613                                         elog(ERROR, "Domain %s constraint %s failed",
1614                                                  constraint->name, constraint->domname);
1615                         }
1616                         break;
1617                 default:
1618                         elog(ERROR, "ExecEvalConstraintTest: Constraint type unknown");
1619                         break;
1620         }
1621
1622         /* If all has gone well (constraint did not fail) return the datum */
1623         return result;
1624 }
1625
1626 /* ----------------------------------------------------------------
1627  *              ExecEvalFieldSelect
1628  *
1629  *              Evaluate a FieldSelect node.
1630  * ----------------------------------------------------------------
1631  */
1632 static Datum
1633 ExecEvalFieldSelect(FieldSelect *fselect,
1634                                         ExprContext *econtext,
1635                                         bool *isNull,
1636                                         ExprDoneCond *isDone)
1637 {
1638         Datum           result;
1639         TupleTableSlot *resSlot;
1640
1641         result = ExecEvalExpr(fselect->arg, econtext, isNull, isDone);
1642         if (*isNull)
1643                 return result;
1644         resSlot = (TupleTableSlot *) DatumGetPointer(result);
1645         Assert(resSlot != NULL && IsA(resSlot, TupleTableSlot));
1646         result = heap_getattr(resSlot->val,
1647                                                   fselect->fieldnum,
1648                                                   resSlot->ttc_tupleDescriptor,
1649                                                   isNull);
1650         return result;
1651 }
1652
1653 /* ----------------------------------------------------------------
1654  *              ExecEvalExpr
1655  *
1656  *              Recursively evaluate a targetlist or qualification expression.
1657  *
1658  * Inputs:
1659  *              expression: the expression tree to evaluate
1660  *              econtext: evaluation context information
1661  *
1662  * Outputs:
1663  *              return value: Datum value of result
1664  *              *isNull: set to TRUE if result is NULL (actual return value is
1665  *                               meaningless if so); set to FALSE if non-null result
1666  *              *isDone: set to indicator of set-result status
1667  *
1668  * A caller that can only accept a singleton (non-set) result should pass
1669  * NULL for isDone; if the expression computes a set result then an elog()
1670  * error will be reported.      If the caller does pass an isDone pointer then
1671  * *isDone is set to one of these three states:
1672  *              ExprSingleResult                singleton result (not a set)
1673  *              ExprMultipleResult              return value is one element of a set
1674  *              ExprEndResult                   there are no more elements in the set
1675  * When ExprMultipleResult is returned, the caller should invoke
1676  * ExecEvalExpr() repeatedly until ExprEndResult is returned.  ExprEndResult
1677  * is returned after the last real set element.  For convenience isNull will
1678  * always be set TRUE when ExprEndResult is returned, but this should not be
1679  * taken as indicating a NULL element of the set.  Note that these return
1680  * conventions allow us to distinguish among a singleton NULL, a NULL element
1681  * of a set, and an empty set.
1682  *
1683  * The caller should already have switched into the temporary memory
1684  * context econtext->ecxt_per_tuple_memory.  The convenience entry point
1685  * ExecEvalExprSwitchContext() is provided for callers who don't prefer to
1686  * do the switch in an outer loop.      We do not do the switch here because
1687  * it'd be a waste of cycles during recursive entries to ExecEvalExpr().
1688  *
1689  * This routine is an inner loop routine and must be as fast as possible.
1690  * ----------------------------------------------------------------
1691  */
1692 Datum
1693 ExecEvalExpr(Node *expression,
1694                          ExprContext *econtext,
1695                          bool *isNull,
1696                          ExprDoneCond *isDone)
1697 {
1698         Datum           retDatum;
1699
1700         /* Set default values for result flags: non-null, not a set result */
1701         *isNull = false;
1702         if (isDone)
1703                 *isDone = ExprSingleResult;
1704
1705         /* Is this still necessary?  Doubtful... */
1706         if (expression == NULL)
1707         {
1708                 *isNull = true;
1709                 return (Datum) 0;
1710         }
1711
1712         /*
1713          * here we dispatch the work to the appropriate type of function given
1714          * the type of our expression.
1715          */
1716         switch (nodeTag(expression))
1717         {
1718                 case T_Var:
1719                         retDatum = ExecEvalVar((Var *) expression, econtext, isNull);
1720                         break;
1721                 case T_Const:
1722                         {
1723                                 Const      *con = (Const *) expression;
1724
1725                                 retDatum = con->constvalue;
1726                                 *isNull = con->constisnull;
1727                                 break;
1728                         }
1729                 case T_Param:
1730                         retDatum = ExecEvalParam((Param *) expression, econtext, isNull);
1731                         break;
1732                 case T_Aggref:
1733                         retDatum = ExecEvalAggref((Aggref *) expression, econtext, isNull);
1734                         break;
1735                 case T_ArrayRef:
1736                         retDatum = ExecEvalArrayRef((ArrayRef *) expression,
1737                                                                                 econtext,
1738                                                                                 isNull,
1739                                                                                 isDone);
1740                         break;
1741                 case T_Expr:
1742                         {
1743                                 Expr       *expr = (Expr *) expression;
1744
1745                                 switch (expr->opType)
1746                                 {
1747                                         case OP_EXPR:
1748                                                 retDatum = ExecEvalOper(expr, econtext,
1749                                                                                                 isNull, isDone);
1750                                                 break;
1751                                         case FUNC_EXPR:
1752                                                 retDatum = ExecEvalFunc(expr, econtext,
1753                                                                                                 isNull, isDone);
1754                                                 break;
1755                                         case OR_EXPR:
1756                                                 retDatum = ExecEvalOr(expr, econtext, isNull);
1757                                                 break;
1758                                         case AND_EXPR:
1759                                                 retDatum = ExecEvalAnd(expr, econtext, isNull);
1760                                                 break;
1761                                         case NOT_EXPR:
1762                                                 retDatum = ExecEvalNot(expr, econtext, isNull);
1763                                                 break;
1764                                         case DISTINCT_EXPR:
1765                                                 retDatum = ExecEvalDistinct(expr, econtext,
1766                                                                                                         isNull, isDone);
1767                                                 break;
1768                                         case SUBPLAN_EXPR:
1769                                                 retDatum = ExecSubPlan((SubPlan *) expr->oper,
1770                                                                                            expr->args, econtext,
1771                                                                                            isNull);
1772                                                 break;
1773                                         default:
1774                                                 elog(ERROR, "ExecEvalExpr: unknown expression type %d",
1775                                                          expr->opType);
1776                                                 retDatum = 0;   /* keep compiler quiet */
1777                                                 break;
1778                                 }
1779                                 break;
1780                         }
1781                 case T_FieldSelect:
1782                         retDatum = ExecEvalFieldSelect((FieldSelect *) expression,
1783                                                                                    econtext,
1784                                                                                    isNull,
1785                                                                                    isDone);
1786                         break;
1787                 case T_RelabelType:
1788                         retDatum = ExecEvalExpr(((RelabelType *) expression)->arg,
1789                                                                         econtext,
1790                                                                         isNull,
1791                                                                         isDone);
1792                         break;
1793                 case T_CaseExpr:
1794                         retDatum = ExecEvalCase((CaseExpr *) expression,
1795                                                                         econtext,
1796                                                                         isNull,
1797                                                                         isDone);
1798                         break;
1799                 case T_NullTest:
1800                         retDatum = ExecEvalNullTest((NullTest *) expression,
1801                                                                                 econtext,
1802                                                                                 isNull,
1803                                                                                 isDone);
1804                         break;
1805                 case T_BooleanTest:
1806                         retDatum = ExecEvalBooleanTest((BooleanTest *) expression,
1807                                                                                    econtext,
1808                                                                                    isNull,
1809                                                                                    isDone);
1810                         break;
1811                 case T_ConstraintTest:
1812                         retDatum = ExecEvalConstraintTest((ConstraintTest *) expression,
1813                                                                                           econtext,
1814                                                                                           isNull,
1815                                                                                           isDone);
1816                         break;
1817                 case T_ConstraintTestValue:
1818                         retDatum = ExecEvalConstraintTestValue((ConstraintTestValue *) expression,
1819                                                                                                   econtext,
1820                                                                                                   isNull,
1821                                                                                                   isDone);
1822                         break;
1823                 default:
1824                         elog(ERROR, "ExecEvalExpr: unknown expression type %d",
1825                                  nodeTag(expression));
1826                         retDatum = 0;           /* keep compiler quiet */
1827                         break;
1828         }
1829
1830         return retDatum;
1831 }       /* ExecEvalExpr() */
1832
1833
1834 /*
1835  * Same as above, but get into the right allocation context explicitly.
1836  */
1837 Datum
1838 ExecEvalExprSwitchContext(Node *expression,
1839                                                   ExprContext *econtext,
1840                                                   bool *isNull,
1841                                                   ExprDoneCond *isDone)
1842 {
1843         Datum           retDatum;
1844         MemoryContext oldContext;
1845
1846         oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
1847         retDatum = ExecEvalExpr(expression, econtext, isNull, isDone);
1848         MemoryContextSwitchTo(oldContext);
1849         return retDatum;
1850 }
1851
1852
1853 /* ----------------------------------------------------------------
1854  *                                       ExecQual / ExecTargetList / ExecProject
1855  * ----------------------------------------------------------------
1856  */
1857
1858 /* ----------------------------------------------------------------
1859  *              ExecQual
1860  *
1861  *              Evaluates a conjunctive boolean expression (qual list) and
1862  *              returns true iff none of the subexpressions are false.
1863  *              (We also return true if the list is empty.)
1864  *
1865  *      If some of the subexpressions yield NULL but none yield FALSE,
1866  *      then the result of the conjunction is NULL (ie, unknown)
1867  *      according to three-valued boolean logic.  In this case,
1868  *      we return the value specified by the "resultForNull" parameter.
1869  *
1870  *      Callers evaluating WHERE clauses should pass resultForNull=FALSE,
1871  *      since SQL specifies that tuples with null WHERE results do not
1872  *      get selected.  On the other hand, callers evaluating constraint
1873  *      conditions should pass resultForNull=TRUE, since SQL also specifies
1874  *      that NULL constraint conditions are not failures.
1875  *
1876  *      NOTE: it would not be correct to use this routine to evaluate an
1877  *      AND subclause of a boolean expression; for that purpose, a NULL
1878  *      result must be returned as NULL so that it can be properly treated
1879  *      in the next higher operator (cf. ExecEvalAnd and ExecEvalOr).
1880  *      This routine is only used in contexts where a complete expression
1881  *      is being evaluated and we know that NULL can be treated the same
1882  *      as one boolean result or the other.
1883  *
1884  * ----------------------------------------------------------------
1885  */
1886 bool
1887 ExecQual(List *qual, ExprContext *econtext, bool resultForNull)
1888 {
1889         bool            result;
1890         MemoryContext oldContext;
1891         List       *qlist;
1892
1893         /*
1894          * debugging stuff
1895          */
1896         EV_printf("ExecQual: qual is ");
1897         EV_nodeDisplay(qual);
1898         EV_printf("\n");
1899
1900         IncrProcessed();
1901
1902         /*
1903          * Run in short-lived per-tuple context while computing expressions.
1904          */
1905         oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
1906
1907         /*
1908          * Evaluate the qual conditions one at a time.  If we find a FALSE
1909          * result, we can stop evaluating and return FALSE --- the AND result
1910          * must be FALSE.  Also, if we find a NULL result when resultForNull
1911          * is FALSE, we can stop and return FALSE --- the AND result must be
1912          * FALSE or NULL in that case, and the caller doesn't care which.
1913          *
1914          * If we get to the end of the list, we can return TRUE.  This will
1915          * happen when the AND result is indeed TRUE, or when the AND result
1916          * is NULL (one or more NULL subresult, with all the rest TRUE) and
1917          * the caller has specified resultForNull = TRUE.
1918          */
1919         result = true;
1920
1921         foreach(qlist, qual)
1922         {
1923                 Node       *clause = (Node *) lfirst(qlist);
1924                 Datum           expr_value;
1925                 bool            isNull;
1926
1927                 expr_value = ExecEvalExpr(clause, econtext, &isNull, NULL);
1928
1929                 if (isNull)
1930                 {
1931                         if (resultForNull == false)
1932                         {
1933                                 result = false; /* treat NULL as FALSE */
1934                                 break;
1935                         }
1936                 }
1937                 else
1938                 {
1939                         if (!DatumGetBool(expr_value))
1940                         {
1941                                 result = false; /* definitely FALSE */
1942                                 break;
1943                         }
1944                 }
1945         }
1946
1947         MemoryContextSwitchTo(oldContext);
1948
1949         return result;
1950 }
1951
1952 /*
1953  * Number of items in a tlist (including any resjunk items!)
1954  */
1955 int
1956 ExecTargetListLength(List *targetlist)
1957 {
1958         int                     len = 0;
1959         List       *tl;
1960
1961         foreach(tl, targetlist)
1962         {
1963                 TargetEntry *curTle = (TargetEntry *) lfirst(tl);
1964
1965                 if (curTle->resdom != NULL)
1966                         len++;
1967                 else
1968                         len += curTle->fjoin->fj_nNodes;
1969         }
1970         return len;
1971 }
1972
1973 /*
1974  * Number of items in a tlist, not including any resjunk items
1975  */
1976 int
1977 ExecCleanTargetListLength(List *targetlist)
1978 {
1979         int                     len = 0;
1980         List       *tl;
1981
1982         foreach(tl, targetlist)
1983         {
1984                 TargetEntry *curTle = (TargetEntry *) lfirst(tl);
1985
1986                 if (curTle->resdom != NULL)
1987                 {
1988                         if (!curTle->resdom->resjunk)
1989                                 len++;
1990                 }
1991                 else
1992                         len += curTle->fjoin->fj_nNodes;
1993         }
1994         return len;
1995 }
1996
1997 /* ----------------------------------------------------------------
1998  *              ExecTargetList
1999  *
2000  *              Evaluates a targetlist with respect to the current
2001  *              expression context and return a tuple.
2002  *
2003  * As with ExecEvalExpr, the caller should pass isDone = NULL if not
2004  * prepared to deal with sets of result tuples.  Otherwise, a return
2005  * of *isDone = ExprMultipleResult signifies a set element, and a return
2006  * of *isDone = ExprEndResult signifies end of the set of tuple.
2007  * ----------------------------------------------------------------
2008  */
2009 static HeapTuple
2010 ExecTargetList(List *targetlist,
2011                            int nodomains,
2012                            TupleDesc targettype,
2013                            Datum *values,
2014                            ExprContext *econtext,
2015                            ExprDoneCond *isDone)
2016 {
2017         MemoryContext oldContext;
2018
2019 #define NPREALLOCDOMAINS 64
2020         char            nullsArray[NPREALLOCDOMAINS];
2021         bool            fjIsNullArray[NPREALLOCDOMAINS];
2022         ExprDoneCond itemIsDoneArray[NPREALLOCDOMAINS];
2023         char       *nulls;
2024         bool       *fjIsNull;
2025         ExprDoneCond *itemIsDone;
2026         List       *tl;
2027         TargetEntry *tle;
2028         AttrNumber      resind;
2029         HeapTuple       newTuple;
2030         bool            isNull;
2031         bool            haveDoneSets;
2032         static struct tupleDesc NullTupleDesc;          /* we assume this inits to
2033                                                                                                  * zeroes */
2034
2035         /*
2036          * debugging stuff
2037          */
2038         EV_printf("ExecTargetList: tl is ");
2039         EV_nodeDisplay(targetlist);
2040         EV_printf("\n");
2041
2042         /*
2043          * Run in short-lived per-tuple context while computing expressions.
2044          */
2045         oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
2046
2047         /*
2048          * There used to be some klugy and demonstrably broken code here that
2049          * special-cased the situation where targetlist == NIL.  Now we just
2050          * fall through and return an empty-but-valid tuple.  We do, however,
2051          * have to cope with the possibility that targettype is NULL ---
2052          * heap_formtuple won't like that, so pass a dummy descriptor with
2053          * natts = 0 to deal with it.
2054          */
2055         if (targettype == NULL)
2056                 targettype = &NullTupleDesc;
2057
2058         /*
2059          * allocate an array of char's to hold the "null" information only if
2060          * we have a really large targetlist.  otherwise we use the stack.
2061          *
2062          * We also allocate a bool array that is used to hold fjoin result state,
2063          * and another array that holds the isDone status for each targetlist
2064          * item. The isDone status is needed so that we can iterate,
2065          * generating multiple tuples, when one or more tlist items return
2066          * sets.  (We expect the caller to call us again if we return:
2067          *
2068          * isDone = ExprMultipleResult.)
2069          */
2070         if (nodomains > NPREALLOCDOMAINS)
2071         {
2072                 nulls = (char *) palloc(nodomains * sizeof(char));
2073                 fjIsNull = (bool *) palloc(nodomains * sizeof(bool));
2074                 itemIsDone = (ExprDoneCond *) palloc(nodomains * sizeof(ExprDoneCond));
2075         }
2076         else
2077         {
2078                 nulls = nullsArray;
2079                 fjIsNull = fjIsNullArray;
2080                 itemIsDone = itemIsDoneArray;
2081         }
2082
2083         /*
2084          * evaluate all the expressions in the target list
2085          */
2086
2087         if (isDone)
2088                 *isDone = ExprSingleResult;             /* until proven otherwise */
2089
2090         haveDoneSets = false;           /* any exhausted set exprs in tlist? */
2091
2092         foreach(tl, targetlist)
2093         {
2094                 tle = lfirst(tl);
2095
2096                 if (tle->resdom != NULL)
2097                 {
2098                         resind = tle->resdom->resno - 1;
2099
2100                         values[resind] = ExecEvalExpr(tle->expr,
2101                                                                                   econtext,
2102                                                                                   &isNull,
2103                                                                                   &itemIsDone[resind]);
2104                         nulls[resind] = isNull ? 'n' : ' ';
2105
2106                         if (itemIsDone[resind] != ExprSingleResult)
2107                         {
2108                                 /* We have a set-valued expression in the tlist */
2109                                 if (isDone == NULL)
2110                                         elog(ERROR, "Set-valued function called in context that cannot accept a set");
2111                                 if (itemIsDone[resind] == ExprMultipleResult)
2112                                 {
2113                                         /* we have undone sets in the tlist, set flag */
2114                                         *isDone = ExprMultipleResult;
2115                                 }
2116                                 else
2117                                 {
2118                                         /* we have done sets in the tlist, set flag for that */
2119                                         haveDoneSets = true;
2120                                 }
2121                         }
2122                 }
2123                 else
2124                 {
2125 #ifdef SETS_FIXED
2126                         int                     curNode;
2127                         Resdom     *fjRes;
2128                         List       *fjTlist = (List *) tle->expr;
2129                         Fjoin      *fjNode = tle->fjoin;
2130                         int                     nNodes = fjNode->fj_nNodes;
2131                         DatumPtr        results = fjNode->fj_results;
2132
2133                         ExecEvalFjoin(tle, econtext, fjIsNull, isDone);
2134
2135                         /*
2136                          * XXX this is wrong, but since fjoin code is completely
2137                          * broken anyway, I'm not going to worry about it now --- tgl
2138                          * 8/23/00
2139                          */
2140                         if (isDone && *isDone == ExprEndResult)
2141                         {
2142                                 MemoryContextSwitchTo(oldContext);
2143                                 newTuple = NULL;
2144                                 goto exit;
2145                         }
2146
2147                         /*
2148                          * get the result from the inner node
2149                          */
2150                         fjRes = (Resdom *) fjNode->fj_innerNode;
2151                         resind = fjRes->resno - 1;
2152                         values[resind] = results[0];
2153                         nulls[resind] = fjIsNull[0] ? 'n' : ' ';
2154
2155                         /*
2156                          * Get results from all of the outer nodes
2157                          */
2158                         for (curNode = 1;
2159                                  curNode < nNodes;
2160                                  curNode++, fjTlist = lnext(fjTlist))
2161                         {
2162                                 Node       *outernode = lfirst(fjTlist);
2163
2164                                 fjRes = (Resdom *) outernode->iterexpr;
2165                                 resind = fjRes->resno - 1;
2166                                 values[resind] = results[curNode];
2167                                 nulls[resind] = fjIsNull[curNode] ? 'n' : ' ';
2168                         }
2169 #else
2170                         elog(ERROR, "ExecTargetList: fjoin nodes not currently supported");
2171 #endif
2172                 }
2173         }
2174
2175         if (haveDoneSets)
2176         {
2177                 /*
2178                  * note: can't get here unless we verified isDone != NULL
2179                  */
2180                 if (*isDone == ExprSingleResult)
2181                 {
2182                         /*
2183                          * all sets are done, so report that tlist expansion is
2184                          * complete.
2185                          */
2186                         *isDone = ExprEndResult;
2187                         MemoryContextSwitchTo(oldContext);
2188                         newTuple = NULL;
2189                         goto exit;
2190                 }
2191                 else
2192                 {
2193                         /*
2194                          * We have some done and some undone sets.      Restart the done
2195                          * ones so that we can deliver a tuple (if possible).
2196                          */
2197                         foreach(tl, targetlist)
2198                         {
2199                                 tle = lfirst(tl);
2200
2201                                 if (tle->resdom != NULL)
2202                                 {
2203                                         resind = tle->resdom->resno - 1;
2204
2205                                         if (itemIsDone[resind] == ExprEndResult)
2206                                         {
2207                                                 values[resind] = ExecEvalExpr(tle->expr,
2208                                                                                                           econtext,
2209                                                                                                           &isNull,
2210                                                                                                         &itemIsDone[resind]);
2211                                                 nulls[resind] = isNull ? 'n' : ' ';
2212
2213                                                 if (itemIsDone[resind] == ExprEndResult)
2214                                                 {
2215                                                         /*
2216                                                          * Oh dear, this item is returning an empty
2217                                                          * set. Guess we can't make a tuple after all.
2218                                                          */
2219                                                         *isDone = ExprEndResult;
2220                                                         break;
2221                                                 }
2222                                         }
2223                                 }
2224                         }
2225
2226                         /*
2227                          * If we cannot make a tuple because some sets are empty, we
2228                          * still have to cycle the nonempty sets to completion, else
2229                          * resources will not be released from subplans etc.
2230                          */
2231                         if (*isDone == ExprEndResult)
2232                         {
2233                                 foreach(tl, targetlist)
2234                                 {
2235                                         tle = lfirst(tl);
2236
2237                                         if (tle->resdom != NULL)
2238                                         {
2239                                                 resind = tle->resdom->resno - 1;
2240
2241                                                 while (itemIsDone[resind] == ExprMultipleResult)
2242                                                 {
2243                                                         (void) ExecEvalExpr(tle->expr,
2244                                                                                                 econtext,
2245                                                                                                 &isNull,
2246                                                                                                 &itemIsDone[resind]);
2247                                                 }
2248                                         }
2249                                 }
2250
2251                                 MemoryContextSwitchTo(oldContext);
2252                                 newTuple = NULL;
2253                                 goto exit;
2254                         }
2255                 }
2256         }
2257
2258         /*
2259          * form the new result tuple (in the caller's memory context!)
2260          */
2261         MemoryContextSwitchTo(oldContext);
2262
2263         newTuple = (HeapTuple) heap_formtuple(targettype, values, nulls);
2264
2265 exit:
2266
2267         /*
2268          * free the status arrays if we palloc'd them
2269          */
2270         if (nodomains > NPREALLOCDOMAINS)
2271         {
2272                 pfree(nulls);
2273                 pfree(fjIsNull);
2274                 pfree(itemIsDone);
2275         }
2276
2277         return newTuple;
2278 }
2279
2280 /* ----------------------------------------------------------------
2281  *              ExecProject
2282  *
2283  *              projects a tuple based on projection info and stores
2284  *              it in the specified tuple table slot.
2285  *
2286  *              Note: someday soon the executor can be extended to eliminate
2287  *                        redundant projections by storing pointers to datums
2288  *                        in the tuple table and then passing these around when
2289  *                        possible.  this should make things much quicker.
2290  *                        -cim 6/3/91
2291  * ----------------------------------------------------------------
2292  */
2293 TupleTableSlot *
2294 ExecProject(ProjectionInfo *projInfo, ExprDoneCond *isDone)
2295 {
2296         TupleTableSlot *slot;
2297         List       *targetlist;
2298         int                     len;
2299         TupleDesc       tupType;
2300         Datum      *tupValue;
2301         ExprContext *econtext;
2302         HeapTuple       newTuple;
2303
2304         /*
2305          * sanity checks
2306          */
2307         if (projInfo == NULL)
2308                 return (TupleTableSlot *) NULL;
2309
2310         /*
2311          * get the projection info we want
2312          */
2313         slot = projInfo->pi_slot;
2314         targetlist = projInfo->pi_targetlist;
2315         len = projInfo->pi_len;
2316         tupType = slot->ttc_tupleDescriptor;
2317
2318         tupValue = projInfo->pi_tupValue;
2319         econtext = projInfo->pi_exprContext;
2320
2321         /*
2322          * form a new result tuple (if possible --- result can be NULL)
2323          */
2324         newTuple = ExecTargetList(targetlist,
2325                                                           len,
2326                                                           tupType,
2327                                                           tupValue,
2328                                                           econtext,
2329                                                           isDone);
2330
2331         /*
2332          * store the tuple in the projection slot and return the slot.
2333          */
2334         return ExecStoreTuple(newTuple,         /* tuple to store */
2335                                                   slot, /* slot to store in */
2336                                                   InvalidBuffer,                /* tuple has no buffer */
2337                                                   true);
2338 }