如何将现有函数(包括聚合)包装到 Postgres 中的新函数中?
Posted
技术标签:
【中文标题】如何将现有函数(包括聚合)包装到 Postgres 中的新函数中?【英文标题】:How to wrap existing functions (including aggregates) into a new one in Postgres? 【发布时间】:2014-06-04 19:51:03 【问题描述】:我正在使用 Postgres 9.2 生成一些 JSON 数据。对于每个嵌套表,我都在做这组嵌套函数:
SELECT array_to_json(
coalesce(
array_agg(
row_to_json(foo)),
ARRAY[]::json[])
)
FROM foo
效果是创建一个json数组,每一行都是该行的json集合。如果表为空,则合并确保我得到一个空数组而不是 nil。在大多数情况下, foo 实际上是一个子查询,但我认为这与问题无关。
我想创建一个函数table_to_json_array(expression),这样就和上面的效果一样:
SELECT table_to_json_array(foo) FROM foo
我需要使用这个批次,所以我打算创建一个 Postgres 函数来组合这些调用来清理我的查询。查看文档似乎我需要创建一个聚合而不是一个函数来获取表参数,但那些看起来我需要自己重新实现 array_agg。
我是否遗漏了什么(可能只是函数需要采用的类型)?有什么建议吗?
【问题讨论】:
【参考方案1】:在大多数情况下 foo 实际上是一个子查询,但我不认为那是 与问题相关。
不幸的是,它是。您可以使用 regclass 参数创建函数:
create or replace function table_to_json(source regclass)
returns json language plpgsql
as $$
declare
t json;
begin
execute format ('
SELECT
array_to_json(
coalesce(array_agg(row_to_json(%s)),
ARRAY[]::json[]))
FROM %s', source, source)
into t;
return t;
end $$;
select table_to_json('my_table');
select table_to_json('my_schema.my_view');
但在上下文中:
select table_to_json_rec(arg)
from (select * from my_table) arg
参数 arg 的类型是 record。 PL/pgSQL 函数不能接受类型记录。获得这个的唯一方法是 C 函数,我猜这不是一个选项。聚合也是如此(您必须具有定义聚合的函数)。
【讨论】:
regclass
值的文本表示会在需要时自动引用,因此它必须是 format('.. %s ..', source)
。 %I
将是错误的,并且对于必须引用的标识符会失败。 Details here.
谢谢,来源是第一版中的文字。
从你的回答来看,你知道细节。我将评论留给公众,因为这是一个常见的错误。【参考方案2】:
Postgres 9.3 添加了一个 json_agg 函数,它简化了我需要的特定查询,尽管这不是聚合函数问题的一般解决方案。它仍然需要一个 coalesce 函数来确保正确返回空集。
SELECT coalesce( json_agg(foo), json'[]')
FROM foo
即使 foo 是子查询,它也可以工作。
【讨论】:
以上是关于如何将现有函数(包括聚合)包装到 Postgres 中的新函数中?的主要内容,如果未能解决你的问题,请参考以下文章