Re: [HACKERS] Continue transactions after errors in psql - Mailing list pgsql-patches

From Bruce Momjian
Subject Re: [HACKERS] Continue transactions after errors in psql
Date
Msg-id 200504281315.j3SDFJw25010@candle.pha.pa.us
Whole thread Raw
List pgsql-patches
Applied.

---------------------------------------------------------------------------

pgman wrote:
> pgman wrote:
> > Tom Lane wrote:
> > > Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > > > Tom Lane wrote:
> > > >> Well, that's just a matter of choosing good (ie short) names for the
> > > >> backslash commands.  I was trying to be clear rather than proposing
> > > >> names I would actually want to use ;-).  Any suggestions?
> > >
> > > > Well, if we allowed ON_ERROR_ROLLBACK to work in non-interactive
> > > > sessions we could just do:
> > >
> > > >     \set ON_ERROR_ROLLBACK on
> > > >     DROP TABLE foo;
> > > >     \set ON_ERROR_ROLLBACK off
> > >
> > > That isn't the same thing at all.  The syntax I was proposing allows the
> > > script writer to define a savepoint covering multiple statements,
> > > whereas the above does not.
> >
> > Well, it fits the use case posted, that is to conditionally roll back a
> > _single_ failed query.  I don't see the need to add a new
> > infrastructure/command unless people have a use case for rolling back a
> > group of statements on failure.  I have no seen such a description yet.
>
> OK, updated patch that allows for 'on/interactive/off'.  Seems there are
> enough use cases to add an 'interactive' option.
>
> --
>   Bruce Momjian                        |  http://candle.pha.pa.us
>   pgman@candle.pha.pa.us               |  (610) 359-1001
>   +  If your life is a hard drive,     |  13 Roberts Road
>   +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

> Index: doc/src/sgml/ref/psql-ref.sgml
> ===================================================================
> RCS file: /cvsroot/pgsql/doc/src/sgml/ref/psql-ref.sgml,v
> retrieving revision 1.134
> diff -c -c -r1.134 psql-ref.sgml
> *** doc/src/sgml/ref/psql-ref.sgml    14 Mar 2005 06:19:01 -0000    1.134
> --- doc/src/sgml/ref/psql-ref.sgml    28 Apr 2005 03:35:00 -0000
> ***************
> *** 2050,2055 ****
> --- 2050,2077 ----
>         </varlistentry>
>
>         <varlistentry>
> +       <indexterm>
> +        <primary>rollback</primary>
> +        <secondary>psql</secondary>
> +       </indexterm>
> +         <term><varname>ON_ERROR_ROLLBACK</varname></term>
> +         <listitem>
> +         <para>
> +         When <literal>on</>, if a statement in a transaction block
> +         generates an error, the error is ignored and the transaction
> +         continues. When <literal>interactive</>, such errors are only
> +         ignored in interactive sessions, and not when reading script
> +         files. When <literal>off</> (the default), a statement in a
> +         transaction block that generates an error aborts the entire
> +         transaction. The on_error_rollback-on mode works by issuing an
> +         implicit <command>SAVEPONT</> for you, just before each command
> +         that is in a transaction block, and rolls back to the savepoint
> +         on error.
> +         </para>
> +         </listitem>
> +       </varlistentry>
> +
> +       <varlistentry>
>           <term><varname>ON_ERROR_STOP</varname></term>
>           <listitem>
>           <para>
> Index: src/bin/psql/common.c
> ===================================================================
> RCS file: /cvsroot/pgsql/src/bin/psql/common.c,v
> retrieving revision 1.96
> diff -c -c -r1.96 common.c
> *** src/bin/psql/common.c    22 Feb 2005 04:40:52 -0000    1.96
> --- src/bin/psql/common.c    28 Apr 2005 03:35:01 -0000
> ***************
> *** 941,951 ****
>   bool
>   SendQuery(const char *query)
>   {
> !     PGresult   *results;
> !     TimevalStruct before,
> !                 after;
> !     bool        OK;
> !
>       if (!pset.db)
>       {
>           psql_error("You are currently not connected to a database.\n");
> --- 941,953 ----
>   bool
>   SendQuery(const char *query)
>   {
> !     PGresult     *results;
> !     TimevalStruct before, after;
> !     bool OK, on_error_rollback_savepoint = false;
> !     PGTransactionStatusType transaction_status;
> !     static bool        on_error_rollback_warning = false;
> !     const char *rollback_str;
> !
>       if (!pset.db)
>       {
>           psql_error("You are currently not connected to a database.\n");
> ***************
> *** 973,979 ****
>
>       SetCancelConn();
>
> !     if (PQtransactionStatus(pset.db) == PQTRANS_IDLE &&
>           !GetVariableBool(pset.vars, "AUTOCOMMIT") &&
>           !command_no_begin(query))
>       {
> --- 975,983 ----
>
>       SetCancelConn();
>
> !     transaction_status = PQtransactionStatus(pset.db);
> !
> !     if (transaction_status == PQTRANS_IDLE &&
>           !GetVariableBool(pset.vars, "AUTOCOMMIT") &&
>           !command_no_begin(query))
>       {
> ***************
> *** 987,992 ****
> --- 991,1023 ----
>           }
>           PQclear(results);
>       }
> +     else if (transaction_status == PQTRANS_INTRANS &&
> +              (rollback_str = GetVariable(pset.vars, "ON_ERROR_ROLLBACK")) != NULL &&
> +              /* !off and !interactive is 'on' */
> +              pg_strcasecmp(rollback_str, "off") != 0 &&
> +              (pset.cur_cmd_interactive ||
> +               pg_strcasecmp(rollback_str, "interactive") != 0))
> +     {
> +         if (on_error_rollback_warning == false && pset.sversion < 80000)
> +         {
> +             fprintf(stderr, _("The server version (%d) does not support savepoints for ON_ERROR_ROLLBACK.\n"),
> +                 pset.sversion);
> +             on_error_rollback_warning = true;
> +         }
> +         else
> +         {
> +             results = PQexec(pset.db, "SAVEPOINT pg_psql_temporary_savepoint");
> +             if (PQresultStatus(results) != PGRES_COMMAND_OK)
> +             {
> +                 psql_error("%s", PQerrorMessage(pset.db));
> +                 PQclear(results);
> +                 ResetCancelConn();
> +                 return false;
> +             }
> +             PQclear(results);
> +             on_error_rollback_savepoint = true;
> +         }
> +     }
>
>       if (pset.timing)
>           GETTIMEOFDAY(&before);
> ***************
> *** 1005,1010 ****
> --- 1036,1076 ----
>
>       PQclear(results);
>
> +     /* If we made a temporary savepoint, possibly release/rollback */
> +     if (on_error_rollback_savepoint)
> +     {
> +         transaction_status = PQtransactionStatus(pset.db);
> +
> +         /* We always rollback on an error */
> +         if (transaction_status == PQTRANS_INERROR)
> +             results = PQexec(pset.db, "ROLLBACK TO pg_psql_temporary_savepoint");
> +         /* If they are no longer in a transaction, then do nothing */
> +         else if (transaction_status != PQTRANS_INTRANS)
> +             results = NULL;
> +         else
> +         {
> +             /*
> +              *    Do nothing if they are messing with savepoints themselves:
> +              *    If the user did RELEASE or ROLLBACK, our savepoint is gone.
> +              *    If they issued a SAVEPOINT, releasing ours would remove theirs.
> +              */
> +             if (strcmp(PQcmdStatus(results), "SAVEPOINT") == 0 ||
> +                 strcmp(PQcmdStatus(results), "RELEASE") == 0 ||
> +                 strcmp(PQcmdStatus(results), "ROLLBACK") ==0)
> +                 results = NULL;
> +             else
> +                 results = PQexec(pset.db, "RELEASE pg_psql_temporary_savepoint");
> +         }
> +         if (PQresultStatus(results) != PGRES_COMMAND_OK)
> +         {
> +             psql_error("%s", PQerrorMessage(pset.db));
> +             PQclear(results);
> +             ResetCancelConn();
> +             return false;
> +         }
> +         PQclear(results);
> +     }
> +
>       /* Possible microtiming output */
>       if (OK && pset.timing)
>           printf(_("Time: %.3f ms\n"), DIFF_MSEC(&after, &before));

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

pgsql-patches by date:

Previous
From: Bruce Momjian
Date:
Subject: Re: [HACKERS] Continue transactions after errors in psql
Next
From: Bruce Momjian
Date:
Subject: Re: Cleaning up unreferenced table files