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