如何在Postgres中将现有函数(包括聚合)包装成新函数?

时间:2014-06-04 19:51:03

标签: json function postgresql aggregate plpgsql

我正在使用Postgres 9.2来生成一些JSON数据。对于每个嵌套表,我都在做这个嵌套的函数集:

SELECT array_to_json(
  coalesce(
    array_agg(
      row_to_json(foo)),
    ARRAY[]::json[])
)
FROM foo

效果是创建一个json数组,每行都是该行的json集合。如果表为空,coalesce确保我得到一个空数组而不是nil。在大多数情况下,foo实际上是一个子查询,但我不认为这与问题相关。

我想创建一个函数 table_to_json_array(expression),以便它具有与上面相同的效果:

SELECT table_to_json_array(foo) FROM foo

我需要使用这些批次,所以我打算创建一个Postgres函数,以便将这些调用组合起来清理我的查询。看看文档,似乎我需要创建一个聚合而不是一个函数来获取一个表参数,但看起来我需要重新实现 array_agg

我错过了什么(可能只是一个函数需要的类型)?有什么建议吗?

2 个答案:

答案 0 :(得分:2)

  

在大多数情况下,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 的类型为记录。 PL / pgSQL函数不能接受类型记录。得到这个的唯一方法是C函数,我想这不是一个选项。聚合也是如此(您必须具有定义聚合的函数)。

答案 1 :(得分:1)

Postgres 9.3增加了一个 json_agg 函数,它简化了我需要的特定查询,尽管这不是聚合函数问题的一般解决方案。它仍然需要 coalesce 函数来确保正确返回空集。

SELECT coalesce( json_agg(foo), json'[]')
FROM foo

即使 foo 是子查询,它也能正常工作。