PostgreSQL:plpython3u 中具有单值的集合返回函数

PostgreSQL: Set-returning function with single value in plpython3u

我想在 PostgreSQL 中编写一个 plpython3u 函数,return 是一组文本。我偶然发现了一个对我来说很奇怪的难题。根据手册,我可以执行以下操作:

drop schema if exists X cascade;
create schema X;

create type X.greeting AS (
  who text
  );

create function X.greet( how text )
  returns setof X.greeting language plpython3u as $$
  for who in [ 'World', 'PostgreSQL', 'PL/Python' ]:
    yield ( who, )
  $$;

这是一个 Python 函数,它 return 是一组具有单个文本的行;这么多工作,我确实得到了预期的输出:

select X.greet( 'helo' );

    greet     
--------------
 (World)
 (PostgreSQL)
 (PL/Python)
(3 rows)

select * from X.greet( 'helo' );

    who     
------------
 World
 PostgreSQL
 PL/Python
(3 rows)

到目前为止一切顺利。但是,我不想为此目的编写 table 定义,我想使用 setof record 代替,就像这个例子(碰巧使用整数,但仍然):

create function X.pairs_of_integers_A( out integer, out integer )
  returns setof record language plpython3u as $$
  return [ ( 12, 24, ), ( 36, 48, ), ( 60, 72, ) ]
  $$;

create function X.pairs_of_integers_B( out integer, out integer )
  returns setof record language plpython3u as $$
  for pair in [ ( 12, 24, ), ( 36, 48, ), ( 60, 72, ) ]:
    yield pair
  $$;

select * from X.pairs_of_integers_A();
select * from X.pairs_of_integers_B();

 column1 | column2 
---------+---------
      12 |      24
      36 |      48
      60 |      72
(3 rows)

 column1 | column2 
---------+---------
      12 |      24
      36 |      48
      60 |      72
(3 rows)

现在我们来到了有趣的部分。从上面概括,下面的一个或多个公式应该是正确的:return 一组单个值,return Python 元组列表,Python 数字,或者迭代具有单个值的元组或单个值:

create function X.single_integers_A( out integer )
  returns setof record language plpython3u as $$
  return [ ( 12, ), ( 36, ), ( 60, ), ]
  $$;

create function X.single_integers_B( out integer )
  returns setof record language plpython3u as $$
  return [ 12, 36, 60, ]
  $$;

create function X.single_integers_C( out integer )
  returns setof record language plpython3u as $$
  for n in [ ( 12, ), ( 36, ), ( 60, ), ]
    yield n
  $$;

create function X.single_integers_D( out integer )
  returns setof record language plpython3u as $$
  for n in [ 12, 36, 60, ]
    yield n
  $$;

原来 none 以上甚至编译 ,它们都导致 SQL 解析器抛出 函数结果类型由于 OUT 参数 ,必须为整数。由于我 SQL 解析器不查看 Python 函数内部,这让我怀疑——

在 PostgreSQL 中,不可能定义一个同时具有 returns setof record 和单个 out 参数的函数;相反,输出类型必须始终定义为 table(或通过类似方式).

有人可以纠正我吗?如果这是真的,那就太烦人了。肯定是我哪里弄错了吧?

你应该return只是一组整数:

create or replace function x.single_integers()
returns setof integer language plpython3u as $$
    return [ 12, 36, 60 ]
$$;

select * from x.single_integers();

 single_integers 
-----------------
              12
              36
              60
(3 rows)    

根据 the documentation(强调已添加):

The key point here is that you must write RETURNS SETOF record to indicate that the function returns multiple rows instead of just one. If there is only one output parameter, write that parameter's type instead of record.