diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2000-05-28 17:56:29 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2000-05-28 17:56:29 +0000 |
commit | 0a7fb4e9184539afcb6fed0f1d2bc0abddc2b0a6 (patch) | |
tree | affcce1c5b6367468fb6dcfd2790585f2e967629 /src/backend/executor/nodeAgg.c | |
parent | 5005bb060b3f3a82cd1bd662c7f8946c9be59db5 (diff) | |
download | postgresql-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/nodeAgg.c')
-rw-r--r-- | src/backend/executor/nodeAgg.c | 95 |
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)) { |