From b86b7767f9f3facc0869d9f1bc4304dce954e8a9 Mon Sep 17 00:00:00 2001 From: Tatsuo Ishii Date: Fri, 25 Nov 2022 16:33:17 +0900 Subject: [PATCH] Fix ROLLBACK TO command to work in aborted transaction. Commit: https://git.postgresql.org/gitweb/?p=pgpool2.git;a=commit;h=eea522ebfcf791a623e865deaa1aa6fb59e3c50b fixed some cases in aborted transaction so that SQL commands except COMMIT/ROLLBACK are not forwarded to backend. But it missed ROLLBACK TO command. As a result even if ROLLBACK TO command is issued, the command was not forwarded to backend and the transaction keeps on in aborted state. Back patched through 4.3 which the commit was brought in. Also add a test case for ROLLBACK TO to test 078. Discussion: https://www.pgpool.net/pipermail/pgpool-general-jp/2022-November/001715.html --- src/include/protocol/pool_proto_modules.h | 1 + src/protocol/pool_process_query.c | 17 ++++++++++++++++- src/protocol/pool_proto_modules.c | 2 +- .../tests/078.aborted_transaction/expected.txt | 18 ++++++++++++++++++ .../tests/078.aborted_transaction/test.sh | 6 ++++++ 5 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/include/protocol/pool_proto_modules.h b/src/include/protocol/pool_proto_modules.h index 1fd6f8c68..57280a3e3 100644 --- a/src/include/protocol/pool_proto_modules.h +++ b/src/include/protocol/pool_proto_modules.h @@ -153,6 +153,7 @@ extern bool is_select_query(Node *node, char *sql); extern bool is_commit_query(Node *node); extern bool is_rollback_query(Node *node); extern bool is_commit_or_rollback_query(Node *node); +extern bool is_rollback_to_query(Node *node); extern bool is_strict_query(Node *node); /* returns non 0 if this is strict * query */ extern int need_insert_lock(POOL_CONNECTION_POOL * backend, char *query, Node *node); diff --git a/src/protocol/pool_process_query.c b/src/protocol/pool_process_query.c index 8d1c0c819..f2db65eab 100644 --- a/src/protocol/pool_process_query.c +++ b/src/protocol/pool_process_query.c @@ -1246,7 +1246,7 @@ is_select_query(Node *node, char *sql) bool is_commit_or_rollback_query(Node *node) { - return is_commit_query(node) || is_rollback_query(node); + return is_commit_query(node) || is_rollback_query(node) || is_rollback_to_query(node); } /* @@ -1281,6 +1281,21 @@ is_rollback_query(Node *node) return stmt->kind == TRANS_STMT_ROLLBACK; } +/* + * Returns true if SQL is transaction rollback to command + */ +bool +is_rollback_to_query(Node *node) +{ + TransactionStmt *stmt; + + if (node == NULL || !IsA(node, TransactionStmt)) + return false; + + stmt = (TransactionStmt *) node; + return stmt->kind == TRANS_STMT_ROLLBACK_TO; +} + /* * send error message to frontend */ diff --git a/src/protocol/pool_proto_modules.c b/src/protocol/pool_proto_modules.c index a20aa6922..255cc4fad 100644 --- a/src/protocol/pool_proto_modules.c +++ b/src/protocol/pool_proto_modules.c @@ -310,7 +310,7 @@ SimpleQuery(POOL_CONNECTION * frontend, /* * Check if the transaction is in abort status. If so, we do nothing * and just return an error message to frontend, execpt for - * transaction commit or abort command. + * transaction COMMIT or ROLLBACK (TO) command. */ if (check_transaction_state_and_abort(contents, node, frontend, backend) == false) { diff --git a/src/test/regression/tests/078.aborted_transaction/expected.txt b/src/test/regression/tests/078.aborted_transaction/expected.txt index be37381b4..f70e6716e 100644 --- a/src/test/regression/tests/078.aborted_transaction/expected.txt +++ b/src/test/regression/tests/078.aborted_transaction/expected.txt @@ -26,3 +26,21 @@ SELECT 1; 1 (1 row) +BEGIN; +BEGIN +SAVEPOINT s1; +SAVEPOINT +aaa; +ERROR: syntax error at or near "aaa" +LINE 1: aaa; + ^ +ROLLBACK TO s1; +ROLLBACK +SELECT 1; + ?column? +---------- + 1 +(1 row) + +END; +COMMIT diff --git a/src/test/regression/tests/078.aborted_transaction/test.sh b/src/test/regression/tests/078.aborted_transaction/test.sh index 47bd280c1..7c8eca387 100755 --- a/src/test/regression/tests/078.aborted_transaction/test.sh +++ b/src/test/regression/tests/078.aborted_transaction/test.sh @@ -33,6 +33,12 @@ aaa; SELECT 1; END; SELECT 1; +BEGIN; +SAVEPOINT s1; +aaa; +ROLLBACK TO s1; +SELECT 1; +END; EOF if cmp ../expected.txt results.txt >/dev/null -- 2.39.5