如何在 PostgreSQL 中获取聚合的 definition/source 代码?
How to get definition/source code of an aggregate in PostgreSQL?
我发现这个相关答案很有用:
- Export "Create Aggregate" functions from PostgreSQL
但是如何在没有 GUI 客户端(例如使用 psql 命令行)的情况下获得 CREATE AGGREGATE
语句?
类似这样,但我不确定这是否涵盖了创建聚合的所有可能方式(它绝对不考虑引用标识符的需要)
SELECT 'create aggregate '||n.nspname||'.'||p.proname||'('||format_type(a.aggtranstype, null)||') (sfunc = '||a.aggtransfn
||', stype = '||format_type(a.aggtranstype, null)
||case when op.oprname is null then '' else ', sortop = '||op.oprname end
||case when a.agginitval is null then '' else ', initcond = '||a.agginitval end
||')' as source
FROM pg_proc p
JOIN pg_namespace n ON p.pronamespace = n.oid
JOIN pg_aggregate a ON a.aggfnoid = p.oid
LEFT JOIN pg_operator op ON op.oid = a.aggsortop
where p.proname = 'your_aggregate'
and n.nspname = 'public' --- replace with your schema name
我的版本使用了一些系统功能
SELECT
format(
E'CREATE AGGREGATE %s (\n%s\n);'
, (pg_identify_object('pg_proc'::regclass, aggfnoid, 0)).identity
, array_to_string(
ARRAY[
format(E'\tSFUNC = %s', aggtransfn::regproc)
, format(E'\tSTYPE = %s', format_type(aggtranstype, NULL))
, CASE aggfinalfn WHEN '-'::regproc THEN NULL ELSE format(E'\tFINALFUNC = %s',aggfinalfn::text) END
, CASE aggsortop WHEN 0 THEN NULL ELSE format(E'\tSORTOP = %s', oprname) END
, CASE WHEN agginitval IS NULL THEN NULL ELSE format(E'\tINITCOND = %s', agginitval) END
]
, E',\n'
)
)
FROM pg_aggregate
LEFT JOIN pg_operator ON pg_operator.oid = aggsortop
WHERE aggfnoid = 'regr_r2'::regproc;
生成 CREATE AGGREGATE
语句的现代版本 - 使用 format()
并转换为对象标识符类型以使其简单,并在需要时自动向标识符添加双引号和模式限定:
SELECT format('CREATE AGGREGATE %s (SFUNC = %s, STYPE = %s%s%s%s%s)'
, aggfnoid::regprocedure
, aggtransfn
, aggtranstype::regtype
, ', SORTOP = ' || NULLIF(aggsortop, 0)::regoper
, ', INITCOND = ' || agginitval
, ', FINALFUNC = ' || NULLIF(aggfinalfn, 0)
, CASE WHEN aggfinalextra THEN ', FINALFUNC_EXTRA' END
-- add more to cover special cases like moving-aggregate etc.
) AS ddl_agg
FROM pg_aggregate
WHERE aggfnoid = 'my_agg_func'::regproc; -- name of agg func here
您可以在必要时对聚合函数的名称进行模式限定:
'public.my_agg_func'::regproc
和/或添加函数参数以在聚合函数重载的情况下消除歧义:
'array_agg(anyarray)'::regprocedure
这不包括移动聚合函数等特殊情况。可以轻松扩展以涵盖当前 Postgres 版本的所有选项。但下一个大版本可能会带来新的选择。
一个类似于现有 pg_get_functiondef()
的函数 pg_get_aggregatedef()
会很好地消除对这个自定义查询的需求——这可能需要适应每个新的主要 Postgres 版本 ...
我发现这个相关答案很有用:
- Export "Create Aggregate" functions from PostgreSQL
但是如何在没有 GUI 客户端(例如使用 psql 命令行)的情况下获得 CREATE AGGREGATE
语句?
类似这样,但我不确定这是否涵盖了创建聚合的所有可能方式(它绝对不考虑引用标识符的需要)
SELECT 'create aggregate '||n.nspname||'.'||p.proname||'('||format_type(a.aggtranstype, null)||') (sfunc = '||a.aggtransfn
||', stype = '||format_type(a.aggtranstype, null)
||case when op.oprname is null then '' else ', sortop = '||op.oprname end
||case when a.agginitval is null then '' else ', initcond = '||a.agginitval end
||')' as source
FROM pg_proc p
JOIN pg_namespace n ON p.pronamespace = n.oid
JOIN pg_aggregate a ON a.aggfnoid = p.oid
LEFT JOIN pg_operator op ON op.oid = a.aggsortop
where p.proname = 'your_aggregate'
and n.nspname = 'public' --- replace with your schema name
我的版本使用了一些系统功能
SELECT
format(
E'CREATE AGGREGATE %s (\n%s\n);'
, (pg_identify_object('pg_proc'::regclass, aggfnoid, 0)).identity
, array_to_string(
ARRAY[
format(E'\tSFUNC = %s', aggtransfn::regproc)
, format(E'\tSTYPE = %s', format_type(aggtranstype, NULL))
, CASE aggfinalfn WHEN '-'::regproc THEN NULL ELSE format(E'\tFINALFUNC = %s',aggfinalfn::text) END
, CASE aggsortop WHEN 0 THEN NULL ELSE format(E'\tSORTOP = %s', oprname) END
, CASE WHEN agginitval IS NULL THEN NULL ELSE format(E'\tINITCOND = %s', agginitval) END
]
, E',\n'
)
)
FROM pg_aggregate
LEFT JOIN pg_operator ON pg_operator.oid = aggsortop
WHERE aggfnoid = 'regr_r2'::regproc;
生成 CREATE AGGREGATE
语句的现代版本 - 使用 format()
并转换为对象标识符类型以使其简单,并在需要时自动向标识符添加双引号和模式限定:
SELECT format('CREATE AGGREGATE %s (SFUNC = %s, STYPE = %s%s%s%s%s)'
, aggfnoid::regprocedure
, aggtransfn
, aggtranstype::regtype
, ', SORTOP = ' || NULLIF(aggsortop, 0)::regoper
, ', INITCOND = ' || agginitval
, ', FINALFUNC = ' || NULLIF(aggfinalfn, 0)
, CASE WHEN aggfinalextra THEN ', FINALFUNC_EXTRA' END
-- add more to cover special cases like moving-aggregate etc.
) AS ddl_agg
FROM pg_aggregate
WHERE aggfnoid = 'my_agg_func'::regproc; -- name of agg func here
您可以在必要时对聚合函数的名称进行模式限定:
'public.my_agg_func'::regproc
和/或添加函数参数以在聚合函数重载的情况下消除歧义:
'array_agg(anyarray)'::regprocedure
这不包括移动聚合函数等特殊情况。可以轻松扩展以涵盖当前 Postgres 版本的所有选项。但下一个大版本可能会带来新的选择。
一个类似于现有 pg_get_functiondef()
的函数 pg_get_aggregatedef()
会很好地消除对这个自定义查询的需求——这可能需要适应每个新的主要 Postgres 版本 ...