Я хочу написать функцию 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
; вместо этого тип вывода всегда должен быть определен как таблица (или аналогичным образом).
Кто-нибудь может исправить меня? Было бы очень обидно, если бы это оказалось правдой. Я точно где-то ошибся?