Можно ли заставить функцию PostgreSQL возвращать «произвольный» тип? - PullRequest
0 голосов
/ 06 февраля 2012

Возможно ли иметь произвольный тип возврата, определенный для некоторой функции PostgreSQL?

Идея состоит в том, что в зависимости от вызова вывод может быть возвращен по-разному.

Например, допустим, у нас есть:

TypeA : (name, email)
TypeB : (name, email, address, phone)

У нас может быть функция:

func1(name varchar);

Но тип возвращаемого значения может быть: TypeA или TypeB

Итак, возможно ли определить func1, чтобы произвольный тип возвращаемого значения работал?

EDIT:

ЕСЛИ решение refcursor ... Может кто-нибудь написать ответ, основываясь на примере из моего вопроса? Это очень поможет!

1 Ответ

3 голосов
/ 25 марта 2013

У вас есть несколько вариантов. Первый - использовать полиморфный тип, который будет приведен по вызову, второй - использовать приведение, а третий - возвращать рефкурсор.

Полиморфный тип

В этом случае вы бы сделали что-то вроде:

 CREATE FUNCTION foo (bar varchar, baz ANYELEMENT) returns ANYELEMENT AS
 $$
   SELECT 'test'::TEXT;
 $$ language sql;

Затем, чтобы вызвать его, вы должны вызвать аргумент NULL при вызове:

SELECT * FROM foo('test', null::varchar);

Настоящая проблема, с которой вы столкнулись, заключается в том, что вам придется указывать тип при каждом вызове.

Одиночный тип возврата с Cast

В вашем примере один тип имеет подмножество полей другого типа. Чтобы вы могли:

CREATE TYPE all_info AS (
   name text,
   email text,
   address text,
   phone text
);
CREATE TYPE email_only AS (
   name text,
   email text
);
CREATE FUNCTION email_only(all_info) returns email_only LANGUAGE SQL IMMUTABLE AS $$
SELECT $1.name, $1.email;
$$;
CREATE CAST (all_info as email_only) WITH FUNCTION email_only(all_info);

Затем вы создаете свою функцию, которая возвращает all_info, и вы можете привести ее к выводу. Что-то вроде:

SELECT (f::email_only).* FROM my_function('foo') f;

Обратите внимание, что эти два позволяют вам использовать функции языка SQL, которые не используются в рефкурсорах.

REFCURSOR

В этом случае вы должны использовать plpgsql

CREATE OR REPLACE FUNCTION foo(bar varchar) RETURNS refcursor LANGUAGE plpgsql AS
$$
DECLARE a REFCURSOR;
BEGIN
   OPEN a FOR SELECT ....;
   RETURN a;
END;
$$;

В общем, я думаю, что проще всего начать с подхода суперсет и приведение актеров, чем с другими. Отражатели, возможно, второй подход. Последний будет настаивать на приведении типа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...