mirror of
https://github.com/postgres/postgres.git
synced 2025-06-05 00:02:04 -04:00
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
This commit is contained in:
parent
4655b607f3
commit
a54141aebc
@ -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> [, ...
|
|||||||
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
|
|||||||
|
|
||||||
<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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
* 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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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)
|
|||||||
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);
|
|||||||
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;
|
|||||||
|
|
||||||
-- 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;
|
|||||||
(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
|
||||||
-----------
|
-----------
|
||||||
|
Loading…
x
Reference in New Issue
Block a user