web-dev-qa-db-ja.com

PostgreSQLのVARIADIC関数の引数として配列を使用するにはどうすればよいですか?

citextモジュールを使用して、大文字と小文字を区別しないjson_extract_path_text()のバージョンを作成しようとしています。

これを組み込み関数の単純なラッパーにしたいと思います。唯一の違いは、citextの代わりにjsonを最初のパラメーターとして受け入れることです。これを、型変換を事前に行うだけで、ネイティブ実装への単純なパススルーにしたいと思います。ここに私がこれまで持っているものがあります:

create extension citext;

create or replace function json_extract_path_text ( string citext, variadic params text[]) RETURNS text IMMUTABLE AS
$$
    BEGIN
        SELECT json_extract_path_text(string::json, params);
    END;
$$
LANGUAGE 'plpgsql';

ただし、タイプが一致しないため、これは正しく機能しません。

ERROR:  function json_extract_path_text(json, text[]) does not exist
LINE 1: SELECT json_extract_path_text(string::json, params)
               ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
QUERY:  SELECT json_extract_path_text(string::json, params)
CONTEXT:  PL/pgSQL function json_extract_path_text(citext,text[]) line 3 at SQL statement

私は動的な文字列構成とEXECUTEを使用してソリューションをハッキングしようとしましたが、これは本当に面倒であり、VARIADIC paramsを内部関数に渡すためのよりクリーンな方法が必要だと思います。しかし、そのための明確な方法はわかりません。どうすればそれを達成できますか?

8
Jake Feasel

呼び出しでVARIADICキーWordを使用して、配列をそのまま渡します

_CREATE OR REPLACE FUNCTION json_extract_path_text(string citext, VARIADIC params text[])
  RETURNS text LANGUAGE sql IMMUTABLE AS
'SELECT json_extract_path_text(string::json, VARIADIC params)';_

コール:

_SELECT json_extract_path_text('{"f1":{"f2":1,"f3":"foo"}}', VARIADIC '{f1, f3}');
_
_ json_extract_path_text
----------------------
 foo
_

VARIADIC:のマニュアル

すでに構築された配列を可変個関数に渡すことができると便利な場合があります。これは、1つの可変関数がその配列パラメーターを別の関数に渡したい場合に特に便利です。これを行うには、呼び出しでVARIADICを指定します。

_SELECT mleast(VARIADIC ARRAY[10, -1, 5, 4.4]);
_

詳細:

明確にするために:関数内では、VARIADICパラメーターは単なる別の配列であり、特別なことは何もありません。 VARIADICを2つの個別の関数definitionsで使用すると、状況が少しわかりにくくなります。解決策は、関数callで関連するが異なる目的で同じキーワードVARIADICを使用することです。さらに混乱しないでください。

補足:言語名は引用符で囲まないでください。これは識別子です。

citextを使用した大文字と小文字を区別しないバージョン?

Citextモジュールを使用して、大文字と小文字を区別しないjson_extract_path_text()のバージョンを作成しようとしています。

上記の関数は機能しますが、大文字と小文字を区別しません。 citextは、text(またはjson)へのキャストで復元される元の入力を保持し、大文字と小文字を混在させることができます。

最初はcitextを使用しません。さまざまなコーナーケースの問題:

あなたの目的のために、私は組み込みの json_extract_path_text()lower(citext_value)で呼び出すことをお勧めします。これは小文字のtextと小文字の2番目のパラメーター(「パス要素」)も同様に、実際には大文字と小文字を区別しません。

_SELECT json_extract_path_text(lower('{"F1":{"f2":1,"f3":"foo"}}'::citext)::json
                            , VARIADIC lower('{f1, F3}')::text[]);
_

lower()の後に_text[]_へのキャストがあることに注意してください。

12