Change SET LOCAL/CONSTRAINTS/TRANSACTION and ABORT behavior
authorBruce Momjian <bruce@momjian.us>
Tue, 26 Nov 2013 00:19:40 +0000 (19:19 -0500)
committerBruce Momjian <bruce@momjian.us>
Tue, 26 Nov 2013 00:19:40 +0000 (19:19 -0500)
Change SET LOCAL/CONSTRAINTS/TRANSACTION behavior outside of a
transaction block from error (post-9.3) to warning.  (Was nothing in <=
9.3.)  Also change ABORT outside of a transaction block from notice to
warning.

doc/src/sgml/ref/abort.sgml
doc/src/sgml/ref/rollback.sgml
doc/src/sgml/ref/set.sgml
doc/src/sgml/ref/set_constraints.sgml
doc/src/sgml/ref/set_transaction.sgml
src/backend/access/transam/xact.c
src/backend/tcop/utility.c
src/backend/utils/misc/guc.c
src/include/access/xact.h
src/test/regress/expected/errors.out
src/test/regress/expected/guc.out

index 246e8f812687b82ce0b0e269111c974544d90bb2..f3a2fa88ff19be0fdadf00459f07fd59151f2625 100644 (file)
@@ -63,8 +63,7 @@ ABORT [ WORK | TRANSACTION ]
   </para>
 
   <para>
-   Issuing <command>ABORT</> when not inside a transaction does
-   no harm, but it will provoke a warning message.
+   Issuing <command>ABORT</> outside of a transaction block has no effect.
   </para>
  </refsect1>
 
index b26554567dbd001b8121f892ff8dc14d83ed988b..4f7962117c8acee850fe702ee141f8e1ad9c97d5 100644 (file)
@@ -59,8 +59,8 @@ ROLLBACK [ WORK | TRANSACTION ]
   </para>
 
   <para>
-   Issuing <command>ROLLBACK</> when not inside a transaction does
-   no harm, but it will provoke a warning message.
+   Issuing <command>ROLLBACK</> outside of a transaction
+   block has no effect.
   </para>
  </refsect1>
 
index 6290c9de70852cb6cb502b9e4804e456fe7c9973..5a84f697e675869fefeba596db7ec13782bc12f8 100644 (file)
@@ -110,9 +110,8 @@ SET [ SESSION | LOCAL ] TIME ZONE { <replaceable class="PARAMETER">timezone</rep
      <para>
       Specifies that the command takes effect for only the current
       transaction.  After <command>COMMIT</> or <command>ROLLBACK</>,
-      the session-level setting takes effect again.
-      <productname>PostgreSQL</productname> reports an error if
-      <command>SET LOCAL</> is used outside a transaction block.
+      the session-level setting takes effect again.  This has no effect
+      outside of a transaction block.
      </para>
     </listitem>
    </varlistentry>
index 895a5fdbc0ec60463e387d7101140c74b91c7f38..a33190cca81f884b8d2da9cb85ead8a810c3fe79 100644 (file)
@@ -99,10 +99,7 @@ SET CONSTRAINTS { ALL | <replaceable class="parameter">name</replaceable> [, ...
 
   <para>
    This command only alters the behavior of constraints within the
-   current transaction. Thus, if you execute this command outside of a
-   transaction block
-   (<command>BEGIN</command>/<command>COMMIT</command> pair), it will
-   generate an error.
+   current transaction.  This has no effect outside of a transaction block.
   </para>
  </refsect1>
 
index 391464ade8380d1c20667e935bbfa0ad52ea84cc..e90ff4af725b9ea07cc205c359d8a7dac9f82910 100644 (file)
@@ -185,7 +185,7 @@ SET SESSION CHARACTERISTICS AS TRANSACTION <replaceable class="parameter">transa
   <para>
    If <command>SET TRANSACTION</command> is executed without a prior
    <command>START TRANSACTION</command> or <command>BEGIN</command>,
-   it will generate an error.
+   it will have no effect.
   </para>
 
   <para>
index 0591f3fd56210d3f4902fce03392f5fc12ec931b..bab048d38a15703a36b4b92c7305b20515a28a77 100644 (file)
@@ -265,6 +265,8 @@ static void CallSubXactCallbacks(SubXactEvent event,
                     SubTransactionId mySubid,
                     SubTransactionId parentSubid);
 static void CleanupTransaction(void);
+static void CheckTransactionChain(bool isTopLevel, bool throwError,
+                    const char *stmtType);
 static void CommitTransaction(void);
 static TransactionId RecordTransactionAbort(bool isSubXact);
 static void StartTransaction(void);
@@ -2948,6 +2950,26 @@ PreventTransactionChain(bool isTopLevel, const char *stmtType)
    /* all okay */
 }
 
+/*
+ * These two functions allow for warnings or errors if a command is
+ * executed outside of a transaction block.
+ *
+ * While top-level transaction control commands (BEGIN/COMMIT/ABORT) and
+ * SET that have no effect issue warnings, all other no-effect commands
+ * generate errors.
+ */
+void
+WarnNoTransactionChain(bool isTopLevel, const char *stmtType)
+{
+   CheckTransactionChain(isTopLevel, false, stmtType);
+}
+
+void
+RequireTransactionChain(bool isTopLevel, const char *stmtType)
+{
+   CheckTransactionChain(isTopLevel, true, stmtType);
+}
+
 /*
  * RequireTransactionChain
  *
@@ -2957,16 +2979,16 @@ PreventTransactionChain(bool isTopLevel, const char *stmtType)
  * is presumably an error).  DECLARE CURSOR is an example.
  *
  * If we appear to be running inside a user-defined function, we do not
- * issue an error, since the function could issue more commands that make
+ * issue anything, since the function could issue more commands that make
  * use of the current statement's results.  Likewise subtransactions.
  * Thus this is an inverse for PreventTransactionChain.
  *
  * isTopLevel: passed down from ProcessUtility to determine whether we are
  * inside a function.
- * stmtType: statement type name, for error messages.
+ * stmtType: statement type name, for warning or error messages.
  */
-void
-RequireTransactionChain(bool isTopLevel, const char *stmtType)
+static void
+CheckTransactionChain(bool isTopLevel, bool throwError, const char *stmtType)
 {
    /*
     * xact block already started?
@@ -2986,11 +3008,12 @@ RequireTransactionChain(bool isTopLevel, const char *stmtType)
    if (!isTopLevel)
        return;
 
-   ereport(ERROR,
+   ereport(throwError ? ERROR : WARNING,
            (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
    /* translator: %s represents an SQL statement name */
             errmsg("%s can only be used in transaction blocks",
                    stmtType)));
+   return;
 }
 
 /*
@@ -3425,12 +3448,12 @@ UserAbortTransactionBlock(void)
 
            /*
             * The user issued ABORT when not inside a transaction. Issue a
-            * NOTICE and go to abort state.  The upcoming call to
+            * WARNING and go to abort state.  The upcoming call to
             * CommitTransactionCommand() will then put us back into the
             * default state.
             */
        case TBLOCK_STARTED:
