mirror of https://github.com/postgres/postgres
Supporting very old Python versions is a maintenance burden,
especially with the several variant test files to maintain for Python
<2.6.
Since we have dropped support for older OpenSSL versions in
7b283d0e1d
, RHEL 5 is now effectively
desupported, and that was also the only mainstream operating system
still using Python versions before 2.6, so it's a good time to drop
those as well.
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://www.postgresql.org/message-id/flat/98b69261-298c-13d2-f34d-836fd9c29b21%402ndquadrant.com
pull/49/head
parent
f5d28710c7
commit
37f21ed132
@ -1,12 +1,8 @@ |
|||||||
Guide to alternative expected files: |
Guide to alternative expected files: |
||||||
|
|
||||||
plpython_error_0.out Python 2.4 and older |
|
||||||
plpython_error_5.out Python 3.5 and newer |
plpython_error_5.out Python 3.5 and newer |
||||||
|
|
||||||
plpython_unicode.out server encoding != SQL_ASCII |
plpython_unicode.out server encoding != SQL_ASCII |
||||||
plpython_unicode_3.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 |
plpython_types_3.out Python 3.x |
||||||
|
@ -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 <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) |
|
||||||
|
|
@ -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 <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. |
|
@ -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 <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. |
|
Loading…
Reference in new issue