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