web-dev-qa-db-ja.com

UDFから返された匿名レコードの既知のテーブルタイプへの自動変換

独自のコード(変更できません)には、次のタイプのユーザー定義関数が多数あります。

create or replace function f() returns record as $$ ... $$

これを次のように呼び出します(たとえば)。

SELECT status, log FROM f() as (status boolean, log text);

(status boolean, log text)は、テーブルTの行タイプです。属性をリストせずに、record(またはsetof record戻り値型)をT行型に自動的に変換することはできますか?私が探しているのは次のようなものです。

SELECT * FROM f() as T%rowtype
8
arthur

やり方がある。

テーブルtと、そのテーブルタイプに一致する匿名レコードを返す関数f()が与えられたとします。

CREATE TABLE t (id int, d date);

列定義リストはが必要であるため、匿名レコードをキャストすることはできません。

SELECT * FROM f()

引用 SELECTコマンドのマニュアル

関数がレコードのデータ型を返すように定義されている場合、エイリアスまたはキーWord ASが存在している必要があります。形式は続いて列定義リスト ...

太字私の強調。

したがって、これらのクエリはすべて機能しますが、

SELECT '(1,2013-11-11)'::t;
SELECT ('(1,2013-11-11)'::t).*;
SELECT f();                      -- returning anonymous record
SELECT * FROM f() AS f(id int, d date);

これらはどちらも行いません:

SELECT * FROM f();
SELECT * FROM f()::t;

後者は例外を発生させます:

エラー:タイプレコードをtにキャストできません

SELECTと列定義リストをVIEWまたは @ a_horse および @ deszo のような関数にラップすることができます。それはうまくいくでしょう:

CREATE OR REPLACE VIEW v1 AS
SELECT * FROM f() AS f(id int, d date);

しかし、それはあなたの質問に答えません:

属性をリストせずにレコード(またはレコードのセットの戻り型)をT行型に変換しますか?

単一行のソリューション

キャストが失敗しても、plpgsqlでの割り当ては機能します。

CREATE OR REPLACE function f1(OUT rec t) AS
$func$
BEGIN
rec := f();   -- assignment succeeds where cast failed (!)
END
$func$ LANGUAGE plpgsql;

コール:

SELECT * FROM f1();

そのパターンでセットを返す関数を書くこともできますが、列定義リストを提供せずに、セットを返す関数からSELECTへの道を見つけられませんでした。 。

-> SQLfiddle

8