函数重载与无函数匹配问题

问题描述 投票:0回答:1

我需要通过 Postgres 的 Rest API 一次更新几行。我想出如何做到这一点的唯一方法是通过函数调用,其中我将 JSON 传递给函数并迭代 JSON 并执行更新。

但是,根据我所做的,我遇到了两个问题之一。

  • 如果我创建接受 json 或 jsonb 类型的通用函数,PostgREST 会告诉我:

    No function matches the given name and argument types. You might need to add explicit type casts.
    
  • 但是,如果我创建一个接受 json 或 jsonb 对象的重载函数,则会收到错误:

    {"code":"PGRST203","details":null,"hint":"Try renaming the parameters or the function itself in the database so function overloading can be resolved","message":"Could not choose the best candidate function..."
    

如何解决这个问题? PostgREST 在没有重载的情况下无法找到该函数,但是在重载时,它可以找到该函数,但不知道该使用哪个函数。

SQL:

-- TABLE --
CREATE TABLE IF NOT EXISTS vehicle_database.test_table(
    test_table_id BIGSERIAL PRIMARY KEY,
    test_data INTEGER,
    test_type VARCHAR(8)
);

-- Overloaded function using json --
CREATE OR REPLACE FUNCTION update_test_table(p_json json)
RETURNS void AS $$
DECLARE
    json_item json;
BEGIN
    FOR json_item IN SELECT json_array_elements(p_json) LOOP
        PERFORM update_test_table_row(
            (json_item->>'data')::integer,
            (json_item->>'test_type')::text);
    END LOOP;
END;
$$ LANGUAGE plpgsql;

-- Overloaded function using jsonb --
CREATE OR REPLACE FUNCTION update_test_table(p_json jsonb)
RETURNS void AS $$
DECLARE
    json_item json;
BEGIN
    FOR json_item IN SELECT json_array_elements(p_json) LOOP
        PERFORM update_test_table_row(
            (json_item->>'data')::integer,
            (json_item->>'test_type')::text);
    END LOOP;
END;
$$ LANGUAGE plpgsql;

-- Overloaded function using text --
CREATE OR REPLACE FUNCTION update_test_table(p_json text)
RETURNS void AS $$
DECLARE
    json_item json;
BEGIN
    json_data = p_json::JSONB;
    PERFORM update_test_table(json_data);
END;
$$ LANGUAGE plpgsql;

-- Update the row
CREATE OR REPLACE FUNCTION update_test_table_row(p_data integer, p_type text)
RETURNS void AS $$
BEGIN
    UPDATE test_table SET test_data = p_data WHERE test_type = p_type;

    IF NOT FOUND THEN
        RAISE NOTICE 'No rows updated for data: %, type: %', p_data, p_type;
    END IF;
END;
$$ LANGUAGE plpgsql;

-- Permissions (same kind of users as in the tutorials)
GRANT EXECUTE ON FUNCTION update_test_table(p_json json) TO web_insert;
GRANT EXECUTE ON FUNCTION update_test_table(p_json jsonb) TO web_insert;
GRANT EXECUTE ON FUNCTION update_test_table(p_json text) TO web_insert;
GRANT EXECUTE ON FUNCTION update_test_table_row(p_data integer, p_type text) TO web_insert;

我是这样称呼它的:

curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '[{"test_data":"4","test_type":"RED"}]' http://127.0.0.1:3000/rpc/update_test_table

$TOKEN
是我的私人令牌,与 jwt-secret 字段中的 PostgREST 一起使用。

不幸的是,PostgREST 没有详细的日志记录,而 Postgres 日志对此并没有真正的帮助。 Postgres 告诉我该函数不存在,但 Postgres 日志实际上并不打印 JSON 参数(它打印所有其他curl 参数,但不打印

-d
中包含的内容)。

postgresql curl postgrest
1个回答
0
投票

找到答案了。

这不在 PostgREST 文档中,但应该包含在内。

如果您尝试从 PostgREST API 调用 RPC 函数,传递 JSON 数据或 JSONB 数据,则必须将该数据分配给变量。

因此,在上面列出的问题实例中,删除带有 text 参数的重载函数,然后删除其他重载函数之一(json 或 jsonb 参数)。

然后你的curl函数需要将JSON分配给与函数中的名称匹配的变量名称。

所以我的解决方案(删除2个重载函数后是):

curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"p_json":[{"test_data":"4","test_type":"RED"}]}' \
  http://127.0.0.1:3000/rpc/update_test_table
© www.soinside.com 2019 - 2024. All rights reserved.