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$;
在 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$;