-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
 
 
Attached is a patch that takes advantage of savepoints to enable
transactions to continue even after errors in psql. The name of it
is \reseterror, and it is off by default. It's backwards compatible,
and allows things like this to work on 8.0 and up servers:
 
\reseterror
BEGIN;
DELETE FROM foobar;
INSERT INTO foobar(a) VALUES(1);
ISNER INTO foobar(a) VALUES(2);
INSERT INTO foobar(a) VALUES(3);
COMMIT;
 
Doing a SELECT(a) FROM foobar will show two values, 1 and 3. This
is a great help for those of us that tend to type typos into our
psql session, and end up cursing as we have to restart our current
transaction. :)
 
- --
Greg Sabino Mullane [EMAIL PROTECTED]
PGP Key: 0x14964AC8 200501252203
http://biglumber.com/x/web?pk=2529DF6AB8F79407E94445B4BC9B906714964AC8
-----BEGIN PGP SIGNATURE-----
 
iD8DBQFB9wlpvJuQZxSWSsgRAsAzAKCxQ/JtR6/RXgV39uDTm9FIxCIp8QCeKC6T
2l10ef5DHkmFC2dSMQLNHjg=
=HKv9
-----END PGP SIGNATURE-----

Index: doc/src/sgml/ref/psql-ref.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/ref/psql-ref.sgml,v
retrieving revision 1.130
diff -c -r1.130 psql-ref.sgml
*** doc/src/sgml/ref/psql-ref.sgml	14 Jan 2005 00:24:23 -0000	1.130
--- doc/src/sgml/ref/psql-ref.sgml	26 Jan 2005 02:57:05 -0000
***************
*** 1604,1609 ****
--- 1604,1619 ----
  
  
        <varlistentry>
+        <term><literal>\reseterror</literal></term>
+         <listitem>
+         <para>
+ 				Toggles allowing transactions to continue after errors.
+         </para>
+        </listitem>
+       </varlistentry>
+ 
+ 
+       <varlistentry>
          <term><literal>\s [ <replaceable class="parameter">filename</replaceable> ]</literal></term>
          <listitem>
          <para>
Index: src/bin/psql/command.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/command.c,v
retrieving revision 1.139
diff -c -r1.139 command.c
*** src/bin/psql/command.c	1 Jan 2005 05:43:08 -0000	1.139
--- src/bin/psql/command.c	26 Jan 2005 02:57:05 -0000
***************
*** 646,651 ****
--- 646,672 ----
  			puts(gettext("Query buffer reset (cleared)."));
  	}
  
