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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy