Wie verwende ich ein Array als Argument für eine VARIADIC-Funktion in PostgreSQL?


8

Ich versuche json_extract_path_text(), mithilfe des citextModuls eine Version zu erstellen , bei der die Groß- und Kleinschreibung nicht berücksichtigt wird.

Ich möchte, dass dies ein einfacher Wrapper um die eingebaute Funktion ist. Der einzige Unterschied besteht darin, dass sie citextstattdessen als erster Parameter akzeptiert wird json. Ich möchte, dass dies ein direkter Durchgang zur nativen Implementierung ist, nur mit einer vorherigen Typkonvertierung. Folgendes habe ich bisher:

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';

Dies funktioniert jedoch aufgrund der Typfehlanpassung nicht richtig:

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

Ich habe versucht, eine Lösung mit dynamischer String-Konstruktion zu hacken EXECUTE, aber das ist ein echtes Problem, und ich VARIADICdenke, es muss einen saubereren Weg geben, um Parameter an die innere Funktion weiterzuleiten . Ich sehe jedoch keinen offensichtlichen Weg, dies zu tun. Wie kann ich das erreichen?

Antworten:


12

Übergeben Sie das Array so, wie es das VARIADICSchlüsselwort im Aufruf verwendet:

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)';

Anruf:

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

Das Handbuch zu VARIADIC:

Manchmal ist es nützlich, ein bereits erstelltes Array an eine variable Funktion übergeben zu können. Dies ist besonders praktisch, wenn eine Variadic-Funktion ihren Array-Parameter an eine andere weitergeben möchte. Sie können dies tun, indem Sie VARIADICim Aufruf Folgendes angeben:

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

Mehr Details:

Um es klar auszudrücken: Innerhalb der Funktion ist der VARIADICParameter nur ein weiteres Array, nichts Besonderes. VARIADICwird in zwei separate Funktion verwendet Definitionen macht den Fall etwas verwirrend. Die Lösung besteht darin, dasselbe Schlüsselwort zu verwendenVARIADIC für einen verwandten , aber unterschiedlichen Zweck in dem Funktionsaufruf . Lass dich nicht noch mehr verwirren.

Nebenbei: Geben Sie nicht den Namen der Sprache an, sondern eine Kennung.

Groß- und Kleinschreibung nicht berücksichtigen mit citext?

Ich versuche json_extract_path_text(), mithilfe des citext-Moduls eine Version zu erstellen, bei der die Groß- und Kleinschreibung nicht berücksichtigt wird.

Die obige Funktion funktioniert zwar , unterscheidet jedoch nicht zwischen Groß- und Kleinschreibung. citextbehält die ursprüngliche Eingabe bei, die mit der Umwandlung in text(oder json) wiederhergestellt wird und in Groß- und Kleinschreibung gemischt werden kann.

Ich würde nicht verwenden citext, um mit zu beginnen. Verschiedene Eckfallprobleme:

Für Ihren Zweck schlage ich vor, das integrierte json_extract_path_text()with aufzurufen lower(citext_value), das Kleinbuchstaben zurückgibt text, und den 2. Parameter ("Pfadelemente") in Kleinbuchstaben, um die Groß- und Kleinschreibung nicht zu berücksichtigen:

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

Beachten Sie die Besetzung text[]nach lower().


Das ist großartiges Zeug, aber ich kann VARIADIC im folgenden Testfall nicht zum Laufen bringen: Gibt es SELECT jsonb_build_array('A', VARIADIC array_agg(value)) FROM jsonb_array_elements_text('["B","C"]'::JSONB)eine Idee warum?
user9645

Sie rufen effektiv auf SELECT jsonb_build_array('A', VARIADIC '{B,C}'::text[]), jsonb_build_array()erwarten jedoch entweder eine Liste von Werten oder ein einzelnes Array nach dem Schlüsselwort VARIADIC. Je nachdem, was Sie erreichen möchten, gibt es verschiedene Lösungen. Bitte stellen Sie eine neue Frage, wenn noch etwas unklar ist. Sie können jederzeit einen Link zu diesem für den Kontext erstellen.
Erwin Brandstetter
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.