mirror of
https://github.com/postgres/postgres.git
synced 2025-05-06 19:59:18 +03:00
PL/Python: Clean up extended error reporting docs and tests
Format the example and test code more to Python style standards. Improve whitespace. Improve documentation formatting.
This commit is contained in:
parent
fab9d1da4a
commit
f0688d6e6c
@ -1341,13 +1341,15 @@ $$ LANGUAGE plpythonu;
|
|||||||
<title>Utility Functions</title>
|
<title>Utility Functions</title>
|
||||||
<para>
|
<para>
|
||||||
The <literal>plpy</literal> module also provides the functions
|
The <literal>plpy</literal> module also provides the functions
|
||||||
<literal>plpy.debug(<replaceable>msg, **kwargs</>)</literal>,
|
<simplelist>
|
||||||
<literal>plpy.log(<replaceable>msg, **kwargs</>)</literal>,
|
<member><literal>plpy.debug(<replaceable>msg, **kwargs</>)</literal></member>
|
||||||
<literal>plpy.info(<replaceable>msg, **kwargs</>)</literal>,
|
<member><literal>plpy.log(<replaceable>msg, **kwargs</>)</literal></member>
|
||||||
<literal>plpy.notice(<replaceable>msg, **kwargs</>)</literal>,
|
<member><literal>plpy.info(<replaceable>msg, **kwargs</>)</literal></member>
|
||||||
<literal>plpy.warning(<replaceable>msg, **kwargs</>)</literal>,
|
<member><literal>plpy.notice(<replaceable>msg, **kwargs</>)</literal></member>
|
||||||
<literal>plpy.error(<replaceable>msg, **kwargs</>)</literal>, and
|
<member><literal>plpy.warning(<replaceable>msg, **kwargs</>)</literal></member>
|
||||||
<literal>plpy.fatal(<replaceable>msg, **kwargs</>)</literal>.
|
<member><literal>plpy.error(<replaceable>msg, **kwargs</>)</literal></member>
|
||||||
|
<member><literal>plpy.fatal(<replaceable>msg, **kwargs</>)</literal></member>
|
||||||
|
</simplelist>
|
||||||
<indexterm><primary>elog</><secondary>in PL/Python</></indexterm>
|
<indexterm><primary>elog</><secondary>in PL/Python</></indexterm>
|
||||||
<function>plpy.error</function> and <function>plpy.fatal</function>
|
<function>plpy.error</function> and <function>plpy.fatal</function>
|
||||||
actually raise a Python exception which, if uncaught, propagates out to
|
actually raise a Python exception which, if uncaught, propagates out to
|
||||||
@ -1366,35 +1368,42 @@ $$ LANGUAGE plpythonu;
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
|
||||||
The <replaceable>msg</> argument is given as a positional argument. For
|
The <replaceable>msg</> argument is given as a positional argument. For
|
||||||
backward compatibility, more than one positional argument can be given. In
|
backward compatibility, more than one positional argument can be given. In
|
||||||
that case, the string representation of the tuple of positional arguments
|
that case, the string representation of the tuple of positional arguments
|
||||||
becomes the message reported to the client.
|
becomes the message reported to the client.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
The following keyword-only arguments are accepted:
|
The following keyword-only arguments are accepted:
|
||||||
<literal>
|
<simplelist>
|
||||||
<replaceable>detail</replaceable>, <replaceable>hint</replaceable>,
|
<member><literal>detail</literal></member>
|
||||||
<replaceable>sqlstate</replaceable>, <replaceable>schema_name</replaceable>,
|
<member><literal>hint</literal></member>
|
||||||
<replaceable>table_name</replaceable>, <replaceable>column_name</replaceable>,
|
<member><literal>sqlstate</literal></member>
|
||||||
<replaceable>datatype_name</replaceable> , <replaceable>constraint_name</replaceable>
|
<member><literal>schema_name</literal></member>
|
||||||
</literal>.
|
<member><literal>table_name</literal></member>
|
||||||
|
<member><literal>column_name</literal></member>
|
||||||
|
<member><literal>datatype_name</literal></member>
|
||||||
|
<member><literal>constraint_name</literal></member>
|
||||||
|
</simplelist>
|
||||||
The string representation of the objects passed as keyword-only arguments
|
The string representation of the objects passed as keyword-only arguments
|
||||||
is used to enrich the messages reported to the client. For example:
|
is used to enrich the messages reported to the client. For example:
|
||||||
|
|
||||||
<programlisting>
|
<programlisting>
|
||||||
CREATE FUNCTION raise_custom_exception() RETURNS void AS $$
|
CREATE FUNCTION raise_custom_exception() RETURNS void AS $$
|
||||||
plpy.error("custom exception message", detail = "some info about exception", hint = "hint for users")
|
plpy.error("custom exception message",
|
||||||
|
detail="some info about exception",
|
||||||
|
hint="hint for users")
|
||||||
$$ LANGUAGE plpythonu;
|
$$ LANGUAGE plpythonu;
|
||||||
|
|
||||||
postgres=# select raise_custom_exception();
|
=# SELECT raise_custom_exception();
|
||||||
ERROR: XX000: plpy.Error: custom exception message
|
ERROR: plpy.Error: custom exception message
|
||||||
DETAIL: some info about exception
|
DETAIL: some info about exception
|
||||||
HINT: hint for users
|
HINT: hint for users
|
||||||
CONTEXT: Traceback (most recent call last):
|
CONTEXT: Traceback (most recent call last):
|
||||||
PL/Python function "raise_custom_exception", line 2, in <module>
|
PL/Python function "raise_custom_exception", line 4, in <module>
|
||||||
plpy.error("custom exception message", detail = "some info about exception", hint = "hint for users")
|
hint="hint for users")
|
||||||
PL/Python function "raise_custom_exception"
|
PL/Python function "raise_custom_exception"
|
||||||
LOCATION: PLy_elog, plpy_elog.c:132
|
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
@ -38,44 +38,50 @@ CONTEXT: Traceback (most recent call last):
|
|||||||
PL/Python function "elog_test", line 18, in <module>
|
PL/Python function "elog_test", line 18, in <module>
|
||||||
plpy.error('stop on error', detail='some detail', hint='some hint')
|
plpy.error('stop on error', detail='some detail', hint='some hint')
|
||||||
PL/Python function "elog_test"
|
PL/Python function "elog_test"
|
||||||
do $$ plpy.info('other types', detail = (10,20)) $$ LANGUAGE plpythonu;
|
DO $$ plpy.info('other types', detail=(10, 20)) $$ LANGUAGE plpythonu;
|
||||||
INFO: other types
|
INFO: other types
|
||||||
DETAIL: (10, 20)
|
DETAIL: (10, 20)
|
||||||
do $$
|
DO $$
|
||||||
import time;
|
import time;
|
||||||
from datetime import date
|
from datetime import date
|
||||||
plpy.info('other types', detail=date(2016, 2, 26))
|
plpy.info('other types', detail=date(2016, 2, 26))
|
||||||
$$ LANGUAGE plpythonu;
|
$$ LANGUAGE plpythonu;
|
||||||
INFO: other types
|
INFO: other types
|
||||||
DETAIL: 2016-02-26
|
DETAIL: 2016-02-26
|
||||||
do $$
|
DO $$
|
||||||
basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
|
basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
|
||||||
plpy.info('other types', detail=basket)
|
plpy.info('other types', detail=basket)
|
||||||
$$ LANGUAGE plpythonu;
|
$$ LANGUAGE plpythonu;
|
||||||
INFO: other types
|
INFO: other types
|
||||||
DETAIL: ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
|
DETAIL: ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
|
||||||
-- should fail
|
-- should fail
|
||||||
do $$ plpy.info('wrong sqlstate', sqlstate='54444A') $$ LANGUAGE plpythonu;
|
DO $$ plpy.info('wrong sqlstate', sqlstate='54444A') $$ LANGUAGE plpythonu;
|
||||||
ERROR: invalid SQLSTATE code
|
ERROR: invalid SQLSTATE code
|
||||||
CONTEXT: PL/Python anonymous code block
|
CONTEXT: PL/Python anonymous code block
|
||||||
do $$ plpy.info('unsupported argument', blabla='fooboo') $$ LANGUAGE plpythonu;
|
DO $$ plpy.info('unsupported argument', blabla='fooboo') $$ LANGUAGE plpythonu;
|
||||||
ERROR: 'blabla' is an invalid keyword argument for this function
|
ERROR: 'blabla' is an invalid keyword argument for this function
|
||||||
CONTEXT: PL/Python anonymous code block
|
CONTEXT: PL/Python anonymous code block
|
||||||
do $$ plpy.info('first message', message='second message') $$ LANGUAGE plpythonu;
|
DO $$ plpy.info('first message', message='second message') $$ LANGUAGE plpythonu;
|
||||||
ERROR: the message is already specified
|
ERROR: the message is already specified
|
||||||
CONTEXT: PL/Python anonymous code block
|
CONTEXT: PL/Python anonymous code block
|
||||||
do $$ plpy.info('first message', 'second message', message='third message') $$ LANGUAGE plpythonu;
|
DO $$ plpy.info('first message', 'second message', message='third message') $$ LANGUAGE plpythonu;
|
||||||
ERROR: the message is already specified
|
ERROR: the message is already specified
|
||||||
CONTEXT: PL/Python anonymous code block
|
CONTEXT: PL/Python anonymous code block
|
||||||
-- raise exception in python, handle exception in plgsql
|
-- raise exception in python, handle exception in plgsql
|
||||||
CREATE OR REPLACE FUNCTION raise_exception(_message text, _detail text DEFAULT NULL, _hint text DEFAULT NULL,
|
CREATE OR REPLACE FUNCTION raise_exception(_message text, _detail text DEFAULT NULL, _hint text DEFAULT NULL,
|
||||||
_sqlstate text DEFAULT NULL,
|
_sqlstate text DEFAULT NULL,
|
||||||
_schema_name text DEFAULT NULL, _table_name text DEFAULT NULL, _column_name text DEFAULT NULL,
|
_schema_name text DEFAULT NULL,
|
||||||
_datatype_name text DEFAULT NULL, _constraint_name text DEFAULT NULL)
|
_table_name text DEFAULT NULL,
|
||||||
|
_column_name text DEFAULT NULL,
|
||||||
|
_datatype_name text DEFAULT NULL,
|
||||||
|
_constraint_name text DEFAULT NULL)
|
||||||
RETURNS void AS $$
|
RETURNS void AS $$
|
||||||
kwargs = { "message":_message, "detail":_detail, "hint":_hint,
|
kwargs = {
|
||||||
|
"message": _message, "detail": _detail, "hint": _hint,
|
||||||
"sqlstate": _sqlstate, "schema_name": _schema_name, "table_name": _table_name,
|
"sqlstate": _sqlstate, "schema_name": _schema_name, "table_name": _table_name,
|
||||||
"column_name":_column_name, "datatype_name":_datatype_name, "constraint_name":_constraint_name }
|
"column_name": _column_name, "datatype_name": _datatype_name,
|
||||||
|
"constraint_name": _constraint_name
|
||||||
|
}
|
||||||
# ignore None values - should work on Python2.3
|
# ignore None values - should work on Python2.3
|
||||||
dict = {}
|
dict = {}
|
||||||
for k in kwargs:
|
for k in kwargs:
|
||||||
@ -87,14 +93,14 @@ SELECT raise_exception('hello', 'world');
|
|||||||
ERROR: plpy.Error: hello
|
ERROR: plpy.Error: hello
|
||||||
DETAIL: world
|
DETAIL: world
|
||||||
CONTEXT: Traceback (most recent call last):
|
CONTEXT: Traceback (most recent call last):
|
||||||
PL/Python function "raise_exception", line 10, in <module>
|
PL/Python function "raise_exception", line 13, in <module>
|
||||||
plpy.error(**dict)
|
plpy.error(**dict)
|
||||||
PL/Python function "raise_exception"
|
PL/Python function "raise_exception"
|
||||||
SELECT raise_exception('message text', 'detail text', _sqlstate => 'YY333');
|
SELECT raise_exception('message text', 'detail text', _sqlstate => 'YY333');
|
||||||
ERROR: plpy.Error: message text
|
ERROR: plpy.Error: message text
|
||||||
DETAIL: detail text
|
DETAIL: detail text
|
||||||
CONTEXT: Traceback (most recent call last):
|
CONTEXT: Traceback (most recent call last):
|
||||||
PL/Python function "raise_exception", line 10, in <module>
|
PL/Python function "raise_exception", line 13, in <module>
|
||||||
plpy.error(**dict)
|
plpy.error(**dict)
|
||||||
PL/Python function "raise_exception"
|
PL/Python function "raise_exception"
|
||||||
SELECT raise_exception(_message => 'message text',
|
SELECT raise_exception(_message => 'message text',
|
||||||
@ -110,7 +116,7 @@ ERROR: plpy.Error: message text
|
|||||||
DETAIL: detail text
|
DETAIL: detail text
|
||||||
HINT: hint text
|
HINT: hint text
|
||||||
CONTEXT: Traceback (most recent call last):
|
CONTEXT: Traceback (most recent call last):
|
||||||
PL/Python function "raise_exception", line 10, in <module>
|
PL/Python function "raise_exception", line 13, in <module>
|
||||||
plpy.error(**dict)
|
plpy.error(**dict)
|
||||||
PL/Python function "raise_exception"
|
PL/Python function "raise_exception"
|
||||||
SELECT raise_exception(_message => 'message text',
|
SELECT raise_exception(_message => 'message text',
|
||||||
@ -121,7 +127,7 @@ SELECT raise_exception(_message => 'message text',
|
|||||||
ERROR: plpy.Error: message text
|
ERROR: plpy.Error: message text
|
||||||
HINT: hint text
|
HINT: hint text
|
||||||
CONTEXT: Traceback (most recent call last):
|
CONTEXT: Traceback (most recent call last):
|
||||||
PL/Python function "raise_exception", line 10, in <module>
|
PL/Python function "raise_exception", line 13, in <module>
|
||||||
plpy.error(**dict)
|
plpy.error(**dict)
|
||||||
PL/Python function "raise_exception"
|
PL/Python function "raise_exception"
|
||||||
DO $$
|
DO $$
|
||||||
@ -166,10 +172,10 @@ END;
|
|||||||
$$;
|
$$;
|
||||||
NOTICE: handled exception
|
NOTICE: handled exception
|
||||||
DETAIL: message:(plpy.Error: message text), detail:(detail text), hint: (hint text), sqlstate: (XX555), schema_name:(schema text), table_name:(table text), column_name:(column text), datatype_name:(datatype text), constraint_name:(constraint text)
|
DETAIL: message:(plpy.Error: message text), detail:(detail text), hint: (hint text), sqlstate: (XX555), schema_name:(schema text), table_name:(table text), column_name:(column text), datatype_name:(datatype text), constraint_name:(constraint text)
|
||||||
-- the displayed context is different between Python2 and Python3,
|
-- The displayed context is different between Python2 and Python3,
|
||||||
-- but that's not important for this test
|
-- but that's not important for this test.
|
||||||
\set SHOW_CONTEXT never
|
\set SHOW_CONTEXT never
|
||||||
do $$
|
DO $$
|
||||||
try:
|
try:
|
||||||
plpy.execute("select raise_exception(_message => 'my message', _sqlstate => 'XX987', _hint => 'some hint', _table_name => 'users_tab', _datatype_name => 'user_type')")
|
plpy.execute("select raise_exception(_message => 'my message', _sqlstate => 'XX987', _hint => 'some hint', _table_name => 'users_tab', _datatype_name => 'user_type')")
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
@ -179,7 +185,7 @@ $$ LANGUAGE plpythonu;
|
|||||||
INFO: (119577128, None, 'some hint', None, 0, None, 'users_tab', None, 'user_type', None)
|
INFO: (119577128, None, 'some hint', None, 0, None, 'users_tab', None, 'user_type', None)
|
||||||
ERROR: plpy.SPIError: plpy.Error: my message
|
ERROR: plpy.SPIError: plpy.Error: my message
|
||||||
HINT: some hint
|
HINT: some hint
|
||||||
do $$
|
DO $$
|
||||||
try:
|
try:
|
||||||
plpy.error(message = 'my message', sqlstate = 'XX987', hint = 'some hint', table_name = 'users_tab', datatype_name = 'user_type')
|
plpy.error(message = 'my message', sqlstate = 'XX987', hint = 'some hint', table_name = 'users_tab', datatype_name = 'user_type')
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
|
@ -21,34 +21,40 @@ $$ LANGUAGE plpythonu;
|
|||||||
|
|
||||||
SELECT elog_test();
|
SELECT elog_test();
|
||||||
|
|
||||||
do $$ plpy.info('other types', detail = (10,20)) $$ LANGUAGE plpythonu;
|
DO $$ plpy.info('other types', detail=(10, 20)) $$ LANGUAGE plpythonu;
|
||||||
|
|
||||||
do $$
|
DO $$
|
||||||
import time;
|
import time;
|
||||||
from datetime import date
|
from datetime import date
|
||||||
plpy.info('other types', detail=date(2016, 2, 26))
|
plpy.info('other types', detail=date(2016, 2, 26))
|
||||||
$$ LANGUAGE plpythonu;
|
$$ LANGUAGE plpythonu;
|
||||||
|
|
||||||
do $$
|
DO $$
|
||||||
basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
|
basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
|
||||||
plpy.info('other types', detail=basket)
|
plpy.info('other types', detail=basket)
|
||||||
$$ LANGUAGE plpythonu;
|
$$ LANGUAGE plpythonu;
|
||||||
|
|
||||||
-- should fail
|
-- should fail
|
||||||
do $$ plpy.info('wrong sqlstate', sqlstate='54444A') $$ LANGUAGE plpythonu;
|
DO $$ plpy.info('wrong sqlstate', sqlstate='54444A') $$ LANGUAGE plpythonu;
|
||||||
do $$ plpy.info('unsupported argument', blabla='fooboo') $$ LANGUAGE plpythonu;
|
DO $$ plpy.info('unsupported argument', blabla='fooboo') $$ LANGUAGE plpythonu;
|
||||||
do $$ plpy.info('first message', message='second message') $$ LANGUAGE plpythonu;
|
DO $$ plpy.info('first message', message='second message') $$ LANGUAGE plpythonu;
|
||||||
do $$ plpy.info('first message', 'second message', message='third message') $$ LANGUAGE plpythonu;
|
DO $$ plpy.info('first message', 'second message', message='third message') $$ LANGUAGE plpythonu;
|
||||||
|
|
||||||
-- raise exception in python, handle exception in plgsql
|
-- raise exception in python, handle exception in plgsql
|
||||||
CREATE OR REPLACE FUNCTION raise_exception(_message text, _detail text DEFAULT NULL, _hint text DEFAULT NULL,
|
CREATE OR REPLACE FUNCTION raise_exception(_message text, _detail text DEFAULT NULL, _hint text DEFAULT NULL,
|
||||||
_sqlstate text DEFAULT NULL,
|
_sqlstate text DEFAULT NULL,
|
||||||
_schema_name text DEFAULT NULL, _table_name text DEFAULT NULL, _column_name text DEFAULT NULL,
|
_schema_name text DEFAULT NULL,
|
||||||
_datatype_name text DEFAULT NULL, _constraint_name text DEFAULT NULL)
|
_table_name text DEFAULT NULL,
|
||||||
|
_column_name text DEFAULT NULL,
|
||||||
|
_datatype_name text DEFAULT NULL,
|
||||||
|
_constraint_name text DEFAULT NULL)
|
||||||
RETURNS void AS $$
|
RETURNS void AS $$
|
||||||
kwargs = { "message":_message, "detail":_detail, "hint":_hint,
|
kwargs = {
|
||||||
|
"message": _message, "detail": _detail, "hint": _hint,
|
||||||
"sqlstate": _sqlstate, "schema_name": _schema_name, "table_name": _table_name,
|
"sqlstate": _sqlstate, "schema_name": _schema_name, "table_name": _table_name,
|
||||||
"column_name":_column_name, "datatype_name":_datatype_name, "constraint_name":_constraint_name }
|
"column_name": _column_name, "datatype_name": _datatype_name,
|
||||||
|
"constraint_name": _constraint_name
|
||||||
|
}
|
||||||
# ignore None values - should work on Python2.3
|
# ignore None values - should work on Python2.3
|
||||||
dict = {}
|
dict = {}
|
||||||
for k in kwargs:
|
for k in kwargs:
|
||||||
@ -116,11 +122,11 @@ BEGIN
|
|||||||
END;
|
END;
|
||||||
$$;
|
$$;
|
||||||
|
|
||||||
-- the displayed context is different between Python2 and Python3,
|
-- The displayed context is different between Python2 and Python3,
|
||||||
-- but that's not important for this test
|
-- but that's not important for this test.
|
||||||
\set SHOW_CONTEXT never
|
\set SHOW_CONTEXT never
|
||||||
|
|
||||||
do $$
|
DO $$
|
||||||
try:
|
try:
|
||||||
plpy.execute("select raise_exception(_message => 'my message', _sqlstate => 'XX987', _hint => 'some hint', _table_name => 'users_tab', _datatype_name => 'user_type')")
|
plpy.execute("select raise_exception(_message => 'my message', _sqlstate => 'XX987', _hint => 'some hint', _table_name => 'users_tab', _datatype_name => 'user_type')")
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
@ -128,7 +134,7 @@ except Exception, e:
|
|||||||
raise e
|
raise e
|
||||||
$$ LANGUAGE plpythonu;
|
$$ LANGUAGE plpythonu;
|
||||||
|
|
||||||
do $$
|
DO $$
|
||||||
try:
|
try:
|
||||||
plpy.error(message = 'my message', sqlstate = 'XX987', hint = 'some hint', table_name = 'users_tab', datatype_name = 'user_type')
|
plpy.error(message = 'my message', sqlstate = 'XX987', hint = 'some hint', table_name = 'users_tab', datatype_name = 'user_type')
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user