Is there a way to remove the “plpy.Error:” prefix from an exception raised with `plpy.error`?

Is there a way to remove the “plpy.Error:” prefix from an exception raised with `plpy.error`?

在 PL/pgSQL 函数中,RAISE EXCEPTION 'mymessage' USING ...;“mymessage” 作为错误消息,但在 PL/Python 函数中,plpy.error('mymessage', ...) 将有 “plpy.Error: mymessage” 作为错误信息。有没有一种直接的方法可以从错误消息中删除该前缀?

恐怕你无论如何也不能改变它。这是设计使然。它有一点点不同的语义。在 plpgsql 中,您可以直接引发 PostgreSQL 异常。在 Python 中是不可能的 - python 异常 plpy.Error 被引发、捕获并转换为 PostgreSQL 异常 - "plpy.Error" 是异常的名称。可以有任何其他异常的任何名称。

本例中 Python 异常的惯例是 - level: name: text

可以看到

ERROR:  ZeroDivisionError: division by zero
ERROR:  plpy.Error: some text

并且无法更改它。这是设计使然 - 这是惯例。

PLpgSQL 没有这个约定——但是 PLpgSQL 与 Postgres 的集成度更高。它没有自己的环境,自己的例外。

如果您确实必须在异常消息中保持一致,您可以将 python 函数包装在 plpgsql 函数中并编辑消息。

CREATE OR REPLACE FUNCTION my_fn_py()
    RETURNS VOID
    LANGUAGE plpython3u VOLATILE
    AS $python$
try:
    # stuff... pretend this is a big complicated thing ...

except Exception as e:
    plpy.error('custom_error', detail = str(e))
$python$;

-- Wrapper fn to normalize the plpython exceptions
CREATE OR REPLACE FUNCTION my_fn()
    RETURNS VOID
    LANGUAGE plpgsql VOLATILE
    AS $body$
DECLARE
    _msg TEXT;
    _detail TEXT;
BEGIN
    PERFORM my_fn_py();

EXCEPTION
    WHEN OTHERS THEN
        GET STACKED DIAGNOSTICS
            _msg = MESSAGE_TEXT,
            _detail = PG_EXCEPTION_DETAIL;

        IF _msg = 'plpy.Error: custom_error' THEN
            RAISE EXCEPTION 'custom_error' -- can't use a variable here :(
                DETAIL := _detail,
                ERRCODE := P0099;
        ELSIF /* other cases... */ THEN
        ELSE
            -- Re-raise the original exception
            RAISE;
        END IF;
END
$body$;