1 /*-------------------------------------------------------------------------
4 * Routines to evaluate qualification and targetlist expressions
6 * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.112 2002/12/01 20:27:32 tgl Exp $
13 *-------------------------------------------------------------------------
17 * ExecEvalExpr - evaluate an expression and return a datum
18 * ExecEvalExprSwitchContext - same, but switch into eval memory context
19 * ExecQual - return true/false if qualification is satisfied
20 * ExecProject - form a new tuple by projecting the given tuple
23 * ExecEvalExpr() and ExecEvalVar() are hotspots. making these faster
24 * will speed up the entire system. Unfortunately they are currently
25 * implemented recursively. Eliminating the recursion is bound to
26 * improve the speed of the executor.
28 * ExecProject() is used to make tuple projections. Rather then
29 * trying to speed it up, the execution plan should be pre-processed
30 * to facilitate attribute sharing between nodes wherever possible,
31 * instead of doing needless copying. -cim 5/31/91
37 #include "access/heapam.h"
38 #include "catalog/pg_type.h"
39 #include "executor/execdebug.h"
40 #include "executor/functions.h"
41 #include "executor/nodeSubplan.h"
42 #include "miscadmin.h"
43 #include "parser/parse_expr.h"
44 #include "utils/array.h"
45 #include "utils/builtins.h"
46 #include "utils/fcache.h"
47 #include "utils/lsyscache.h"
50 /* static function decls */
51 static Datum ExecEvalAggref(Aggref *aggref, ExprContext *econtext,
53 static Datum ExecEvalArrayRef(ArrayRef *arrayRef, ExprContext *econtext,
54 bool *isNull, ExprDoneCond *isDone);
55 static Datum ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull);
56 static Datum ExecEvalOper(Expr *opClause, ExprContext *econtext,
57 bool *isNull, ExprDoneCond *isDone);
58 static Datum ExecEvalDistinct(Expr *opClause, ExprContext *econtext,
59 bool *isNull, ExprDoneCond *isDone);
60 static Datum ExecEvalFunc(Expr *funcClause, ExprContext *econtext,
61 bool *isNull, ExprDoneCond *isDone);
62 static ExprDoneCond ExecEvalFuncArgs(FunctionCallInfo fcinfo,
63 List *argList, ExprContext *econtext);
64 static Datum ExecEvalNot(Expr *notclause, ExprContext *econtext, bool *isNull);
65 static Datum ExecEvalAnd(Expr *andExpr, ExprContext *econtext, bool *isNull);
66 static Datum ExecEvalOr(Expr *orExpr, ExprContext *econtext, bool *isNull);
67 static Datum ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext,
68 bool *isNull, ExprDoneCond *isDone);
69 static Datum ExecEvalNullTest(NullTest *ntest, ExprContext *econtext,
70 bool *isNull, ExprDoneCond *isDone);
71 static Datum ExecEvalBooleanTest(BooleanTest *btest, ExprContext *econtext,
72 bool *isNull, ExprDoneCond *isDone);
73 static Datum ExecEvalConstraintTest(ConstraintTest *constraint,
74 ExprContext *econtext,
75 bool *isNull, ExprDoneCond *isDone);
76 static Datum ExecEvalConstraintTestValue(ConstraintTestValue *conVal,
77 ExprContext *econtext,
78 bool *isNull, ExprDoneCond *isDone);
84 * This function takes an ArrayRef and returns the extracted Datum
85 * if it's a simple reference, or the modified array value if it's
86 * an array assignment (i.e., array element or slice insertion).
88 * NOTE: if we get a NULL result from a subexpression, we return NULL when
89 * it's an array reference, or the unmodified source array when it's an
90 * array assignment. This may seem peculiar, but if we return NULL (as was
91 * done in versions up through 7.0) then an assignment like
92 * UPDATE table SET arrayfield[4] = NULL
93 * will result in setting the whole array to NULL, which is certainly not
94 * very desirable. By returning the source array we make the assignment
95 * into a no-op, instead. (Eventually we need to redesign arrays so that
96 * individual elements can be NULL, but for now, let's try to protect users
97 * from shooting themselves in the foot.)
99 * NOTE: we deliberately refrain from applying DatumGetArrayTypeP() here,
100 * even though that might seem natural, because this code needs to support
101 * both varlena arrays and fixed-length array types. DatumGetArrayTypeP()
102 * only works for the varlena kind. The routines we call in arrayfuncs.c
103 * have to know the difference (that's what they need refattrlength for).
107 ExecEvalArrayRef(ArrayRef *arrayRef,
108 ExprContext *econtext,
110 ExprDoneCond *isDone)
112 ArrayType *array_source;
113 ArrayType *resultArray;
114 bool isAssignment = (arrayRef->refassgnexpr != NULL);
122 if (arrayRef->refexpr != NULL)
124 array_source = (ArrayType *)
125 DatumGetPointer(ExecEvalExpr(arrayRef->refexpr,
131 * If refexpr yields NULL, result is always NULL, for now anyway.
132 * (This means you cannot assign to an element or slice of an
133 * array that's NULL; it'll just stay NULL.)
141 * Empty refexpr indicates we are doing an INSERT into an array
142 * column. For now, we just take the refassgnexpr (which the
143 * parser will have ensured is an array value) and return it
144 * as-is, ignoring any subscripts that may have been supplied in
145 * the INSERT column list. This is a kluge, but it's not real
146 * clear what the semantics ought to be...
151 foreach(elt, arrayRef->refupperindexpr)
154 elog(ERROR, "ExecEvalArrayRef: can only handle %d dimensions",
157 upper.indx[i++] = DatumGetInt32(ExecEvalExpr((Node *) lfirst(elt),
161 /* If any index expr yields NULL, result is NULL or source array */
164 if (!isAssignment || array_source == NULL)
167 return PointerGetDatum(array_source);
171 if (arrayRef->reflowerindexpr != NIL)
173 foreach(elt, arrayRef->reflowerindexpr)
176 elog(ERROR, "ExecEvalArrayRef: can only handle %d dimensions",
179 lower.indx[j++] = DatumGetInt32(ExecEvalExpr((Node *) lfirst(elt),
185 * If any index expr yields NULL, result is NULL or source
190 if (!isAssignment || array_source == NULL)
193 return PointerGetDatum(array_source);
198 "ExecEvalArrayRef: upper and lower indices mismatch");
206 Datum sourceData = ExecEvalExpr(arrayRef->refassgnexpr,
212 * For now, can't cope with inserting NULL into an array, so make
213 * it a no-op per discussion above...
217 if (array_source == NULL)
220 return PointerGetDatum(array_source);
223 if (array_source == NULL)
224 return sourceData; /* XXX do something else? */
227 resultArray = array_set(array_source, i,
230 arrayRef->refattrlength,
231 arrayRef->refelemlength,
232 arrayRef->refelembyval,
233 arrayRef->refelemalign,
236 resultArray = array_set_slice(array_source, i,
237 upper.indx, lower.indx,
238 (ArrayType *) DatumGetPointer(sourceData),
239 arrayRef->refattrlength,
240 arrayRef->refelemlength,
241 arrayRef->refelembyval,
242 arrayRef->refelemalign,
244 return PointerGetDatum(resultArray);
248 return array_ref(array_source, i, upper.indx,
249 arrayRef->refattrlength,
250 arrayRef->refelemlength,
251 arrayRef->refelembyval,
252 arrayRef->refelemalign,
256 resultArray = array_get_slice(array_source, i,
257 upper.indx, lower.indx,
258 arrayRef->refattrlength,
259 arrayRef->refelemlength,
260 arrayRef->refelembyval,
261 arrayRef->refelemalign,
263 return PointerGetDatum(resultArray);
268 /* ----------------------------------------------------------------
271 * Returns a Datum whose value is the value of the precomputed
272 * aggregate found in the given expression context.
273 * ----------------------------------------------------------------
276 ExecEvalAggref(Aggref *aggref, ExprContext *econtext, bool *isNull)
278 if (econtext->ecxt_aggvalues == NULL) /* safety check */
279 elog(ERROR, "ExecEvalAggref: no aggregates in this expression context");
281 *isNull = econtext->ecxt_aggnulls[aggref->aggno];
282 return econtext->ecxt_aggvalues[aggref->aggno];
285 /* ----------------------------------------------------------------
288 * Returns a Datum whose value is the value of a range
289 * variable with respect to given expression context.
292 * As an entry condition, we expect that the datatype the
293 * plan expects to get (as told by our "variable" argument) is in
294 * fact the datatype of the attribute the plan says to fetch (as
295 * seen in the current context, identified by our "econtext"
298 * If we fetch a Type A attribute and Caller treats it as if it
299 * were Type B, there will be undefined results (e.g. crash).
300 * One way these might mismatch now is that we're accessing a
301 * catalog class and the type information in the pg_attribute
302 * class does not match the hardcoded pg_attribute information
303 * (in pg_attribute.h) for the class in question.
305 * We have an Assert to make sure this entry condition is met.
307 * ---------------------------------------------------------------- */
309 ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull)
312 TupleTableSlot *slot;
315 TupleDesc tuple_type;
318 * get the slot we want
320 switch (variable->varno)
322 case INNER: /* get the tuple from the inner node */
323 slot = econtext->ecxt_innertuple;
326 case OUTER: /* get the tuple from the outer node */
327 slot = econtext->ecxt_outertuple;
330 default: /* get the tuple from the relation being
332 slot = econtext->ecxt_scantuple;
337 * extract tuple information from the slot
339 heapTuple = slot->val;
340 tuple_type = slot->ttc_tupleDescriptor;
342 attnum = variable->varattno;
344 /* (See prolog for explanation of this Assert) */
345 Assert(attnum <= 0 ||
346 (attnum - 1 <= tuple_type->natts - 1 &&
347 tuple_type->attrs[attnum - 1] != NULL &&
348 variable->vartype == tuple_type->attrs[attnum - 1]->atttypid));
351 * If the attribute number is invalid, then we are supposed to return
352 * the entire tuple; we give back a whole slot so that callers know
353 * what the tuple looks like.
355 * XXX this is a horrid crock: since the pointer to the slot might live
356 * longer than the current evaluation context, we are forced to copy
357 * the tuple and slot into a long-lived context --- we use
358 * TransactionCommandContext which should be safe enough. This
359 * represents a serious memory leak if many such tuples are processed
360 * in one command, however. We ought to redesign the representation
361 * of whole-tuple datums so that this is not necessary.
363 * We assume it's OK to point to the existing tupleDescriptor, rather
364 * than copy that too.
366 if (attnum == InvalidAttrNumber)
368 MemoryContext oldContext;
369 TupleTableSlot *tempSlot;
372 oldContext = MemoryContextSwitchTo(TransactionCommandContext);
373 tempSlot = MakeTupleTableSlot();
374 tup = heap_copytuple(heapTuple);
375 ExecStoreTuple(tup, tempSlot, InvalidBuffer, true);
376 ExecSetSlotDescriptor(tempSlot, tuple_type, false);
377 MemoryContextSwitchTo(oldContext);
378 return PointerGetDatum(tempSlot);
381 result = heap_getattr(heapTuple, /* tuple containing attribute */
382 attnum, /* attribute number of desired
384 tuple_type, /* tuple descriptor of tuple */
385 isNull); /* return: is attribute null? */
390 /* ----------------------------------------------------------------
393 * Returns the value of a parameter. A param node contains
394 * something like ($.name) and the expression context contains
395 * the current parameter bindings (name = "sam") (age = 34)...
396 * so our job is to find and return the appropriate datum ("sam").
398 * Q: if we have a parameter ($.foo) without a binding, i.e.
399 * there is no (foo = xxx) in the parameter list info,
400 * is this a fatal error or should this be a "not available"
401 * (in which case we could return NULL)? -cim 10/13/89
402 * ----------------------------------------------------------------
405 ExecEvalParam(Param *expression, ExprContext *econtext, bool *isNull)
407 int thisParamKind = expression->paramkind;
408 AttrNumber thisParamId = expression->paramid;
410 if (thisParamKind == PARAM_EXEC)
413 * PARAM_EXEC params (internal executor parameters) are stored in
414 * the ecxt_param_exec_vals array, and can be accessed by array index.
418 prm = &(econtext->ecxt_param_exec_vals[thisParamId]);
419 if (prm->execPlan != NULL)
421 /* Parameter not evaluated yet, so go do it */
422 ExecSetParamPlan(prm->execPlan, econtext);
423 /* ExecSetParamPlan should have processed this param... */
424 Assert(prm->execPlan == NULL);
426 *isNull = prm->isnull;
432 * All other parameter types must be sought in ecxt_param_list_info.
433 * NOTE: The last entry in the param array is always an
434 * entry with kind == PARAM_INVALID.
436 ParamListInfo paramList = econtext->ecxt_param_list_info;
437 char *thisParamName = expression->paramname;
438 bool matchFound = false;
440 if (paramList != NULL)
442 while (paramList->kind != PARAM_INVALID && !matchFound)
444 if (thisParamKind == paramList->kind)
446 switch (thisParamKind)
449 if (strcmp(paramList->name, thisParamName) == 0)
453 if (paramList->id == thisParamId)
457 elog(ERROR, "ExecEvalParam: invalid paramkind %d",
468 if (thisParamKind == PARAM_NAMED)
469 elog(ERROR, "ExecEvalParam: Unknown value for parameter %s",
472 elog(ERROR, "ExecEvalParam: Unknown value for parameter %d",
476 *isNull = paramList->isnull;
477 return paramList->value;
482 /* ----------------------------------------------------------------
483 * ExecEvalOper / ExecEvalFunc support routines
484 * ----------------------------------------------------------------
491 * These are functions which return the value of the
492 * named attribute out of the tuple from the arg slot. User defined
493 * C functions which take a tuple as an argument are expected
494 * to use this. Ex: overpaid(EMP) might call GetAttributeByNum().
497 GetAttributeByNum(TupleTableSlot *slot,
503 if (!AttributeNumberIsValid(attrno))
504 elog(ERROR, "GetAttributeByNum: Invalid attribute number");
506 if (!AttrNumberIsForUserDefinedAttr(attrno))
507 elog(ERROR, "GetAttributeByNum: cannot access system attributes here");
509 if (isNull == (bool *) NULL)
510 elog(ERROR, "GetAttributeByNum: a NULL isNull flag was passed");
518 retval = heap_getattr(slot->val,
520 slot->ttc_tupleDescriptor,
529 GetAttributeByName(TupleTableSlot *slot, char *attname, bool *isNull)
538 elog(ERROR, "GetAttributeByName: Invalid attribute name");
540 if (isNull == (bool *) NULL)
541 elog(ERROR, "GetAttributeByName: a NULL isNull flag was passed");
549 tupdesc = slot->ttc_tupleDescriptor;
550 natts = slot->val->t_data->t_natts;
552 attrno = InvalidAttrNumber;
553 for (i = 0; i < tupdesc->natts; i++)
555 if (namestrcmp(&(tupdesc->attrs[i]->attname), attname) == 0)
557 attrno = tupdesc->attrs[i]->attnum;
562 if (attrno == InvalidAttrNumber)
563 elog(ERROR, "GetAttributeByName: attribute %s not found", attname);
565 retval = heap_getattr(slot->val,
576 * Evaluate arguments for a function.
579 ExecEvalFuncArgs(FunctionCallInfo fcinfo,
581 ExprContext *econtext)
583 ExprDoneCond argIsDone;
587 argIsDone = ExprSingleResult; /* default assumption */
590 foreach(arg, argList)
592 ExprDoneCond thisArgIsDone;
594 fcinfo->arg[i] = ExecEvalExpr((Node *) lfirst(arg),
599 if (thisArgIsDone != ExprSingleResult)
602 * We allow only one argument to have a set value; we'd need
603 * much more complexity to keep track of multiple set
604 * arguments (cf. ExecTargetList) and it doesn't seem worth
607 if (argIsDone != ExprSingleResult)
608 elog(ERROR, "Functions and operators can take only one set argument");
609 argIsDone = thisArgIsDone;
620 * ExecMakeFunctionResult
622 * Evaluate the arguments to a function and then the function itself.
625 ExecMakeFunctionResult(FunctionCachePtr fcache,
627 ExprContext *econtext,
629 ExprDoneCond *isDone)
632 FunctionCallInfoData fcinfo;
633 ReturnSetInfo rsinfo; /* for functions returning sets */
634 ExprDoneCond argDone;
639 * arguments is a list of expressions to evaluate before passing to
640 * the function manager. We skip the evaluation if it was already
641 * done in the previous call (ie, we are continuing the evaluation of
642 * a set-valued function). Otherwise, collect the current argument
643 * values into fcinfo.
645 if (!fcache->setArgsValid)
647 /* Need to prep callinfo structure */
648 MemSet(&fcinfo, 0, sizeof(fcinfo));
649 fcinfo.flinfo = &(fcache->func);
650 argDone = ExecEvalFuncArgs(&fcinfo, arguments, econtext);
651 if (argDone == ExprEndResult)
653 /* input is an empty set, so return an empty set. */
656 *isDone = ExprEndResult;
658 elog(ERROR, "Set-valued function called in context that cannot accept a set");
661 hasSetArg = (argDone != ExprSingleResult);
665 /* Copy callinfo from previous evaluation */
666 memcpy(&fcinfo, &fcache->setArgs, sizeof(fcinfo));
667 hasSetArg = fcache->setHasSetArg;
668 /* Reset flag (we may set it again below) */
669 fcache->setArgsValid = false;
673 * If function returns set, prepare a resultinfo node for
676 if (fcache->func.fn_retset)
678 fcinfo.resultinfo = (Node *) &rsinfo;
679 rsinfo.type = T_ReturnSetInfo;
680 rsinfo.econtext = econtext;
681 rsinfo.expectedDesc = NULL;
682 rsinfo.allowedModes = (int) SFRM_ValuePerCall;
683 rsinfo.returnMode = SFRM_ValuePerCall;
684 /* isDone is filled below */
685 rsinfo.setResult = NULL;
686 rsinfo.setDesc = NULL;
690 * now return the value gotten by calling the function manager,
691 * passing the function the evaluated parameter values.
693 if (fcache->func.fn_retset || hasSetArg)
696 * We need to return a set result. Complain if caller not ready
700 elog(ERROR, "Set-valued function called in context that cannot accept a set");
703 * This loop handles the situation where we have both a set
704 * argument and a set-valued function. Once we have exhausted the
705 * function's value(s) for a particular argument value, we have to
706 * get the next argument value and start the function over again.
707 * We might have to do it more than once, if the function produces
708 * an empty result set for a particular input value.
713 * If function is strict, and there are any NULL arguments,
714 * skip calling the function (at least for this set of args).
718 if (fcache->func.fn_strict)
720 for (i = 0; i < fcinfo.nargs; i++)
722 if (fcinfo.argnull[i])
732 fcinfo.isnull = false;
733 rsinfo.isDone = ExprSingleResult;
734 result = FunctionCallInvoke(&fcinfo);
735 *isNull = fcinfo.isnull;
736 *isDone = rsinfo.isDone;
742 *isDone = ExprEndResult;
745 if (*isDone != ExprEndResult)
748 * Got a result from current argument. If function itself
749 * returns set, save the current argument values to re-use
752 if (fcache->func.fn_retset)
754 memcpy(&fcache->setArgs, &fcinfo, sizeof(fcinfo));
755 fcache->setHasSetArg = hasSetArg;
756 fcache->setArgsValid = true;
760 * Make sure we say we are returning a set, even if the
761 * function itself doesn't return sets.
763 *isDone = ExprMultipleResult;
767 /* Else, done with this argument */
769 break; /* input not a set, so done */
771 /* Re-eval args to get the next element of the input set */
772 argDone = ExecEvalFuncArgs(&fcinfo, arguments, econtext);
774 if (argDone != ExprMultipleResult)
776 /* End of argument set, so we're done. */
778 *isDone = ExprEndResult;
784 * If we reach here, loop around to run the function on the
792 * Non-set case: much easier.
794 * If function is strict, and there are any NULL arguments, skip
795 * calling the function and return NULL.
797 if (fcache->func.fn_strict)
799 for (i = 0; i < fcinfo.nargs; i++)
801 if (fcinfo.argnull[i])
808 fcinfo.isnull = false;
809 result = FunctionCallInvoke(&fcinfo);
810 *isNull = fcinfo.isnull;
818 * ExecMakeTableFunctionResult
820 * Evaluate a table function, producing a materialized result in a Tuplestore
821 * object. (If function returns an empty set, we just return NULL instead.)
824 ExecMakeTableFunctionResult(Node *funcexpr,
825 ExprContext *econtext,
826 TupleDesc expectedDesc,
827 TupleDesc *returnDesc)
829 Tuplestorestate *tupstore = NULL;
830 TupleDesc tupdesc = NULL;
832 FunctionCallInfoData fcinfo;
833 ReturnSetInfo rsinfo;
834 MemoryContext callerContext;
835 MemoryContext oldcontext;
836 TupleTableSlot *slot;
837 bool direct_function_call;
838 bool first_time = true;
839 bool returnsTuple = false;
842 * Normally the passed expression tree will be a FUNC_EXPR, since the
843 * grammar only allows a function call at the top level of a table
844 * function reference. However, if the function doesn't return set then
845 * the planner might have replaced the function call via constant-folding
846 * or inlining. So if we see any other kind of expression node, execute
847 * it via the general ExecEvalExpr() code; the only difference is that
848 * we don't get a chance to pass a special ReturnSetInfo to any functions
849 * buried in the expression.
852 IsA(funcexpr, Expr) &&
853 ((Expr *) funcexpr)->opType == FUNC_EXPR)
857 FunctionCachePtr fcache;
858 ExprDoneCond argDone;
861 * This path is similar to ExecMakeFunctionResult.
863 direct_function_call = true;
865 funcrettype = ((Expr *) funcexpr)->typeOid;
866 func = (Func *) ((Expr *) funcexpr)->oper;
867 argList = ((Expr *) funcexpr)->args;
870 * get the fcache from the Func node. If it is NULL, then initialize
873 fcache = func->func_fcache;
876 fcache = init_fcache(func->funcid, length(argList),
877 econtext->ecxt_per_query_memory);
878 func->func_fcache = fcache;
882 * Evaluate the function's argument list.
884 * Note: ideally, we'd do this in the per-tuple context, but then the
885 * argument values would disappear when we reset the context in the
886 * inner loop. So do it in caller context. Perhaps we should make a
887 * separate context just to hold the evaluated arguments?
889 MemSet(&fcinfo, 0, sizeof(fcinfo));
890 fcinfo.flinfo = &(fcache->func);
891 argDone = ExecEvalFuncArgs(&fcinfo, argList, econtext);
892 /* We don't allow sets in the arguments of the table function */
893 if (argDone != ExprSingleResult)
894 elog(ERROR, "Set-valued function called in context that cannot accept a set");
897 * If function is strict, and there are any NULL arguments, skip
898 * calling the function and return NULL (actually an empty set).
900 if (fcache->func.fn_strict)
904 for (i = 0; i < fcinfo.nargs; i++)
906 if (fcinfo.argnull[i])
916 /* Treat funcexpr as a generic expression */
917 direct_function_call = false;
918 funcrettype = exprType(funcexpr);
922 * Prepare a resultinfo node for communication. We always do this
923 * even if not expecting a set result, so that we can pass
924 * expectedDesc. In the generic-expression case, the expression
925 * doesn't actually get to see the resultinfo, but set it up anyway
926 * because we use some of the fields as our own state variables.
928 fcinfo.resultinfo = (Node *) &rsinfo;
929 rsinfo.type = T_ReturnSetInfo;
930 rsinfo.econtext = econtext;
931 rsinfo.expectedDesc = expectedDesc;
932 rsinfo.allowedModes = (int) (SFRM_ValuePerCall | SFRM_Materialize);
933 rsinfo.returnMode = SFRM_ValuePerCall;
934 /* isDone is filled below */
935 rsinfo.setResult = NULL;
936 rsinfo.setDesc = NULL;
939 * Switch to short-lived context for calling the function or expression.
941 callerContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
944 * Loop to handle the ValuePerCall protocol (which is also the same
945 * behavior needed in the generic ExecEvalExpr path).
953 * reset per-tuple memory context before each call of the
954 * function or expression. This cleans up any local memory the
955 * function may leak when called.
957 ResetExprContext(econtext);
959 /* Call the function or expression one time */
960 if (direct_function_call)
962 fcinfo.isnull = false;
963 rsinfo.isDone = ExprSingleResult;
964 result = FunctionCallInvoke(&fcinfo);
968 result = ExecEvalExpr(funcexpr, econtext,
969 &fcinfo.isnull, &rsinfo.isDone);
972 /* Which protocol does function want to use? */
973 if (rsinfo.returnMode == SFRM_ValuePerCall)
976 * Check for end of result set.
978 * Note: if function returns an empty set, we don't build a
979 * tupdesc or tuplestore (since we can't get a tupdesc in the
980 * function-returning-tuple case)
982 if (rsinfo.isDone == ExprEndResult)
986 * If first time through, build tupdesc and tuplestore for
991 oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
992 if (funcrettype == RECORDOID ||
993 get_typtype(funcrettype) == 'c')
996 * Composite type, so function should have returned a
997 * TupleTableSlot; use its descriptor
999 slot = (TupleTableSlot *) DatumGetPointer(result);
1000 if (fcinfo.isnull ||
1002 !IsA(slot, TupleTableSlot) ||
1003 !slot->ttc_tupleDescriptor)
1004 elog(ERROR, "ExecMakeTableFunctionResult: Invalid result from function returning tuple");
1005 tupdesc = CreateTupleDescCopy(slot->ttc_tupleDescriptor);
1006 returnsTuple = true;
1011 * Scalar type, so make a single-column descriptor
1013 tupdesc = CreateTemplateTupleDesc(1, false);
1014 TupleDescInitEntry(tupdesc,
1022 tupstore = tuplestore_begin_heap(true, /* randomAccess */
1024 MemoryContextSwitchTo(oldcontext);
1025 rsinfo.setResult = tupstore;
1026 rsinfo.setDesc = tupdesc;
1030 * Store current resultset item.
1034 slot = (TupleTableSlot *) DatumGetPointer(result);
1035 if (fcinfo.isnull ||
1037 !IsA(slot, TupleTableSlot) ||
1039 elog(ERROR, "ExecMakeTableFunctionResult: Invalid result from function returning tuple");
1046 nullflag = fcinfo.isnull ? 'n' : ' ';
1047 tuple = heap_formtuple(tupdesc, &result, &nullflag);
1050 oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
1051 tuplestore_puttuple(tupstore, tuple);
1052 MemoryContextSwitchTo(oldcontext);
1057 if (rsinfo.isDone != ExprMultipleResult)
1060 else if (rsinfo.returnMode == SFRM_Materialize)
1062 /* check we're on the same page as the function author */
1063 if (!first_time || rsinfo.isDone != ExprSingleResult)
1064 elog(ERROR, "ExecMakeTableFunctionResult: Materialize-mode protocol not followed");
1065 /* Done evaluating the set result */
1069 elog(ERROR, "ExecMakeTableFunctionResult: unknown returnMode %d",
1070 (int) rsinfo.returnMode);
1075 /* If we have a locally-created tupstore, close it up */
1078 MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
1079 tuplestore_donestoring(tupstore);
1082 MemoryContextSwitchTo(callerContext);
1084 /* The returned pointers are those in rsinfo */
1085 *returnDesc = rsinfo.setDesc;
1086 return rsinfo.setResult;
1090 /* ----------------------------------------------------------------
1095 * Evaluate the functional result of a list of arguments by calling the
1097 * ----------------------------------------------------------------
1100 /* ----------------------------------------------------------------
1102 * ----------------------------------------------------------------
1105 ExecEvalOper(Expr *opClause,
1106 ExprContext *econtext,
1108 ExprDoneCond *isDone)
1112 FunctionCachePtr fcache;
1115 * we extract the oid of the function associated with the op and then
1116 * pass the work onto ExecMakeFunctionResult which evaluates the
1117 * arguments and returns the result of calling the function on the
1118 * evaluated arguments.
1120 op = (Oper *) opClause->oper;
1121 argList = opClause->args;
1124 * get the fcache from the Oper node. If it is NULL, then initialize
1127 fcache = op->op_fcache;
1130 fcache = init_fcache(op->opid, length(argList),
1131 econtext->ecxt_per_query_memory);
1132 op->op_fcache = fcache;
1135 return ExecMakeFunctionResult(fcache, argList, econtext,
1139 /* ----------------------------------------------------------------
1141 * ----------------------------------------------------------------
1145 ExecEvalFunc(Expr *funcClause,
1146 ExprContext *econtext,
1148 ExprDoneCond *isDone)
1152 FunctionCachePtr fcache;
1155 * we extract the oid of the function associated with the func node
1156 * and then pass the work onto ExecMakeFunctionResult which evaluates
1157 * the arguments and returns the result of calling the function on the
1158 * evaluated arguments.
1160 * this is nearly identical to the ExecEvalOper code.
1162 func = (Func *) funcClause->oper;
1163 argList = funcClause->args;
1166 * get the fcache from the Func node. If it is NULL, then initialize
1169 fcache = func->func_fcache;
1172 fcache = init_fcache(func->funcid, length(argList),
1173 econtext->ecxt_per_query_memory);
1174 func->func_fcache = fcache;
1177 return ExecMakeFunctionResult(fcache, argList, econtext,
1181 /* ----------------------------------------------------------------
1184 * IS DISTINCT FROM must evaluate arguments to determine whether
1185 * they are NULL; if either is NULL then the result is already
1186 * known. If neither is NULL, then proceed to evaluate the
1187 * function. Note that this is *always* derived from the equals
1188 * operator, but since we need special processing of the arguments
1189 * we can not simply reuse ExecEvalOper() or ExecEvalFunc().
1190 * ----------------------------------------------------------------
1193 ExecEvalDistinct(Expr *opClause,
1194 ExprContext *econtext,
1196 ExprDoneCond *isDone)
1199 FunctionCachePtr fcache;
1200 FunctionCallInfoData fcinfo;
1201 ExprDoneCond argDone;
1206 * extract info from opClause
1208 op = (Oper *) opClause->oper;
1209 argList = opClause->args;
1212 * get the fcache from the Oper node. If it is NULL, then initialize
1215 fcache = op->op_fcache;
1218 fcache = init_fcache(op->opid, length(argList),
1219 econtext->ecxt_per_query_memory);
1220 op->op_fcache = fcache;
1222 Assert(!fcache->func.fn_retset);
1224 /* Need to prep callinfo structure */
1225 MemSet(&fcinfo, 0, sizeof(fcinfo));
1226 fcinfo.flinfo = &(fcache->func);
1227 argDone = ExecEvalFuncArgs(&fcinfo, argList, econtext);
1228 if (argDone != ExprSingleResult)
1229 elog(ERROR, "IS DISTINCT FROM does not support set arguments");
1230 Assert(fcinfo.nargs == 2);
1232 if (fcinfo.argnull[0] && fcinfo.argnull[1])
1234 /* Both NULL? Then is not distinct... */
1235 result = BoolGetDatum(FALSE);
1237 else if (fcinfo.argnull[0] || fcinfo.argnull[1])
1239 /* Only one is NULL? Then is distinct... */
1240 result = BoolGetDatum(TRUE);
1244 fcinfo.isnull = false;
1245 result = FunctionCallInvoke(&fcinfo);
1246 *isNull = fcinfo.isnull;
1247 /* Must invert result of "=" */
1248 result = BoolGetDatum(!DatumGetBool(result));
1254 /* ----------------------------------------------------------------
1259 * Evaluate boolean expressions. Evaluation of 'or' is
1260 * short-circuited when the first true (or null) value is found.
1262 * The query planner reformulates clause expressions in the
1263 * qualification to conjunctive normal form. If we ever get
1264 * an AND to evaluate, we can be sure that it's not a top-level
1265 * clause in the qualification, but appears lower (as a function
1266 * argument, for example), or in the target list. Not that you
1267 * need to know this, mind you...
1268 * ----------------------------------------------------------------
1271 ExecEvalNot(Expr *notclause, ExprContext *econtext, bool *isNull)
1276 clause = lfirst(notclause->args);
1278 expr_value = ExecEvalExpr(clause, econtext, isNull, NULL);
1281 * if the expression evaluates to null, then we just cascade the null
1282 * back to whoever called us.
1288 * evaluation of 'not' is simple.. expr is false, then return 'true'
1291 return BoolGetDatum(!DatumGetBool(expr_value));
1294 /* ----------------------------------------------------------------
1296 * ----------------------------------------------------------------
1299 ExecEvalOr(Expr *orExpr, ExprContext *econtext, bool *isNull)
1306 clauses = orExpr->args;
1310 * If any of the clauses is TRUE, the OR result is TRUE regardless of
1311 * the states of the rest of the clauses, so we can stop evaluating
1312 * and return TRUE immediately. If none are TRUE and one or more is
1313 * NULL, we return NULL; otherwise we return FALSE. This makes sense
1314 * when you interpret NULL as "don't know": if we have a TRUE then the
1315 * OR is TRUE even if we aren't sure about some of the other inputs.
1316 * If all the known inputs are FALSE, but we have one or more "don't
1317 * knows", then we have to report that we "don't know" what the OR's
1318 * result should be --- perhaps one of the "don't knows" would have
1319 * been TRUE if we'd known its value. Only when all the inputs are
1320 * known to be FALSE can we state confidently that the OR's result is
1323 foreach(clause, clauses)
1325 clause_value = ExecEvalExpr((Node *) lfirst(clause),
1326 econtext, isNull, NULL);
1329 * if we have a non-null true result, then return it.
1332 AnyNull = true; /* remember we got a null */
1333 else if (DatumGetBool(clause_value))
1334 return clause_value;
1337 /* AnyNull is true if at least one clause evaluated to NULL */
1339 return BoolGetDatum(false);
1342 /* ----------------------------------------------------------------
1344 * ----------------------------------------------------------------
1347 ExecEvalAnd(Expr *andExpr, ExprContext *econtext, bool *isNull)
1354 clauses = andExpr->args;
1358 * If any of the clauses is FALSE, the AND result is FALSE regardless
1359 * of the states of the rest of the clauses, so we can stop evaluating
1360 * and return FALSE immediately. If none are FALSE and one or more is
1361 * NULL, we return NULL; otherwise we return TRUE. This makes sense
1362 * when you interpret NULL as "don't know", using the same sort of
1363 * reasoning as for OR, above.
1365 foreach(clause, clauses)
1367 clause_value = ExecEvalExpr((Node *) lfirst(clause),
1368 econtext, isNull, NULL);
1371 * if we have a non-null false result, then return it.
1374 AnyNull = true; /* remember we got a null */
1375 else if (!DatumGetBool(clause_value))
1376 return clause_value;
1379 /* AnyNull is true if at least one clause evaluated to NULL */
1381 return BoolGetDatum(!AnyNull);
1384 /* ----------------------------------------------------------------
1387 * Evaluate a CASE clause. Will have boolean expressions
1388 * inside the WHEN clauses, and will have expressions
1390 * - thomas 1998-11-09
1391 * ----------------------------------------------------------------
1394 ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext,
1395 bool *isNull, ExprDoneCond *isDone)
1401 clauses = caseExpr->args;
1404 * we evaluate each of the WHEN clauses in turn, as soon as one is
1405 * true we return the corresponding result. If none are true then we
1406 * return the value of the default clause, or NULL if there is none.
1408 foreach(clause, clauses)
1410 CaseWhen *wclause = lfirst(clause);
1412 clause_value = ExecEvalExpr(wclause->expr,
1418 * if we have a true test, then we return the result, since the
1419 * case statement is satisfied. A NULL result from the test is
1420 * not considered true.
1422 if (DatumGetBool(clause_value) && !*isNull)
1424 return ExecEvalExpr(wclause->result,
1431 if (caseExpr->defresult)
1433 return ExecEvalExpr(caseExpr->defresult,
1443 /* ----------------------------------------------------------------
1446 * Evaluate a NullTest node.
1447 * ----------------------------------------------------------------
1450 ExecEvalNullTest(NullTest *ntest,
1451 ExprContext *econtext,
1453 ExprDoneCond *isDone)
1457 result = ExecEvalExpr(ntest->arg, econtext, isNull, isDone);
1458 switch (ntest->nulltesttype)
1464 return BoolGetDatum(true);
1467 return BoolGetDatum(false);
1472 return BoolGetDatum(false);
1475 return BoolGetDatum(true);
1477 elog(ERROR, "ExecEvalNullTest: unexpected nulltesttype %d",
1478 (int) ntest->nulltesttype);
1479 return (Datum) 0; /* keep compiler quiet */
1483 /* ----------------------------------------------------------------
1484 * ExecEvalBooleanTest
1486 * Evaluate a BooleanTest node.
1487 * ----------------------------------------------------------------
1490 ExecEvalBooleanTest(BooleanTest *btest,
1491 ExprContext *econtext,
1493 ExprDoneCond *isDone)
1497 result = ExecEvalExpr(btest->arg, econtext, isNull, isDone);
1498 switch (btest->booltesttype)
1504 return BoolGetDatum(false);
1506 else if (DatumGetBool(result))
1507 return BoolGetDatum(true);
1509 return BoolGetDatum(false);
1514 return BoolGetDatum(true);
1516 else if (DatumGetBool(result))
1517 return BoolGetDatum(false);
1519 return BoolGetDatum(true);
1524 return BoolGetDatum(false);
1526 else if (DatumGetBool(result))
1527 return BoolGetDatum(false);
1529 return BoolGetDatum(true);
1534 return BoolGetDatum(true);
1536 else if (DatumGetBool(result))
1537 return BoolGetDatum(true);
1539 return BoolGetDatum(false);
1544 return BoolGetDatum(true);
1547 return BoolGetDatum(false);
1548 case IS_NOT_UNKNOWN:
1552 return BoolGetDatum(false);
1555 return BoolGetDatum(true);
1557 elog(ERROR, "ExecEvalBooleanTest: unexpected booltesttype %d",
1558 (int) btest->booltesttype);
1559 return (Datum) 0; /* keep compiler quiet */
1564 * ExecEvalConstraintTestValue
1566 * Return the value stored by constraintTest.
1569 ExecEvalConstraintTestValue(ConstraintTestValue *conVal, ExprContext *econtext,
1570 bool *isNull, ExprDoneCond *isDone)
1573 * If the Datum hasn't been set, then it's ExecEvalConstraintTest
1574 * hasn't been called.
1576 *isNull = econtext->domainValue_isNull;
1577 return econtext->domainValue_datum;
1581 * ExecEvalConstraintTest
1583 * Test the constraint against the data provided. If the data fits
1584 * within the constraint specifications, pass it through (return the
1585 * datum) otherwise throw an error.
1588 ExecEvalConstraintTest(ConstraintTest *constraint, ExprContext *econtext,
1589 bool *isNull, ExprDoneCond *isDone)
1593 result = ExecEvalExpr(constraint->arg, econtext, isNull, isDone);
1595 switch (constraint->testtype)
1597 case CONSTR_TEST_NOTNULL:
1599 elog(ERROR, "Domain %s does not allow NULL values",
1600 constraint->domname);
1602 case CONSTR_TEST_CHECK:
1606 /* Var with attnum == UnassignedAttrNum uses the result */
1607 econtext->domainValue_datum = result;
1608 econtext->domainValue_isNull = *isNull;
1610 conResult = ExecEvalExpr(constraint->check_expr, econtext, isNull, isDone);
1612 if (!DatumGetBool(conResult))
1613 elog(ERROR, "Domain %s constraint %s failed",
1614 constraint->name, constraint->domname);
1618 elog(ERROR, "ExecEvalConstraintTest: Constraint type unknown");
1622 /* If all has gone well (constraint did not fail) return the datum */
1626 /* ----------------------------------------------------------------
1627 * ExecEvalFieldSelect
1629 * Evaluate a FieldSelect node.
1630 * ----------------------------------------------------------------
1633 ExecEvalFieldSelect(FieldSelect *fselect,
1634 ExprContext *econtext,
1636 ExprDoneCond *isDone)
1639 TupleTableSlot *resSlot;
1641 result = ExecEvalExpr(fselect->arg, econtext, isNull, isDone);
1644 resSlot = (TupleTableSlot *) DatumGetPointer(result);
1645 Assert(resSlot != NULL && IsA(resSlot, TupleTableSlot));
1646 result = heap_getattr(resSlot->val,
1648 resSlot->ttc_tupleDescriptor,
1653 /* ----------------------------------------------------------------
1656 * Recursively evaluate a targetlist or qualification expression.
1659 * expression: the expression tree to evaluate
1660 * econtext: evaluation context information
1663 * return value: Datum value of result
1664 * *isNull: set to TRUE if result is NULL (actual return value is
1665 * meaningless if so); set to FALSE if non-null result
1666 * *isDone: set to indicator of set-result status
1668 * A caller that can only accept a singleton (non-set) result should pass
1669 * NULL for isDone; if the expression computes a set result then an elog()
1670 * error will be reported. If the caller does pass an isDone pointer then
1671 * *isDone is set to one of these three states:
1672 * ExprSingleResult singleton result (not a set)
1673 * ExprMultipleResult return value is one element of a set
1674 * ExprEndResult there are no more elements in the set
1675 * When ExprMultipleResult is returned, the caller should invoke
1676 * ExecEvalExpr() repeatedly until ExprEndResult is returned. ExprEndResult
1677 * is returned after the last real set element. For convenience isNull will
1678 * always be set TRUE when ExprEndResult is returned, but this should not be
1679 * taken as indicating a NULL element of the set. Note that these return
1680 * conventions allow us to distinguish among a singleton NULL, a NULL element
1681 * of a set, and an empty set.
1683 * The caller should already have switched into the temporary memory
1684 * context econtext->ecxt_per_tuple_memory. The convenience entry point
1685 * ExecEvalExprSwitchContext() is provided for callers who don't prefer to
1686 * do the switch in an outer loop. We do not do the switch here because
1687 * it'd be a waste of cycles during recursive entries to ExecEvalExpr().
1689 * This routine is an inner loop routine and must be as fast as possible.
1690 * ----------------------------------------------------------------
1693 ExecEvalExpr(Node *expression,
1694 ExprContext *econtext,
1696 ExprDoneCond *isDone)
1700 /* Set default values for result flags: non-null, not a set result */
1703 *isDone = ExprSingleResult;
1705 /* Is this still necessary? Doubtful... */
1706 if (expression == NULL)
1713 * here we dispatch the work to the appropriate type of function given
1714 * the type of our expression.
1716 switch (nodeTag(expression))
1719 retDatum = ExecEvalVar((Var *) expression, econtext, isNull);
1723 Const *con = (Const *) expression;
1725 retDatum = con->constvalue;
1726 *isNull = con->constisnull;
1730 retDatum = ExecEvalParam((Param *) expression, econtext, isNull);
1733 retDatum = ExecEvalAggref((Aggref *) expression, econtext, isNull);
1736 retDatum = ExecEvalArrayRef((ArrayRef *) expression,
1743 Expr *expr = (Expr *) expression;
1745 switch (expr->opType)
1748 retDatum = ExecEvalOper(expr, econtext,
1752 retDatum = ExecEvalFunc(expr, econtext,
1756 retDatum = ExecEvalOr(expr, econtext, isNull);
1759 retDatum = ExecEvalAnd(expr, econtext, isNull);
1762 retDatum = ExecEvalNot(expr, econtext, isNull);
1765 retDatum = ExecEvalDistinct(expr, econtext,
1769 retDatum = ExecSubPlan((SubPlan *) expr->oper,
1770 expr->args, econtext,
1774 elog(ERROR, "ExecEvalExpr: unknown expression type %d",
1776 retDatum = 0; /* keep compiler quiet */
1782 retDatum = ExecEvalFieldSelect((FieldSelect *) expression,
1788 retDatum = ExecEvalExpr(((RelabelType *) expression)->arg,
1794 retDatum = ExecEvalCase((CaseExpr *) expression,
1800 retDatum = ExecEvalNullTest((NullTest *) expression,
1806 retDatum = ExecEvalBooleanTest((BooleanTest *) expression,
1811 case T_ConstraintTest:
1812 retDatum = ExecEvalConstraintTest((ConstraintTest *) expression,
1817 case T_ConstraintTestValue:
1818 retDatum = ExecEvalConstraintTestValue((ConstraintTestValue *) expression,
1824 elog(ERROR, "ExecEvalExpr: unknown expression type %d",
1825 nodeTag(expression));
1826 retDatum = 0; /* keep compiler quiet */
1831 } /* ExecEvalExpr() */
1835 * Same as above, but get into the right allocation context explicitly.
1838 ExecEvalExprSwitchContext(Node *expression,
1839 ExprContext *econtext,
1841 ExprDoneCond *isDone)
1844 MemoryContext oldContext;
1846 oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
1847 retDatum = ExecEvalExpr(expression, econtext, isNull, isDone);
1848 MemoryContextSwitchTo(oldContext);
1853 /* ----------------------------------------------------------------
1854 * ExecQual / ExecTargetList / ExecProject
1855 * ----------------------------------------------------------------
1858 /* ----------------------------------------------------------------
1861 * Evaluates a conjunctive boolean expression (qual list) and
1862 * returns true iff none of the subexpressions are false.
1863 * (We also return true if the list is empty.)
1865 * If some of the subexpressions yield NULL but none yield FALSE,
1866 * then the result of the conjunction is NULL (ie, unknown)
1867 * according to three-valued boolean logic. In this case,
1868 * we return the value specified by the "resultForNull" parameter.
1870 * Callers evaluating WHERE clauses should pass resultForNull=FALSE,
1871 * since SQL specifies that tuples with null WHERE results do not
1872 * get selected. On the other hand, callers evaluating constraint
1873 * conditions should pass resultForNull=TRUE, since SQL also specifies
1874 * that NULL constraint conditions are not failures.
1876 * NOTE: it would not be correct to use this routine to evaluate an
1877 * AND subclause of a boolean expression; for that purpose, a NULL
1878 * result must be returned as NULL so that it can be properly treated
1879 * in the next higher operator (cf. ExecEvalAnd and ExecEvalOr).
1880 * This routine is only used in contexts where a complete expression
1881 * is being evaluated and we know that NULL can be treated the same
1882 * as one boolean result or the other.
1884 * ----------------------------------------------------------------
1887 ExecQual(List *qual, ExprContext *econtext, bool resultForNull)
1890 MemoryContext oldContext;
1896 EV_printf("ExecQual: qual is ");
1897 EV_nodeDisplay(qual);
1903 * Run in short-lived per-tuple context while computing expressions.
1905 oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
1908 * Evaluate the qual conditions one at a time. If we find a FALSE
1909 * result, we can stop evaluating and return FALSE --- the AND result
1910 * must be FALSE. Also, if we find a NULL result when resultForNull
1911 * is FALSE, we can stop and return FALSE --- the AND result must be
1912 * FALSE or NULL in that case, and the caller doesn't care which.
1914 * If we get to the end of the list, we can return TRUE. This will
1915 * happen when the AND result is indeed TRUE, or when the AND result
1916 * is NULL (one or more NULL subresult, with all the rest TRUE) and
1917 * the caller has specified resultForNull = TRUE.
1921 foreach(qlist, qual)
1923 Node *clause = (Node *) lfirst(qlist);
1927 expr_value = ExecEvalExpr(clause, econtext, &isNull, NULL);
1931 if (resultForNull == false)
1933 result = false; /* treat NULL as FALSE */
1939 if (!DatumGetBool(expr_value))
1941 result = false; /* definitely FALSE */
1947 MemoryContextSwitchTo(oldContext);
1953 * Number of items in a tlist (including any resjunk items!)
1956 ExecTargetListLength(List *targetlist)
1961 foreach(tl, targetlist)
1963 TargetEntry *curTle = (TargetEntry *) lfirst(tl);
1965 if (curTle->resdom != NULL)
1968 len += curTle->fjoin->fj_nNodes;
1974 * Number of items in a tlist, not including any resjunk items
1977 ExecCleanTargetListLength(List *targetlist)
1982 foreach(tl, targetlist)
1984 TargetEntry *curTle = (TargetEntry *) lfirst(tl);
1986 if (curTle->resdom != NULL)
1988 if (!curTle->resdom->resjunk)
1992 len += curTle->fjoin->fj_nNodes;
1997 /* ----------------------------------------------------------------
2000 * Evaluates a targetlist with respect to the current
2001 * expression context and return a tuple.
2003 * As with ExecEvalExpr, the caller should pass isDone = NULL if not
2004 * prepared to deal with sets of result tuples. Otherwise, a return
2005 * of *isDone = ExprMultipleResult signifies a set element, and a return
2006 * of *isDone = ExprEndResult signifies end of the set of tuple.
2007 * ----------------------------------------------------------------
2010 ExecTargetList(List *targetlist,
2012 TupleDesc targettype,
2014 ExprContext *econtext,
2015 ExprDoneCond *isDone)
2017 MemoryContext oldContext;
2019 #define NPREALLOCDOMAINS 64
2020 char nullsArray[NPREALLOCDOMAINS];
2021 bool fjIsNullArray[NPREALLOCDOMAINS];
2022 ExprDoneCond itemIsDoneArray[NPREALLOCDOMAINS];
2025 ExprDoneCond *itemIsDone;
2032 static struct tupleDesc NullTupleDesc; /* we assume this inits to
2038 EV_printf("ExecTargetList: tl is ");
2039 EV_nodeDisplay(targetlist);
2043 * Run in short-lived per-tuple context while computing expressions.
2045 oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
2048 * There used to be some klugy and demonstrably broken code here that
2049 * special-cased the situation where targetlist == NIL. Now we just
2050 * fall through and return an empty-but-valid tuple. We do, however,
2051 * have to cope with the possibility that targettype is NULL ---
2052 * heap_formtuple won't like that, so pass a dummy descriptor with
2053 * natts = 0 to deal with it.
2055 if (targettype == NULL)
2056 targettype = &NullTupleDesc;
2059 * allocate an array of char's to hold the "null" information only if
2060 * we have a really large targetlist. otherwise we use the stack.
2062 * We also allocate a bool array that is used to hold fjoin result state,
2063 * and another array that holds the isDone status for each targetlist
2064 * item. The isDone status is needed so that we can iterate,
2065 * generating multiple tuples, when one or more tlist items return
2066 * sets. (We expect the caller to call us again if we return:
2068 * isDone = ExprMultipleResult.)
2070 if (nodomains > NPREALLOCDOMAINS)
2072 nulls = (char *) palloc(nodomains * sizeof(char));
2073 fjIsNull = (bool *) palloc(nodomains * sizeof(bool));
2074 itemIsDone = (ExprDoneCond *) palloc(nodomains * sizeof(ExprDoneCond));
2079 fjIsNull = fjIsNullArray;
2080 itemIsDone = itemIsDoneArray;
2084 * evaluate all the expressions in the target list
2088 *isDone = ExprSingleResult; /* until proven otherwise */
2090 haveDoneSets = false; /* any exhausted set exprs in tlist? */
2092 foreach(tl, targetlist)
2096 if (tle->resdom != NULL)
2098 resind = tle->resdom->resno - 1;
2100 values[resind] = ExecEvalExpr(tle->expr,
2103 &itemIsDone[resind]);
2104 nulls[resind] = isNull ? 'n' : ' ';
2106 if (itemIsDone[resind] != ExprSingleResult)
2108 /* We have a set-valued expression in the tlist */
2110 elog(ERROR, "Set-valued function called in context that cannot accept a set");
2111 if (itemIsDone[resind] == ExprMultipleResult)
2113 /* we have undone sets in the tlist, set flag */
2114 *isDone = ExprMultipleResult;
2118 /* we have done sets in the tlist, set flag for that */
2119 haveDoneSets = true;
2128 List *fjTlist = (List *) tle->expr;
2129 Fjoin *fjNode = tle->fjoin;
2130 int nNodes = fjNode->fj_nNodes;
2131 DatumPtr results = fjNode->fj_results;
2133 ExecEvalFjoin(tle, econtext, fjIsNull, isDone);
2136 * XXX this is wrong, but since fjoin code is completely
2137 * broken anyway, I'm not going to worry about it now --- tgl
2140 if (isDone && *isDone == ExprEndResult)
2142 MemoryContextSwitchTo(oldContext);
2148 * get the result from the inner node
2150 fjRes = (Resdom *) fjNode->fj_innerNode;
2151 resind = fjRes->resno - 1;
2152 values[resind] = results[0];
2153 nulls[resind] = fjIsNull[0] ? 'n' : ' ';
2156 * Get results from all of the outer nodes
2160 curNode++, fjTlist = lnext(fjTlist))
2162 Node *outernode = lfirst(fjTlist);
2164 fjRes = (Resdom *) outernode->iterexpr;
2165 resind = fjRes->resno - 1;
2166 values[resind] = results[curNode];
2167 nulls[resind] = fjIsNull[curNode] ? 'n' : ' ';
2170 elog(ERROR, "ExecTargetList: fjoin nodes not currently supported");
2178 * note: can't get here unless we verified isDone != NULL
2180 if (*isDone == ExprSingleResult)
2183 * all sets are done, so report that tlist expansion is
2186 *isDone = ExprEndResult;
2187 MemoryContextSwitchTo(oldContext);
2194 * We have some done and some undone sets. Restart the done
2195 * ones so that we can deliver a tuple (if possible).
2197 foreach(tl, targetlist)
2201 if (tle->resdom != NULL)
2203 resind = tle->resdom->resno - 1;
2205 if (itemIsDone[resind] == ExprEndResult)
2207 values[resind] = ExecEvalExpr(tle->expr,
2210 &itemIsDone[resind]);
2211 nulls[resind] = isNull ? 'n' : ' ';
2213 if (itemIsDone[resind] == ExprEndResult)
2216 * Oh dear, this item is returning an empty
2217 * set. Guess we can't make a tuple after all.
2219 *isDone = ExprEndResult;
2227 * If we cannot make a tuple because some sets are empty, we
2228 * still have to cycle the nonempty sets to completion, else
2229 * resources will not be released from subplans etc.
2231 if (*isDone == ExprEndResult)
2233 foreach(tl, targetlist)
2237 if (tle->resdom != NULL)
2239 resind = tle->resdom->resno - 1;
2241 while (itemIsDone[resind] == ExprMultipleResult)
2243 (void) ExecEvalExpr(tle->expr,
2246 &itemIsDone[resind]);
2251 MemoryContextSwitchTo(oldContext);
2259 * form the new result tuple (in the caller's memory context!)
2261 MemoryContextSwitchTo(oldContext);
2263 newTuple = (HeapTuple) heap_formtuple(targettype, values, nulls);
2268 * free the status arrays if we palloc'd them
2270 if (nodomains > NPREALLOCDOMAINS)
2280 /* ----------------------------------------------------------------
2283 * projects a tuple based on projection info and stores
2284 * it in the specified tuple table slot.
2286 * Note: someday soon the executor can be extended to eliminate
2287 * redundant projections by storing pointers to datums
2288 * in the tuple table and then passing these around when
2289 * possible. this should make things much quicker.
2291 * ----------------------------------------------------------------
2294 ExecProject(ProjectionInfo *projInfo, ExprDoneCond *isDone)
2296 TupleTableSlot *slot;
2301 ExprContext *econtext;
2307 if (projInfo == NULL)
2308 return (TupleTableSlot *) NULL;
2311 * get the projection info we want
2313 slot = projInfo->pi_slot;
2314 targetlist = projInfo->pi_targetlist;
2315 len = projInfo->pi_len;
2316 tupType = slot->ttc_tupleDescriptor;
2318 tupValue = projInfo->pi_tupValue;
2319 econtext = projInfo->pi_exprContext;
2322 * form a new result tuple (if possible --- result can be NULL)
2324 newTuple = ExecTargetList(targetlist,
2332 * store the tuple in the projection slot and return the slot.
2334 return ExecStoreTuple(newTuple, /* tuple to store */
2335 slot, /* slot to store in */
2336 InvalidBuffer, /* tuple has no buffer */