如何使用数组作为 PostgreSQL 中 VARIADIC 函数的参数?

Jak*_*sel 10 postgresql parameter functions array case-sensitive

我正在尝试json_extract_path_text()使用citext模块制作不区分大小写的版本。

我希望这是一个围绕内置函数的简单包装器,唯一的区别是它接受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';
Run Code Online (Sandbox Code Playgroud)

但是,由于类型不匹配,这不能正常工作:

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
Run Code Online (Sandbox Code Playgroud)

我尝试过使用动态字符串构造和 来绕过解决方案EXECUTE,但这真的很麻烦,我觉得必须有一种更简洁的方法来将VARIADIC参数传递给内部函数。但是,我看不到任何明显的方法。我怎样才能做到这一点?

Erw*_*ter 13

使用调用中的关键字按原样传递数组VARIADIC

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)';
Run Code Online (Sandbox Code Playgroud)

称呼:

SELECT json_extract_path_text('{"f1":{"f2":1,"f3":"foo"}}', VARIADIC '{f1, f3}');
Run Code Online (Sandbox Code Playgroud)
 json_extract_path_text
----------------------
 foo
Run Code Online (Sandbox Code Playgroud)

手册VARIADIC

有时,能够将已经构造好的数组传递给可变参数函数是很有用的;当一个可变参数函数想要将其数组参数传递给另一个时,这特别方便。您可以通过VARIADIC在调用中指定来做到这一点:

SELECT mleast(VARIADIC ARRAY[10, -1, 5, 4.4]);
Run Code Online (Sandbox Code Playgroud)

更多细节:

需要明确的是:在函数内部,VARIADIC参数只是另一个数组,没有什么特别之处。VARIADIC在两个单独的函数定义中使用会使情况有点混乱。解决方案是VARIADIC在函数调用中为相关但不同的目的使用相同的关键字。不要再糊涂了。

旁白:不要引用语言名称,它是一个标识符。

不区分大小写的版本citext

我正在尝试json_extract_path_text()使用 citext 模块制作不区分大小写的版本。

虽然上述功能有效,但它根本不区分大小写。citext保留原始输入,通过转换为text(或json)恢复原始输入,并且可以混合大小写。

我不会使用citext开始。各种角落案例问题:

为了您的目的,我建议调用内置json_extract_path_text()with lower(citext_value),它返回小写text,并小写第二个参数(“路径元素”),使其实际上不区分大小写:

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

注意转换为text[]after lower()