Обзор
Я использую PostgreSQL 9.1.14, и я пытаюсь передать результаты функции в другую функцию. Общая идея (с учетом минимального примера) заключается в том, что мы можем написать:
select * from (select * from foo ...) 
и мы можем абстрагировать подвыбор в функции и выбрать из него:
create function foos() 
returns setof foo
language sql as $$
  select * from foo ...
$$;
select * from foos()
Есть ли способ абстрагироваться на один уровень дальше, чтобы иметь возможность делать что-то вроде этого (я знаю, что функции не могут иметь аргументы с типами setof):
create function more_foos( some_foos setof foo )
language sql as $$
  select * from some_foos ...  -- or unnest(some_foos), or ???
$$:
select * from more_foos(foos())
Минимальный пример и предпринятые обходные методы
Я использую PostgreSQL 9.1.14. Вот минимальный пример:
-- 1. create a table x with three rows                                                                                                                                                            
drop table if exists x cascade;
create table if not exists x (id int, name text);
insert into x values (1,'a'), (2,'b'), (3,'c');
-- 2. xs() is a function with type `setof x`
create or replace function xs()
returns setof x
language sql as $$
  select * from x
$$;
-- 3. xxs() should return the context of x, too
--    Ideally the argument would be a `setof x`,
--    but that not allowed (see below).
create or replace function xxs(x[])  
returns setof x
language sql as $$
  select x.* from x
  join unnest($1) y
       on x.id = y.id
$$;
Когда я загружаю этот код, я получаю ожидаемый вывод для определений таблиц, и я могу позвонить и выбрать из xs(), как я ожидал. Но когда я пытаюсь передать результат xs() на xxs(), я получаю сообщение об ошибке "Функция xxs (x) не существует":
db=> \i test.sql 
DROP TABLE
CREATE TABLE
INSERT 0 3
CREATE FUNCTION
CREATE FUNCTION
db=> select * from xs();
  1 | a
  2 | b
  3 | c
db=> select * from xxs(xs());
ERROR:  function xxs(x) does not exist
LINE 1: select * from xxs(xs());
                      ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
Я немного смущен о "функции xxs (x) не существует"; так как возвращаемый тип xs() был setof x, я ожидал, что его тип возврата будет setof x (или, может быть, x[]), а не x. После жалоб на тип, я могу перейти к одному из следующих, но хотя с любым определением я могу select xxs(xs());, я не могу select * from xxs(xs());.
create or replace function xxs( x )
returns setof x
language sql as $$
  select x.* from x
  join unnest(array[$1]) y    -- unnest(array[...]) seems pretty bad
       on x.id = y.id
$$;
create or replace function xxs( x )
returns setof x
language sql as $$
  select * from x
         where x.id in ($1.id)
$$;
db=> select xxs(xs());
 (1,a)
 (2,b)
 (3,c)
db=> select * from xxs(xs());
ERROR:  set-valued function called in context that cannot accept a set
Резюме
Каков правильный способ передачи результатов функции возвращающего множество в другую функцию? (Я заметил, что создать функцию... xxs (setof)... приводит к ошибке: ОШИБКА: функции не могут принимать заданные аргументы, поэтому ответ не будет буквально передаваться набор строк из одной функции в другую.)
