postgres.git / summary / log / commit / refs
commit b0bd9327dd74b48dbd2b18b0de22388490ddca71
Author: Michael Paquier <michael@paquier.xyz>
Date: Mon Jun 06 02:07:35 2022 +0000
First released in: 15.0, REL_10_STABLE (reverted before release), REL_11_STABLE (reverted before release), REL_12_STABLE (reverted before release), REL_13_STABLE (reverted before release), REL_14_STABLE (reverted before release)
Reverted by: db713aa7fcbe (in 10.22), aaa88d3828c3 (in 11.17), 030da9b6fd52 (in 12.12), 3f7f06738529 (in 13.8), f25b5519c99a (in 14.4)
Fix psql's single transaction mode on client-side errors with -c/-f switches
psql --single-transaction is able to handle multiple -c and -f switches
in a single transaction since d5563d7d, but this had the surprising
behavior of forcing a transaction COMMIT even if psql failed with an
error in the client (for example incorrect path given to \copy), which
would generate an error, but still commit any changes that were already
applied in the backend. This commit makes the behavior more consistent,
by enforcing a transaction ROLLBACK if any commands fail, both
client-side and backend-side, so as no changes are applied if one error
happens in any of them.
Some tests are added on HEAD to provide some coverage about all that.
Backend-side errors are unreliable as IPC::Run can complain on SIGPIPE
if psql quits before reading a query result, but that should work
properly in the case where any errors come from psql itself, which is
what the original report is about.
Reported-by: Christoph Berg
Author: Kyotaro Horiguchi, Michael Paquier
Discussion: https://postgr.es/m/17504-76b68018e130415e@postgresql.org
Backpatch-through: 10
doc/src/sgml/ref/psql-ref.sgml | 6 ++++--
src/bin/psql/startup.c | 4 +++-
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index fa58f71e15f..7dd177a70cd 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -582,8 +582,10 @@ EOF
<application>psql</application> to issue a <command>BEGIN</command> command
before the first such option and a <command>COMMIT</command> command after
the last one, thereby wrapping all the commands into a single
- transaction. This ensures that either all the commands complete
- successfully, or no changes are applied.
+ transaction. If any of the commands fails, a
+ <command>ROLLBACK</command> command is sent instead. This ensures that
+ either all the commands complete successfully, or no changes are
+ applied.
</para>
<para>
diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c
index d688a5d7d6c..08dc7786a4e 100644
--- a/src/bin/psql/startup.c
+++ b/src/bin/psql/startup.c
@@ -386,7 +386,9 @@ main(int argc, char *argv[])
if (options.single_txn)
{
- if ((res = PSQLexec("COMMIT")) == NULL)
+ res = PSQLexec((successResult == EXIT_SUCCESS) ?
+ "COMMIT" : "ROLLBACK");
+ if (res == NULL)
{
if (pset.on_error_stop)
{
[parent: 668656d52f9a]