ストアド関数の自明ではない挙動

PostgreSQLはリファレンスが非常に充実していますが、サポートする機能が多彩であるため個別のケースの挙動が自明ではないことがあります。
ストアド関数は複雑なケースを扱うことが多く、挙動の観察が重要です。

呼び出し形式

ストアド関数の呼び出しはSELECT some_function();で実行できます。
ただしテーブルを返す関数の場合には、この形式で呼び出すとカラム名が割り当てられないケースがあります。

SELECT id, name FROM some_function();のようにFROM句で関数を呼び出すと、戻り値のテーブルにカラム指定できます。

早期リターン

PL/pgSQLのRETURNは他の言語と異なる挙動をとる場合があるため、基本的に注意が必要です。
注意したうえで、以下のような早期リターンは実装可能です。

CREATE FUNCTION get_inventories(IN in_id integer)
  RETURNS TABLE (name text, quantity integer) AS $$
  BEGIN
    PERFORM 1 FROM privileges p
     WHERE p.id = in_id;
    IF NOT FOUND THEN
      RETURN;
    END IF;

    RETURN QUERY SELECT
        i.name AS name,
        i.qty AS quantity,
      FROM inventories i;
  END;
$$ LANGUAGE plpgsql;

テーブルを返すストアド関数では、CREATE FUNCTION ... RETURNS TABLEの定義と、RETURN QUERYの返す型と列名を一致させる必要があります。

よって、目的外のテーブルの値を返したい場合の簡潔な方法はありません。
この例では冒頭で別のテーブル(アクセス権限照会など)を検索し、引数にマッチするレコードがない場合にRETURNしています。

この例では、大方の期待どおり早期リターンの挙動となります。
他のテーブルから定義に一致する型をとり出すことは難しいのですが、戻り値をセットしない場合には空行となり、型不一致エラーを避けられます。

また、引数をとるRETURNの中には関数処理を中断しない(一般的な想像どおりでない)挙動の文もありますが、この例の書き方であればその場で関数を抜ける挙動をとります。

つまり書き方によっては早期リターンに見えるクエリが早期リターンしないことがあるものの、注意すれば早期リターンは実装可能です。

⁋ 2022/09/22↻ 2024/11/07
中馬崇尋
Chuma Takahiro