aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execQual.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2000-05-28 17:56:29 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2000-05-28 17:56:29 +0000
commit0a7fb4e9184539afcb6fed0f1d2bc0abddc2b0a6 (patch)
treeaffcce1c5b6367468fb6dcfd2790585f2e967629 /src/backend/executor/execQual.c
parent5005bb060b3f3a82cd1bd662c7f8946c9be59db5 (diff)
downloadpostgresql-0a7fb4e9184539afcb6fed0f1d2bc0abddc2b0a6.tar.gz
postgresql-0a7fb4e9184539afcb6fed0f1d2bc0abddc2b0a6.zip
First round of changes for new fmgr interface. fmgr itself and the
key call sites are changed, but most called functions are still oldstyle. An exception is that the PL managers are updated (so, for example, NULL handling now behaves as expected in plperl and plpgsql functions). NOTE initdb is forced due to added column in pg_proc.
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;
}