-           ereport(NOTICE,
+           ereport(WARNING,
                    (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
                     errmsg("there is no transaction in progress")));
            s->blockState = TBLOCK_ABORT_PENDING;
index 6a7bf0de7d72ee111f896bb5d513f6a0b872f955..5895102b518460490ebbc8be7bce723c06249bde 100644 (file)
@@ -754,7 +754,7 @@ standard_ProcessUtility(Node *parsetree,
            break;
 
        case T_ConstraintsSetStmt:
-           RequireTransactionChain(isTopLevel, "SET CONSTRAINTS");
+           WarnNoTransactionChain(isTopLevel, "SET CONSTRAINTS");
            AfterTriggerSetState((ConstraintsSetStmt *) parsetree);
            break;
 
index 54d8078fe7a9e8aa13ca324a34e4f77b45e31123..cbf3186789c57168837e086a5f500601d2ab04ae 100644 (file)
@@ -6274,7 +6274,7 @@ ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel)
        case VAR_SET_VALUE:
        case VAR_SET_CURRENT:
            if (stmt->is_local)
-               RequireTransactionChain(isTopLevel, "SET LOCAL");
+               WarnNoTransactionChain(isTopLevel, "SET LOCAL");
            (void) set_config_option(stmt->name,
                                     ExtractSetVariableArgs(stmt),
                                     (superuser() ? PGC_SUSET : PGC_USERSET),
@@ -6295,7 +6295,7 @@ ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel)
            {
                ListCell   *head;
 
-               RequireTransactionChain(isTopLevel, "SET TRANSACTION");
+               WarnNoTransactionChain(isTopLevel, "SET TRANSACTION");
 
                foreach(head, stmt->args)
                {
@@ -6346,7 +6346,7 @@ ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel)
                            (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                             errmsg("SET LOCAL TRANSACTION SNAPSHOT is not implemented")));
 
-               RequireTransactionChain(isTopLevel, "SET TRANSACTION");
+               WarnNoTransactionChain(isTopLevel, "SET TRANSACTION");
                Assert(IsA(con, A_Const));
                Assert(nodeTag(&con->val) == T_String);
                ImportSnapshot(strVal(&con->val));
@@ -6357,11 +6357,11 @@ ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel)
            break;
        case VAR_SET_DEFAULT:
            if (stmt->is_local)
-               RequireTransactionChain(isTopLevel, "SET LOCAL");
+               WarnNoTransactionChain(isTopLevel, "SET LOCAL");
            /* fall through */
        case VAR_RESET:
            if (strcmp(stmt->name, "transaction_isolation") == 0)
-               RequireTransactionChain(isTopLevel, "RESET TRANSACTION");
+               WarnNoTransactionChain(isTopLevel, "RESET TRANSACTION");
 
            (void) set_config_option(stmt->name,
                                     NULL,
index 835f6acbee0e10ee51e5a2295429efd5141e3b77..1d3e7d8938adf35256077995898226fd02d6d639 100644 (file)
@@ -245,6 +245,7 @@ extern char TransactionBlockStatusCode(void);
 extern void AbortOutOfAnyTransaction(void);
 extern void PreventTransactionChain(bool isTopLevel, const char *stmtType);
 extern void RequireTransactionChain(bool isTopLevel, const char *stmtType);
+extern void WarnNoTransactionChain(bool isTopLevel, const char *stmtType);
 extern bool IsInTransactionChain(bool isTopLevel);
 extern void RegisterXactCallback(XactCallback callback, void *arg);
 extern void UnregisterXactCallback(XactCallback callback, void *arg);
index fa0bd82819a89e1702b4cd26957dd9988420cfbc..4061512977845bfce2150c46e9d954365f0ee404 100644 (file)
@@ -114,7 +114,7 @@ ERROR:  column name "oid" conflicts with a system column name
 -- TRANSACTION STUFF
 -- not in a xact
 abort;
-NOTICE:  there is no transaction in progress
+WARNING:  there is no transaction in progress
 -- not in a xact
 end;
 WARNING:  there is no transaction in progress
index 203fa6ef8ea2488e05c8c491f7eab50f2dedc6c7..4f0065cb7efb845652b520f1ab8a2ae20645c962 100644 (file)
@@ -29,7 +29,7 @@ SELECT '2006-08-13 12:34:56'::timestamptz;
 
 -- SET LOCAL has no effect outside of a transaction
 SET LOCAL vacuum_cost_delay TO 50;
-ERROR:  SET LOCAL can only be used in transaction blocks
+WARNING:  SET LOCAL can only be used in transaction blocks
 SHOW vacuum_cost_delay;
  vacuum_cost_delay 
 -------------------
@@ -37,7 +37,7 @@ SHOW vacuum_cost_delay;
 (1 row)
 
 SET LOCAL datestyle = 'SQL';
-ERROR:  SET LOCAL can only be used in transaction blocks
+WARNING:  SET LOCAL can only be used in transaction blocks
 SHOW datestyle;
  DateStyle 
 -----------