Index: startup.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/bin/psql/startup.c,v
retrieving revision 1.100
diff -u -r1.100 startup.c
--- startup.c	13 Sep 2004 23:07:12 -0000	1.100
+++ startup.c	21 Sep 2004 12:29:27 -0000
@@ -143,6 +143,7 @@
 
 	/* Default values for variables that are used in noninteractive cases */
 	SetVariableBool(pset.vars, "AUTOCOMMIT");
+	SetVariable(pset.vars, "IMPLICIT_SAVEPOINTS", "off");
 	SetVariable(pset.vars, "VERBOSITY", "default");
 	pset.verbosity = PQERRORS_DEFAULT;
 
Index: common.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/bin/psql/common.c,v
retrieving revision 1.91
diff -u -r1.91 common.c
--- common.c	20 Sep 2004 18:51:19 -0000	1.91
+++ common.c	21 Sep 2004 12:29:27 -0000
@@ -865,6 +865,7 @@
 	TimevalStruct before,
 				after;
 	bool		OK;
+	bool		implicit_savepoint = false;
 
 	if (!pset.db)
 	{
@@ -908,6 +909,25 @@
 		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.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 savepoints, 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;
 }
 
