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