aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execQual.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/execQual.c')
-rw-r--r--src/backend/executor/execQual.c168
1 files changed, 104 insertions, 64 deletions
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 58307e6a695..a53957c4f4a 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.69 2000/04/12 17:15:08 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.70 2000/05/28 17:55:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -41,6 +41,7 @@
#include "executor/functions.h"
#include "executor/nodeSubplan.h"
#include "utils/builtins.h"
+#include "utils/fmgroids.h"
#include "utils/fcache2.h"
@@ -64,7 +65,8 @@ static Datum ExecEvalAnd(Expr *andExpr, ExprContext *econtext, bool *isNull);
static Datum ExecEvalFunc(Expr *funcClause, ExprContext *econtext,
bool *isNull, bool *isDone);
static void ExecEvalFuncArgs(FunctionCachePtr fcache, ExprContext *econtext,
- List *argList, Datum argV[], bool *argIsDone);
+ List *argList, FunctionCallInfo fcinfo,
+ bool *argIsDone);
static Datum ExecEvalNot(Expr *notclause, ExprContext *econtext, bool *isNull);
static Datum ExecEvalOper(Expr *opClause, ExprContext *econtext,
bool *isNull);
@@ -614,15 +616,12 @@ static void
ExecEvalFuncArgs(FunctionCachePtr fcache,
ExprContext *econtext,
List *argList,
- Datum argV[],
+ FunctionCallInfo fcinfo,
bool *argIsDone)
{
int i;
- bool *nullVect;
List *arg;
- nullVect = fcache->nullVect;
-
i = 0;
foreach(arg, argList)
{
@@ -632,16 +631,16 @@ ExecEvalFuncArgs(FunctionCachePtr fcache,
* as arguments but we make an exception in the case of nested dot
* expressions. We have to watch out for this case here.
*/
- argV[i] = ExecEvalExpr((Node *) lfirst(arg),
- econtext,
- &nullVect[i],
- argIsDone);
+ fcinfo->arg[i] = ExecEvalExpr((Node *) lfirst(arg),
+ econtext,
+ &fcinfo->argnull[i],
+ argIsDone);
if (!(*argIsDone))
{
if (i != 0)
elog(ERROR, "functions can only take sets in their first argument");
- fcache->setArg = (char *) argV[0];
+ fcache->setArg = fcinfo->arg[0];
fcache->hasSetArg = true;
}
i++;
@@ -658,40 +657,45 @@ ExecMakeFunctionResult(Node *node,
bool *isNull,
bool *isDone)
{
- Datum argV[FUNC_MAX_ARGS];
- FunctionCachePtr fcache;
- Func *funcNode = NULL;
- Oper *operNode = NULL;
- bool funcisset = false;
+ FunctionCallInfoData fcinfo;
+ FunctionCachePtr fcache;
+ List *ftlist;
+ bool funcisset;
+ Datum result;
+ bool argDone;
+
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
/*
* This is kind of ugly, Func nodes now have targetlists so that we
* know when and what to project out from postquel function results.
- * This means we have to pass the func node all the way down instead
- * of using only the fcache struct as before. ExecMakeFunctionResult
- * becomes a little bit more of a dual personality as a result.
+ * ExecMakeFunctionResult becomes a little bit more of a dual personality
+ * as a result.
*/
if (IsA(node, Func))
{
- funcNode = (Func *) node;
- fcache = funcNode->func_fcache;
+ fcache = ((Func *) node)->func_fcache;
+ ftlist = ((Func *) node)->func_tlist;
+ funcisset = (((Func *) node)->funcid == F_SETEVAL);
}
else
{
- operNode = (Oper *) node;
- fcache = operNode->op_fcache;
+ fcache = ((Oper *) node)->op_fcache;
+ ftlist = NIL;
+ funcisset = false;
}
+ fcinfo.flinfo = &fcache->func;
+ fcinfo.nargs = fcache->nargs;
+
/*
* arguments is a list of expressions to evaluate before passing to
- * the function manager. We collect the results of evaluating the
- * expressions into a datum array (argV) and pass this array to
- * arrayFmgr()
+ * the function manager. We collect the results of evaluating the
+ * expressions into the FunctionCallInfo struct. Note we assume that
+ * fcache->nargs is the correct length of the arguments list!
*/
- if (fcache->nargs != 0)
+ if (fcache->nargs > 0)
{
- bool argDone;
-
if (fcache->nargs > FUNC_MAX_ARGS)
elog(ERROR, "ExecMakeFunctionResult: too many arguments");
@@ -700,21 +704,23 @@ ExecMakeFunctionResult(Node *node,
* returning a set of tuples (i.e. a nested dot expression). We
* don't want to evaluate the arguments again until the function
* is done. hasSetArg will always be false until we eval the args
- * for the first time. We should set this in the parser.
+ * for the first time.
*/
- if ((fcache->hasSetArg) && fcache->setArg != NULL)
+ if (fcache->hasSetArg && fcache->setArg != (Datum) 0)
{
- argV[0] = (Datum) fcache->setArg;
+ fcinfo.arg[0] = fcache->setArg;
argDone = false;
}
else
- ExecEvalFuncArgs(fcache, econtext, arguments, argV, &argDone);
+ ExecEvalFuncArgs(fcache, econtext, arguments, &fcinfo, &argDone);
- if ((fcache->hasSetArg) && (argDone))
+ if (fcache->hasSetArg && argDone)
{
+ /* can only get here if input is an empty set. */
if (isDone)
*isDone = true;
- return (Datum) NULL;
+ *isNull = true;
+ return (Datum) 0;
}
}
@@ -731,27 +737,23 @@ ExecMakeFunctionResult(Node *node,
* which defines this set. So replace the existing funcid in the
* funcnode with the set's OID. Also, we want a new fcache which
* points to the right function, so get that, now that we have the
- * right OID. Also zero out the argV, since the real set doesn't take
+ * right OID. Also zero out fcinfo.arg, since the real set doesn't take
* any arguments.
*/
- if (((Func *) node)->funcid == F_SETEVAL)
+ if (funcisset)
{
- funcisset = true;
if (fcache->setArg)
{
- argV[0] = 0;
-
- ((Func *) node)->funcid = (Oid) PointerGetDatum(fcache->setArg);
-
+ ((Func *) node)->funcid = DatumGetObjectId(fcache->setArg);
}
else
{
- ((Func *) node)->funcid = (Oid) argV[0];
- setFcache(node, argV[0], NIL, econtext);
+ ((Func *) node)->funcid = DatumGetObjectId(fcinfo.arg[0]);
+ setFcache(node, DatumGetObjectId(fcinfo.arg[0]), NIL, econtext);
fcache = ((Func *) node)->func_fcache;
- fcache->setArg = (char *) argV[0];
- argV[0] = (Datum) 0;
+ fcache->setArg = fcinfo.arg[0];
}
+ fcinfo.arg[0] = (Datum) 0;
}
/*
@@ -760,11 +762,6 @@ ExecMakeFunctionResult(Node *node,
*/
if (fcache->language == SQLlanguageId)
{
- Datum result;
- bool argDone;
-
- Assert(funcNode);
-
/*--------------------
* This loop handles the situation where we are iterating through
* all results in a nested dot function (whose argument function
@@ -777,8 +774,37 @@ ExecMakeFunctionResult(Node *node,
*/
for (;;)
{
- result = postquel_function(funcNode, (char **) argV,
- isNull, isDone);
+ /*
+ * If function is strict, and there are any NULL arguments,
+ * skip calling the function (at least for this set of args).
+ */
+ bool callit = true;
+
+ if (fcinfo.flinfo->fn_strict)
+ {
+ int i;
+
+ for (i = 0; i < fcinfo.nargs; i++)
+ {
+ if (fcinfo.argnull[i])
+ {
+ callit = false;
+ break;
+ }
+ }
+ }
+
+ if (callit)
+ {
+ result = postquel_function(&fcinfo, fcache, ftlist, isDone);
+ *isNull = fcinfo.isnull;
+ }
+ else
+ {
+ result = (Datum) 0;
+ *isDone = true;
+ *isNull = true;
+ }
if (!*isDone)
break; /* got a result from current argument */
@@ -786,7 +812,7 @@ ExecMakeFunctionResult(Node *node,
break; /* input not a set, so done */
/* OK, get the next argument... */
- ExecEvalFuncArgs(fcache, econtext, arguments, argV, &argDone);
+ ExecEvalFuncArgs(fcache, econtext, arguments, &fcinfo, &argDone);
if (argDone)
{
@@ -795,10 +821,11 @@ ExecMakeFunctionResult(Node *node,
* End of arguments, so reset the setArg flag and say
* "Done"
*/
- fcache->setArg = (char *) NULL;
+ fcache->setArg = (Datum) 0;
fcache->hasSetArg = false;
*isDone = true;
- result = (Datum) NULL;
+ *isNull = true;
+ result = (Datum) 0;
break;
}
@@ -826,21 +853,34 @@ ExecMakeFunctionResult(Node *node,
if (*isDone)
((Func *) node)->func_fcache = NULL;
}
-
- return result;
}
else
{
- int i;
-
+ /* A non-SQL function cannot return a set, at present. */
if (isDone)
*isDone = true;
- for (i = 0; i < fcache->nargs; i++)
- if (fcache->nullVect[i] == true)
- *isNull = true;
+ /*
+ * If function is strict, and there are any NULL arguments,
+ * skip calling the function and return NULL.
+ */
+ if (fcinfo.flinfo->fn_strict)
+ {
+ int i;
- return (Datum) fmgr_c(&fcache->func, (FmgrValues *) argV, isNull);
+ for (i = 0; i < fcinfo.nargs; i++)
+ {
+ if (fcinfo.argnull[i])
+ {
+ *isNull = true;
+ return (Datum) 0;
+ }
+ }
+ }
+ result = FunctionCallInvoke(&fcinfo);
+ *isNull = fcinfo.isnull;
}
+
+ return result;
}