Commit a54141ae authored by Bruce Momjian's avatar Bruce Momjian

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
parent 4655b607
...@@ -110,10 +110,9 @@ SET [ SESSION | LOCAL ] TIME ZONE { <replaceable class="PARAMETER">timezone</rep ...@@ -110,10 +110,9 @@ SET [ SESSION | LOCAL ] TIME ZONE { <replaceable class="PARAMETER">timezone</rep
<para> <para>
Specifies that the command takes effect for only the current Specifies that the command takes effect for only the current
transaction. After <command>COMMIT</> or <command>ROLLBACK</>, transaction. After <command>COMMIT</> or <command>ROLLBACK</>,
the session-level setting takes effect again. Note that the session-level setting takes effect again.
<command>SET LOCAL</> will appear to have no effect if it is <productname>PostgreSQL</productname> reports an error if
executed outside a <command>BEGIN</> block, since the <command>SET LOCAL</> is used outside a transaction block.
transaction will end immediately.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
......
...@@ -102,7 +102,7 @@ SET CONSTRAINTS { ALL | <replaceable class="parameter">name</replaceable> [, ... ...@@ -102,7 +102,7 @@ SET CONSTRAINTS { ALL | <replaceable class="parameter">name</replaceable> [, ...
current transaction. Thus, if you execute this command outside of a current transaction. Thus, if you execute this command outside of a
transaction block transaction block
(<command>BEGIN</command>/<command>COMMIT</command> pair), it will (<command>BEGIN</command>/<command>COMMIT</command> pair), it will
not appear to have any effect. generate an error.
</para> </para>
</refsect1> </refsect1>
......
...@@ -184,9 +184,8 @@ SET SESSION CHARACTERISTICS AS TRANSACTION <replaceable class="parameter">transa ...@@ -184,9 +184,8 @@ SET SESSION CHARACTERISTICS AS TRANSACTION <replaceable class="parameter">transa
<para> <para>
If <command>SET TRANSACTION</command> is executed without a prior If <command>SET TRANSACTION</command> is executed without a prior
<command>START TRANSACTION</command> or <command>BEGIN</command>, <command>START TRANSACTION</command> or <command>BEGIN</command>,
it will appear to have no effect, since the transaction will immediately it will generate an error.
end.
</para> </para>
<para> <para>
......
...@@ -688,7 +688,7 @@ standard_ProcessUtility(Node *parsetree, ...@@ -688,7 +688,7 @@ standard_ProcessUtility(Node *parsetree,
break; break;
case T_VariableSetStmt: case T_VariableSetStmt:
ExecSetVariableStmt((VariableSetStmt *) parsetree); ExecSetVariableStmt((VariableSetStmt *) parsetree, isTopLevel);
break; break;
case T_VariableShowStmt: case T_VariableShowStmt:
...@@ -754,6 +754,7 @@ standard_ProcessUtility(Node *parsetree, ...@@ -754,6 +754,7 @@ standard_ProcessUtility(Node *parsetree,
break; break;
case T_ConstraintsSetStmt: case T_ConstraintsSetStmt:
RequireTransactionChain(isTopLevel, "SET CONSTRAINTS");
AfterTriggerSetState((ConstraintsSetStmt *) parsetree); AfterTriggerSetState((ConstraintsSetStmt *) parsetree);
break; break;
......
...@@ -6252,7 +6252,7 @@ flatten_set_variable_args(const char *name, List *args) ...@@ -6252,7 +6252,7 @@ flatten_set_variable_args(const char *name, List *args)
* SET command * SET command
*/ */
void void
ExecSetVariableStmt(VariableSetStmt *stmt) ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel)
{ {
GucAction action = stmt->is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET; GucAction action = stmt->is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET;
...@@ -6260,6 +6260,8 @@ ExecSetVariableStmt(VariableSetStmt *stmt) ...@@ -6260,6 +6260,8 @@ ExecSetVariableStmt(VariableSetStmt *stmt)
{ {
case VAR_SET_VALUE: case VAR_SET_VALUE:
case VAR_SET_CURRENT: case VAR_SET_CURRENT:
if (stmt->is_local)
RequireTransactionChain(isTopLevel, "SET LOCAL");
(void) set_config_option(stmt->name, (void) set_config_option(stmt->name,
ExtractSetVariableArgs(stmt), ExtractSetVariableArgs(stmt),
(superuser() ? PGC_SUSET : PGC_USERSET), (superuser() ? PGC_SUSET : PGC_USERSET),
...@@ -6269,7 +6271,6 @@ ExecSetVariableStmt(VariableSetStmt *stmt) ...@@ -6269,7 +6271,6 @@ ExecSetVariableStmt(VariableSetStmt *stmt)
0); 0);
break; break;
case VAR_SET_MULTI: case VAR_SET_MULTI:
/* /*
* Special-case SQL syntaxes. The TRANSACTION and SESSION * Special-case SQL syntaxes. The TRANSACTION and SESSION
* CHARACTERISTICS cases effectively set more than one variable * CHARACTERISTICS cases effectively set more than one variable
...@@ -6281,6 +6282,8 @@ ExecSetVariableStmt(VariableSetStmt *stmt) ...@@ -6281,6 +6282,8 @@ ExecSetVariableStmt(VariableSetStmt *stmt)
{ {
ListCell *head; ListCell *head;
RequireTransactionChain(isTopLevel, "SET TRANSACTION");
foreach(head, stmt->args) foreach(head, stmt->args)
{ {
DefElem *item = (DefElem *) lfirst(head); DefElem *item = (DefElem *) lfirst(head);
...@@ -6329,6 +6332,8 @@ ExecSetVariableStmt(VariableSetStmt *stmt) ...@@ -6329,6 +6332,8 @@ ExecSetVariableStmt(VariableSetStmt *stmt)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("SET LOCAL TRANSACTION SNAPSHOT is not implemented"))); errmsg("SET LOCAL TRANSACTION SNAPSHOT is not implemented")));
RequireTransactionChain(isTopLevel, "SET TRANSACTION");
Assert(IsA(con, A_Const)); Assert(IsA(con, A_Const));
Assert(nodeTag(&con->val) == T_String); Assert(nodeTag(&con->val) == T_String);
ImportSnapshot(strVal(&con->val)); ImportSnapshot(strVal(&con->val));
...@@ -6338,7 +6343,13 @@ ExecSetVariableStmt(VariableSetStmt *stmt) ...@@ -6338,7 +6343,13 @@ ExecSetVariableStmt(VariableSetStmt *stmt)
stmt->name); stmt->name);
break; break;
case VAR_SET_DEFAULT: case VAR_SET_DEFAULT:
if (stmt->is_local)
RequireTransactionChain(isTopLevel, "SET LOCAL");
/* fall through */
case VAR_RESET: case VAR_RESET:
if (strcmp(stmt->name, "transaction_isolation") == 0)
RequireTransactionChain(isTopLevel, "RESET TRANSACTION");
(void) set_config_option(stmt->name, (void) set_config_option(stmt->name,
NULL, NULL,
(superuser() ? PGC_SUSET : PGC_USERSET), (superuser() ? PGC_SUSET : PGC_USERSET),
......
...@@ -334,7 +334,7 @@ extern void SetPGVariable(const char *name, List *args, bool is_local); ...@@ -334,7 +334,7 @@ extern void SetPGVariable(const char *name, List *args, bool is_local);
extern void GetPGVariable(const char *name, DestReceiver *dest); extern void GetPGVariable(const char *name, DestReceiver *dest);
extern TupleDesc GetPGVariableResultDesc(const char *name); extern TupleDesc GetPGVariableResultDesc(const char *name);
extern void ExecSetVariableStmt(VariableSetStmt *stmt); extern void ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel);
extern char *ExtractSetVariableArgs(VariableSetStmt *stmt); extern char *ExtractSetVariableArgs(VariableSetStmt *stmt);
extern void ProcessGUCArray(ArrayType *array, extern void ProcessGUCArray(ArrayType *array,
......
...@@ -29,6 +29,7 @@ SELECT '2006-08-13 12:34:56'::timestamptz; ...@@ -29,6 +29,7 @@ SELECT '2006-08-13 12:34:56'::timestamptz;
-- SET LOCAL has no effect outside of a transaction -- SET LOCAL has no effect outside of a transaction
SET LOCAL vacuum_cost_delay TO 50; SET LOCAL vacuum_cost_delay TO 50;
ERROR: SET LOCAL can only be used in transaction blocks
SHOW vacuum_cost_delay; SHOW vacuum_cost_delay;
vacuum_cost_delay vacuum_cost_delay
------------------- -------------------
...@@ -36,6 +37,7 @@ SHOW vacuum_cost_delay; ...@@ -36,6 +37,7 @@ SHOW vacuum_cost_delay;
(1 row) (1 row)
SET LOCAL datestyle = 'SQL'; SET LOCAL datestyle = 'SQL';
ERROR: SET LOCAL can only be used in transaction blocks
SHOW datestyle; SHOW datestyle;
DateStyle DateStyle
----------- -----------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment