aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeAgg.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/nodeAgg.c')
-rw-r--r--src/backend/executor/nodeAgg.c95
1 files changed, 71 insertions, 24 deletions
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index e2db06f84d1..853fa96e2c3 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -32,7 +32,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.63 2000/04/12 17:15:09 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.64 2000/05/28 17:55:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -218,8 +218,13 @@ static void
advance_transition_functions(AggStatePerAgg peraggstate,
Datum newVal, bool isNull)
{
- Datum args[2];
+ FunctionCallInfoData fcinfo;
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+
+ /*
+ * XXX reconsider isNULL handling here
+ */
if (OidIsValid(peraggstate->xfn1_oid) && !isNull)
{
if (peraggstate->noInitValue)
@@ -244,28 +249,48 @@ advance_transition_functions(AggStatePerAgg peraggstate,
else
{
/* apply transition function 1 */
- args[0] = peraggstate->value1;
- args[1] = newVal;
- newVal = (Datum) fmgr_c(&peraggstate->xfn1,
- (FmgrValues *) args,
- &isNull);
- if (!peraggstate->transtype1ByVal)
+ fcinfo.flinfo = &peraggstate->xfn1;
+ fcinfo.nargs = 2;
+ fcinfo.arg[0] = peraggstate->value1;
+ fcinfo.argnull[0] = peraggstate->value1IsNull;
+ fcinfo.arg[1] = newVal;
+ fcinfo.argnull[1] = isNull;
+ if (fcinfo.flinfo->fn_strict &&
+ (peraggstate->value1IsNull || isNull))
+ {
+ /* don't call a strict function with NULL inputs */
+ newVal = (Datum) 0;
+ fcinfo.isnull = true;
+ }
+ else
+ newVal = FunctionCallInvoke(&fcinfo);
+ if (!peraggstate->transtype1ByVal && !peraggstate->value1IsNull)
pfree(peraggstate->value1);
peraggstate->value1 = newVal;
+ peraggstate->value1IsNull = fcinfo.isnull;
}
}
if (OidIsValid(peraggstate->xfn2_oid))
{
/* apply transition function 2 */
- args[0] = peraggstate->value2;
- isNull = false; /* value2 cannot be null, currently */
- newVal = (Datum) fmgr_c(&peraggstate->xfn2,
- (FmgrValues *) args,
- &isNull);
- if (!peraggstate->transtype2ByVal)
+ fcinfo.flinfo = &peraggstate->xfn2;
+ fcinfo.nargs = 1;
+ fcinfo.arg[0] = peraggstate->value2;
+ fcinfo.argnull[0] = peraggstate->value2IsNull;
+ fcinfo.isnull = false; /* must reset after use by xfn1 */
+ if (fcinfo.flinfo->fn_strict && peraggstate->value2IsNull)
+ {
+ /* don't call a strict function with NULL inputs */
+ newVal = (Datum) 0;
+ fcinfo.isnull = true;
+ }
+ else
+ newVal = FunctionCallInvoke(&fcinfo);
+ if (!peraggstate->transtype2ByVal && !peraggstate->value2IsNull)
pfree(peraggstate->value2);
peraggstate->value2 = newVal;
+ peraggstate->value2IsNull = fcinfo.isnull;
}
}
@@ -276,8 +301,10 @@ static void
finalize_aggregate(AggStatePerAgg peraggstate,
Datum *resultVal, bool *resultIsNull)
{
- Aggref *aggref = peraggstate->aggref;
- char *args[2];
+ Aggref *aggref = peraggstate->aggref;
+ FunctionCallInfoData fcinfo;
+
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
/*
* If it's a DISTINCT aggregate, all we've done so far is to stuff the
@@ -337,21 +364,41 @@ finalize_aggregate(AggStatePerAgg peraggstate,
if (OidIsValid(peraggstate->finalfn_oid) &&
!peraggstate->noInitValue)
{
+ fcinfo.flinfo = &peraggstate->finalfn;
if (peraggstate->finalfn.fn_nargs > 1)
{
- args[0] = (char *) peraggstate->value1;
- args[1] = (char *) peraggstate->value2;
+ fcinfo.nargs = 2;
+ fcinfo.arg[0] = peraggstate->value1;
+ fcinfo.argnull[0] = peraggstate->value1IsNull;
+ fcinfo.arg[1] = peraggstate->value2;
+ fcinfo.argnull[1] = peraggstate->value2IsNull;
}
else if (OidIsValid(peraggstate->xfn1_oid))
- args[0] = (char *) peraggstate->value1;
+ {
+ fcinfo.nargs = 1;
+ fcinfo.arg[0] = peraggstate->value1;
+ fcinfo.argnull[0] = peraggstate->value1IsNull;
+ }
else if (OidIsValid(peraggstate->xfn2_oid))
- args[0] = (char *) peraggstate->value2;
+ {
+ fcinfo.nargs = 1;
+ fcinfo.arg[0] = peraggstate->value2;
+ fcinfo.argnull[0] = peraggstate->value2IsNull;
+ }
else
elog(ERROR, "ExecAgg: no valid transition functions??");
- *resultIsNull = false;
- *resultVal = (Datum) fmgr_c(&peraggstate->finalfn,
- (FmgrValues *) args,
- resultIsNull);
+ if (fcinfo.flinfo->fn_strict &&
+ (fcinfo.argnull[0] || fcinfo.argnull[1]))
+ {
+ /* don't call a strict function with NULL inputs */
+ *resultVal = (Datum) 0;
+ *resultIsNull = true;
+ }
+ else
+ {
+ *resultVal = FunctionCallInvoke(&fcinfo);
+ *resultIsNull = fcinfo.isnull;
+ }
}
else if (OidIsValid(peraggstate->xfn1_oid))
{