2

I am creating a user-defined aggregate function that needs an additional parameter. More precisely it is a cumulative (aka window) minimum that takes as second parameter a time interval defining the window. Since the aggregate function operates on my user-defined data types I have conveyed a dummy example that computes the average of the n last values of a column. I am aware that I can solve this dummy problem in PostgreSQL but the purpose of the example is only to highlight my problem.

CREATE FUNCTION lastNavg_transfn(state integer[], next integer, n integer)
    RETURNS integer[] AS $$
    BEGIN
        RETURN array_append(state, next);
    END;
    $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE;

CREATE FUNCTION lastNavg_finalfn(state integer[], n integer)
    RETURNS float AS $$
    DECLARE
        card integer;
        count float;
        sum float;
    BEGIN
        count := 0;
        sum := 0;
        card := array_length(state, 1);
        FOR i IN greatest(1,card-n+1)..card
        LOOP 
            sum := sum + state[i];
            count := count + 1;
        END LOOP;
        RETURN sum/count;
    END;
    $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE;

CREATE AGGREGATE lastNavg(integer, integer) (
    SFUNC = lastNavg_transfn,
    STYPE = integer[],
    INITCOND = '{}',
    FINALFUNC = lastNavg_finalfn,
    PARALLEL = SAFE
);

I receive the following error

ERROR: function lastnavg_finalfn(integer[]) does not exist
SQL state: 42883

How to tell PostgreSQL that my final function also needs a direct parameter? I am working on PostgreSQL 10.1. I know that according to the documentation direct parameters are only allowed for ordered-set aggregates, but I would also need a direct parameter for "normal" aggregates.

1 Answer 1

1

You could define an aggregate with two arguments and supply your additional parameter as constant second argument.

The SFUNC simply stores the second argument e.g. as 0-th element of the STYPE integer array.

FINALFUNC has only a single argument and gets n from the 0-th element of the array.

If you need a second argument that is not an integer, define a composite type and use that as STYPE.

Not pretty, but it should do the trick.

Sign up to request clarification or add additional context in comments.

2 Comments

Indeed, I already thought about this possibility but the problem is that arrays in PostgreSQL are not polymorphic and thus, in my case, the type of the 0-th element of the array would of type interval, and the type of the other elements in the state array would be my user-defined data type (e.g., temporal floats) :-(
No problem. Use a composite type. I have extended the answer accordingly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.