python_minorversion=`echo "$python_fullversion" | sed '[s/^[0-9]*\.\([0-9]*\).*/\1/]'`
python_version=`echo "$python_fullversion" | sed '[s/^\([0-9]*\.[0-9]*\).*/\1/]'`
# Reject unsupported Python versions as soon as practical.
-if test "$python_majorversion" -lt 3 -a "$python_minorversion" -lt 4; then
- AC_MSG_ERROR([Python version $python_version is too old (version 2.4 or later is required)])
+if test "$python_majorversion" -lt 3 -a "$python_minorversion" -lt 6; then
+ AC_MSG_ERROR([Python version $python_version is too old (version 2.6 or later is required)])
fi
AC_MSG_CHECKING([for Python distutils module])
python_minorversion=`echo "$python_fullversion" | sed 's/^[0-9]*\.\([0-9]*\).*/\1/'`
python_version=`echo "$python_fullversion" | sed 's/^\([0-9]*\.[0-9]*\).*/\1/'`
# Reject unsupported Python versions as soon as practical.
-if test "$python_majorversion" -lt 3 -a "$python_minorversion" -lt 4; then
- as_fn_error $? "Python version $python_version is too old (version 2.4 or later is required)" "$LINENO" 5
+if test "$python_majorversion" -lt 3 -a "$python_minorversion" -lt 6; then
+ as_fn_error $? "Python version $python_version is too old (version 2.6 or later is required)" "$LINENO" 5
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python distutils module" >&5
language, you need a <productname>Python</productname>
installation with the header files and
the <application>distutils</application> module. The minimum
- required version is <productname>Python</productname> 2.4.
+ required version is <productname>Python</productname> 2.6.
<productname>Python 3</productname> is supported if it's
version 3.1 or later; but see
<xref linkend="plpython-python23"/>
<para>
Context managers syntax using the <literal>with</literal> keyword
- is available by default in Python 2.6. If using PL/Python with an
- older Python version, it is still possible to use explicit
- subtransactions, although not as transparently. You can call the
+ is available by default in Python 2.6. For compatibility with
+ older Python versions, you can call the
subtransaction manager's <literal>__enter__</literal> and
<literal>__exit__</literal> functions using the
<literal>enter</literal> and <literal>exit</literal> convenience
$$ LANGUAGE plpythonu;
</programlisting>
</para>
-
- <note>
- <para>
- Although context managers were implemented in Python 2.5, to use
- the <literal>with</literal> syntax in that version you need to
- use a <ulink
- url="https://docs.python.org/release/2.5/ref/future.html">future
- statement</ulink>. Because of implementation details, however,
- you cannot use future statements in PL/Python functions.
- </para>
- </note>
</sect2>
</sect1>
Guide to alternative expected files:
-plpython_error_0.out Python 2.4 and older
plpython_error_5.out Python 3.5 and newer
plpython_unicode.out server encoding != SQL_ASCII
plpython_unicode_3.out server encoding == SQL_ASCII
-plpython_subtransaction_0.out Python 2.4 and older (without with statement)
-plpython_subtransaction_5.out Python 2.5 (without with statement)
-
plpython_types_3.out Python 3.x
+++ /dev/null
--- test error handling, i forgot to restore Warn_restart in
--- the trigger handler once. the errors and subsequent core dump were
--- interesting.
-/* Flat out Python syntax error
- */
-CREATE FUNCTION python_syntax_error() RETURNS text
- AS
-'.syntaxerror'
- LANGUAGE plpythonu;
-ERROR: could not compile PL/Python function "python_syntax_error"
-DETAIL: SyntaxError: invalid syntax (line 2)
-/* With check_function_bodies = false the function should get defined
- * and the error reported when called
- */
-SET check_function_bodies = false;
-CREATE FUNCTION python_syntax_error() RETURNS text
- AS
-'.syntaxerror'
- LANGUAGE plpythonu;
-SELECT python_syntax_error();
-ERROR: could not compile PL/Python function "python_syntax_error"
-DETAIL: SyntaxError: invalid syntax (line 2)
-/* Run the function twice to check if the hashtable entry gets cleaned up */
-SELECT python_syntax_error();
-ERROR: could not compile PL/Python function "python_syntax_error"
-DETAIL: SyntaxError: invalid syntax (line 2)
-RESET check_function_bodies;
-/* Flat out syntax error
- */
-CREATE FUNCTION sql_syntax_error() RETURNS text
- AS
-'plpy.execute("syntax error")'
- LANGUAGE plpythonu;
-SELECT sql_syntax_error();
-ERROR: spiexceptions.SyntaxError: syntax error at or near "syntax"
-LINE 1: syntax error
- ^
-QUERY: syntax error
-CONTEXT: Traceback (most recent call last):
- PL/Python function "sql_syntax_error", line 1, in <module>
- plpy.execute("syntax error")
-PL/Python function "sql_syntax_error"
-/* check the handling of uncaught python exceptions
- */
-CREATE FUNCTION exception_index_invalid(text) RETURNS text
- AS
-'return args[1]'
- LANGUAGE plpythonu;
-SELECT exception_index_invalid('test');
-ERROR: IndexError: list index out of range
-CONTEXT: Traceback (most recent call last):
- PL/Python function "exception_index_invalid", line 1, in <module>
- return args[1]
-PL/Python function "exception_index_invalid"
-/* check handling of nested exceptions
- */
-CREATE FUNCTION exception_index_invalid_nested() RETURNS text
- AS
-'rv = plpy.execute("SELECT test5(''foo'')")
-return rv[0]'
- LANGUAGE plpythonu;
-SELECT exception_index_invalid_nested();
-ERROR: spiexceptions.UndefinedFunction: function test5(unknown) does not exist
-LINE 1: SELECT test5('foo')
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
-QUERY: SELECT test5('foo')
-CONTEXT: Traceback (most recent call last):
- PL/Python function "exception_index_invalid_nested", line 1, in <module>
- rv = plpy.execute("SELECT test5('foo')")
-PL/Python function "exception_index_invalid_nested"
-/* a typo
- */
-CREATE FUNCTION invalid_type_uncaught(a text) RETURNS text
- AS
-'if "plan" not in SD:
- q = "SELECT fname FROM users WHERE lname = $1"
- SD["plan"] = plpy.prepare(q, [ "test" ])
-rv = plpy.execute(SD["plan"], [ a ])
-if len(rv):
- return rv[0]["fname"]
-return None
-'
- LANGUAGE plpythonu;
-SELECT invalid_type_uncaught('rick');
-ERROR: spiexceptions.UndefinedObject: type "test" does not exist
-CONTEXT: Traceback (most recent call last):
- PL/Python function "invalid_type_uncaught", line 3, in <module>
- SD["plan"] = plpy.prepare(q, [ "test" ])
-PL/Python function "invalid_type_uncaught"
-/* for what it's worth catch the exception generated by
- * the typo, and return None
- */
-CREATE FUNCTION invalid_type_caught(a text) RETURNS text
- AS
-'if "plan" not in SD:
- q = "SELECT fname FROM users WHERE lname = $1"
- try:
- SD["plan"] = plpy.prepare(q, [ "test" ])
- except plpy.SPIError, ex:
- plpy.notice(str(ex))
- return None
-rv = plpy.execute(SD["plan"], [ a ])
-if len(rv):
- return rv[0]["fname"]
-return None
-'
- LANGUAGE plpythonu;
-SELECT invalid_type_caught('rick');
-NOTICE: type "test" does not exist
- invalid_type_caught
----------------------
-
-(1 row)
-
-/* for what it's worth catch the exception generated by
- * the typo, and reraise it as a plain error
- */
-CREATE FUNCTION invalid_type_reraised(a text) RETURNS text
- AS
-'if "plan" not in SD:
- q = "SELECT fname FROM users WHERE lname = $1"
- try:
- SD["plan"] = plpy.prepare(q, [ "test" ])
- except plpy.SPIError, ex:
- plpy.error(str(ex))
-rv = plpy.execute(SD["plan"], [ a ])
-if len(rv):
- return rv[0]["fname"]
-return None
-'
- LANGUAGE plpythonu;
-SELECT invalid_type_reraised('rick');
-ERROR: plpy.Error: type "test" does not exist
-CONTEXT: Traceback (most recent call last):
- PL/Python function "invalid_type_reraised", line 6, in <module>
- plpy.error(str(ex))
-PL/Python function "invalid_type_reraised"
-/* no typo no messing about
- */
-CREATE FUNCTION valid_type(a text) RETURNS text
- AS
-'if "plan" not in SD:
- SD["plan"] = plpy.prepare("SELECT fname FROM users WHERE lname = $1", [ "text" ])
-rv = plpy.execute(SD["plan"], [ a ])
-if len(rv):
- return rv[0]["fname"]
-return None
-'
- LANGUAGE plpythonu;
-SELECT valid_type('rick');
- valid_type
-------------
-
-(1 row)
-
-/* error in nested functions to get a traceback
-*/
-CREATE FUNCTION nested_error() RETURNS text
- AS
-'def fun1():
- plpy.error("boom")
-
-def fun2():
- fun1()
-
-def fun3():
- fun2()
-
-fun3()
-return "not reached"
-'
- LANGUAGE plpythonu;
-SELECT nested_error();
-ERROR: plpy.Error: boom
-CONTEXT: Traceback (most recent call last):
- PL/Python function "nested_error", line 10, in <module>
- fun3()
- PL/Python function "nested_error", line 8, in fun3
- fun2()
- PL/Python function "nested_error", line 5, in fun2
- fun1()
- PL/Python function "nested_error", line 2, in fun1
- plpy.error("boom")
-PL/Python function "nested_error"
-/* raising plpy.Error is just like calling plpy.error
-*/
-CREATE FUNCTION nested_error_raise() RETURNS text
- AS
-'def fun1():
- raise plpy.Error("boom")
-
-def fun2():
- fun1()
-
-def fun3():
- fun2()
-
-fun3()
-return "not reached"
-'
- LANGUAGE plpythonu;
-SELECT nested_error_raise();
-ERROR: plpy.Error: boom
-CONTEXT: Traceback (most recent call last):
- PL/Python function "nested_error_raise", line 10, in <module>
- fun3()
- PL/Python function "nested_error_raise", line 8, in fun3
- fun2()
- PL/Python function "nested_error_raise", line 5, in fun2
- fun1()
- PL/Python function "nested_error_raise", line 2, in fun1
- raise plpy.Error("boom")
-PL/Python function "nested_error_raise"
-/* using plpy.warning should not produce a traceback
-*/
-CREATE FUNCTION nested_warning() RETURNS text
- AS
-'def fun1():
- plpy.warning("boom")
-
-def fun2():
- fun1()
-
-def fun3():
- fun2()
-
-fun3()
-return "you''ve been warned"
-'
- LANGUAGE plpythonu;
-SELECT nested_warning();
-WARNING: boom
- nested_warning
---------------------
- you've been warned
-(1 row)
-
-/* AttributeError at toplevel used to give segfaults with the traceback
-*/
-CREATE FUNCTION toplevel_attribute_error() RETURNS void AS
-$$
-plpy.nonexistent
-$$ LANGUAGE plpythonu;
-SELECT toplevel_attribute_error();
-ERROR: AttributeError: 'module' object has no attribute 'nonexistent'
-CONTEXT: Traceback (most recent call last):
- PL/Python function "toplevel_attribute_error", line 2, in <module>
- plpy.nonexistent
-PL/Python function "toplevel_attribute_error"
-/* Calling PL/Python functions from SQL and vice versa should not lose context.
- */
-CREATE OR REPLACE FUNCTION python_traceback() RETURNS void AS $$
-def first():
- second()
-
-def second():
- third()
-
-def third():
- plpy.execute("select sql_error()")
-
-first()
-$$ LANGUAGE plpythonu;
-CREATE OR REPLACE FUNCTION sql_error() RETURNS void AS $$
-begin
- select 1/0;
-end
-$$ LANGUAGE plpgsql;
-CREATE OR REPLACE FUNCTION python_from_sql_error() RETURNS void AS $$
-begin
- select python_traceback();
-end
-$$ LANGUAGE plpgsql;
-CREATE OR REPLACE FUNCTION sql_from_python_error() RETURNS void AS $$
-plpy.execute("select sql_error()")
-$$ LANGUAGE plpythonu;
-SELECT python_traceback();
-ERROR: spiexceptions.DivisionByZero: division by zero
-CONTEXT: Traceback (most recent call last):
- PL/Python function "python_traceback", line 11, in <module>
- first()
- PL/Python function "python_traceback", line 3, in first
- second()
- PL/Python function "python_traceback", line 6, in second
- third()
- PL/Python function "python_traceback", line 9, in third
- plpy.execute("select sql_error()")
-PL/Python function "python_traceback"
-SELECT sql_error();
-ERROR: division by zero
-CONTEXT: SQL statement "select 1/0"
-PL/pgSQL function sql_error() line 3 at SQL statement
-SELECT python_from_sql_error();
-ERROR: spiexceptions.DivisionByZero: division by zero
-CONTEXT: Traceback (most recent call last):
- PL/Python function "python_traceback", line 11, in <module>
- first()
- PL/Python function "python_traceback", line 3, in first
- second()
- PL/Python function "python_traceback", line 6, in second
- third()
- PL/Python function "python_traceback", line 9, in third
- plpy.execute("select sql_error()")
-PL/Python function "python_traceback"
-SQL statement "select python_traceback()"
-PL/pgSQL function python_from_sql_error() line 3 at SQL statement
-SELECT sql_from_python_error();
-ERROR: spiexceptions.DivisionByZero: division by zero
-CONTEXT: Traceback (most recent call last):
- PL/Python function "sql_from_python_error", line 2, in <module>
- plpy.execute("select sql_error()")
-PL/Python function "sql_from_python_error"
-/* check catching specific types of exceptions
- */
-CREATE TABLE specific (
- i integer PRIMARY KEY
-);
-CREATE FUNCTION specific_exception(i integer) RETURNS void AS
-$$
-from plpy import spiexceptions
-try:
- plpy.execute("insert into specific values (%s)" % (i or "NULL"));
-except spiexceptions.NotNullViolation, e:
- plpy.notice("Violated the NOT NULL constraint, sqlstate %s" % e.sqlstate)
-except spiexceptions.UniqueViolation, e:
- plpy.notice("Violated the UNIQUE constraint, sqlstate %s" % e.sqlstate)
-$$ LANGUAGE plpythonu;
-SELECT specific_exception(2);
- specific_exception
---------------------
-
-(1 row)
-
-SELECT specific_exception(NULL);
-NOTICE: Violated the NOT NULL constraint, sqlstate 23502
- specific_exception
---------------------
-
-(1 row)
-
-SELECT specific_exception(2);
-NOTICE: Violated the UNIQUE constraint, sqlstate 23505
- specific_exception
---------------------
-
-(1 row)
-
-/* SPI errors in PL/Python functions should preserve the SQLSTATE value
- */
-CREATE FUNCTION python_unique_violation() RETURNS void AS $$
-plpy.execute("insert into specific values (1)")
-plpy.execute("insert into specific values (1)")
-$$ LANGUAGE plpythonu;
-CREATE FUNCTION catch_python_unique_violation() RETURNS text AS $$
-begin
- begin
- perform python_unique_violation();
- exception when unique_violation then
- return 'ok';
- end;
- return 'not reached';
-end;
-$$ language plpgsql;
-SELECT catch_python_unique_violation();
- catch_python_unique_violation
--------------------------------
- ok
-(1 row)
-
-/* manually starting subtransactions - a bad idea
- */
-CREATE FUNCTION manual_subxact() RETURNS void AS $$
-plpy.execute("savepoint save")
-plpy.execute("create table foo(x integer)")
-plpy.execute("rollback to save")
-$$ LANGUAGE plpythonu;
-SELECT manual_subxact();
-ERROR: plpy.SPIError: SPI_execute failed: SPI_ERROR_TRANSACTION
-CONTEXT: Traceback (most recent call last):
- PL/Python function "manual_subxact", line 2, in <module>
- plpy.execute("savepoint save")
-PL/Python function "manual_subxact"
-/* same for prepared plans
- */
-CREATE FUNCTION manual_subxact_prepared() RETURNS void AS $$
-save = plpy.prepare("savepoint save")
-rollback = plpy.prepare("rollback to save")
-plpy.execute(save)
-plpy.execute("create table foo(x integer)")
-plpy.execute(rollback)
-$$ LANGUAGE plpythonu;
-SELECT manual_subxact_prepared();
-ERROR: plpy.SPIError: SPI_execute_plan failed: SPI_ERROR_TRANSACTION
-CONTEXT: Traceback (most recent call last):
- PL/Python function "manual_subxact_prepared", line 4, in <module>
- plpy.execute(save)
-PL/Python function "manual_subxact_prepared"
-/* raising plpy.spiexception.* from python code should preserve sqlstate
- */
-CREATE FUNCTION plpy_raise_spiexception() RETURNS void AS $$
-raise plpy.spiexceptions.DivisionByZero()
-$$ LANGUAGE plpythonu;
-DO $$
-BEGIN
- SELECT plpy_raise_spiexception();
-EXCEPTION WHEN division_by_zero THEN
- -- NOOP
-END
-$$ LANGUAGE plpgsql;
-/* setting a custom sqlstate should be handled
- */
-CREATE FUNCTION plpy_raise_spiexception_override() RETURNS void AS $$
-exc = plpy.spiexceptions.DivisionByZero()
-exc.sqlstate = 'SILLY'
-raise exc
-$$ LANGUAGE plpythonu;
-DO $$
-BEGIN
- SELECT plpy_raise_spiexception_override();
-EXCEPTION WHEN SQLSTATE 'SILLY' THEN
- -- NOOP
-END
-$$ LANGUAGE plpgsql;
-/* test the context stack trace for nested execution levels
- */
-CREATE FUNCTION notice_innerfunc() RETURNS int AS $$
-plpy.execute("DO LANGUAGE plpythonu $x$ plpy.notice('inside DO') $x$")
-return 1
-$$ LANGUAGE plpythonu;
-CREATE FUNCTION notice_outerfunc() RETURNS int AS $$
-plpy.execute("SELECT notice_innerfunc()")
-return 1
-$$ LANGUAGE plpythonu;
-\set SHOW_CONTEXT always
-SELECT notice_outerfunc();
-NOTICE: inside DO
-CONTEXT: PL/Python anonymous code block
-SQL statement "DO LANGUAGE plpythonu $x$ plpy.notice('inside DO') $x$"
-PL/Python function "notice_innerfunc"
-SQL statement "SELECT notice_innerfunc()"
-PL/Python function "notice_outerfunc"
- notice_outerfunc
-------------------
- 1
-(1 row)
-
CREATE TABLE subtransaction_tbl (
i integer
);
--- Explicit case for Python <2.6
-CREATE FUNCTION subtransaction_test(what_error text = NULL) RETURNS text
-AS $$
-import sys
-subxact = plpy.subtransaction()
-subxact.__enter__()
-exc = True
-try:
- try:
- plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
- plpy.execute("INSERT INTO subtransaction_tbl VALUES (2)")
- if what_error == "SPI":
- plpy.execute("INSERT INTO subtransaction_tbl VALUES ('oops')")
- elif what_error == "Python":
- raise Exception("Python exception")
- except:
- exc = False
- subxact.__exit__(*sys.exc_info())
- raise
-finally:
- if exc:
- subxact.__exit__(None, None, None)
-$$ LANGUAGE plpythonu;
-SELECT subtransaction_test();
- subtransaction_test
----------------------
-
-(1 row)
-
-SELECT * FROM subtransaction_tbl;
- i
----
- 1
- 2
-(2 rows)
-
-TRUNCATE subtransaction_tbl;
-SELECT subtransaction_test('SPI');
-ERROR: spiexceptions.InvalidTextRepresentation: invalid input syntax for type integer: "oops"
-LINE 1: INSERT INTO subtransaction_tbl VALUES ('oops')
- ^
-QUERY: INSERT INTO subtransaction_tbl VALUES ('oops')
-CONTEXT: Traceback (most recent call last):
- PL/Python function "subtransaction_test", line 11, in <module>
- plpy.execute("INSERT INTO subtransaction_tbl VALUES ('oops')")
-PL/Python function "subtransaction_test"
-SELECT * FROM subtransaction_tbl;
- i
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
-SELECT subtransaction_test('Python');
-ERROR: Exception: Python exception
-CONTEXT: Traceback (most recent call last):
- PL/Python function "subtransaction_test", line 13, in <module>
- raise Exception("Python exception")
-PL/Python function "subtransaction_test"
-SELECT * FROM subtransaction_tbl;
- i
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
--- Context manager case for Python >=2.6
CREATE FUNCTION subtransaction_ctx_test(what_error text = NULL) RETURNS text
AS $$
with plpy.subtransaction():
+++ /dev/null
---
--- Test explicit subtransactions
---
--- Test table to see if transactions get properly rolled back
-CREATE TABLE subtransaction_tbl (
- i integer
-);
--- Explicit case for Python <2.6
-CREATE FUNCTION subtransaction_test(what_error text = NULL) RETURNS text
-AS $$
-import sys
-subxact = plpy.subtransaction()
-subxact.__enter__()
-exc = True
-try:
- try:
- plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
- plpy.execute("INSERT INTO subtransaction_tbl VALUES (2)")
- if what_error == "SPI":
- plpy.execute("INSERT INTO subtransaction_tbl VALUES ('oops')")
- elif what_error == "Python":
- raise Exception("Python exception")
- except:
- exc = False
- subxact.__exit__(*sys.exc_info())
- raise
-finally:
- if exc:
- subxact.__exit__(None, None, None)
-$$ LANGUAGE plpythonu;
-SELECT subtransaction_test();
- subtransaction_test
----------------------
-
-(1 row)
-
-SELECT * FROM subtransaction_tbl;
- i
----
- 1
- 2
-(2 rows)
-
-TRUNCATE subtransaction_tbl;
-SELECT subtransaction_test('SPI');
-ERROR: spiexceptions.InvalidTextRepresentation: invalid input syntax for type integer: "oops"
-LINE 1: INSERT INTO subtransaction_tbl VALUES ('oops')
- ^
-QUERY: INSERT INTO subtransaction_tbl VALUES ('oops')
-CONTEXT: Traceback (most recent call last):
- PL/Python function "subtransaction_test", line 11, in <module>
- plpy.execute("INSERT INTO subtransaction_tbl VALUES ('oops')")
-PL/Python function "subtransaction_test"
-SELECT * FROM subtransaction_tbl;
- i
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
-SELECT subtransaction_test('Python');
-ERROR: Exception: Python exception
-CONTEXT: Traceback (most recent call last):
- PL/Python function "subtransaction_test", line 13, in <module>
- raise Exception("Python exception")
-PL/Python function "subtransaction_test"
-SELECT * FROM subtransaction_tbl;
- i
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
--- Context manager case for Python >=2.6
-CREATE FUNCTION subtransaction_ctx_test(what_error text = NULL) RETURNS text
-AS $$
-with plpy.subtransaction():
- plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
- plpy.execute("INSERT INTO subtransaction_tbl VALUES (2)")
- if what_error == "SPI":
- plpy.execute("INSERT INTO subtransaction_tbl VALUES ('oops')")
- elif what_error == "Python":
- raise Exception("Python exception")
-$$ LANGUAGE plpythonu;
-ERROR: could not compile PL/Python function "subtransaction_ctx_test"
-DETAIL: SyntaxError: invalid syntax (line 3)
-SELECT subtransaction_ctx_test();
-ERROR: function subtransaction_ctx_test() does not exist
-LINE 1: SELECT subtransaction_ctx_test();
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
-SELECT subtransaction_ctx_test('SPI');
-ERROR: function subtransaction_ctx_test(unknown) does not exist
-LINE 1: SELECT subtransaction_ctx_test('SPI');
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
-SELECT subtransaction_ctx_test('Python');
-ERROR: function subtransaction_ctx_test(unknown) does not exist
-LINE 1: SELECT subtransaction_ctx_test('Python');
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
--- Nested subtransactions
-CREATE FUNCTION subtransaction_nested_test(swallow boolean = 'f') RETURNS text
-AS $$
-plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
-with plpy.subtransaction():
- plpy.execute("INSERT INTO subtransaction_tbl VALUES (2)")
- try:
- with plpy.subtransaction():
- plpy.execute("INSERT INTO subtransaction_tbl VALUES (3)")
- plpy.execute("error")
- except plpy.SPIError, e:
- if not swallow:
- raise
- plpy.notice("Swallowed %s(%r)" % (e.__class__.__name__, e.args[0]))
-return "ok"
-$$ LANGUAGE plpythonu;
-ERROR: could not compile PL/Python function "subtransaction_nested_test"
-DETAIL: SyntaxError: invalid syntax (line 4)
-SELECT subtransaction_nested_test();
-ERROR: function subtransaction_nested_test() does not exist
-LINE 1: SELECT subtransaction_nested_test();
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
-SELECT subtransaction_nested_test('t');
-ERROR: function subtransaction_nested_test(unknown) does not exist
-LINE 1: SELECT subtransaction_nested_test('t');
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
--- Nested subtransactions that recursively call code dealing with
--- subtransactions
-CREATE FUNCTION subtransaction_deeply_nested_test() RETURNS text
-AS $$
-plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
-with plpy.subtransaction():
- plpy.execute("INSERT INTO subtransaction_tbl VALUES (2)")
- plpy.execute("SELECT subtransaction_nested_test('t')")
-return "ok"
-$$ LANGUAGE plpythonu;
-ERROR: could not compile PL/Python function "subtransaction_deeply_nested_test"
-DETAIL: SyntaxError: invalid syntax (line 4)
-SELECT subtransaction_deeply_nested_test();
-ERROR: function subtransaction_deeply_nested_test() does not exist
-LINE 1: SELECT subtransaction_deeply_nested_test();
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
--- Error conditions from not opening/closing subtransactions
-CREATE FUNCTION subtransaction_exit_without_enter() RETURNS void
-AS $$
-plpy.subtransaction().__exit__(None, None, None)
-$$ LANGUAGE plpythonu;
-CREATE FUNCTION subtransaction_enter_without_exit() RETURNS void
-AS $$
-plpy.subtransaction().__enter__()
-$$ LANGUAGE plpythonu;
-CREATE FUNCTION subtransaction_exit_twice() RETURNS void
-AS $$
-plpy.subtransaction().__enter__()
-plpy.subtransaction().__exit__(None, None, None)
-plpy.subtransaction().__exit__(None, None, None)
-$$ LANGUAGE plpythonu;
-CREATE FUNCTION subtransaction_enter_twice() RETURNS void
-AS $$
-plpy.subtransaction().__enter__()
-plpy.subtransaction().__enter__()
-$$ LANGUAGE plpythonu;
-CREATE FUNCTION subtransaction_exit_same_subtransaction_twice() RETURNS void
-AS $$
-s = plpy.subtransaction()
-s.__enter__()
-s.__exit__(None, None, None)
-s.__exit__(None, None, None)
-$$ LANGUAGE plpythonu;
-CREATE FUNCTION subtransaction_enter_same_subtransaction_twice() RETURNS void
-AS $$
-s = plpy.subtransaction()
-s.__enter__()
-s.__enter__()
-s.__exit__(None, None, None)
-$$ LANGUAGE plpythonu;
--- No warnings here, as the subtransaction gets indeed closed
-CREATE FUNCTION subtransaction_enter_subtransaction_in_with() RETURNS void
-AS $$
-with plpy.subtransaction() as s:
- s.__enter__()
-$$ LANGUAGE plpythonu;
-ERROR: could not compile PL/Python function "subtransaction_enter_subtransaction_in_with"
-DETAIL: SyntaxError: invalid syntax (line 3)
-CREATE FUNCTION subtransaction_exit_subtransaction_in_with() RETURNS void
-AS $$
-with plpy.subtransaction() as s:
- s.__exit__(None, None, None)
-$$ LANGUAGE plpythonu;
-ERROR: could not compile PL/Python function "subtransaction_exit_subtransaction_in_with"
-DETAIL: SyntaxError: invalid syntax (line 3)
-SELECT subtransaction_exit_without_enter();
-ERROR: ValueError: this subtransaction has not been entered
-CONTEXT: Traceback (most recent call last):
- PL/Python function "subtransaction_exit_without_enter", line 2, in <module>
- plpy.subtransaction().__exit__(None, None, None)
-PL/Python function "subtransaction_exit_without_enter"
-SELECT subtransaction_enter_without_exit();
-WARNING: forcibly aborting a subtransaction that has not been exited
- subtransaction_enter_without_exit
------------------------------------
-
-(1 row)
-
-SELECT subtransaction_exit_twice();
-WARNING: forcibly aborting a subtransaction that has not been exited
-ERROR: ValueError: this subtransaction has not been entered
-CONTEXT: Traceback (most recent call last):
- PL/Python function "subtransaction_exit_twice", line 3, in <module>
- plpy.subtransaction().__exit__(None, None, None)
-PL/Python function "subtransaction_exit_twice"
-SELECT subtransaction_enter_twice();
-WARNING: forcibly aborting a subtransaction that has not been exited
-WARNING: forcibly aborting a subtransaction that has not been exited
- subtransaction_enter_twice
-----------------------------
-
-(1 row)
-
-SELECT subtransaction_exit_same_subtransaction_twice();
-ERROR: ValueError: this subtransaction has already been exited
-CONTEXT: Traceback (most recent call last):
- PL/Python function "subtransaction_exit_same_subtransaction_twice", line 5, in <module>
- s.__exit__(None, None, None)
-PL/Python function "subtransaction_exit_same_subtransaction_twice"
-SELECT subtransaction_enter_same_subtransaction_twice();
-WARNING: forcibly aborting a subtransaction that has not been exited
-ERROR: ValueError: this subtransaction has already been entered
-CONTEXT: Traceback (most recent call last):
- PL/Python function "subtransaction_enter_same_subtransaction_twice", line 4, in <module>
- s.__enter__()
-PL/Python function "subtransaction_enter_same_subtransaction_twice"
-SELECT subtransaction_enter_subtransaction_in_with();
-ERROR: function subtransaction_enter_subtransaction_in_with() does not exist
-LINE 1: SELECT subtransaction_enter_subtransaction_in_with();
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
-SELECT subtransaction_exit_subtransaction_in_with();
-ERROR: function subtransaction_exit_subtransaction_in_with() does not exist
-LINE 1: SELECT subtransaction_exit_subtransaction_in_with();
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
--- Make sure we don't get a "current transaction is aborted" error
-SELECT 1 as test;
- test
-------
- 1
-(1 row)
-
--- Mix explicit subtransactions and normal SPI calls
-CREATE FUNCTION subtransaction_mix_explicit_and_implicit() RETURNS void
-AS $$
-p = plpy.prepare("INSERT INTO subtransaction_tbl VALUES ($1)", ["integer"])
-try:
- with plpy.subtransaction():
- plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
- plpy.execute(p, [2])
- plpy.execute(p, ["wrong"])
-except plpy.SPIError:
- plpy.warning("Caught a SPI error from an explicit subtransaction")
-
-try:
- plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
- plpy.execute(p, [2])
- plpy.execute(p, ["wrong"])
-except plpy.SPIError:
- plpy.warning("Caught a SPI error")
-$$ LANGUAGE plpythonu;
-ERROR: could not compile PL/Python function "subtransaction_mix_explicit_and_implicit"
-DETAIL: SyntaxError: invalid syntax (line 5)
-SELECT subtransaction_mix_explicit_and_implicit();
-ERROR: function subtransaction_mix_explicit_and_implicit() does not exist
-LINE 1: SELECT subtransaction_mix_explicit_and_implicit();
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
--- Alternative method names for Python <2.6
-CREATE FUNCTION subtransaction_alternative_names() RETURNS void
-AS $$
-s = plpy.subtransaction()
-s.enter()
-s.exit(None, None, None)
-$$ LANGUAGE plpythonu;
-SELECT subtransaction_alternative_names();
- subtransaction_alternative_names
-----------------------------------
-
-(1 row)
-
--- try/catch inside a subtransaction block
-CREATE FUNCTION try_catch_inside_subtransaction() RETURNS void
-AS $$
-with plpy.subtransaction():
- plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
- try:
- plpy.execute("INSERT INTO subtransaction_tbl VALUES ('a')")
- except plpy.SPIError:
- plpy.notice("caught")
-$$ LANGUAGE plpythonu;
-ERROR: could not compile PL/Python function "try_catch_inside_subtransaction"
-DETAIL: SyntaxError: invalid syntax (line 3)
-SELECT try_catch_inside_subtransaction();
-ERROR: function try_catch_inside_subtransaction() does not exist
-LINE 1: SELECT try_catch_inside_subtransaction();
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
-ALTER TABLE subtransaction_tbl ADD PRIMARY KEY (i);
-CREATE FUNCTION pk_violation_inside_subtransaction() RETURNS void
-AS $$
-with plpy.subtransaction():
- plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
- try:
- plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
- except plpy.SPIError:
- plpy.notice("caught")
-$$ LANGUAGE plpythonu;
-ERROR: could not compile PL/Python function "pk_violation_inside_subtransaction"
-DETAIL: SyntaxError: invalid syntax (line 3)
-SELECT pk_violation_inside_subtransaction();
-ERROR: function pk_violation_inside_subtransaction() does not exist
-LINE 1: SELECT pk_violation_inside_subtransaction();
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i
----
-(0 rows)
-
-DROP TABLE subtransaction_tbl;
--- cursor/subtransactions interactions
-CREATE FUNCTION cursor_in_subxact() RETURNS int AS $$
-with plpy.subtransaction():
- cur = plpy.cursor("select * from generate_series(1, 20) as gen(i)")
- cur.fetch(10)
-fetched = cur.fetch(10);
-return int(fetched[5]["i"])
-$$ LANGUAGE plpythonu;
-ERROR: could not compile PL/Python function "cursor_in_subxact"
-DETAIL: SyntaxError: invalid syntax (line 3)
-CREATE FUNCTION cursor_aborted_subxact() RETURNS int AS $$
-try:
- with plpy.subtransaction():
- cur = plpy.cursor("select * from generate_series(1, 20) as gen(i)")
- cur.fetch(10);
- plpy.execute("select no_such_function()")
-except plpy.SPIError:
- fetched = cur.fetch(10)
- return int(fetched[5]["i"])
-return 0 # not reached
-$$ LANGUAGE plpythonu;
-ERROR: could not compile PL/Python function "cursor_aborted_subxact"
-DETAIL: SyntaxError: invalid syntax (line 4)
-CREATE FUNCTION cursor_plan_aborted_subxact() RETURNS int AS $$
-try:
- with plpy.subtransaction():
- plpy.execute('create temporary table tmp(i) '
- 'as select generate_series(1, 10)')
- plan = plpy.prepare("select i from tmp")
- cur = plpy.cursor(plan)
- plpy.execute("select no_such_function()")
-except plpy.SPIError:
- fetched = cur.fetch(5)
- return fetched[2]["i"]
-return 0 # not reached
-$$ LANGUAGE plpythonu;
-ERROR: could not compile PL/Python function "cursor_plan_aborted_subxact"
-DETAIL: SyntaxError: invalid syntax (line 4)
-CREATE FUNCTION cursor_close_aborted_subxact() RETURNS boolean AS $$
-try:
- with plpy.subtransaction():
- cur = plpy.cursor('select 1')
- plpy.execute("select no_such_function()")
-except plpy.SPIError:
- cur.close()
- return True
-return False # not reached
-$$ LANGUAGE plpythonu;
-ERROR: could not compile PL/Python function "cursor_close_aborted_subxact"
-DETAIL: SyntaxError: invalid syntax (line 4)
-SELECT cursor_in_subxact();
-ERROR: function cursor_in_subxact() does not exist
-LINE 1: SELECT cursor_in_subxact();
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
-SELECT cursor_aborted_subxact();
-ERROR: function cursor_aborted_subxact() does not exist
-LINE 1: SELECT cursor_aborted_subxact();
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
-SELECT cursor_plan_aborted_subxact();
-ERROR: function cursor_plan_aborted_subxact() does not exist
-LINE 1: SELECT cursor_plan_aborted_subxact();
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
-SELECT cursor_close_aborted_subxact();
-ERROR: function cursor_close_aborted_subxact() does not exist
-LINE 1: SELECT cursor_close_aborted_subxact();
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
+++ /dev/null
---
--- Test explicit subtransactions
---
--- Test table to see if transactions get properly rolled back
-CREATE TABLE subtransaction_tbl (
- i integer
-);
--- Explicit case for Python <2.6
-CREATE FUNCTION subtransaction_test(what_error text = NULL) RETURNS text
-AS $$
-import sys
-subxact = plpy.subtransaction()
-subxact.__enter__()
-exc = True
-try:
- try:
- plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
- plpy.execute("INSERT INTO subtransaction_tbl VALUES (2)")
- if what_error == "SPI":
- plpy.execute("INSERT INTO subtransaction_tbl VALUES ('oops')")
- elif what_error == "Python":
- raise Exception("Python exception")
- except:
- exc = False
- subxact.__exit__(*sys.exc_info())
- raise
-finally:
- if exc:
- subxact.__exit__(None, None, None)
-$$ LANGUAGE plpythonu;
-SELECT subtransaction_test();
- subtransaction_test
----------------------
-
-(1 row)
-
-SELECT * FROM subtransaction_tbl;
- i
----
- 1
- 2
-(2 rows)
-
-TRUNCATE subtransaction_tbl;
-SELECT subtransaction_test('SPI');
-ERROR: spiexceptions.InvalidTextRepresentation: invalid input syntax for type integer: "oops"
-LINE 1: INSERT INTO subtransaction_tbl VALUES ('oops')
- ^
-QUERY: INSERT INTO subtransaction_tbl VALUES ('oops')
-CONTEXT: Traceback (most recent call last):
- PL/Python function "subtransaction_test", line 11, in <module>
- plpy.execute("INSERT INTO subtransaction_tbl VALUES ('oops')")
-PL/Python function "subtransaction_test"
-SELECT * FROM subtransaction_tbl;
- i
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
-SELECT subtransaction_test('Python');
-ERROR: Exception: Python exception
-CONTEXT: Traceback (most recent call last):
- PL/Python function "subtransaction_test", line 13, in <module>
- raise Exception("Python exception")
-PL/Python function "subtransaction_test"
-SELECT * FROM subtransaction_tbl;
- i
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
--- Context manager case for Python >=2.6
-CREATE FUNCTION subtransaction_ctx_test(what_error text = NULL) RETURNS text
-AS $$
-with plpy.subtransaction():
- plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
- plpy.execute("INSERT INTO subtransaction_tbl VALUES (2)")
- if what_error == "SPI":
- plpy.execute("INSERT INTO subtransaction_tbl VALUES ('oops')")
- elif what_error == "Python":
- raise Exception("Python exception")
-$$ LANGUAGE plpythonu;
-ERROR: could not compile PL/Python function "subtransaction_ctx_test"
-DETAIL: SyntaxError: invalid syntax (<string>, line 3)
-SELECT subtransaction_ctx_test();
-ERROR: function subtransaction_ctx_test() does not exist
-LINE 1: SELECT subtransaction_ctx_test();
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
-SELECT subtransaction_ctx_test('SPI');
-ERROR: function subtransaction_ctx_test(unknown) does not exist
-LINE 1: SELECT subtransaction_ctx_test('SPI');
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
-SELECT subtransaction_ctx_test('Python');
-ERROR: function subtransaction_ctx_test(unknown) does not exist
-LINE 1: SELECT subtransaction_ctx_test('Python');
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
--- Nested subtransactions
-CREATE FUNCTION subtransaction_nested_test(swallow boolean = 'f') RETURNS text
-AS $$
-plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
-with plpy.subtransaction():
- plpy.execute("INSERT INTO subtransaction_tbl VALUES (2)")
- try:
- with plpy.subtransaction():
- plpy.execute("INSERT INTO subtransaction_tbl VALUES (3)")
- plpy.execute("error")
- except plpy.SPIError, e:
- if not swallow:
- raise
- plpy.notice("Swallowed %s(%r)" % (e.__class__.__name__, e.args[0]))
-return "ok"
-$$ LANGUAGE plpythonu;
-ERROR: could not compile PL/Python function "subtransaction_nested_test"
-DETAIL: SyntaxError: invalid syntax (<string>, line 4)
-SELECT subtransaction_nested_test();
-ERROR: function subtransaction_nested_test() does not exist
-LINE 1: SELECT subtransaction_nested_test();
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
-SELECT subtransaction_nested_test('t');
-ERROR: function subtransaction_nested_test(unknown) does not exist
-LINE 1: SELECT subtransaction_nested_test('t');
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
--- Nested subtransactions that recursively call code dealing with
--- subtransactions
-CREATE FUNCTION subtransaction_deeply_nested_test() RETURNS text
-AS $$
-plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
-with plpy.subtransaction():
- plpy.execute("INSERT INTO subtransaction_tbl VALUES (2)")
- plpy.execute("SELECT subtransaction_nested_test('t')")
-return "ok"
-$$ LANGUAGE plpythonu;
-ERROR: could not compile PL/Python function "subtransaction_deeply_nested_test"
-DETAIL: SyntaxError: invalid syntax (<string>, line 4)
-SELECT subtransaction_deeply_nested_test();
-ERROR: function subtransaction_deeply_nested_test() does not exist
-LINE 1: SELECT subtransaction_deeply_nested_test();
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
--- Error conditions from not opening/closing subtransactions
-CREATE FUNCTION subtransaction_exit_without_enter() RETURNS void
-AS $$
-plpy.subtransaction().__exit__(None, None, None)
-$$ LANGUAGE plpythonu;
-CREATE FUNCTION subtransaction_enter_without_exit() RETURNS void
-AS $$
-plpy.subtransaction().__enter__()
-$$ LANGUAGE plpythonu;
-CREATE FUNCTION subtransaction_exit_twice() RETURNS void
-AS $$
-plpy.subtransaction().__enter__()
-plpy.subtransaction().__exit__(None, None, None)
-plpy.subtransaction().__exit__(None, None, None)
-$$ LANGUAGE plpythonu;
-CREATE FUNCTION subtransaction_enter_twice() RETURNS void
-AS $$
-plpy.subtransaction().__enter__()
-plpy.subtransaction().__enter__()
-$$ LANGUAGE plpythonu;
-CREATE FUNCTION subtransaction_exit_same_subtransaction_twice() RETURNS void
-AS $$
-s = plpy.subtransaction()
-s.__enter__()
-s.__exit__(None, None, None)
-s.__exit__(None, None, None)
-$$ LANGUAGE plpythonu;
-CREATE FUNCTION subtransaction_enter_same_subtransaction_twice() RETURNS void
-AS $$
-s = plpy.subtransaction()
-s.__enter__()
-s.__enter__()
-s.__exit__(None, None, None)
-$$ LANGUAGE plpythonu;
--- No warnings here, as the subtransaction gets indeed closed
-CREATE FUNCTION subtransaction_enter_subtransaction_in_with() RETURNS void
-AS $$
-with plpy.subtransaction() as s:
- s.__enter__()
-$$ LANGUAGE plpythonu;
-ERROR: could not compile PL/Python function "subtransaction_enter_subtransaction_in_with"
-DETAIL: SyntaxError: invalid syntax (<string>, line 3)
-CREATE FUNCTION subtransaction_exit_subtransaction_in_with() RETURNS void
-AS $$
-with plpy.subtransaction() as s:
- s.__exit__(None, None, None)
-$$ LANGUAGE plpythonu;
-ERROR: could not compile PL/Python function "subtransaction_exit_subtransaction_in_with"
-DETAIL: SyntaxError: invalid syntax (<string>, line 3)
-SELECT subtransaction_exit_without_enter();
-ERROR: ValueError: this subtransaction has not been entered
-CONTEXT: Traceback (most recent call last):
- PL/Python function "subtransaction_exit_without_enter", line 2, in <module>
- plpy.subtransaction().__exit__(None, None, None)
-PL/Python function "subtransaction_exit_without_enter"
-SELECT subtransaction_enter_without_exit();
-WARNING: forcibly aborting a subtransaction that has not been exited
- subtransaction_enter_without_exit
------------------------------------
-
-(1 row)
-
-SELECT subtransaction_exit_twice();
-WARNING: forcibly aborting a subtransaction that has not been exited
-ERROR: ValueError: this subtransaction has not been entered
-CONTEXT: Traceback (most recent call last):
- PL/Python function "subtransaction_exit_twice", line 3, in <module>
- plpy.subtransaction().__exit__(None, None, None)
-PL/Python function "subtransaction_exit_twice"
-SELECT subtransaction_enter_twice();
-WARNING: forcibly aborting a subtransaction that has not been exited
-WARNING: forcibly aborting a subtransaction that has not been exited
- subtransaction_enter_twice
-----------------------------
-
-(1 row)
-
-SELECT subtransaction_exit_same_subtransaction_twice();
-ERROR: ValueError: this subtransaction has already been exited
-CONTEXT: Traceback (most recent call last):
- PL/Python function "subtransaction_exit_same_subtransaction_twice", line 5, in <module>
- s.__exit__(None, None, None)
-PL/Python function "subtransaction_exit_same_subtransaction_twice"
-SELECT subtransaction_enter_same_subtransaction_twice();
-WARNING: forcibly aborting a subtransaction that has not been exited
-ERROR: ValueError: this subtransaction has already been entered
-CONTEXT: Traceback (most recent call last):
- PL/Python function "subtransaction_enter_same_subtransaction_twice", line 4, in <module>
- s.__enter__()
-PL/Python function "subtransaction_enter_same_subtransaction_twice"
-SELECT subtransaction_enter_subtransaction_in_with();
-ERROR: function subtransaction_enter_subtransaction_in_with() does not exist
-LINE 1: SELECT subtransaction_enter_subtransaction_in_with();
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
-SELECT subtransaction_exit_subtransaction_in_with();
-ERROR: function subtransaction_exit_subtransaction_in_with() does not exist
-LINE 1: SELECT subtransaction_exit_subtransaction_in_with();
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
--- Make sure we don't get a "current transaction is aborted" error
-SELECT 1 as test;
- test
-------
- 1
-(1 row)
-
--- Mix explicit subtransactions and normal SPI calls
-CREATE FUNCTION subtransaction_mix_explicit_and_implicit() RETURNS void
-AS $$
-p = plpy.prepare("INSERT INTO subtransaction_tbl VALUES ($1)", ["integer"])
-try:
- with plpy.subtransaction():
- plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
- plpy.execute(p, [2])
- plpy.execute(p, ["wrong"])
-except plpy.SPIError:
- plpy.warning("Caught a SPI error from an explicit subtransaction")
-
-try:
- plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
- plpy.execute(p, [2])
- plpy.execute(p, ["wrong"])
-except plpy.SPIError:
- plpy.warning("Caught a SPI error")
-$$ LANGUAGE plpythonu;
-ERROR: could not compile PL/Python function "subtransaction_mix_explicit_and_implicit"
-DETAIL: SyntaxError: invalid syntax (<string>, line 5)
-SELECT subtransaction_mix_explicit_and_implicit();
-ERROR: function subtransaction_mix_explicit_and_implicit() does not exist
-LINE 1: SELECT subtransaction_mix_explicit_and_implicit();
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
--- Alternative method names for Python <2.6
-CREATE FUNCTION subtransaction_alternative_names() RETURNS void
-AS $$
-s = plpy.subtransaction()
-s.enter()
-s.exit(None, None, None)
-$$ LANGUAGE plpythonu;
-SELECT subtransaction_alternative_names();
- subtransaction_alternative_names
-----------------------------------
-
-(1 row)
-
--- try/catch inside a subtransaction block
-CREATE FUNCTION try_catch_inside_subtransaction() RETURNS void
-AS $$
-with plpy.subtransaction():
- plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
- try:
- plpy.execute("INSERT INTO subtransaction_tbl VALUES ('a')")
- except plpy.SPIError:
- plpy.notice("caught")
-$$ LANGUAGE plpythonu;
-ERROR: could not compile PL/Python function "try_catch_inside_subtransaction"
-DETAIL: SyntaxError: invalid syntax (<string>, line 3)
-SELECT try_catch_inside_subtransaction();
-ERROR: function try_catch_inside_subtransaction() does not exist
-LINE 1: SELECT try_catch_inside_subtransaction();
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i
----
-(0 rows)
-
-TRUNCATE subtransaction_tbl;
-ALTER TABLE subtransaction_tbl ADD PRIMARY KEY (i);
-CREATE FUNCTION pk_violation_inside_subtransaction() RETURNS void
-AS $$
-with plpy.subtransaction():
- plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
- try:
- plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
- except plpy.SPIError:
- plpy.notice("caught")
-$$ LANGUAGE plpythonu;
-ERROR: could not compile PL/Python function "pk_violation_inside_subtransaction"
-DETAIL: SyntaxError: invalid syntax (<string>, line 3)
-SELECT pk_violation_inside_subtransaction();
-ERROR: function pk_violation_inside_subtransaction() does not exist
-LINE 1: SELECT pk_violation_inside_subtransaction();
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
-SELECT * FROM subtransaction_tbl;
- i
----
-(0 rows)
-
-DROP TABLE subtransaction_tbl;
--- cursor/subtransactions interactions
-CREATE FUNCTION cursor_in_subxact() RETURNS int AS $$
-with plpy.subtransaction():
- cur = plpy.cursor("select * from generate_series(1, 20) as gen(i)")
- cur.fetch(10)
-fetched = cur.fetch(10);
-return int(fetched[5]["i"])
-$$ LANGUAGE plpythonu;
-ERROR: could not compile PL/Python function "cursor_in_subxact"
-DETAIL: SyntaxError: invalid syntax (<string>, line 3)
-CREATE FUNCTION cursor_aborted_subxact() RETURNS int AS $$
-try:
- with plpy.subtransaction():
- cur = plpy.cursor("select * from generate_series(1, 20) as gen(i)")
- cur.fetch(10);
- plpy.execute("select no_such_function()")
-except plpy.SPIError:
- fetched = cur.fetch(10)
- return int(fetched[5]["i"])
-return 0 # not reached
-$$ LANGUAGE plpythonu;
-ERROR: could not compile PL/Python function "cursor_aborted_subxact"
-DETAIL: SyntaxError: invalid syntax (<string>, line 4)
-CREATE FUNCTION cursor_plan_aborted_subxact() RETURNS int AS $$
-try:
- with plpy.subtransaction():
- plpy.execute('create temporary table tmp(i) '
- 'as select generate_series(1, 10)')
- plan = plpy.prepare("select i from tmp")
- cur = plpy.cursor(plan)
- plpy.execute("select no_such_function()")
-except plpy.SPIError:
- fetched = cur.fetch(5)
- return fetched[2]["i"]
-return 0 # not reached
-$$ LANGUAGE plpythonu;
-ERROR: could not compile PL/Python function "cursor_plan_aborted_subxact"
-DETAIL: SyntaxError: invalid syntax (<string>, line 4)
-CREATE FUNCTION cursor_close_aborted_subxact() RETURNS boolean AS $$
-try:
- with plpy.subtransaction():
- cur = plpy.cursor('select 1')
- plpy.execute("select no_such_function()")
-except plpy.SPIError:
- cur.close()
- return True
-return False # not reached
-$$ LANGUAGE plpythonu;
-ERROR: could not compile PL/Python function "cursor_close_aborted_subxact"
-DETAIL: SyntaxError: invalid syntax (<string>, line 4)
-SELECT cursor_in_subxact();
-ERROR: function cursor_in_subxact() does not exist
-LINE 1: SELECT cursor_in_subxact();
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
-SELECT cursor_aborted_subxact();
-ERROR: function cursor_aborted_subxact() does not exist
-LINE 1: SELECT cursor_aborted_subxact();
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
-SELECT cursor_plan_aborted_subxact();
-ERROR: function cursor_plan_aborted_subxact() does not exist
-LINE 1: SELECT cursor_plan_aborted_subxact();
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
-SELECT cursor_close_aborted_subxact();
-ERROR: function cursor_close_aborted_subxact() does not exist
-LINE 1: SELECT cursor_close_aborted_subxact();
- ^
-HINT: No function matches the given name and argument types. You might need to add explicit type casts.
PG_TRY();
{
- /*
- * Ancient versions of Python (circa 2.3) contain a bug whereby
- * the fetches below can fail if the error indicator is set.
- */
- PyErr_Clear();
-
lineno = PyObject_GetAttrString(tb, "tb_lineno");
if (lineno == NULL)
elog(ERROR, "could not get line number from Python traceback");
#include <Python.h>
#endif
-/*
- * Py_ssize_t compat for Python <= 2.4
- */
-#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
-typedef int Py_ssize_t;
-
-#define PY_SSIZE_T_MAX INT_MAX
-#define PY_SSIZE_T_MIN INT_MIN
-#endif
-
/*
* Python 2/3 strings/unicode/bytes handling. Python 2 has strings
* and unicode, Python 3 has strings, which are unicode on the C
* string to a Python string it converts the C string from the
* PostgreSQL server encoding to a Python Unicode object.
*/
-
-#if PY_VERSION_HEX < 0x02060000
-/* This is exactly the compatibility layer that Python 2.6 uses. */
-#define PyBytes_AsString PyString_AsString
-#define PyBytes_FromStringAndSize PyString_FromStringAndSize
-#define PyBytes_Size PyString_Size
-#define PyObject_Bytes PyObject_Str
-#endif
-
#if PY_MAJOR_VERSION >= 3
#define PyString_Check(x) 0
#define PyString_AsString(x) PLyUnicode_AsString(x)
#define PyInt_AsLong(x) PyLong_AsLong(x)
#endif
-/*
- * PyVarObject_HEAD_INIT was added in Python 2.6. Its use is
- * necessary to handle both Python 2 and 3. This replacement
- * definition is for Python <=2.5
- */
-#ifndef PyVarObject_HEAD_INIT
-#define PyVarObject_HEAD_INIT(type, size) \
- PyObject_HEAD_INIT(type) size,
-#endif
-
/* Python 3 removed the Py_TPFLAGS_HAVE_ITER flag */
#if PY_MAJOR_VERSION >= 3
#define Py_TPFLAGS_HAVE_ITER 0
i integer
);
--- Explicit case for Python <2.6
-
-CREATE FUNCTION subtransaction_test(what_error text = NULL) RETURNS text
-AS $$
-import sys
-subxact = plpy.subtransaction()
-subxact.__enter__()
-exc = True
-try:
- try:
- plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
- plpy.execute("INSERT INTO subtransaction_tbl VALUES (2)")
- if what_error == "SPI":
- plpy.execute("INSERT INTO subtransaction_tbl VALUES ('oops')")
- elif what_error == "Python":
- raise Exception("Python exception")
- except:
- exc = False
- subxact.__exit__(*sys.exc_info())
- raise
-finally:
- if exc:
- subxact.__exit__(None, None, None)
-$$ LANGUAGE plpythonu;
-
-SELECT subtransaction_test();
-SELECT * FROM subtransaction_tbl;
-TRUNCATE subtransaction_tbl;
-SELECT subtransaction_test('SPI');
-SELECT * FROM subtransaction_tbl;
-TRUNCATE subtransaction_tbl;
-SELECT subtransaction_test('Python');
-SELECT * FROM subtransaction_tbl;
-TRUNCATE subtransaction_tbl;
-
--- Context manager case for Python >=2.6
-
CREATE FUNCTION subtransaction_ctx_test(what_error text = NULL) RETURNS text
AS $$
with plpy.subtransaction():