Skip to content

Commit a54141a

Browse files
committed
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
1 parent 4655b60 commit a54141a

File tree

7 files changed

+24
-12
lines changed

7 files changed

+24
-12
lines changed

doc/src/sgml/ref/set.sgml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,9 @@ SET [ SESSION | LOCAL ] TIME ZONE { <replaceable class="PARAMETER">timezone</rep
110110
<para>
111111
Specifies that the command takes effect for only the current
112112
transaction. After <command>COMMIT</> or <command>ROLLBACK</>,
113-
the session-level setting takes effect again. Note that
114-
<command>SET LOCAL</> will appear to have no effect if it is
115-
executed outside a <command>BEGIN</> block, since the
116-
transaction will end immediately.
113+
the session-level setting takes effect again.
114+
<productname>PostgreSQL</productname> reports an error if
115+
<command>SET LOCAL</> is used outside a transaction block.
117116
</para>
118117
</listitem>
119118
</varlistentry>

doc/src/sgml/ref/set_constraints.sgml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ SET CONSTRAINTS { ALL | <replaceable class="parameter">name</replaceable> [, ...
102102
current transaction. Thus, if you execute this command outside of a
103103
transaction block
104104
(<command>BEGIN</command>/<command>COMMIT</command> pair), it will
105-
not appear to have any effect.
105+
generate an error.
106106
</para>
107107
</refsect1>
108108

doc/src/sgml/ref/set_transaction.sgml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,9 +184,8 @@ SET SESSION CHARACTERISTICS AS TRANSACTION <replaceable class="parameter">transa
184184

185185
<para>
186186
If <command>SET TRANSACTION</command> is executed without a prior
187-
<command>START TRANSACTION</command> or <command>BEGIN</command>,
188-
it will appear to have no effect, since the transaction will immediately
189-
end.
187+
<command>START TRANSACTION</command> or <command>BEGIN</command>,
188+
it will generate an error.
190189
</para>
191190

192191
<para>

src/backend/tcop/utility.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -688,7 +688,7 @@ standard_ProcessUtility(Node *parsetree,
688688
break;
689689

690690
case T_VariableSetStmt:
691-
ExecSetVariableStmt((VariableSetStmt *) parsetree);
691+
ExecSetVariableStmt((VariableSetStmt *) parsetree, isTopLevel);
692692
break;
693693

694694
case T_VariableShowStmt:
@@ -754,6 +754,7 @@ standard_ProcessUtility(Node *parsetree,
754754
break;
755755

756756
case T_ConstraintsSetStmt:
757+
RequireTransactionChain(isTopLevel, "SET CONSTRAINTS");
757758
AfterTriggerSetState((ConstraintsSetStmt *) parsetree);
758759
break;
759760

src/backend/utils/misc/guc.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6252,14 +6252,16 @@ flatten_set_variable_args(const char *name, List *args)
62526252
* SET command
62536253
*/
62546254
void
6255-
ExecSetVariableStmt(VariableSetStmt *stmt)
6255+
ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel)
62566256
{
62576257
GucAction action = stmt->is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET;
62586258

62596259
switch (stmt->kind)
62606260
{
62616261
case VAR_SET_VALUE:
62626262
case VAR_SET_CURRENT:
6263+
if (stmt->is_local)
6264+
RequireTransactionChain(isTopLevel, "SET LOCAL");
62636265
(void) set_config_option(stmt->name,
62646266
ExtractSetVariableArgs(stmt),
62656267
(superuser() ? PGC_SUSET : PGC_USERSET),
@@ -6269,7 +6271,6 @@ ExecSetVariableStmt(VariableSetStmt *stmt)
62696271
0);
62706272
break;
62716273
case VAR_SET_MULTI:
6272-
62736274
/*
62746275
* Special-case SQL syntaxes. The TRANSACTION and SESSION
62756276
* CHARACTERISTICS cases effectively set more than one variable
@@ -6281,6 +6282,8 @@ ExecSetVariableStmt(VariableSetStmt *stmt)
62816282
{
62826283
ListCell *head;
62836284

6285+
RequireTransactionChain(isTopLevel, "SET TRANSACTION");
6286+
62846287
foreach(head, stmt->args)
62856288
{
62866289
DefElem *item = (DefElem *) lfirst(head);
@@ -6329,6 +6332,8 @@ ExecSetVariableStmt(VariableSetStmt *stmt)
63296332
ereport(ERROR,
63306333
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
63316334
errmsg("SET LOCAL TRANSACTION SNAPSHOT is not implemented")));
6335+
6336+
RequireTransactionChain(isTopLevel, "SET TRANSACTION");
63326337
Assert(IsA(con, A_Const));
63336338
Assert(nodeTag(&con->val) == T_String);
63346339
ImportSnapshot(strVal(&con->val));
@@ -6338,7 +6343,13 @@ ExecSetVariableStmt(VariableSetStmt *stmt)
63386343
stmt->name);
63396344
break;
63406345
case VAR_SET_DEFAULT:
6346+
if (stmt->is_local)
6347+
RequireTransactionChain(isTopLevel, "SET LOCAL");
6348+
/* fall through */
63416349
case VAR_RESET:
6350+
if (strcmp(stmt->name, "transaction_isolation") == 0)
6351+
RequireTransactionChain(isTopLevel, "RESET TRANSACTION");
6352+
63426353
(void) set_config_option(stmt->name,
63436354
NULL,
63446355
(superuser() ? PGC_SUSET : PGC_USERSET),

src/include/utils/guc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ extern void SetPGVariable(const char *name, List *args, bool is_local);
334334
extern void GetPGVariable(const char *name, DestReceiver *dest);
335335
extern TupleDesc GetPGVariableResultDesc(const char *name);
336336

337-
extern void ExecSetVariableStmt(VariableSetStmt *stmt);
337+
extern void ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel);
338338
extern char *ExtractSetVariableArgs(VariableSetStmt *stmt);
339339

340340
extern void ProcessGUCArray(ArrayType *array,

src/test/regress/expected/guc.out

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,15 @@ SELECT '2006-08-13 12:34:56'::timestamptz;
2929

3030
-- SET LOCAL has no effect outside of a transaction
3131
SET LOCAL vacuum_cost_delay TO 50;
32+
ERROR: SET LOCAL can only be used in transaction blocks
3233
SHOW vacuum_cost_delay;
3334
vacuum_cost_delay
3435
-------------------
3536
40ms
3637
(1 row)
3738

3839
SET LOCAL datestyle = 'SQL';
40+
ERROR: SET LOCAL can only be used in transaction blocks
3941
SHOW datestyle;
4042
DateStyle
4143
-----------

0 commit comments

Comments
 (0)