<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>
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>
<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>
break;
case T_VariableSetStmt:
- ExecSetVariableStmt((VariableSetStmt *) parsetree);
+ ExecSetVariableStmt((VariableSetStmt *) parsetree, isTopLevel);
break;
case T_VariableShowStmt:
break;
case T_ConstraintsSetStmt:
+ RequireTransactionChain(isTopLevel, "SET CONSTRAINTS");
AfterTriggerSetState((ConstraintsSetStmt *) parsetree);
break;
* SET command
*/
void
-ExecSetVariableStmt(VariableSetStmt *stmt)
+ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel)
{
GucAction action = stmt->is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET;
{
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),
0);
break;
case VAR_SET_MULTI:
-
/*
* Special-case SQL syntaxes. The TRANSACTION and SESSION
* CHARACTERISTICS cases effectively set more than one variable
{
ListCell *head;
+ RequireTransactionChain(isTopLevel, "SET TRANSACTION");
+
foreach(head, stmt->args)
{
DefElem *item = (DefElem *) lfirst(head);
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));
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),
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,
-- 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
-------------------
(1 row)
SET LOCAL datestyle = 'SQL';
+ERROR: SET LOCAL can only be used in transaction blocks
SHOW datestyle;
DateStyle
-----------