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