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