I’m trying to figure out from a column type, which aggregates the data type supports. There’s a lot of variety amongst types, just a sample below (some of these support more aggregates, of course):
uuid count()
text count(), min(), max()
integer count(), min, max(),avg(),sum()
I’ve been thrashing around in the system catalogs and views, but haven’t found what I’m after. (See “thrashing around.”) I’ve poked at pg_type
, pg_aggregate
, pg_operator
, and a few more.
Is there a straightforward way to start from a column type and gather all supported aggregates?
For background, I’m writing a client-side cross-tab code generator, and the UX is better when the tool automatically prevents you from selecting an aggregation that’s not supported. I’ve hacked in some hard-coded rules for now, but would like to improve the system.
We’re on Postgres 11.4.
Advertisement
Answer
A plain list of available aggregate functions can be based on pg_proc
like this:
SELECT oid::regprocedure::text AS agg_func_plus_args
FROM pg_proc
WHERE prokind = 'a'
ORDER BY 1;
Or with separate function name and arguments:
SELECT proname AS agg_func, pg_get_function_identity_arguments(oid) AS args
FROM pg_proc
WHERE prokind = 'a'
ORDER BY 1, 2;
pg_proc.prokind
replaces proisagg
in Postgres 11. In Postgres 10 or older use:
WHERE proisagg
Related:
- How to drop all of my functions in PostgreSQL?
- How to get function parameter lists (so I can drop a function)
To get a list of available functions for every data type (your question), start with:
SELECT type_id::regtype::text, array_agg(proname) AS agg_functions
FROM (
SELECT proname, unnest(proargtypes::regtype[])::text AS type_id
FROM pg_proc
WHERE proisagg
ORDER BY 2, 1
) sub
GROUP BY type_id;
db<>fiddle here
Just a start. Some of the arguments are just “direct” (non-aggregated) (That’s also why some functions are listed multiple times – due to those additional non-aggregate columns, example string_agg
). And there are special cases for “ordered-set” and “hypothetical-set” aggregates. See the columns aggkind
and aggnumdirectargs
of the additional system catalog pg_aggregate
. (You may want to exclude the exotic special cases for starters …)
And many types have an implicit cast to one of the types listed by the query. Prominent example string_agg()
works with varchar
, too, but it’s only listed for text
above. You can extend the query with information from pg_cast
to get the full picture.
Plus, some aggregates work for pseudo types "any"
, anyarray
etc. You’ll want to factor those in for every applicable data type.
The complication of multiple aliases for the same data type names can be eliminated easily, though: cast to regtype
to get canonical names. Or use pg_typeof()
which returns standard names. Related: