Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita65b1b7

Browse files
committed
Add psql \set ON_ERROR_ROLLBACK to allow statements in a transaction to
error without affecting the entire transaction. Valid values are"on|interactive|off".
1 parent989b55c commita65b1b7

File tree

2 files changed

+96
-8
lines changed

2 files changed

+96
-8
lines changed

‎doc/src/sgml/ref/psql-ref.sgml

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.134 2005/03/14 06:19:01 tgl Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.135 2005/04/28 13:09:59 momjian Exp $
33
PostgreSQL documentation
44
-->
55

@@ -2049,6 +2049,28 @@ bar
20492049
</listitem>
20502050
</varlistentry>
20512051

2052+
<varlistentry>
2053+
<indexterm>
2054+
<primary>rollback</primary>
2055+
<secondary>psql</secondary>
2056+
</indexterm>
2057+
<term><varname>ON_ERROR_ROLLBACK</varname></term>
2058+
<listitem>
2059+
<para>
2060+
When <literal>on</>, if a statement in a transaction block
2061+
generates an error, the error is ignored and the transaction
2062+
continues. When <literal>interactive</>, such errors are only
2063+
ignored in interactive sessions, and not when reading script
2064+
files. When <literal>off</> (the default), a statement in a
2065+
transaction block that generates an error aborts the entire
2066+
transaction. The on_error_rollback-on mode works by issuing an
2067+
implicit <command>SAVEPONT</> for you, just before each command
2068+
that is in a transaction block, and rolls back to the savepoint
2069+
on error.
2070+
</para>
2071+
</listitem>
2072+
</varlistentry>
2073+
20522074
<varlistentry>
20532075
<term><varname>ON_ERROR_STOP</varname></term>
20542076
<listitem>

‎src/bin/psql/common.c

Lines changed: 73 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* Copyright (c) 2000-2005, PostgreSQL Global Development Group
55
*
6-
* $PostgreSQL: pgsql/src/bin/psql/common.c,v 1.96 2005/02/22 04:40:52 momjian Exp $
6+
* $PostgreSQL: pgsql/src/bin/psql/common.c,v 1.97 2005/04/28 13:09:59 momjian Exp $
77
*/
88
#include"postgres_fe.h"
99
#include"common.h"
@@ -941,11 +941,13 @@ PrintQueryResults(PGresult *results)
941941
bool
942942
SendQuery(constchar*query)
943943
{
944-
PGresult*results;
945-
TimevalStructbefore,
946-
after;
947-
boolOK;
948-
944+
PGresult*results;
945+
TimevalStructbefore,after;
946+
boolOK,on_error_rollback_savepoint= false;
947+
PGTransactionStatusTypetransaction_status;
948+
staticboolon_error_rollback_warning= false;
949+
constchar*rollback_str;
950+
949951
if (!pset.db)
950952
{
951953
psql_error("You are currently not connected to a database.\n");
@@ -973,7 +975,9 @@ SendQuery(const char *query)
973975

974976
SetCancelConn();
975977

976-
if (PQtransactionStatus(pset.db)==PQTRANS_IDLE&&
978+
transaction_status=PQtransactionStatus(pset.db);
979+
980+
if (transaction_status==PQTRANS_IDLE&&
977981
!GetVariableBool(pset.vars,"AUTOCOMMIT")&&
978982
!command_no_begin(query))
979983
{
@@ -987,6 +991,33 @@ SendQuery(const char *query)
987991
}
988992
PQclear(results);
989993
}
994+
elseif (transaction_status==PQTRANS_INTRANS&&
995+
(rollback_str=GetVariable(pset.vars,"ON_ERROR_ROLLBACK"))!=NULL&&
996+
/* !off and !interactive is 'on' */
997+
pg_strcasecmp(rollback_str,"off")!=0&&
998+
(pset.cur_cmd_interactive||
999+
pg_strcasecmp(rollback_str,"interactive")!=0))
1000+
{
1001+
if (on_error_rollback_warning== false&&pset.sversion<80000)
1002+
{
1003+
fprintf(stderr,_("The server version (%d) does not support savepoints for ON_ERROR_ROLLBACK.\n"),
1004+
pset.sversion);
1005+
on_error_rollback_warning= true;
1006+
}
1007+
else
1008+
{
1009+
results=PQexec(pset.db,"SAVEPOINT pg_psql_temporary_savepoint");
1010+
if (PQresultStatus(results)!=PGRES_COMMAND_OK)
1011+
{
1012+
psql_error("%s",PQerrorMessage(pset.db));
1013+
PQclear(results);
1014+
ResetCancelConn();
1015+
return false;
1016+
}
1017+
PQclear(results);
1018+
on_error_rollback_savepoint= true;
1019+
}
1020+
}
9901021

9911022
if (pset.timing)
9921023
GETTIMEOFDAY(&before);
@@ -1005,6 +1036,41 @@ SendQuery(const char *query)
10051036

10061037
PQclear(results);
10071038

1039+
/* If we made a temporary savepoint, possibly release/rollback */
1040+
if (on_error_rollback_savepoint)
1041+
{
1042+
transaction_status=PQtransactionStatus(pset.db);
1043+
1044+
/* We always rollback on an error */
1045+
if (transaction_status==PQTRANS_INERROR)
1046+
results=PQexec(pset.db,"ROLLBACK TO pg_psql_temporary_savepoint");
1047+
/* If they are no longer in a transaction, then do nothing */
1048+
elseif (transaction_status!=PQTRANS_INTRANS)
1049+
results=NULL;
1050+
else
1051+
{
1052+
/*
1053+
*Do nothing if they are messing with savepoints themselves:
1054+
*If the user did RELEASE or ROLLBACK, our savepoint is gone.
1055+
*If they issued a SAVEPOINT, releasing ours would remove theirs.
1056+
*/
1057+
if (strcmp(PQcmdStatus(results),"SAVEPOINT")==0||
1058+
strcmp(PQcmdStatus(results),"RELEASE")==0||
1059+
strcmp(PQcmdStatus(results),"ROLLBACK")==0)
1060+
results=NULL;
1061+
else
1062+
results=PQexec(pset.db,"RELEASE pg_psql_temporary_savepoint");
1063+
}
1064+
if (PQresultStatus(results)!=PGRES_COMMAND_OK)
1065+
{
1066+
psql_error("%s",PQerrorMessage(pset.db));
1067+
PQclear(results);
1068+
ResetCancelConn();
1069+
return false;
1070+
}
1071+
PQclear(results);
1072+
}
1073+
10081074
/* Possible microtiming output */
10091075
if (OK&&pset.timing)
10101076
printf(_("Time: %.3f ms\n"),DIFF_MSEC(&after,&before));

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp