PostgreSQL: функция возврата набора с одним значением в plpython3u

Я хочу написать функцию plpython3u в PostgreSQL, которая возвращает набор текстов. Я наткнулся на загадку, которая кажется мне странной. По мануалу могу сделать так:

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, которая возвращает набор строк с отдельными текстами; так много работает, и я получаю ожидаемый результат:

select X.greet( 'helo' );

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

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

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

Все идет нормально. Однако я не хочу писать определение таблицы для этой цели, вместо этого я хотел бы использовать 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)

Теперь мы подошли к интересной части. Обобщая вышеизложенное, одна или несколько формулировок ниже должны быть правильными: чтобы вернуть набор одиночных значений, либо вернуть список кортежей 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
  $$;

Оказывается, ни одно из вышеперечисленных действий даже не компилируется, все они вызывают синтаксический анализатор SQL с ошибкой тип результата функции должен быть целым числом из-за параметров OUT. Поскольку синтаксический анализатор SQL не заглядывает внутрь функций Python, это заставляет меня подозревать, что:

В PostgreSQL невозможно определить функцию как с параметром returns setof record, так и с одним параметром out; вместо этого тип вывода всегда должен быть определен как таблица (или аналогичным образом).

Кто-нибудь может исправить меня? Было бы очень обидно, если бы это оказалось правдой. Я точно где-то ошибся?


person John Frazer    schedule 09.11.2017    source источник
comment
да - функция либо имеет выходные параметры и возвращает пустоту, либо возвращает что-то и не имеет выходных параметров, я думаю   -  person Vao Tsun    schedule 09.11.2017
comment
postgresql.org/docs/current/static/   -  person Vao Tsun    schedule 09.11.2017
comment
1) спасибо за комментарии 2) соответствующая ссылка postgresql.org/ docs/current/static/ 3) в документах говорится, что также поддерживаются функции, возвращающие набор, с параметрами OUT (с использованием записи RETURNS SETOF).   -  person John Frazer    schedule 09.11.2017


Ответы (1)


Вы должны вернуть только набор целых чисел:

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)    

Согласно документации (выделено мной):

Ключевым моментом здесь является то, что вы должны написать запись RETURNS SETOF, чтобы указать, что функция возвращает несколько строк вместо одной. Если имеется только один выходной параметр, укажите тип этого параметра вместо записи.

person klin    schedule 09.11.2017
comment
Я рад, что обнаружил пробел в своем понимании SQL, а не ошибку/оплошность/несоответствие в SQL. - person John Frazer; 09.11.2017