+ 	/* \reseterror -- use savepoints to make transaction errors recoverable */
+ 	else if (strcmp(cmd, "reseterror") == 0)
+ 	{
+ 		if (pset.sversion < 80000)
+ 		{
+ 				printf(gettext("The server version (%d) does not support savepoints.\n"),
+ 								pset.sversion);
+ 		}
+ 		else
+ 		{
+ 				pset.reseterror = !pset.reseterror;
+ 				if (!quiet)
+ 				{
+ 						if (pset.reseterror)
+ 								puts(gettext("Reset error is on."));
+ 						else
+ 								puts(gettext("Reset error is off."));
+ 				}
+ 		}
+ 	}
+ 
  	/* \s save history in a file or show it on the screen */
  	else if (strcmp(cmd, "s") == 0)
  	{
Index: src/bin/psql/common.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/common.c,v
retrieving revision 1.95
diff -c -r1.95 common.c
*** src/bin/psql/common.c	1 Jan 2005 05:43:08 -0000	1.95
--- src/bin/psql/common.c	26 Jan 2005 02:57:05 -0000
***************
*** 941,950 ****
  bool
  SendQuery(const char *query)
  {
! 	PGresult   *results;
  	TimevalStruct before,
  				after;
  	bool		OK;
  
  	if (!pset.db)
  	{
--- 941,951 ----
  bool
  SendQuery(const char *query)
  {
! 		PGresult   *results, *res;
  	TimevalStruct before,
  				after;
  	bool		OK;
+ 	PGTransactionStatusType tstatus;
  
  	if (!pset.db)
  	{
***************
*** 973,979 ****
  
  	SetCancelConn();
  
! 	if (PQtransactionStatus(pset.db) == PQTRANS_IDLE &&
  		!GetVariableBool(pset.vars, "AUTOCOMMIT") &&
  		!command_no_begin(query))
  	{
--- 974,982 ----
  
  	SetCancelConn();
  
! 	tstatus = PQtransactionStatus(pset.db);
! 
! 	if (PQTRANS_IDLE == tstatus &&
  		!GetVariableBool(pset.vars, "AUTOCOMMIT") &&
  		!command_no_begin(query))
  	{
***************
*** 987,992 ****
--- 990,1010 ----
  		}
  		PQclear(results);
  	}
+ 	else {
+ 			/* If we are in error recovery mode and inside a transaction, 
+ 				 possibly issue a temporary savepoint */
+ 			if (PQTRANS_INTRANS==tstatus && pset.reseterror) {
+ 					res = PQexec(pset.db, "SAVEPOINT psql_savepoint");
+ 					if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ 					{
+ 							psql_error("%s", PQerrorMessage(pset.db));
+ 							PQclear(res);
+ 							ResetCancelConn();
+ 							return false;
+ 					}
+ 					PQclear(res);
+ 			}
+ 	}
  
  	if (pset.timing)
  		GETTIMEOFDAY(&before);
***************
*** 1001,1008 ****
  
  	/* but printing results isn't: */
  	if (OK)
! 		OK = PrintQueryResults(results);
! 
  	PQclear(results);
  
  	/* Possible microtiming output */
--- 1019,1041 ----
  
  	/* but printing results isn't: */
  	if (OK)
! 			OK = PrintQueryResults(results);
! 	
! 	/* If in error recovery mode, release the savepoint */
! 	if (PQTRANS_INTRANS==tstatus && pset.reseterror) {
! 			tstatus = PQtransactionStatus(pset.db);
! 			res = PQexec(pset.db, PQTRANS_INERROR==tstatus ? 
! 									 "ROLLBACK TO psql_savepoint" : "RELEASE psql_savepoint");
! 			if (PQresultStatus(res) != PGRES_COMMAND_OK)
! 			{
! 					psql_error("%s", PQerrorMessage(pset.db));
! 					PQclear(res);
! 					ResetCancelConn();
! 					return false;
! 			}
! 			PQclear(res);
! 	}
! 		
  	PQclear(results);
  
  	/* Possible microtiming output */
Index: src/bin/psql/help.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/help.c,v
retrieving revision 1.100
diff -c -r1.100 help.c
*** src/bin/psql/help.c	8 Jan 2005 22:51:13 -0000	1.100
--- src/bin/psql/help.c	26 Jan 2005 02:57:05 -0000
***************
*** 182,187 ****
--- 182,189 ----
  					  "                 show or set client encoding\n"));
  	fprintf(output, _("  \\h [NAME]      help on syntax of SQL commands, * for all commands\n"));
  	fprintf(output, _("  \\q             quit psql\n"));
+ 	fprintf(output, _("  \\reseterror    toggle resetting of errors within transactions (currently %s)\n"),
+ 			ON(pset.reseterror));
  	fprintf(output, _("  \\set [NAME [VALUE]]\n"
  					  "                 set internal variable, or list all if no parameters\n"));
  	fprintf(output, _("  \\timing        toggle timing of commands (currently %s)\n"),
Index: src/bin/psql/settings.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/settings.h,v
retrieving revision 1.23
diff -c -r1.23 settings.h
*** src/bin/psql/settings.h	1 Jan 2005 05:43:08 -0000	1.23
--- src/bin/psql/settings.h	26 Jan 2005 02:57:05 -0000
***************
*** 52,57 ****
--- 52,58 ----
  	unsigned	lineno;			/* also for error reporting */
  
  	bool		timing;			/* enable timing of all queries */
+ 	bool    reseterror; /* for error recovery mode */
  
  	PGVerbosity verbosity;		/* current error verbosity level */
  } PsqlSettings;
Index: src/bin/psql/tab-complete.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/tab-complete.c,v
retrieving revision 1.121
diff -c -r1.121 tab-complete.c
*** src/bin/psql/tab-complete.c	23 Jan 2005 15:58:50 -0000	1.121
--- src/bin/psql/tab-complete.c	26 Jan 2005 02:57:05 -0000
***************
*** 615,622 ****
  		"\\e", "\\echo", "\\encoding",
  		"\\f", "\\g", "\\h", "\\help", "\\H", "\\i", "\\l",
  		"\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
! 		"\\o", "\\p", "\\pset", "\\q", "\\qecho", "\\r", "\\set", "\\t", "\\T",
! 		"\\timing", "\\unset", "\\x", "\\w", "\\z", "\\!", NULL
  	};
  
  	(void) end;					/* not used */
--- 615,622 ----
  		"\\e", "\\echo", "\\encoding",
  		"\\f", "\\g", "\\h", "\\help", "\\H", "\\i", "\\l",
  		"\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
! 		"\\o", "\\p", "\\pset", "\\q", "\\qecho", "\\r", "\\reseterror", "\\set",
! 		"\\t", "\\T",	"\\timing", "\\unset", "\\x", "\\w", "\\z", "\\!", NULL
  	};
  
  	(void) end;					/* not used */
---------------------------(end of broadcast)---------------------------
TIP 9: the planner will ignore your desire to choose an index scan if your
      joining column's datatypes do not match

Reply via email to