diff options
author | Bruce Momjian | 2013-10-04 17:50:28 +0000 |
---|---|---|
committer | Bruce Momjian | 2013-10-04 17:50:28 +0000 |
commit | a54141aebcafa02cba5204596758dadbbeb0f78e (patch) | |
tree | 0aaccd0fb99565c20d8449f8d2bbe6a5cdbb042c | |
parent | 4655b607f34836ae19f262bfdfe95c0be74d920c (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.sgml | 7 | ||||
-rw-r--r-- | doc/src/sgml/ref/set_constraints.sgml | 2 | ||||
-rw-r--r-- | doc/src/sgml/ref/set_transaction.sgml | 5 | ||||
-rw-r--r-- | src/backend/tcop/utility.c | 3 | ||||
-rw-r--r-- | src/backend/utils/misc/guc.c | 15 | ||||
-rw-r--r-- | src/include/utils/guc.h | 2 | ||||
-rw-r--r-- | src/test/regress/expected/guc.out | 2 |
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 ----------- |