Index: doc/src/sgml/ref/psql-ref.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql-server/doc/src/sgml/ref/psql-ref.sgml,v
retrieving revision 1.122
diff -u -r1.122 psql-ref.sgml
--- doc/src/sgml/ref/psql-ref.sgml 20 Sep 2004 18:51:17 -0000 1.122
+++ doc/src/sgml/ref/psql-ref.sgml 23 Sep 2004 19:51:36 -0000
@@ -2021,6 +2021,32 @@
+ IMPLICIT_SAVEPOINTS
+
+
+ When on> (default is off>) a savepoint is created
+ before each interactive SQL command executed in psql>. If
+ the command results in an error, psql> will rollback to
+ the created savepoint. It thereby protects the user from a rollback of
+ the whole transaction. This option has no effect on none-interactive
+ mode, i.e. when commands are read from a file from stdin> or
+ using \i>. A SQL script cannot react to an error and the
+ behaviour would have unexpected results.
+
+
+
+
+ Savepoints have a rather high cost in the current implementation of
+ PostgreSQL> (shared memory). Also keep in mind that
+ locks are held in transactions until commit. For those two reasons
+ you should not make transactions longer then neccessary in
+ interactive mode.
+
+
+
+
+
+
LASTOID
Index: src/bin/psql/command.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/bin/psql/command.c,v
retrieving revision 1.125
diff -u -r1.125 command.c
--- src/bin/psql/command.c 29 Aug 2004 05:06:54 -0000 1.125
+++ src/bin/psql/command.c 23 Sep 2004 19:51:36 -0000
@@ -1261,6 +1261,7 @@
FILE *fd;
int result;
char *oldfilename;
+ bool impl_savepoints_state;
if (!filename)
return false;
@@ -1274,11 +1275,19 @@
return false;
}
+ /*
+ * Disable implicit savepoints during processing commands from files.
+ */
+ impl_savepoints_state = pset.impl_savepoints_disabled;
+ pset.impl_savepoints_disabled = true;
+
oldfilename = pset.inputfile;
pset.inputfile = filename;
result = MainLoop(fd);
fclose(fd);
pset.inputfile = oldfilename;
+
+ pset.impl_savepoints_disabled = impl_savepoints_state;
return result;
}
Index: src/bin/psql/common.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/bin/psql/common.c,v
retrieving revision 1.91
diff -u -r1.91 common.c
--- src/bin/psql/common.c 20 Sep 2004 18:51:19 -0000 1.91
+++ src/bin/psql/common.c 23 Sep 2004 19:51:36 -0000
@@ -61,7 +61,6 @@
extern bool prompt_state;
-
static bool command_no_begin(const char *query);
@@ -865,6 +864,7 @@
TimevalStruct before,
after;
bool OK;
+ bool implicit_savepoint = false;
if (!pset.db)
{
@@ -908,6 +908,26 @@
PQclear(results);
}
+ /*
+ * Implicit savepoints make it possible to only rollback the last statement
+ * on errors (interactive mode only, backend version >= 8.0).
+ *
+ * Note: We assume that the savepoint pg_internal_psql will not be used by a user.
+ */
+ if (PQtransactionStatus(pset.db) == PQTRANS_INTRANS &&
+ PQserverVersion(pset.db) >= 80000 &&
+ GetVariableBool(pset.vars, "IMPLICIT_SAVEPOINTS") &&
+ !pset.impl_savepoints_disabled &&
+ !pset.notty)
+ {
+ /* use PSQLexec instead of PQexec here, so -E prints this query */
+ results = PSQLexec("SAVEPOINT pg_internal_psql", false);
+ if (!results)
+ return false;
+ PQclear(results);
+ implicit_savepoint = true;
+ }
+
if (pset.timing)
GETTIMEOFDAY(&before);
@@ -943,6 +963,26 @@
PrintNotifications();
+ /*
+ * If we have created an implicit savepoint, the query failed, and the
+ * connection is in transaction aborted state, try to rollback to the
+ * savepoint set before executing the user query.
+ *
+ * Note: we must not release the savepoint if there is no error since that
+ * would have the side effect of releasing any savepoint created by the user
+ * in the executed query.
+ *
+ * Should we send a message to the user here?
+ */
+ if (!OK
+ && implicit_savepoint
+ && PQtransactionStatus(pset.db) == PQTRANS_INERROR)
+ {
+ results = PSQLexec("ROLLBACK TO pg_internal_psql", false);
+ if (results)
+ PQclear(results);
+ }
+
return OK;
}
Index: src/bin/psql/startup.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/bin/psql/startup.c,v
retrieving revision 1.100
diff -u -r1.100 startup.c
--- src/bin/psql/startup.c 13 Sep 2004 23:07:12 -0000 1.100
+++ src/bin/psql/startup.c 23 Sep 2004 19:51:36 -0000
@@ -146,6 +146,10 @@
SetVariable(pset.vars, "VERBOSITY", "default");
pset.verbosity = PQERRORS_DEFAULT;
+ /* Default values for implicit savepoints */
+ SetVariable(pset.vars, "IMPLICIT_SAVEPOINTS", "off");
+ pset.impl_savepoints_disabled = false;
+
pset.notty = (!isatty(fileno(stdin)) || !isatty(fileno(stdout)));
/* This is obsolete and should be removed sometime. */