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