325 lines
11 KiB
Plaintext
325 lines
11 KiB
Plaintext
--
|
|
-- CREATE_AGGREGATE
|
|
--
|
|
-- all functions CREATEd
|
|
CREATE AGGREGATE newavg (
|
|
sfunc = int4_avg_accum, basetype = int4, stype = _int8,
|
|
finalfunc = int8_avg,
|
|
initcond1 = '{0,0}'
|
|
);
|
|
-- test comments
|
|
COMMENT ON AGGREGATE newavg_wrong (int4) IS 'an agg comment';
|
|
ERROR: aggregate newavg_wrong(integer) does not exist
|
|
COMMENT ON AGGREGATE newavg (int4) IS 'an agg comment';
|
|
COMMENT ON AGGREGATE newavg (int4) IS NULL;
|
|
-- without finalfunc; test obsolete spellings 'sfunc1' etc
|
|
CREATE AGGREGATE newsum (
|
|
sfunc1 = int4pl, basetype = int4, stype1 = int4,
|
|
initcond1 = '0'
|
|
);
|
|
-- zero-argument aggregate
|
|
CREATE AGGREGATE newcnt (*) (
|
|
sfunc = int8inc, stype = int8,
|
|
initcond = '0', parallel = safe
|
|
);
|
|
-- old-style spelling of same (except without parallel-safe; that's too new)
|
|
CREATE AGGREGATE oldcnt (
|
|
sfunc = int8inc, basetype = 'ANY', stype = int8,
|
|
initcond = '0'
|
|
);
|
|
-- aggregate that only cares about null/nonnull input
|
|
CREATE AGGREGATE newcnt ("any") (
|
|
sfunc = int8inc_any, stype = int8,
|
|
initcond = '0'
|
|
);
|
|
COMMENT ON AGGREGATE nosuchagg (*) IS 'should fail';
|
|
ERROR: aggregate nosuchagg(*) does not exist
|
|
COMMENT ON AGGREGATE newcnt (*) IS 'an agg(*) comment';
|
|
COMMENT ON AGGREGATE newcnt ("any") IS 'an agg(any) comment';
|
|
-- multi-argument aggregate
|
|
create function sum3(int8,int8,int8) returns int8 as
|
|
'select $1 + $2 + $3' language sql strict immutable;
|
|
create aggregate sum2(int8,int8) (
|
|
sfunc = sum3, stype = int8,
|
|
initcond = '0'
|
|
);
|
|
-- multi-argument aggregates sensitive to distinct/order, strict/nonstrict
|
|
create type aggtype as (a integer, b integer, c text);
|
|
create function aggf_trans(aggtype[],integer,integer,text) returns aggtype[]
|
|
as 'select array_append($1,ROW($2,$3,$4)::aggtype)'
|
|
language sql strict immutable;
|
|
create function aggfns_trans(aggtype[],integer,integer,text) returns aggtype[]
|
|
as 'select array_append($1,ROW($2,$3,$4)::aggtype)'
|
|
language sql immutable;
|
|
create aggregate aggfstr(integer,integer,text) (
|
|
sfunc = aggf_trans, stype = aggtype[],
|
|
initcond = '{}'
|
|
);
|
|
create aggregate aggfns(integer,integer,text) (
|
|
sfunc = aggfns_trans, stype = aggtype[], sspace = 10000,
|
|
initcond = '{}'
|
|
);
|
|
-- check error cases that would require run-time type coercion
|
|
create function least_accum(int8, int8) returns int8 language sql as
|
|
'select least($1, $2)';
|
|
create aggregate least_agg(int4) (
|
|
stype = int8, sfunc = least_accum
|
|
); -- fails
|
|
ERROR: function least_accum(bigint, bigint) requires run-time type coercion
|
|
drop function least_accum(int8, int8);
|
|
create function least_accum(anycompatible, anycompatible)
|
|
returns anycompatible language sql as
|
|
'select least($1, $2)';
|
|
create aggregate least_agg(int4) (
|
|
stype = int8, sfunc = least_accum
|
|
); -- fails
|
|
ERROR: function least_accum(bigint, bigint) requires run-time type coercion
|
|
create aggregate least_agg(int8) (
|
|
stype = int8, sfunc = least_accum
|
|
);
|
|
drop function least_accum(anycompatible, anycompatible) cascade;
|
|
NOTICE: drop cascades to function least_agg(bigint)
|
|
-- variadic aggregates
|
|
create function least_accum(anyelement, variadic anyarray)
|
|
returns anyelement language sql as
|
|
'select least($1, min($2[i])) from generate_subscripts($2,1) g(i)';
|
|
create aggregate least_agg(variadic items anyarray) (
|
|
stype = anyelement, sfunc = least_accum
|
|
);
|
|
create function cleast_accum(anycompatible, variadic anycompatiblearray)
|
|
returns anycompatible language sql as
|
|
'select least($1, min($2[i])) from generate_subscripts($2,1) g(i)';
|
|
create aggregate cleast_agg(variadic items anycompatiblearray) (
|
|
stype = anycompatible, sfunc = cleast_accum
|
|
);
|
|
-- test ordered-set aggs using built-in support functions
|
|
create aggregate my_percentile_disc(float8 ORDER BY anyelement) (
|
|
stype = internal,
|
|
sfunc = ordered_set_transition,
|
|
finalfunc = percentile_disc_final,
|
|
finalfunc_extra = true,
|
|
finalfunc_modify = read_write
|
|
);
|
|
create aggregate my_rank(VARIADIC "any" ORDER BY VARIADIC "any") (
|
|
stype = internal,
|
|
sfunc = ordered_set_transition_multi,
|
|
finalfunc = rank_final,
|
|
finalfunc_extra = true,
|
|
hypothetical
|
|
);
|
|
alter aggregate my_percentile_disc(float8 ORDER BY anyelement)
|
|
rename to test_percentile_disc;
|
|
alter aggregate my_rank(VARIADIC "any" ORDER BY VARIADIC "any")
|
|
rename to test_rank;
|
|
\da test_*
|
|
List of aggregate functions
|
|
Schema | Name | Result data type | Argument data types | Description
|
|
--------+----------------------+------------------+----------------------------------------+-------------
|
|
public | test_percentile_disc | anyelement | double precision ORDER BY anyelement |
|
|
public | test_rank | bigint | VARIADIC "any" ORDER BY VARIADIC "any" |
|
|
(2 rows)
|
|
|
|
-- moving-aggregate options
|
|
CREATE AGGREGATE sumdouble (float8)
|
|
(
|
|
stype = float8,
|
|
sfunc = float8pl,
|
|
mstype = float8,
|
|
msfunc = float8pl,
|
|
minvfunc = float8mi
|
|
);
|
|
-- aggregate combine and serialization functions
|
|
-- can't specify just one of serialfunc and deserialfunc
|
|
CREATE AGGREGATE myavg (numeric)
|
|
(
|
|
stype = internal,
|
|
sfunc = numeric_avg_accum,
|
|
serialfunc = numeric_avg_serialize
|
|
);
|
|
ERROR: must specify both or neither of serialization and deserialization functions
|
|
-- serialfunc must have correct parameters
|
|
CREATE AGGREGATE myavg (numeric)
|
|
(
|
|
stype = internal,
|
|
sfunc = numeric_avg_accum,
|
|
serialfunc = numeric_avg_deserialize,
|
|
deserialfunc = numeric_avg_deserialize
|
|
);
|
|
ERROR: function numeric_avg_deserialize(internal) does not exist
|
|
-- deserialfunc must have correct parameters
|
|
CREATE AGGREGATE myavg (numeric)
|
|
(
|
|
stype = internal,
|
|
sfunc = numeric_avg_accum,
|
|
serialfunc = numeric_avg_serialize,
|
|
deserialfunc = numeric_avg_serialize
|
|
);
|
|
ERROR: function numeric_avg_serialize(bytea, internal) does not exist
|
|
-- ensure combine function parameters are checked
|
|
CREATE AGGREGATE myavg (numeric)
|
|
(
|
|
stype = internal,
|
|
sfunc = numeric_avg_accum,
|
|
serialfunc = numeric_avg_serialize,
|
|
deserialfunc = numeric_avg_deserialize,
|
|
combinefunc = int4larger
|
|
);
|
|
ERROR: function int4larger(internal, internal) does not exist
|
|
-- ensure create aggregate works.
|
|
CREATE AGGREGATE myavg (numeric)
|
|
(
|
|
stype = internal,
|
|
sfunc = numeric_avg_accum,
|
|
finalfunc = numeric_avg,
|
|
serialfunc = numeric_avg_serialize,
|
|
deserialfunc = numeric_avg_deserialize,
|
|
combinefunc = numeric_avg_combine,
|
|
finalfunc_modify = shareable -- just to test a non-default setting
|
|
);
|
|
-- Ensure all these functions made it into the catalog
|
|
SELECT aggfnoid, aggtransfn, aggcombinefn, aggtranstype::regtype,
|
|
aggserialfn, aggdeserialfn, aggfinalmodify
|
|
FROM pg_aggregate
|
|
WHERE aggfnoid = 'myavg'::REGPROC;
|
|
aggfnoid | aggtransfn | aggcombinefn | aggtranstype | aggserialfn | aggdeserialfn | aggfinalmodify
|
|
----------+-------------------+---------------------+--------------+-----------------------+-------------------------+----------------
|
|
myavg | numeric_avg_accum | numeric_avg_combine | internal | numeric_avg_serialize | numeric_avg_deserialize | s
|
|
(1 row)
|
|
|
|
DROP AGGREGATE myavg (numeric);
|
|
-- create or replace aggregate
|
|
CREATE AGGREGATE myavg (numeric)
|
|
(
|
|
stype = internal,
|
|
sfunc = numeric_avg_accum,
|
|
finalfunc = numeric_avg
|
|
);
|
|
CREATE OR REPLACE AGGREGATE myavg (numeric)
|
|
(
|
|
stype = internal,
|
|
sfunc = numeric_avg_accum,
|
|
finalfunc = numeric_avg,
|
|
serialfunc = numeric_avg_serialize,
|
|
deserialfunc = numeric_avg_deserialize,
|
|
combinefunc = numeric_avg_combine,
|
|
finalfunc_modify = shareable -- just to test a non-default setting
|
|
);
|
|
-- Ensure all these functions made it into the catalog again
|
|
SELECT aggfnoid, aggtransfn, aggcombinefn, aggtranstype::regtype,
|
|
aggserialfn, aggdeserialfn, aggfinalmodify
|
|
FROM pg_aggregate
|
|
WHERE aggfnoid = 'myavg'::REGPROC;
|
|
aggfnoid | aggtransfn | aggcombinefn | aggtranstype | aggserialfn | aggdeserialfn | aggfinalmodify
|
|
----------+-------------------+---------------------+--------------+-----------------------+-------------------------+----------------
|
|
myavg | numeric_avg_accum | numeric_avg_combine | internal | numeric_avg_serialize | numeric_avg_deserialize | s
|
|
(1 row)
|
|
|
|
-- can change stype:
|
|
CREATE OR REPLACE AGGREGATE myavg (numeric)
|
|
(
|
|
stype = numeric,
|
|
sfunc = numeric_add
|
|
);
|
|
SELECT aggfnoid, aggtransfn, aggcombinefn, aggtranstype::regtype,
|
|
aggserialfn, aggdeserialfn, aggfinalmodify
|
|
FROM pg_aggregate
|
|
WHERE aggfnoid = 'myavg'::REGPROC;
|
|
aggfnoid | aggtransfn | aggcombinefn | aggtranstype | aggserialfn | aggdeserialfn | aggfinalmodify
|
|
----------+-------------+--------------+--------------+-------------+---------------+----------------
|
|
myavg | numeric_add | - | numeric | - | - | r
|
|
(1 row)
|
|
|
|
-- can't change return type:
|
|
CREATE OR REPLACE AGGREGATE myavg (numeric)
|
|
(
|
|
stype = numeric,
|
|
sfunc = numeric_add,
|
|
finalfunc = numeric_out
|
|
);
|
|
ERROR: cannot change return type of existing function
|
|
HINT: Use DROP AGGREGATE myavg(numeric) first.
|
|
-- can't change to a different kind:
|
|
CREATE OR REPLACE AGGREGATE myavg (order by numeric)
|
|
(
|
|
stype = numeric,
|
|
sfunc = numeric_add
|
|
);
|
|
ERROR: cannot change routine kind
|
|
DETAIL: "myavg" is an ordinary aggregate function.
|
|
-- can't change plain function to aggregate:
|
|
create function sum4(int8,int8,int8,int8) returns int8 as
|
|
'select $1 + $2 + $3 + $4' language sql strict immutable;
|
|
CREATE OR REPLACE AGGREGATE sum3 (int8,int8,int8)
|
|
(
|
|
stype = int8,
|
|
sfunc = sum4
|
|
);
|
|
ERROR: cannot change routine kind
|
|
DETAIL: "sum3" is a function.
|
|
drop function sum4(int8,int8,int8,int8);
|
|
DROP AGGREGATE myavg (numeric);
|
|
-- invalid: bad parallel-safety marking
|
|
CREATE AGGREGATE mysum (int)
|
|
(
|
|
stype = int,
|
|
sfunc = int4pl,
|
|
parallel = pear
|
|
);
|
|
ERROR: parameter "parallel" must be SAFE, RESTRICTED, or UNSAFE
|
|
-- invalid: nonstrict inverse with strict forward function
|
|
CREATE FUNCTION float8mi_n(float8, float8) RETURNS float8 AS
|
|
$$ SELECT $1 - $2; $$
|
|
LANGUAGE SQL;
|
|
CREATE AGGREGATE invalidsumdouble (float8)
|
|
(
|
|
stype = float8,
|
|
sfunc = float8pl,
|
|
mstype = float8,
|
|
msfunc = float8pl,
|
|
minvfunc = float8mi_n
|
|
);
|
|
ERROR: strictness of aggregate's forward and inverse transition functions must match
|
|
-- invalid: non-matching result types
|
|
CREATE FUNCTION float8mi_int(float8, float8) RETURNS int AS
|
|
$$ SELECT CAST($1 - $2 AS INT); $$
|
|
LANGUAGE SQL;
|
|
CREATE AGGREGATE wrongreturntype (float8)
|
|
(
|
|
stype = float8,
|
|
sfunc = float8pl,
|
|
mstype = float8,
|
|
msfunc = float8pl,
|
|
minvfunc = float8mi_int
|
|
);
|
|
ERROR: return type of inverse transition function float8mi_int is not double precision
|
|
-- invalid: non-lowercase quoted identifiers
|
|
CREATE AGGREGATE case_agg ( -- old syntax
|
|
"Sfunc1" = int4pl,
|
|
"Basetype" = int4,
|
|
"Stype1" = int4,
|
|
"Initcond1" = '0',
|
|
"Parallel" = safe
|
|
);
|
|
WARNING: aggregate attribute "Sfunc1" not recognized
|
|
WARNING: aggregate attribute "Basetype" not recognized
|
|
WARNING: aggregate attribute "Stype1" not recognized
|
|
WARNING: aggregate attribute "Initcond1" not recognized
|
|
WARNING: aggregate attribute "Parallel" not recognized
|
|
ERROR: aggregate stype must be specified
|
|
CREATE AGGREGATE case_agg(float8)
|
|
(
|
|
"Stype" = internal,
|
|
"Sfunc" = ordered_set_transition,
|
|
"Finalfunc" = percentile_disc_final,
|
|
"Finalfunc_extra" = true,
|
|
"Finalfunc_modify" = read_write,
|
|
"Parallel" = safe
|
|
);
|
|
WARNING: aggregate attribute "Stype" not recognized
|
|
WARNING: aggregate attribute "Sfunc" not recognized
|
|
WARNING: aggregate attribute "Finalfunc" not recognized
|
|
WARNING: aggregate attribute "Finalfunc_extra" not recognized
|
|
WARNING: aggregate attribute "Finalfunc_modify" not recognized
|
|
WARNING: aggregate attribute "Parallel" not recognized
|
|
ERROR: aggregate stype must be specified
|