Commit f0688d6e authored by Peter Eisentraut's avatar Peter Eisentraut

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.
parent fab9d1da
......@@ -1341,13 +1341,15 @@ $$ LANGUAGE plpythonu;
<title>Utility Functions</title>
<para>
The <literal>plpy</literal> module also provides the functions
<literal>plpy.debug(<replaceable>msg, **kwargs</>)</literal>,
<literal>plpy.log(<replaceable>msg, **kwargs</>)</literal>,
<literal>plpy.info(<replaceable>msg, **kwargs</>)</literal>,
<literal>plpy.notice(<replaceable>msg, **kwargs</>)</literal>,
<literal>plpy.warning(<replaceable>msg, **kwargs</>)</literal>,
<literal>plpy.error(<replaceable>msg, **kwargs</>)</literal>, and
<literal>plpy.fatal(<replaceable>msg, **kwargs</>)</literal>.
<simplelist>
<member><literal>plpy.debug(<replaceable>msg, **kwargs</>)</literal></member>
<member><literal>plpy.log(<replaceable>msg, **kwargs</>)</literal></member>
<member><literal>plpy.info(<replaceable>msg, **kwargs</>)</literal></member>
<member><literal>plpy.notice(<replaceable>msg, **kwargs</>)</literal></member>
<member><literal>plpy.warning(<replaceable>msg, **kwargs</>)</literal></member>
<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>
<function>plpy.error</function> and <function>plpy.fatal</function>
actually raise a Python exception which, if uncaught, propagates out to
......@@ -1366,35 +1368,42 @@ $$ LANGUAGE plpythonu;
</para>
<para>
The <replaceable>msg</> argument is given as a positional argument. For
backward compatibility, more than one positional argument can be given. In
that case, the string representation of the tuple of positional arguments
becomes the message reported to the client.
</para>
<para>
The following keyword-only arguments are accepted:
<literal>
<replaceable>detail</replaceable>, <replaceable>hint</replaceable>,
<replaceable>sqlstate</replaceable>, <replaceable>schema_name</replaceable>,
<replaceable>table_name</replaceable>, <replaceable>column_name</replaceable>,
<replaceable>datatype_name</replaceable> , <replaceable>constraint_name</replaceable>
</literal>.
<simplelist>
<member><literal>detail</literal></member>
<member><literal>hint</literal></member>
<member><literal>sqlstate</literal></member>
<member><literal>schema_name</literal></member>
<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
is used to enrich the messages reported to the client. For example:
<programlisting>
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;
postgres=# select raise_custom_exception();
ERROR: XX000: plpy.Error: custom exception message
=# SELECT raise_custom_exception();
ERROR: plpy.Error: custom exception message
DETAIL: some info about exception
HINT: hint for users
CONTEXT: Traceback (most recent call last):
PL/Python function "raise_custom_exception", line 2, in &lt;module&gt;
plpy.error("custom exception message", detail = "some info about exception", hint = "hint for users")
PL/Python function "raise_custom_exception", line 4, in &lt;module&gt;
hint="hint for users")
PL/Python function "raise_custom_exception"
LOCATION: PLy_elog, plpy_elog.c:132
</programlisting>
</para>
......
CREATE FUNCTION elog_test() RETURNS void
AS $$
plpy.debug('debug', detail = 'some detail')
plpy.log('log', detail = 'some detail')
plpy.info('info', detail = 'some detail')
plpy.debug('debug', detail='some detail')
plpy.log('log', detail='some detail')
plpy.info('info', detail='some detail')
plpy.info()
plpy.info('the question', detail = 42);
plpy.info('the question', detail=42);
plpy.info('This is message text.',
detail = 'This is detail text',
hint = 'This is hint text.',
sqlstate = 'XX000',
schema_name = 'any info about schema',
table_name = 'any info about table',
column_name = 'any info about column',
datatype_name = 'any info about datatype',
constraint_name = 'any info about constraint')
plpy.notice('notice', detail = 'some detail')
plpy.warning('warning', detail = 'some detail')
plpy.error('stop on error', detail = 'some detail', hint = 'some hint')
detail='This is detail text',
hint='This is hint text.',
sqlstate='XX000',
schema_name='any info about schema',
table_name='any info about table',
column_name='any info about column',
datatype_name='any info about datatype',
constraint_name='any info about constraint')
plpy.notice('notice', detail='some detail')
plpy.warning('warning', detail='some detail')
plpy.error('stop on error', detail='some detail', hint='some hint')
$$ LANGUAGE plpythonu;
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;
from datetime import date
plpy.info('other types', detail = date(2016,2,26))
plpy.info('other types', detail=date(2016, 2, 26))
$$ LANGUAGE plpythonu;
do $$
DO $$
basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
plpy.info('other types', detail = basket)
plpy.info('other types', detail=basket)
$$ LANGUAGE plpythonu;
-- should fail
do $$ plpy.info('wrong sqlstate', sqlstate='54444A') $$ 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', 'second message', message='third message') $$ LANGUAGE plpythonu;
DO $$ plpy.info('wrong sqlstate', sqlstate='54444A') $$ 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', 'second message', message='third message') $$ LANGUAGE plpythonu;
-- raise exception in python, handle exception in plgsql
CREATE OR REPLACE FUNCTION raise_exception(_message text, _detail text DEFAULT NULL, _hint text DEFAULT NULL,
_sqlstate text DEFAULT NULL,
_schema_name text DEFAULT NULL, _table_name text DEFAULT NULL, _column_name text DEFAULT NULL,
_datatype_name text DEFAULT NULL, _constraint_name text DEFAULT NULL)
_sqlstate text DEFAULT NULL,
_schema_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 $$
kwargs = { "message":_message, "detail":_detail, "hint":_hint,
"sqlstate":_sqlstate, "schema_name":_schema_name, "table_name":_table_name,
"column_name":_column_name, "datatype_name":_datatype_name, "constraint_name":_constraint_name }
kwargs = {
"message": _message, "detail": _detail, "hint": _hint,
"sqlstate": _sqlstate, "schema_name": _schema_name, "table_name": _table_name,
"column_name": _column_name, "datatype_name": _datatype_name,
"constraint_name": _constraint_name
}
# ignore None values - should work on Python2.3
dict = {}
for k in kwargs:
if kwargs[k] is not None:
dict[k] = kwargs[k]
if kwargs[k] is not None:
dict[k] = kwargs[k]
plpy.error(**dict)
$$ LANGUAGE plpythonu;
SELECT raise_exception('hello', 'world');
SELECT raise_exception('message text', 'detail text', _sqlstate => 'YY333');
SELECT raise_exception(_message => '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 => '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');
SELECT raise_exception(_message => 'message text',
_hint => 'hint text',
_schema_name => 'schema text',
_column_name => 'column text',
_constraint_name => 'constraint text');
_hint => 'hint text',
_schema_name => 'schema text',
_column_name => 'column text',
_constraint_name => 'constraint text');
DO $$
DECLARE
......@@ -108,30 +114,30 @@ BEGIN
__datatype_name = PG_DATATYPE_NAME,
__constraint_name = CONSTRAINT_NAME;
RAISE NOTICE 'handled exception'
USING DETAIL = format('message:(%s), detail:(%s), hint: (%s), sqlstate: (%s), '
'schema_name:(%s), table_name:(%s), column_name:(%s), datatype_name:(%s), constraint_name:(%s)',
__message, __detail, __hint, __sqlstate, __schema_name,
__table_name, __column_name, __datatype_name, __constraint_name);
USING DETAIL = format('message:(%s), detail:(%s), hint: (%s), sqlstate: (%s), '
'schema_name:(%s), table_name:(%s), column_name:(%s), datatype_name:(%s), constraint_name:(%s)',
__message, __detail, __hint, __sqlstate, __schema_name,
__table_name, __column_name, __datatype_name, __constraint_name);
END;
END;
$$;
-- the displayed context is different between Python2 and Python3,
-- but that's not important for this test
-- The displayed context is different between Python2 and Python3,
-- but that's not important for this test.
\set SHOW_CONTEXT never
do $$
DO $$
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:
plpy.info(e.spidata)
raise e
plpy.info(e.spidata)
raise e
$$ LANGUAGE plpythonu;
do $$
DO $$
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:
plpy.info('sqlstate: %s, hint: %s, table_name: %s, datatype_name: %s' % (e.sqlstate, e.hint, e.table_name, e.datatype_name))
raise e
plpy.info('sqlstate: %s, hint: %s, table_name: %s, datatype_name: %s' % (e.sqlstate, e.hint, e.table_name, e.datatype_name))
raise e
$$ LANGUAGE plpythonu;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment