Re: Allow SET to not start a transaction - Mailing list pgsql-patches

From Bruce Momjian
Subject Re: Allow SET to not start a transaction
Date
Msg-id 200210090458.g994wll09989@candle.pha.pa.us
Whole thread Raw
In response to Allow SET to not start a transaction  (Bruce Momjian <pgman@candle.pha.pa.us>)
List pgsql-patches
OK, I have finished the patch and applied it, with doc updates.

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

Bruce Momjian wrote:
> We have on the open items list:
>
>     Make SET not start a transaction with autocommit off, document it
>
> The attached patch does exactly that (though without documentation).  It
> checks for the TRANS_DEFAULT transaction state, which is the state right
> after a COMMIT.  If the backend is in that state, and autocommit is off,
> and the command is SET/SHOW/RESET, then a COMMIT will be forced, rather
> than keeping the transaction open for the next command.  It seems to
> work, but i want to test it more before applying to CVS.
>
> ---------------------------------------------------------------------------
>
> test=> set autocommit = off;
> SET
> test=> commit;
> WARNING:  COMMIT: no transaction in progress
> COMMIT
> test=> set statement_timeout = 9999999;
> SET
> test=> select 1;
>  ?column?
> ----------
>         1
> (1 row)
>
> test=> abort;
> ROLLBACK
> test=> show statement_timeout;
>  statement_timeout
> -------------------
>  9999999
> (1 row)
>

--
  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/runtime.sgml
===================================================================
RCS file: /cvsroot/pgsql-server/doc/src/sgml/runtime.sgml,v
retrieving revision 1.143
diff -c -c -r1.143 runtime.sgml
*** doc/src/sgml/runtime.sgml    3 Oct 2002 02:26:49 -0000    1.143
--- doc/src/sgml/runtime.sgml    9 Oct 2002 04:55:22 -0000
***************
*** 1235,1250 ****
      that is not inside an explicit transaction block (that is, unless a
      <command>BEGIN</> with no matching <command>COMMIT</> has been
      given).
!     If set to false, <productname>PostgreSQL</productname> will commit
!     the effects of commands only on receiving an explicit
!     <command>COMMIT</> command.  This mode can also be thought of as
!     implicitly issuing <command>BEGIN</> whenever a command is received
!     and <productname>PostgreSQL</productname> is not already inside
!     a transaction block.
!     The default is true, for compatibility with historical
!     <productname>PostgreSQL</productname> behavior.  But for maximum
!     compatibility with the SQL specification, set it to false.
         </para>
        </listitem>
       </varlistentry>

--- 1235,1266 ----
      that is not inside an explicit transaction block (that is, unless a
      <command>BEGIN</> with no matching <command>COMMIT</> has been
      given).
!     If set to false, <productname>PostgreSQL</productname> will
!     commit the commands only when receiving an explicit
!     <command>COMMIT</> command. This mode can also be thought of as
!     implicitly issuing <command>BEGIN</> whenever a command is
!     received that is not already inside a transaction block. The
!     default is true, for compatibility with historical
!     <productname>PostgreSQL</productname> behavior. However, for
!     maximum compatibility with the SQL specification, set it to
!     false.
         </para>
+        <note>
+         <para>
+      With <varname>autocommit</> set to false, <command>SET</>,
+      <command>SHOW</>, and <command>RESET</> do not start new
+      transaction blocks. They are run in their own transactions.
+      Once another command is issued, multi-statement transaction
+      behavior begins and any <command>SET</>, <command>SHOW</>, or
+      <command>RESET</> commands are considered to be part of the
+      transaction, i.e. they are committed or rolled back depending
+      on the completion status of the transaction. To have
+      <command>SET</>, <command>SHOW</>, and <command>RESET</>
+      commands at the start of a transaction, use <command>BEGIN</>
+      first.
+         </para>
+        </note>
+
        </listitem>
       </varlistentry>

Index: doc/src/sgml/ref/reset.sgml
===================================================================
RCS file: /cvsroot/pgsql-server/doc/src/sgml/ref/reset.sgml,v
retrieving revision 1.15
diff -c -c -r1.15 reset.sgml
*** doc/src/sgml/ref/reset.sgml    21 Sep 2002 18:32:54 -0000    1.15
--- doc/src/sgml/ref/reset.sgml    9 Oct 2002 04:55:23 -0000
***************
*** 66,71 ****
--- 66,77 ----
     switches, or per-database or per-user default settings.  See the
     <citetitle>Administrator's Guide</citetitle> for details.
    </para>
+
+   <para>
+    See the <command>SHOW</> manual page for details on the transaction
+    behavior of <command>RESET</>.
+   </para>
+
   </refsect1>

   <refsect1>
