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