* initialize_peragg * * Almost same as in nodeAgg.c, except we don't support DISTINCT currently. */
| 2984 | * Almost same as in nodeAgg.c, except we don't support DISTINCT currently. |
| 2985 | */ |
| 2986 | static WindowStatePerAggData * |
| 2987 | initialize_peragg(WindowAggState *winstate, WindowFunc *wfunc, |
| 2988 | WindowStatePerAgg peraggstate) |
| 2989 | { |
| 2990 | Oid inputTypes[FUNC_MAX_ARGS]; |
| 2991 | int numArguments; |
| 2992 | HeapTuple aggTuple; |
| 2993 | Form_pg_aggregate aggform; |
| 2994 | Oid aggtranstype; |
| 2995 | AttrNumber initvalAttNo; |
| 2996 | AclResult aclresult; |
| 2997 | bool use_ma_code; |
| 2998 | Oid transfn_oid, |
| 2999 | invtransfn_oid, |
| 3000 | finalfn_oid; |
| 3001 | bool finalextra; |
| 3002 | char finalmodify; |
| 3003 | Expr *transfnexpr, |
| 3004 | *invtransfnexpr, |
| 3005 | *finalfnexpr; |
| 3006 | Datum textInitVal; |
| 3007 | int i; |
| 3008 | ListCell *lc; |
| 3009 | |
| 3010 | numArguments = list_length(wfunc->args); |
| 3011 | |
| 3012 | i = 0; |
| 3013 | foreach(lc, wfunc->args) |
| 3014 | { |
| 3015 | inputTypes[i++] = exprType((Node *) lfirst(lc)); |
| 3016 | } |
| 3017 | |
| 3018 | aggTuple = SearchSysCache1(AGGFNOID, ObjectIdGetDatum(wfunc->winfnoid)); |
| 3019 | if (!HeapTupleIsValid(aggTuple)) |
| 3020 | elog(ERROR, "cache lookup failed for aggregate %u", |
| 3021 | wfunc->winfnoid); |
| 3022 | aggform = (Form_pg_aggregate) GETSTRUCT(aggTuple); |
| 3023 | |
| 3024 | /* |
| 3025 | * Figure out whether we want to use the moving-aggregate implementation, |
| 3026 | * and collect the right set of fields from the pg_attribute entry. |
| 3027 | * |
| 3028 | * It's possible that an aggregate would supply a safe moving-aggregate |
| 3029 | * implementation and an unsafe normal one, in which case our hand is |
| 3030 | * forced. Otherwise, if the frame head can't move, we don't need |
| 3031 | * moving-aggregate code. Even if we'd like to use it, don't do so if the |
| 3032 | * aggregate's arguments (and FILTER clause if any) contain any calls to |
| 3033 | * volatile functions. Otherwise, the difference between restarting and |
| 3034 | * not restarting the aggregation would be user-visible. |
| 3035 | */ |
| 3036 | if (!OidIsValid(aggform->aggminvtransfn)) |
| 3037 | use_ma_code = false; /* sine qua non */ |
| 3038 | else if (aggform->aggmfinalmodify == AGGMODIFY_READ_ONLY && |
| 3039 | aggform->aggfinalmodify != AGGMODIFY_READ_ONLY) |
| 3040 | use_ma_code = true; /* decision forced by safety */ |
| 3041 | else if (winstate->frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING) |
| 3042 | use_ma_code = false; /* non-moving frame head */ |
| 3043 | else if (contain_volatile_functions((Node *) wfunc)) |
no test coverage detected