do_not_commit_after_client-side_failure.patch
text/x-patch
Filename: do_not_commit_after_client-side_failure.patch
Type: text/x-patch
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| doc/src/sgml/ref/psql-ref.sgml | 4 | 2 |
| src/bin/psql/startup.c | 3 | 1 |
| src/bin/psql/t/001_basic.pl | 10 | 0 |
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index 47bf3342a5..6f5476d99e 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -584,8 +584,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 ddff903915..2261f78f81 100644
--- a/src/bin/psql/startup.c
+++ b/src/bin/psql/startup.c
@@ -426,7 +426,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)
{
diff --git a/src/bin/psql/t/001_basic.pl b/src/bin/psql/t/001_basic.pl
index c3ed18e84d..0cae05ca4b 100644
--- a/src/bin/psql/t/001_basic.pl
+++ b/src/bin/psql/t/001_basic.pl
@@ -198,4 +198,14 @@ like(
^LOCATION: .*$/m,
'\errverbose after \gdesc with error');
+# Check if client-side error causes the whole transaction rolled-back
+$node->safe_psql('postgres', "CREATE TABLE t AS SELECT 1 AS a");
+
+$node->command_fails(['psql', '--single-transaction', '-v', 'ON_ERROR_STOP=1',
+ '-c', 'DELETE FROM t',
+ '-c', "\\copy t FROM '/nonexistent'"]);
+
+is($node->safe_psql('postgres', 'SELECT count(*) FROM t'), 1,
+ 'Non-server error when ON_ERROR_STOP rolls back the transaction');
+
done_testing();