summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Momjian2013-10-04 17:50:28 +0000
committerBruce Momjian2013-10-04 17:50:28 +0000
commita54141aebcafa02cba5204596758dadbbeb0f78e (patch)
tree0aaccd0fb99565c20d8449f8d2bbe6a5cdbb042c
parent4655b607f34836ae19f262bfdfe95c0be74d920c (diff)
Issue error on SET outside transaction block in some cases
Issue error for SET LOCAL/CONSTRAINTS/TRANSACTION outside a transaction block, as they have no effect. Per suggestion from Morten Hustveit
-rw-r--r--doc/src/sgml/ref/set.sgml7
-rw-r--r--doc/src/sgml/ref/set_constraints.sgml2
-rw-r--r--doc/src/sgml/ref/set_transaction.sgml5
-rw-r--r--src/backend/tcop/utility.c3
-rw-r--r--src/backend/utils/misc/guc.c15
-rw-r--r--src/include/utils/guc.h2
-rw-r--r--src/test/regress/expected/guc.out2
7 files changed, 24 insertions, 12 deletions
diff --git a/doc/src/sgml/ref/set.sgml b/doc/src/sgml/ref/set.sgml
index 21745db4627..d108dd4831c 100644
--- a/doc/src/sgml/ref/set.sgml
+++ b/doc/src/sgml/ref/set.sgml
@@ -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>
diff --git a/doc/src/sgml/ref/set_constraints.sgml b/doc/src/sgml/ref/set_constraints.sgml
index 8098b7b6678..895a5fdbc0e 100644
--- a/doc/src/sgml/ref/set_constraints.sgml
+++ b/doc/src/sgml/ref/set_constraints.sgml
@@ -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>
diff --git a/doc/src/sgml/ref/set_transaction.sgml b/doc/src/sgml/ref/set_transaction.sgml
index f0607296802..391464ade83 100644
--- a/doc/src/sgml/ref/set_transaction.sgml
+++ b/doc/src/sgml/ref/set_transaction.sgml
@@ -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>
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index fffaa35d344..6a7bf0de7d7 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -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;
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 3107f9cf027..d9a06b4d881 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -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),
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 99211c1f6c3..89ee40c334a 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -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,
diff --git a/src/test/regress/expected/guc.out b/src/test/regress/expected/guc.out
index 7b5a624eb8f..203fa6ef8ea 100644
--- a/src/test/regress/expected/guc.out
+++ b/src/test/regress/expected/guc.out
@@ -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
-----------