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