]> granicus.if.org Git - postgresql/commitdiff
Issue error on SET outside transaction block in some cases
authorBruce Momjian <bruce@momjian.us>
Fri, 4 Oct 2013 17:50:28 +0000 (13:50 -0400)
committerBruce Momjian <bruce@momjian.us>
Fri, 4 Oct 2013 17:50:28 +0000 (13:50 -0400)
Issue error for SET LOCAL/CONSTRAINTS/TRANSACTION outside a transaction
block, as they have no effect.

Per suggestion from Morten Hustveit

doc/src/sgml/ref/set.sgml
doc/src/sgml/ref/set_constraints.sgml
doc/src/sgml/ref/set_transaction.sgml
src/backend/tcop/utility.c
src/backend/utils/misc/guc.c
src/include/utils/guc.h
src/test/regress/expected/guc.out

index 21745db4627bc90c2ab400ff851c20f71354fcca..d108dd4831c56757ccabd394406c2ec976a0fa6b 100644 (file)
@@ -110,10 +110,9 @@ 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.  Note that
-      <command>SET LOCAL</> will appear to have no effect if it is
-      executed outside a <command>BEGIN</> block, since the
-      transaction will end immediately.
+      the session-level setting takes effect again.
+      <productname>PostgreSQL</productname> reports an error if
+      <command>SET LOCAL</> is used outside a transaction block.
      </para>
     </listitem>
    </varlistentry>
index 8098b7b66782df8c78a11dfbe5695b87c4f5faf0..895a5fdbc0ec60463e387d7101140c74b91c7f38 100644 (file)
@@ -102,7 +102,7 @@ SET CONSTRAINTS { ALL | <replaceable class="parameter">name</replaceable> [, ...
    current transaction. Thus, if you execute this command outside of a
    transaction block
    (<command>BEGIN</command>/<command>COMMIT</command> pair), it will
-   not appear to have any effect.
+   generate an error.
   </para>
  </refsect1>
 
index f0607296802a3ba3a083ef33d4b785d64e2d1853..391464ade8380d1c20667e935bbfa0ad52ea84cc 100644 (file)
@@ -184,9 +184,8 @@ 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 appear to have no effect, since the transaction will immediately
-   end.
+   <command>START TRANSACTION</command> or <command>BEGIN</command>,
+   it will generate an error.
   </para>
 
   <para>
index fffaa35d344d808a713738a92feb9ba9831727fb..6a7bf0de7d72ee111f896bb5d513f6a0b872f955 100644 (file)
@@ -688,7 +688,7 @@ standard_ProcessUtility(Node *parsetree,
                        break;
 
                case T_VariableSetStmt:
-                       ExecSetVariableStmt((VariableSetStmt *) parsetree);
+                       ExecSetVariableStmt((VariableSetStmt *) parsetree, isTopLevel);
                        break;
 
                case T_VariableShowStmt:
@@ -754,6 +754,7 @@ standard_ProcessUtility(Node *parsetree,
                        break;
 
                case T_ConstraintsSetStmt:
+                       RequireTransactionChain(isTopLevel, "SET CONSTRAINTS");
                        AfterTriggerSetState((ConstraintsSetStmt *) parsetree);
                        break;
 
index 3107f9cf0274177a88d5974128f7c64e18d334ad..d9a06b4d881bdbe7b71edfedc2f65e8c1b48be38 100644 (file)
@@ -6252,7 +6252,7 @@ flatten_set_variable_args(const char *name, List *args)
  * SET command
  */
 void
-ExecSetVariableStmt(VariableSetStmt *stmt)
+ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel)
 {
        GucAction       action = stmt->is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET;
 
@@ -6260,6 +6260,8 @@ ExecSetVariableStmt(VariableSetStmt *stmt)
        {
                case VAR_SET_VALUE:
                case VAR_SET_CURRENT:
+                       if (stmt->is_local)
+                               RequireTransactionChain(isTopLevel, "SET LOCAL");
                        (void) set_config_option(stmt->name,
                                                                         ExtractSetVariableArgs(stmt),
                                                                         (superuser() ? PGC_SUSET : PGC_USERSET),
@@ -6269,7 +6271,6 @@ ExecSetVariableStmt(VariableSetStmt *stmt)
                                                                         0);
                        break;
                case VAR_SET_MULTI:
-
                        /*
                         * Special-case SQL syntaxes.  The TRANSACTION and SESSION
                         * CHARACTERISTICS cases effectively set more than one variable
@@ -6281,6 +6282,8 @@ ExecSetVariableStmt(VariableSetStmt *stmt)
                        {
                                ListCell   *head;
 
+                               RequireTransactionChain(isTopLevel, "SET TRANSACTION");
+
                                foreach(head, stmt->args)
                                {
                                        DefElem    *item = (DefElem *) lfirst(head);
@@ -6329,6 +6332,8 @@ ExecSetVariableStmt(VariableSetStmt *stmt)
                                        ereport(ERROR,
                                                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                                         errmsg("SET LOCAL TRANSACTION SNAPSHOT is not implemented")));
+
+                               RequireTransactionChain(isTopLevel, "SET TRANSACTION");
                                Assert(IsA(con, A_Const));
                                Assert(nodeTag(&con->val) == T_String);
                                ImportSnapshot(strVal(&con->val));
@@ -6338,7 +6343,13 @@ ExecSetVariableStmt(VariableSetStmt *stmt)
                                         stmt->name);
                        break;
                case VAR_SET_DEFAULT:
+                       if (stmt->is_local)
+                               RequireTransactionChain(isTopLevel, "SET LOCAL");
+                       /* fall through */
                case VAR_RESET:
+                       if (strcmp(stmt->name, "transaction_isolation") == 0)
+                               RequireTransactionChain(isTopLevel, "RESET TRANSACTION");
+
                        (void) set_config_option(stmt->name,
                                                                         NULL,
                                                                         (superuser() ? PGC_SUSET : PGC_USERSET),
index 99211c1f6c3313e393051bb818c49e63e5695a8d..89ee40c334a1eddd9a945f33d011c170a45a07a4 100644 (file)
@@ -334,7 +334,7 @@ extern void SetPGVariable(const char *name, List *args, bool is_local);
 extern void GetPGVariable(const char *name, DestReceiver *dest);
 extern TupleDesc GetPGVariableResultDesc(const char *name);
 
-extern void ExecSetVariableStmt(VariableSetStmt *stmt);
+extern void ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel);
 extern char *ExtractSetVariableArgs(VariableSetStmt *stmt);
 
 extern void ProcessGUCArray(ArrayType *array,
index 7b5a624eb8faf7fa7a0af93236301a2fb31d7e54..203fa6ef8ea2488e05c8c491f7eab50f2dedc6c7 100644 (file)
@@ -29,6 +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
 SHOW vacuum_cost_delay;
  vacuum_cost_delay 
 -------------------
@@ -36,6 +37,7 @@ SHOW vacuum_cost_delay;
 (1 row)
 
 SET LOCAL datestyle = 'SQL';
+ERROR:  SET LOCAL can only be used in transaction blocks
 SHOW datestyle;
  DateStyle 
 -----------