* Compute the final value of one aggregate. * * This function handles only one grouping set (already set in * aggstate->current_set). * * The finalfn will be run, and the result delivered, in the * output-tuple context; caller's CurrentMemoryContext does not matter. * * The finalfn uses the state as set in the transno. This also might be * being used by another aggregate function, so it's
| 1071 | * nothing destructive here. |
| 1072 | */ |
| 1073 | static void |
| 1074 | finalize_aggregate(AggState *aggstate, |
| 1075 | AggStatePerAgg peragg, |
| 1076 | AggStatePerGroup pergroupstate, |
| 1077 | Datum *resultVal, bool *resultIsNull) |
| 1078 | { |
| 1079 | LOCAL_FCINFO(fcinfo, FUNC_MAX_ARGS); |
| 1080 | bool anynull = false; |
| 1081 | MemoryContext oldContext; |
| 1082 | int i; |
| 1083 | ListCell *lc; |
| 1084 | AggStatePerTrans pertrans = &aggstate->pertrans[peragg->transno]; |
| 1085 | |
| 1086 | oldContext = MemoryContextSwitchTo(aggstate->ss.ps.ps_ExprContext->ecxt_per_tuple_memory); |
| 1087 | |
| 1088 | /* |
| 1089 | * Evaluate any direct arguments. We do this even if there's no finalfn |
| 1090 | * (which is unlikely anyway), so that side-effects happen as expected. |
| 1091 | * The direct arguments go into arg positions 1 and up, leaving position 0 |
| 1092 | * for the transition state value. |
| 1093 | */ |
| 1094 | i = 1; |
| 1095 | foreach(lc, peragg->aggdirectargs) |
| 1096 | { |
| 1097 | ExprState *expr = (ExprState *) lfirst(lc); |
| 1098 | |
| 1099 | fcinfo->args[i].value = ExecEvalExpr(expr, |
| 1100 | aggstate->ss.ps.ps_ExprContext, |
| 1101 | &fcinfo->args[i].isnull); |
| 1102 | anynull |= fcinfo->args[i].isnull; |
| 1103 | i++; |
| 1104 | } |
| 1105 | |
| 1106 | /* |
| 1107 | * Apply the agg's finalfn if one is provided, else return transValue. |
| 1108 | */ |
| 1109 | if (OidIsValid(peragg->finalfn_oid)) |
| 1110 | { |
| 1111 | int numFinalArgs = peragg->numFinalArgs; |
| 1112 | |
| 1113 | /* set up aggstate->curperagg for AggGetAggref() */ |
| 1114 | aggstate->curperagg = peragg; |
| 1115 | |
| 1116 | InitFunctionCallInfoData(*fcinfo, &peragg->finalfn, |
| 1117 | numFinalArgs, |
| 1118 | pertrans->aggCollation, |
| 1119 | (void *) aggstate, NULL); |
| 1120 | |
| 1121 | /* Fill in the transition state value */ |
| 1122 | fcinfo->args[0].value = |
| 1123 | MakeExpandedObjectReadOnly(pergroupstate->transValue, |
| 1124 | pergroupstate->transValueIsNull, |
| 1125 | pertrans->transtypeLen); |
| 1126 | fcinfo->args[0].isnull = pergroupstate->transValueIsNull; |
| 1127 | anynull |= pergroupstate->transValueIsNull; |
| 1128 | |
| 1129 | /* Fill any remaining argument positions with nulls */ |
| 1130 | for (; i < numFinalArgs; i++) |
no test coverage detected