mirror of
https://github.com/postgres/postgres.git
synced 2025-04-21 12:05:57 +03:00
Change SET LOCAL/CONSTRAINTS/TRANSACTION and ABORT behavior
Change SET LOCAL/CONSTRAINTS/TRANSACTION behavior outside of a transaction block from error (post-9.3) to warning. (Was nothing in <= 9.3.) Also change ABORT outside of a transaction block from notice to warning.
This commit is contained in:
parent
05b476c298
commit
a6542a4b68
@ -63,8 +63,7 @@ ABORT [ WORK | TRANSACTION ]
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Issuing <command>ABORT</> when not inside a transaction does
|
Issuing <command>ABORT</> outside of a transaction block has no effect.
|
||||||
no harm, but it will provoke a warning message.
|
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
@ -59,8 +59,8 @@ ROLLBACK [ WORK | TRANSACTION ]
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Issuing <command>ROLLBACK</> when not inside a transaction does
|
Issuing <command>ROLLBACK</> outside of a transaction
|
||||||
no harm, but it will provoke a warning message.
|
block has no effect.
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
@ -110,9 +110,8 @@ 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.
|
the session-level setting takes effect again. This has no effect
|
||||||
<productname>PostgreSQL</productname> reports an error if
|
outside of a transaction block.
|
||||||
<command>SET LOCAL</> is used outside a transaction block.
|
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
@ -99,10 +99,7 @@ SET CONSTRAINTS { ALL | <replaceable class="parameter">name</replaceable> [, ...
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
This command only alters the behavior of constraints within the
|
This command only alters the behavior of constraints within the
|
||||||
current transaction. Thus, if you execute this command outside of a
|
current transaction. This has no effect outside of a transaction block.
|
||||||
transaction block
|
|
||||||
(<command>BEGIN</command>/<command>COMMIT</command> pair), it will
|
|
||||||
generate an error.
|
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ 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 generate an error.
|
it will have no effect.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
@ -265,6 +265,8 @@ static void CallSubXactCallbacks(SubXactEvent event,
|
|||||||
SubTransactionId mySubid,
|
SubTransactionId mySubid,
|
||||||
SubTransactionId parentSubid);
|
SubTransactionId parentSubid);
|
||||||
static void CleanupTransaction(void);
|
static void CleanupTransaction(void);
|
||||||
|
static void CheckTransactionChain(bool isTopLevel, bool throwError,
|
||||||
|
const char *stmtType);
|
||||||
static void CommitTransaction(void);
|
static void CommitTransaction(void);
|
||||||
static TransactionId RecordTransactionAbort(bool isSubXact);
|
static TransactionId RecordTransactionAbort(bool isSubXact);
|
||||||
static void StartTransaction(void);
|
static void StartTransaction(void);
|
||||||
@ -2948,6 +2950,26 @@ PreventTransactionChain(bool isTopLevel, const char *stmtType)
|
|||||||
/* all okay */
|
/* all okay */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These two functions allow for warnings or errors if a command is
|
||||||
|
* executed outside of a transaction block.
|
||||||
|
*
|
||||||
|
* While top-level transaction control commands (BEGIN/COMMIT/ABORT) and
|
||||||
|
* SET that have no effect issue warnings, all other no-effect commands
|
||||||
|
* generate errors.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
WarnNoTransactionChain(bool isTopLevel, const char *stmtType)
|
||||||
|
{
|
||||||
|
CheckTransactionChain(isTopLevel, false, stmtType);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RequireTransactionChain(bool isTopLevel, const char *stmtType)
|
||||||
|
{
|
||||||
|
CheckTransactionChain(isTopLevel, true, stmtType);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RequireTransactionChain
|
* RequireTransactionChain
|
||||||
*
|
*
|
||||||
@ -2957,16 +2979,16 @@ PreventTransactionChain(bool isTopLevel, const char *stmtType)
|
|||||||
* is presumably an error). DECLARE CURSOR is an example.
|
* is presumably an error). DECLARE CURSOR is an example.
|
||||||
*
|
*
|
||||||
* If we appear to be running inside a user-defined function, we do not
|
* If we appear to be running inside a user-defined function, we do not
|
||||||
* issue an error, since the function could issue more commands that make
|
* issue anything, since the function could issue more commands that make
|
||||||
* use of the current statement's results. Likewise subtransactions.
|
* use of the current statement's results. Likewise subtransactions.
|
||||||
* Thus this is an inverse for PreventTransactionChain.
|
* Thus this is an inverse for PreventTransactionChain.
|
||||||
*
|
*
|
||||||
* isTopLevel: passed down from ProcessUtility to determine whether we are
|
* isTopLevel: passed down from ProcessUtility to determine whether we are
|
||||||
* inside a function.
|
* inside a function.
|
||||||
* stmtType: statement type name, for error messages.
|
* stmtType: statement type name, for warning or error messages.
|
||||||
*/
|
*/
|
||||||
void
|
static void
|
||||||
RequireTransactionChain(bool isTopLevel, const char *stmtType)
|
CheckTransactionChain(bool isTopLevel, bool throwError, const char *stmtType)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* xact block already started?
|
* xact block already started?
|
||||||
@ -2986,11 +3008,12 @@ RequireTransactionChain(bool isTopLevel, const char *stmtType)
|
|||||||
if (!isTopLevel)
|
if (!isTopLevel)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ereport(ERROR,
|
ereport(throwError ? ERROR : WARNING,
|
||||||
(errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
|
(errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
|
||||||
/* translator: %s represents an SQL statement name */
|
/* translator: %s represents an SQL statement name */
|
||||||
errmsg("%s can only be used in transaction blocks",
|
errmsg("%s can only be used in transaction blocks",
|
||||||
stmtType)));
|
stmtType)));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3425,12 +3448,12 @@ UserAbortTransactionBlock(void)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* The user issued ABORT when not inside a transaction. Issue a
|
* The user issued ABORT when not inside a transaction. Issue a
|
||||||
* NOTICE and go to abort state. The upcoming call to
|
* WARNING and go to abort state. The upcoming call to
|
||||||
* CommitTransactionCommand() will then put us back into the
|
* CommitTransactionCommand() will then put us back into the
|
||||||
* default state.
|
* default state.
|
||||||
*/
|
*/
|
||||||
case TBLOCK_STARTED:
|
case TBLOCK_STARTED:
|
||||||
ereport(NOTICE,
|
ereport(WARNING,
|
||||||
(errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
|
(errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
|
||||||
errmsg("there is no transaction in progress")));
|
errmsg("there is no transaction in progress")));
|
||||||
s->blockState = TBLOCK_ABORT_PENDING;
|
s->blockState = TBLOCK_ABORT_PENDING;
|
||||||
|
@ -754,7 +754,7 @@ standard_ProcessUtility(Node *parsetree,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case T_ConstraintsSetStmt:
|
case T_ConstraintsSetStmt:
|
||||||
RequireTransactionChain(isTopLevel, "SET CONSTRAINTS");
|
WarnNoTransactionChain(isTopLevel, "SET CONSTRAINTS");
|
||||||
AfterTriggerSetState((ConstraintsSetStmt *) parsetree);
|
AfterTriggerSetState((ConstraintsSetStmt *) parsetree);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -6274,7 +6274,7 @@ ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel)
|
|||||||
case VAR_SET_VALUE:
|
case VAR_SET_VALUE:
|
||||||
case VAR_SET_CURRENT:
|
case VAR_SET_CURRENT:
|
||||||
if (stmt->is_local)
|
if (stmt->is_local)
|
||||||
RequireTransactionChain(isTopLevel, "SET LOCAL");
|
WarnNoTransactionChain(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),
|
||||||
@ -6295,7 +6295,7 @@ ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel)
|
|||||||
{
|
{
|
||||||
ListCell *head;
|
ListCell *head;
|
||||||
|
|
||||||
RequireTransactionChain(isTopLevel, "SET TRANSACTION");
|
WarnNoTransactionChain(isTopLevel, "SET TRANSACTION");
|
||||||
|
|
||||||
foreach(head, stmt->args)
|
foreach(head, stmt->args)
|
||||||
{
|
{
|
||||||
@ -6346,7 +6346,7 @@ ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel)
|
|||||||
(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");
|
WarnNoTransactionChain(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));
|
||||||
@ -6357,11 +6357,11 @@ ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel)
|
|||||||
break;
|
break;
|
||||||
case VAR_SET_DEFAULT:
|
case VAR_SET_DEFAULT:
|
||||||
if (stmt->is_local)
|
if (stmt->is_local)
|
||||||
RequireTransactionChain(isTopLevel, "SET LOCAL");
|
WarnNoTransactionChain(isTopLevel, "SET LOCAL");
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case VAR_RESET:
|
case VAR_RESET:
|
||||||
if (strcmp(stmt->name, "transaction_isolation") == 0)
|
if (strcmp(stmt->name, "transaction_isolation") == 0)
|
||||||
RequireTransactionChain(isTopLevel, "RESET TRANSACTION");
|
WarnNoTransactionChain(isTopLevel, "RESET TRANSACTION");
|
||||||
|
|
||||||
(void) set_config_option(stmt->name,
|
(void) set_config_option(stmt->name,
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -245,6 +245,7 @@ extern char TransactionBlockStatusCode(void);
|
|||||||
extern void AbortOutOfAnyTransaction(void);
|
extern void AbortOutOfAnyTransaction(void);
|
||||||
extern void PreventTransactionChain(bool isTopLevel, const char *stmtType);
|
extern void PreventTransactionChain(bool isTopLevel, const char *stmtType);
|
||||||
extern void RequireTransactionChain(bool isTopLevel, const char *stmtType);
|
extern void RequireTransactionChain(bool isTopLevel, const char *stmtType);
|
||||||
|
extern void WarnNoTransactionChain(bool isTopLevel, const char *stmtType);
|
||||||
extern bool IsInTransactionChain(bool isTopLevel);
|
extern bool IsInTransactionChain(bool isTopLevel);
|
||||||
extern void RegisterXactCallback(XactCallback callback, void *arg);
|
extern void RegisterXactCallback(XactCallback callback, void *arg);
|
||||||
extern void UnregisterXactCallback(XactCallback callback, void *arg);
|
extern void UnregisterXactCallback(XactCallback callback, void *arg);
|
||||||
|
@ -114,7 +114,7 @@ ERROR: column name "oid" conflicts with a system column name
|
|||||||
-- TRANSACTION STUFF
|
-- TRANSACTION STUFF
|
||||||
-- not in a xact
|
-- not in a xact
|
||||||
abort;
|
abort;
|
||||||
NOTICE: there is no transaction in progress
|
WARNING: there is no transaction in progress
|
||||||
-- not in a xact
|
-- not in a xact
|
||||||
end;
|
end;
|
||||||
WARNING: there is no transaction in progress
|
WARNING: there is no transaction in progress
|
||||||
|
@ -29,7 +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
|
WARNING: SET LOCAL can only be used in transaction blocks
|
||||||
SHOW vacuum_cost_delay;
|
SHOW vacuum_cost_delay;
|
||||||
vacuum_cost_delay
|
vacuum_cost_delay
|
||||||
-------------------
|
-------------------
|
||||||
@ -37,7 +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
|
WARNING: SET LOCAL can only be used in transaction blocks
|
||||||
SHOW datestyle;
|
SHOW datestyle;
|
||||||
DateStyle
|
DateStyle
|
||||||
-----------
|
-----------
|
||||||
|
Loading…
x
Reference in New Issue
Block a user