diff --git a/.travis.yml b/.travis.yml index 45189e8..80d5de7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,6 +20,9 @@ notifications: on_failure: always env: + - PG_VERSION=16 LEVEL=nightmare + - PG_VERSION=16 LEVEL=hardcore + - PG_VERSION=16 - PG_VERSION=15 LEVEL=nightmare - PG_VERSION=15 LEVEL=hardcore - PG_VERSION=15 @@ -44,3 +47,4 @@ matrix: - env: PG_VERSION=13 LEVEL=nightmare - env: PG_VERSION=14 LEVEL=nightmare - env: PG_VERSION=15 LEVEL=nightmare + - env: PG_VERSION=16 LEVEL=nightmare diff --git a/Dockerfile.tmpl b/Dockerfile.tmpl index 0bcd176..2792b6e 100644 --- a/Dockerfile.tmpl +++ b/Dockerfile.tmpl @@ -6,7 +6,7 @@ RUN apk add --no-cache \ perl perl-ipc-run \ make musl-dev gcc bison flex coreutils \ zlib-dev libedit-dev linux-headers \ - clang clang-analyzer; + pkgconf icu-dev clang clang15 clang-analyzer; # Install fresh valgrind RUN apk add valgrind \ diff --git a/expected/pg_variables_atx_pkg.out b/expected/pg_variables_atx_pkg.out index 527d5cc..e9c8412 100644 --- a/expected/pg_variables_atx_pkg.out +++ b/expected/pg_variables_atx_pkg.out @@ -436,3 +436,38 @@ SELECT pgv_free(); (1 row) +-- +-- +-- PGPRO-7856 +-- Test for case: we don't remove the package object without any variables at +-- the end of autonomous transaction but need to move the state of this object +-- to upper level. +-- +BEGIN; + BEGIN AUTONOMOUS; + SAVEPOINT sp1; + SELECT pgv_set('vars2', 'any1', 'variable exists'::text, true); + pgv_set +--------- + +(1 row) + + SELECT pgv_free(); + pgv_free +---------- + +(1 row) + + RELEASE sp1; + ROLLBACK; + BEGIN AUTONOMOUS; + SAVEPOINT sp2; + SAVEPOINT sp3; + SELECT pgv_free(); + pgv_free +---------- + +(1 row) + + COMMIT; +ROLLBACK; diff --git a/expected/pg_variables_atx_pkg_1.out b/expected/pg_variables_atx_pkg_1.out index d45c6ce..8e36d0a 100644 --- a/expected/pg_variables_atx_pkg_1.out +++ b/expected/pg_variables_atx_pkg_1.out @@ -474,3 +474,42 @@ SELECT pgv_free(); (1 row) +-- +-- +-- PGPRO-7856 +-- Test for case: we don't remove the package object without any variables at +-- the end of autonomous transaction but need to move the state of this object +-- to upper level. +-- +BEGIN; + BEGIN AUTONOMOUS; +ERROR: syntax error at or near "AUTONOMOUS" +LINE 1: BEGIN AUTONOMOUS; + ^ + SAVEPOINT sp1; +ERROR: current transaction is aborted, commands ignored until end of transaction block + SELECT pgv_set('vars2', 'any1', 'variable exists'::text, true); +ERROR: current transaction is aborted, commands ignored until end of transaction block + SELECT pgv_free(); +ERROR: current transaction is aborted, commands ignored until end of transaction block + RELEASE sp1; +ERROR: current transaction is aborted, commands ignored until end of transaction block + ROLLBACK; + BEGIN AUTONOMOUS; +ERROR: syntax error at or near "AUTONOMOUS" +LINE 1: BEGIN AUTONOMOUS; + ^ + SAVEPOINT sp2; +ERROR: SAVEPOINT can only be used in transaction blocks + SAVEPOINT sp3; +ERROR: SAVEPOINT can only be used in transaction blocks + SELECT pgv_free(); + pgv_free +---------- + +(1 row) + + COMMIT; +WARNING: there is no transaction in progress +ROLLBACK; +WARNING: there is no transaction in progress diff --git a/pg_variables.c b/pg_variables.c index b7b1302..c8ee939 100644 --- a/pg_variables.c +++ b/pg_variables.c @@ -2206,7 +2206,7 @@ removeState(TransObject *object, TransObjectType type, TransState *stateToDelete } /* Remove package or variable (either transactional or regular) */ -void +bool removeObject(TransObject *object, TransObjectType type) { bool found; @@ -2228,7 +2228,7 @@ removeObject(TransObject *object, TransObjectType type) if (getNestLevelATX() > 0 && !dlist_is_empty(&object->states)) { GetActualState(object)->is_valid = false; - return; + return false; } #endif @@ -2289,6 +2289,8 @@ removeObject(TransObject *object, TransObjectType type) } resetVariablesCache(); + + return true; } /* @@ -2429,8 +2431,8 @@ releaseSavepoint(TransObject *object, TransObjectType type, bool sub) dlist_is_empty(changesStack)) ) { - removeObject(object, type); - return; + if (removeObject(object, type)) + return; } /* diff --git a/pg_variables.h b/pg_variables.h index afa9b22..6508e9f 100644 --- a/pg_variables.h +++ b/pg_variables.h @@ -193,7 +193,7 @@ extern bool update_record(Variable *variable, HeapTupleHeader tupleHeader); extern bool delete_record(Variable *variable, Datum value, bool is_null); extern void insert_record_copy(RecordVar *dest_record, Datum src_tuple, Variable *variable); -extern void removeObject(TransObject *object, TransObjectType type); +extern bool removeObject(TransObject *object, TransObjectType type); #define GetActualState(object) \ (dlist_head_element(TransState, node, &((TransObject *) object)->states)) diff --git a/sql/pg_variables_atx_pkg.sql b/sql/pg_variables_atx_pkg.sql index a4a4943..49113d6 100644 --- a/sql/pg_variables_atx_pkg.sql +++ b/sql/pg_variables_atx_pkg.sql @@ -215,3 +215,24 @@ ROLLBACK; SELECT pgv_remove('vars1', 'int1'); SELECT pgv_free(); +-- +-- +-- PGPRO-7856 +-- Test for case: we don't remove the package object without any variables at +-- the end of autonomous transaction but need to move the state of this object +-- to upper level. +-- +BEGIN; + BEGIN AUTONOMOUS; + SAVEPOINT sp1; + SELECT pgv_set('vars2', 'any1', 'variable exists'::text, true); + SELECT pgv_free(); + RELEASE sp1; + ROLLBACK; + + BEGIN AUTONOMOUS; + SAVEPOINT sp2; + SAVEPOINT sp3; + SELECT pgv_free(); + COMMIT; +ROLLBACK;