From 2ab6474ac961bc4b061062ab9121d89735c12657 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Mon, 9 Dec 2019 11:14:02 +0100 Subject: [PATCH 1/2] Remove support for Python older than 2.6 --- config/python.m4 | 4 +- configure | 4 +- doc/src/sgml/installation.sgml | 2 +- doc/src/sgml/plpython.sgml | 16 +- src/pl/plpython/expected/README | 4 - src/pl/plpython/expected/plpython_error_0.out | 447 ----------------- .../expected/plpython_subtransaction.out | 65 --- .../expected/plpython_subtransaction_0.out | 448 ------------------ .../expected/plpython_subtransaction_5.out | 448 ------------------ src/pl/plpython/plpy_elog.c | 6 - src/pl/plpython/plpython.h | 29 -- .../plpython/sql/plpython_subtransaction.sql | 37 -- 12 files changed, 7 insertions(+), 1503 deletions(-) delete mode 100644 src/pl/plpython/expected/plpython_error_0.out delete mode 100644 src/pl/plpython/expected/plpython_subtransaction_0.out delete mode 100644 src/pl/plpython/expected/plpython_subtransaction_5.out diff --git a/config/python.m4 b/config/python.m4 index c51aa4e332..d41aeb2876 100644 --- a/config/python.m4 +++ b/config/python.m4 @@ -37,8 +37,8 @@ python_majorversion=`echo "$python_fullversion" | sed '[s/^\([0-9]*\).*/\1/]'` 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]) diff --git a/configure b/configure index 3d9bd0bdf8..da62d23552 100755 --- a/configure +++ b/configure @@ -9614,8 +9614,8 @@ python_majorversion=`echo "$python_fullversion" | sed 's/^\([0-9]*\).*/\1/'` 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 diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml index 9c10a897f1..bcbcea2162 100644 --- a/doc/src/sgml/installation.sgml +++ b/doc/src/sgml/installation.sgml @@ -196,7 +196,7 @@ Requirements language, you need a Python installation with the header files and the distutils module. The minimum - required version is Python 2.4. + required version is Python 2.6. Python 3 is supported if it's version 3.1 or later; but see diff --git a/doc/src/sgml/plpython.sgml b/doc/src/sgml/plpython.sgml index 4c2f7e85fd..31a0dd3e40 100644 --- a/doc/src/sgml/plpython.sgml +++ b/doc/src/sgml/plpython.sgml @@ -1335,9 +1335,8 @@ Older Python Versions Context managers syntax using the with 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 __enter__ and __exit__ functions using the enter and exit convenience @@ -1367,17 +1366,6 @@ Older Python Versions $$ LANGUAGE plpythonu; - - - - Although context managers were implemented in Python 2.5, to use - the with syntax in that version you need to - use a future - statement. Because of implementation details, however, - you cannot use future statements in PL/Python functions. - - diff --git a/src/pl/plpython/expected/README b/src/pl/plpython/expected/README index b890563377..d735ae989b 100644 --- a/src/pl/plpython/expected/README +++ b/src/pl/plpython/expected/README @@ -1,12 +1,8 @@ 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 diff --git a/src/pl/plpython/expected/plpython_error_0.out b/src/pl/plpython/expected/plpython_error_0.out deleted file mode 100644 index 290902b182..0000000000 --- a/src/pl/plpython/expected/plpython_error_0.out +++ /dev/null @@ -1,447 +0,0 @@ --- 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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) - diff --git a/src/pl/plpython/expected/plpython_subtransaction.out b/src/pl/plpython/expected/plpython_subtransaction.out index 069f0992ab..8df64e7619 100644 --- a/src/pl/plpython/expected/plpython_subtransaction.out +++ b/src/pl/plpython/expected/plpython_subtransaction.out @@ -5,71 +5,6 @@ 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 - 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 - 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(): diff --git a/src/pl/plpython/expected/plpython_subtransaction_0.out b/src/pl/plpython/expected/plpython_subtransaction_0.out deleted file mode 100644 index 97ee42b5a9..0000000000 --- a/src/pl/plpython/expected/plpython_subtransaction_0.out +++ /dev/null @@ -1,448 +0,0 @@ --- --- 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 - 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 - 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 - 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 - 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 - 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 - 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. diff --git a/src/pl/plpython/expected/plpython_subtransaction_5.out b/src/pl/plpython/expected/plpython_subtransaction_5.out deleted file mode 100644 index e172e98f86..0000000000 --- a/src/pl/plpython/expected/plpython_subtransaction_5.out +++ /dev/null @@ -1,448 +0,0 @@ --- --- 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 - 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 - 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 - 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 - 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 - 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 - 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. diff --git a/src/pl/plpython/plpy_elog.c b/src/pl/plpython/plpy_elog.c index eb562821a2..71b433ef26 100644 --- a/src/pl/plpython/plpy_elog.c +++ b/src/pl/plpython/plpy_elog.c @@ -242,12 +242,6 @@ PLy_traceback(PyObject *e, PyObject *v, PyObject *tb, 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"); diff --git a/src/pl/plpython/plpython.h b/src/pl/plpython/plpython.h index dc8fcee001..d685d12d84 100644 --- a/src/pl/plpython/plpython.h +++ b/src/pl/plpython/plpython.h @@ -59,16 +59,6 @@ #include #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 @@ -80,15 +70,6 @@ typedef int Py_ssize_t; * 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) @@ -104,16 +85,6 @@ typedef int Py_ssize_t; #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 diff --git a/src/pl/plpython/sql/plpython_subtransaction.sql b/src/pl/plpython/sql/plpython_subtransaction.sql index 398c65720c..38c8617828 100644 --- a/src/pl/plpython/sql/plpython_subtransaction.sql +++ b/src/pl/plpython/sql/plpython_subtransaction.sql @@ -8,43 +8,6 @@ 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(); -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(): -- 2.24.0