Làm cách nào để sử dụng một mảng làm đối số cho hàm VariADIC trong PostgreSQL?


8

Tôi đang cố gắng tạo một phiên bản không phân biệt chữ hoa chữ thường json_extract_path_text(), sử dụng citextmô-đun.

Tôi muốn đây là một trình bao bọc đơn giản xung quanh hàm tích hợp, sự khác biệt duy nhất là nó chấp nhận citextlàm tham số đầu tiên thay vì json. Tôi muốn điều này là một sự chuyển tiếp thẳng đến việc thực hiện riêng, chỉ với một chuyển đổi loại trước đó. Đây là những gì tôi có cho đến nay:

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

Điều này không hoạt động đúng, tuy nhiên, do loại khớp sai:

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

Tôi đã thử hack xung quanh một giải pháp bằng cách sử dụng cấu trúc chuỗi động và EXECUTE, nhưng đây là một rắc rối thực sự và tôi cảm thấy như phải có một cách sạch hơn để truyền VARIADICthông số vào chức năng bên trong. Tôi không thể thấy bất kỳ cách rõ ràng để làm như vậy, tuy nhiên. Làm thế nào tôi có thể hoàn thành nó?

Câu trả lời:


12

Truyền mảng như đang sử dụng VARIADICtừ khóa trong cuộc gọi:

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

Gọi:

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

Hướng dẫn về VARIADIC:

Đôi khi nó rất hữu ích để có thể chuyển một mảng đã được xây dựng sang một hàm matrixdic; điều này đặc biệt hữu ích khi một hàm matrixdic muốn truyền tham số mảng của nó sang một tham số khác. Bạn có thể làm điều đó bằng cách chỉ định VARIADICtrong cuộc gọi:

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

Thêm chi tiết:

Để rõ ràng: Bên trong hàm, VARIADICtham số chỉ là một mảng khác, không có gì đặc biệt về nó. VARIADICđược sử dụng trong hai định nghĩa hàm riêng biệt làm cho trường hợp hơi khó hiểu. Giải pháp là sử dụng cùng một từ khóa VARIADICcho một mục đích liên quan nhưng khác nhau trong lệnh gọi hàm . Đừng nhầm lẫn nhiều hơn.

Ngoài ra: Không trích dẫn tên ngôn ngữ, đó là một định danh.

Phiên bản không phân biệt chữ hoa chữ thường với citext?

Tôi đang cố gắng tạo một phiên bản không phân biệt chữ hoa chữ thường json_extract_path_text(), sử dụng mô đun citext.

Mặc dù chức năng trên hoạt động , nhưng nó không phân biệt chữ hoa chữ thường. citextduy trì đầu vào ban đầu, được khôi phục với các biểu tượng thành text(hoặc json) và có thể được trộn lẫn.

Tôi sẽ không sử dụng citextđể bắt đầu với. Các vấn đề góc khác nhau:

Đối với mục đích của bạn tôi khuyên bạn nên gọi built-in json_extract_path_text()với lower(citext_value), mà lợi nhuận giảm hợp cụ thể text, và giảm hợp cụ thể các tham số thứ 2 ( "yếu tố con đường") là tốt, để làm cho nó thực sự case-insensitive:

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

Lưu ý các diễn viên để text[]sau lower().


Đây là một công cụ tuyệt vời, nhưng dường như tôi không thể khiến VariADIC hoạt động trong trường hợp thử nghiệm sau : SELECT jsonb_build_array('A', VARIADIC array_agg(value)) FROM jsonb_array_elements_text('["B","C"]'::JSONB), có ý tưởng nào tại sao không?
dùng9645

Bạn đang gọi một cách hiệu quả SELECT jsonb_build_array('A', VARIADIC '{B,C}'::text[]), nhưng jsonb_build_array()hy vọng một trong hai danh sách các giá trị, hoặc một mảng đơn sau từ khóa VARIADIC. Tùy thuộc vào những gì bạn đang cố gắng để đạt được, có nhiều giải pháp khác nhau. Xin hỏi một câu hỏi mới về nó nếu bất cứ điều gì vẫn chưa rõ ràng. Bạn luôn có thể liên kết đến cái này cho bối cảnh.
Erwin Brandstetter
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.