Make SET really not start a transaction.

This commit is contained in:
Tom Lane 2002-10-13 16:55:05 +00:00
parent 5261bf9733
commit ad4ce7aa5b
5 changed files with 40 additions and 41 deletions

View File

@ -1,5 +1,5 @@
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/reset.sgml,v 1.16 2002/10/09 04:59:38 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/ref/reset.sgml,v 1.17 2002/10/13 16:55:05 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
@ -68,7 +68,7 @@ SET <replaceable class="parameter">variable</replaceable> TO DEFAULT
</para> </para>
<para> <para>
See the <command>SHOW</> manual page for details on the transaction See the <command>SET</> manual page for details on the transaction
behavior of <command>RESET</>. behavior of <command>RESET</>.
</para> </para>

View File

@ -1,5 +1,5 @@
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/set.sgml,v 1.67 2002/10/09 16:27:48 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/ref/set.sgml,v 1.68 2002/10/13 16:55:05 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
@ -109,9 +109,10 @@ SET [ SESSION | LOCAL ] TIME ZONE { <replaceable class="PARAMETER">timezone</rep
</para> </para>
<para> <para>
With <literal>autocommit</> set to <literal>off</>, <command>SET</> Even with <literal>autocommit</> set to <literal>off</>, <command>SET</>
does not start a new transaction block. See the does not start a new transaction block. See the
<literal>autocommit</> section of the documentation for details. <literal>autocommit</> section of the <citetitle>Administrator's
Guide</citetitle> for details.
</para> </para>
<para> <para>

View File

@ -1,5 +1,5 @@
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/show.sgml,v 1.21 2002/09/01 01:59:48 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/ref/show.sgml,v 1.22 2002/10/13 16:55:05 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
@ -60,6 +60,13 @@ SHOW ALL
command-line flag when starting the command-line flag when starting the
<application>postmaster</application>. <application>postmaster</application>.
</para> </para>
<para>
Even with <literal>autocommit</> set to <literal>off</>, <command>SHOW</>
does not start a new transaction block. See the
<literal>autocommit</> section of the <citetitle>Administrator's
Guide</citetitle> for details.
</para>
</refsect1> </refsect1>
<refsect1> <refsect1>

View File

@ -1,5 +1,5 @@
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.144 2002/10/09 04:59:38 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.145 2002/10/13 16:55:05 tgl Exp $
--> -->
<Chapter Id="runtime"> <Chapter Id="runtime">
@ -1236,7 +1236,7 @@ env PGOPTIONS='-c geqo=off' psql
<command>BEGIN</> with no matching <command>COMMIT</> has been <command>BEGIN</> with no matching <command>COMMIT</> has been
given). given).
If set to false, <productname>PostgreSQL</productname> will If set to false, <productname>PostgreSQL</productname> will
commit the commands only when receiving an explicit commit only upon receiving an explicit
<command>COMMIT</> command. This mode can also be thought of as <command>COMMIT</> command. This mode can also be thought of as
implicitly issuing <command>BEGIN</> whenever a command is implicitly issuing <command>BEGIN</> whenever a command is
received that is not already inside a transaction block. The received that is not already inside a transaction block. The
@ -1247,16 +1247,16 @@ env PGOPTIONS='-c geqo=off' psql
</para> </para>
<note> <note>
<para> <para>
With <varname>autocommit</> set to false, <command>SET</>, Even with <varname>autocommit</> set to false, <command>SET</>,
<command>SHOW</>, and <command>RESET</> do not start new <command>SHOW</>, and <command>RESET</> do not start new
transaction blocks. They are run in their own transactions. transaction blocks. They are run in their own transactions.
Once another command is issued, multi-statement transaction Once another command is issued, a transaction block
behavior begins and any <command>SET</>, <command>SHOW</>, or begins and any <command>SET</>, <command>SHOW</>, or
<command>RESET</> commands are considered to be part of the <command>RESET</> commands are considered to be part of the
transaction, i.e. they are committed or rolled back depending transaction, i.e. they are committed or rolled back depending
on the completion status of the transaction. To have on the completion status of the transaction. To execute a
<command>SET</>, <command>SHOW</>, and <command>RESET</> <command>SET</>, <command>SHOW</>, or <command>RESET</>
commands at the start of a transaction, use <command>BEGIN</> command at the start of a transaction block, use <command>BEGIN</>
first. first.
</para> </para>
</note> </note>

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.300 2002/10/09 04:59:38 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.301 2002/10/13 16:55:05 tgl Exp $
* *
* NOTES * NOTES
* this is the "main" module of the postgres backend and * this is the "main" module of the postgres backend and
@ -76,7 +76,6 @@ char *debug_query_string; /* for pgmonitor and
CommandDest whereToSendOutput = Debug; CommandDest whereToSendOutput = Debug;
extern int StatementTimeout; extern int StatementTimeout;
extern bool autocommit;
static bool dontExecute = false; static bool dontExecute = false;
@ -620,15 +619,11 @@ pg_exec_query_string(StringInfo query_string, /* string to execute */
foreach(parsetree_item, parsetree_list) foreach(parsetree_item, parsetree_list)
{ {
Node *parsetree = (Node *) lfirst(parsetree_item); Node *parsetree = (Node *) lfirst(parsetree_item);
bool isTransactionStmt;
const char *commandTag; const char *commandTag;
char completionTag[COMPLETION_TAG_BUFSIZE]; char completionTag[COMPLETION_TAG_BUFSIZE];
List *querytree_list, List *querytree_list,
*querytree_item; *querytree_item;
/* Transaction control statements need some special handling */
isTransactionStmt = IsA(parsetree, TransactionStmt);
/* /*
* First we set the command-completion tag to the main query (as * First we set the command-completion tag to the main query (as
* opposed to each of the others that may be generated by analyze * opposed to each of the others that may be generated by analyze
@ -653,7 +648,7 @@ pg_exec_query_string(StringInfo query_string, /* string to execute */
{ {
bool allowit = false; bool allowit = false;
if (isTransactionStmt) if (IsA(parsetree, TransactionStmt))
{ {
TransactionStmt *stmt = (TransactionStmt *) parsetree; TransactionStmt *stmt = (TransactionStmt *) parsetree;
@ -698,6 +693,7 @@ pg_exec_query_string(StringInfo query_string, /* string to execute */
foreach(querytree_item, querytree_list) foreach(querytree_item, querytree_list)
{ {
Query *querytree = (Query *) lfirst(querytree_item); Query *querytree = (Query *) lfirst(querytree_item);
bool endTransactionBlock = false;
/* Make sure we are in a transaction command */ /* Make sure we are in a transaction command */
if (!xact_started) if (!xact_started)
@ -733,6 +729,13 @@ pg_exec_query_string(StringInfo query_string, /* string to execute */
IsA(utilityStmt, ReindexStmt)) IsA(utilityStmt, ReindexStmt))
SetQuerySnapshot(); SetQuerySnapshot();
/* end transaction block if transaction or variable stmt */
if (IsA(utilityStmt, TransactionStmt) ||
IsA(utilityStmt, VariableSetStmt) ||
IsA(utilityStmt, VariableShowStmt) ||
IsA(utilityStmt, VariableResetStmt))
endTransactionBlock = true;
if (querytree->originalQuery) if (querytree->originalQuery)
{ {
/* utility statement can override default tag string */ /* utility statement can override default tag string */
@ -805,7 +808,7 @@ pg_exec_query_string(StringInfo query_string, /* string to execute */
* visible to subsequent ones. In particular we'd better do * visible to subsequent ones. In particular we'd better do
* so before checking constraints. * so before checking constraints.
*/ */
if (!isTransactionStmt) if (!endTransactionBlock)
CommandCounterIncrement(); CommandCounterIncrement();
/* /*
@ -820,13 +823,13 @@ pg_exec_query_string(StringInfo query_string, /* string to execute */
MemoryContextResetAndDeleteChildren(CurrentMemoryContext); MemoryContextResetAndDeleteChildren(CurrentMemoryContext);
/* /*
* If this was a transaction control statement, commit it and * If this was a transaction control statement or a variable
* arrange to start a new xact command for the next command * set/show/reset statement, commit it and arrange to start a
* (if any). * new xact command for the next command (if any).
*/ */
if (isTransactionStmt) if (endTransactionBlock)
{ {
finish_xact_command(false); finish_xact_command(true);
xact_started = false; xact_started = false;
} }
} /* end loop over queries generated from a } /* end loop over queries generated from a
@ -844,19 +847,7 @@ pg_exec_query_string(StringInfo query_string, /* string to execute */
*/ */
if (lnext(parsetree_item) == NIL && xact_started) if (lnext(parsetree_item) == NIL && xact_started)
{ {
/* finish_xact_command(false);
* Don't allow SET/SHOW/RESET to start a new transaction
* with autocommit off. We do this by forcing a COMMIT
* when these commands start a transaction.
*/
if (autocommit ||
IsTransactionState() ||
(strcmp(commandTag, "SET") != 0 &&
strcmp(commandTag, "SHOW") != 0 &&
strcmp(commandTag, "RESET") != 0))
finish_xact_command(false);
else
finish_xact_command(true);
xact_started = false; xact_started = false;
} }
@ -1733,7 +1724,7 @@ PostgresMain(int argc, char *argv[], const char *username)
if (!IsUnderPostmaster) if (!IsUnderPostmaster)
{ {
puts("\nPOSTGRES backend interactive interface "); puts("\nPOSTGRES backend interactive interface ");
puts("$Revision: 1.300 $ $Date: 2002/10/09 04:59:38 $\n"); puts("$Revision: 1.301 $ $Date: 2002/10/13 16:55:05 $\n");
} }
/* /*