Index: doc/src/sgml/ref/set.sgml
===================================================================
RCS file: /cvsroot/pgsql-server/doc/src/sgml/ref/set.sgml,v
retrieving revision 1.65
diff -c -c -r1.65 set.sgml
*** doc/src/sgml/ref/set.sgml    21 Sep 2002 18:32:54 -0000    1.65
--- doc/src/sgml/ref/set.sgml    9 Oct 2002 04:55:25 -0000
***************
*** 109,114 ****
--- 109,120 ----
    </para>

    <para>
+    With <literal>autocommit</> set to <literal>off</>, <command>SET</>
+    does not start a new transaction block. See the
+    <literal>autocommit</> section of the documentation for details.
+   </para>
+
+   <para>
     Here are additional details about a few of the parameters that can be set:

     <variablelist>
Index: src/backend/tcop/postgres.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/tcop/postgres.c,v
retrieving revision 1.299
diff -c -c -r1.299 postgres.c
*** src/backend/tcop/postgres.c    8 Oct 2002 17:17:19 -0000    1.299
--- src/backend/tcop/postgres.c    9 Oct 2002 04:55:35 -0000
***************
*** 76,81 ****
--- 76,82 ----
  CommandDest whereToSendOutput = Debug;

  extern int    StatementTimeout;
+ extern bool autocommit;

  static bool dontExecute = false;

***************
*** 122,128 ****
  static List *pg_parse_query(StringInfo query_string, Oid *typev, int nargs);
  static List *pg_analyze_and_rewrite(Node *parsetree);
  static void start_xact_command(void);
! static void finish_xact_command(void);
  static void SigHupHandler(SIGNAL_ARGS);
  static void FloatExceptionHandler(SIGNAL_ARGS);
  static const char *CreateCommandTag(Node *parsetree);
--- 123,129 ----
  static List *pg_parse_query(StringInfo query_string, Oid *typev, int nargs);
  static List *pg_analyze_and_rewrite(Node *parsetree);
  static void start_xact_command(void);
! static void finish_xact_command(bool forceCommit);
  static void SigHupHandler(SIGNAL_ARGS);
  static void FloatExceptionHandler(SIGNAL_ARGS);
  static const char *CreateCommandTag(Node *parsetree);
***************
*** 825,831 ****
               */
              if (isTransactionStmt)
              {
!                 finish_xact_command();
                  xact_started = false;
              }
          }                        /* end loop over queries generated from a
--- 826,832 ----
               */
              if (isTransactionStmt)
              {
!                 finish_xact_command(false);
                  xact_started = false;
              }
          }                        /* end loop over queries generated from a
***************
*** 843,849 ****
           */
          if (lnext(parsetree_item) == NIL && xact_started)
          {
!             finish_xact_command();
              xact_started = false;
          }

--- 844,862 ----
           */
          if (lnext(parsetree_item) == NIL && xact_started)
          {
!             /*
!              *    Don't allow SET/SHOW/RESET to start a new transaction
!              *    with autocommit off.  We do this by forcing a COMMIT
!              *    when these commands start a transaction.
!              */
!             if (autocommit ||
!                 IsTransactionState() ||
!                 (strcmp(commandTag, "SET") != 0 &&
!                  strcmp(commandTag, "SHOW") != 0 &&
!                  strcmp(commandTag, "RESET") != 0))
!                 finish_xact_command(false);
!             else
!                 finish_xact_command(true);
              xact_started = false;
          }

***************
*** 878,884 ****
       * will only happen if the querystring was empty.)
       */
      if (xact_started)
!         finish_xact_command();

      if (save_Log_duration)
      {
--- 891,897 ----
       * will only happen if the querystring was empty.)
       */
      if (xact_started)
!         finish_xact_command(false);

      if (save_Log_duration)
      {
***************
*** 907,913 ****
  }

  static void
! finish_xact_command(void)
  {
      /* Invoke IMMEDIATE constraint triggers */
      DeferredTriggerEndQuery();
--- 920,926 ----
  }

  static void
! finish_xact_command(bool forceCommit)
  {
      /* Invoke IMMEDIATE constraint triggers */
      DeferredTriggerEndQuery();
***************
*** 915,921 ****
      /* Now commit the command */
      elog(DEBUG1, "CommitTransactionCommand");

!     CommitTransactionCommand(false);

  #ifdef SHOW_MEMORY_STATS
      /* Print mem stats at each commit for leak tracking */
--- 928,934 ----
      /* Now commit the command */
      elog(DEBUG1, "CommitTransactionCommand");

!     CommitTransactionCommand(forceCommit);

  #ifdef SHOW_MEMORY_STATS
      /* Print mem stats at each commit for leak tracking */
***************
*** 1923,1929 ****
                  }

                  /* commit the function-invocation transaction */
!                 finish_xact_command();
                  break;

                  /*
--- 1936,1942 ----
                  }

                  /* commit the function-invocation transaction */
!                 finish_xact_command(false);
                  break;

                  /*

pgsql-patches by date:

Previous
From: Bruce Momjian
Date:
Subject: Re: inline newNode()
Next
From: Bruce Momjian
Date:
Subject: Re: inline newNode()