From 26993b2918551552b74b559ab410228dc0670cd5 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 30 Aug 2002 22:18:07 +0000 Subject: [PATCH] AUTOCOMMIT mode is now an available backend GUC variable; setting it to false provides more SQL-spec-compliant behavior than we had before. I am not sure that setting it false is actually a good idea yet; there is a lot of client-side code that will probably be broken by turning autocommit off. But it's a start. Loosely based on a patch by David Van Wie. --- doc/src/sgml/release.sgml | 3 +- doc/src/sgml/runtime.sgml | 25 ++++++++- src/backend/access/transam/xact.c | 53 ++++++++++++++++--- src/backend/bootstrap/bootparse.y | 6 +-- src/backend/bootstrap/bootstrap.c | 6 +-- src/backend/catalog/namespace.c | 6 +-- src/backend/commands/async.c | 10 ++-- src/backend/commands/indexcmds.c | 11 ++-- src/backend/commands/vacuum.c | 26 +++++---- src/backend/tcop/postgres.c | 8 +-- src/backend/utils/init/postinit.c | 6 +-- src/backend/utils/misc/guc.c | 7 ++- src/backend/utils/misc/postgresql.conf.sample | 3 +- src/bin/psql/tab-complete.c | 3 +- src/include/access/xact.h | 6 +-- 15 files changed, 126 insertions(+), 53 deletions(-) diff --git a/doc/src/sgml/release.sgml b/doc/src/sgml/release.sgml index 78606b68e9..3ba21bc1ab 100644 --- a/doc/src/sgml/release.sgml +++ b/doc/src/sgml/release.sgml @@ -1,5 +1,5 @@ @@ -24,6 +24,7 @@ CDATA means the content is "SGML-free", so you can write without worries about funny characters. --> @@ -1135,6 +1135,29 @@ env PGOPTIONS='-c geqo=off' psql + + AUTOCOMMIT (bool) + autocommit + + + If set to true, PostgreSQL will + automatically do a COMMIT after each successful command + that is not inside an explicit transaction block (that is, unless a + BEGIN with no matching COMMIT has been + given). + If set to false, PostgreSQL will commit + the effects of commands only on receiving an explicit + COMMIT command. This mode can also be thought of as + implicitly issuing BEGIN whenever a command is received + and PostgreSQL is not already inside + a transaction block. + The default is true, for compatibility with historical + PostgreSQL behavior. But for maximum + compatibility with the SQL specification, set it to false. + + + + AUSTRALIAN_TIMEZONES (bool) Australian time zones diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index c9b60daef5..1c1121e3e1 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.130 2002/08/06 02:36:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.131 2002/08/30 22:18:05 tgl Exp $ * * NOTES * Transaction aborts can now occur two ways: @@ -220,10 +220,15 @@ TransactionState CurrentTransactionState = &CurrentTransactionStateData; int DefaultXactIsoLevel = XACT_READ_COMMITTED; int XactIsoLevel; +bool autocommit = true; + int CommitDelay = 0; /* precommit delay in microseconds */ int CommitSiblings = 5; /* number of concurrent xacts needed to * sleep */ + +static bool suppressChain = false; + static void (*_RollbackFunc) (void *) = NULL; static void *_RollbackData = NULL; @@ -1149,13 +1154,24 @@ CleanupTransaction(void) /* -------------------------------- * StartTransactionCommand + * + * preventChain, if true, forces autocommit behavior at the next + * CommitTransactionCommand call. * -------------------------------- */ void -StartTransactionCommand(void) +StartTransactionCommand(bool preventChain) { TransactionState s = CurrentTransactionState; + /* + * Remember if caller wants to prevent autocommit-off chaining. + * This is only allowed if not already in a transaction block. + */ + suppressChain = preventChain; + if (preventChain && s->blockState != TBLOCK_DEFAULT) + elog(ERROR, "StartTransactionCommand: can't prevent chain"); + switch (s->blockState) { /* @@ -1231,21 +1247,41 @@ StartTransactionCommand(void) /* -------------------------------- * CommitTransactionCommand + * + * forceCommit = true forces autocommit behavior even when autocommit is off. * -------------------------------- */ void -CommitTransactionCommand(void) +CommitTransactionCommand(bool forceCommit) { TransactionState s = CurrentTransactionState; switch (s->blockState) { /* - * if we aren't in a transaction block, we just do our usual - * transaction commit + * If we aren't in a transaction block, and we are doing + * autocommit, just do our usual transaction commit. But + * if we aren't doing autocommit, start a transaction block + * automatically by switching to INPROGRESS state. (We handle + * this choice here, and not earlier, so that an explicit BEGIN + * issued in autocommit-off mode won't issue strange warnings.) + * + * Autocommit mode is forced by either a true forceCommit parameter + * to me, or a true preventChain parameter to the preceding + * StartTransactionCommand call. This is needed so that commands + * like VACUUM can ensure that the right things happen. */ case TBLOCK_DEFAULT: - CommitTransaction(); + if (autocommit || forceCommit || suppressChain) + CommitTransaction(); + else + { + BeginTransactionBlock(); + Assert(s->blockState == TBLOCK_INPROGRESS); + /* This code must match the TBLOCK_INPROGRESS case below: */ + CommandCounterIncrement(); + MemoryContextResetAndDeleteChildren(TransactionCommandContext); + } break; /* @@ -1406,7 +1442,10 @@ BeginTransactionBlock(void) s->blockState = TBLOCK_BEGIN; /* - * do begin processing + * do begin processing. NOTE: if you put anything here, check that + * it behaves properly in both autocommit-on and autocommit-off modes. + * In the latter case we will already have done some work in the new + * transaction. */ /* diff --git a/src/backend/bootstrap/bootparse.y b/src/backend/bootstrap/bootparse.y index f2d31356d9..a50e9ac88d 100644 --- a/src/backend/bootstrap/bootparse.y +++ b/src/backend/bootstrap/bootparse.y @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootparse.y,v 1.50 2002/07/20 05:16:56 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootparse.y,v 1.51 2002/08/30 22:18:05 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -55,7 +55,7 @@ static void do_start() { - StartTransactionCommand(); + StartTransactionCommand(true); elog(DEBUG3, "start transaction"); } @@ -63,7 +63,7 @@ do_start() static void do_end() { - CommitTransactionCommand(); + CommitTransactionCommand(true); elog(DEBUG3, "commit transaction"); if (isatty(0)) { diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index ae4a86d1d4..ef9ee498db 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.138 2002/08/17 15:12:06 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.139 2002/08/30 22:18:05 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -448,7 +448,7 @@ BootstrapMain(int argc, char *argv[]) SetProcessingMode(BootstrapProcessing); /* clean up processing */ - StartTransactionCommand(); + StartTransactionCommand(true); cleanup(); /* not reached, here to make compiler happy */ @@ -821,7 +821,7 @@ cleanup() } if (boot_reldesc != NULL) closerel(NULL); - CommitTransactionCommand(); + CommitTransactionCommand(true); proc_exit(Warnings); } diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c index 33fc901e86..f8a271f908 100644 --- a/src/backend/catalog/namespace.c +++ b/src/backend/catalog/namespace.c @@ -13,7 +13,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.32 2002/08/29 00:17:02 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.33 2002/08/30 22:18:05 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1610,11 +1610,11 @@ RemoveTempRelationsCallback(void) { /* Need to ensure we have a usable transaction. */ AbortOutOfAnyTransaction(); - StartTransactionCommand(); + StartTransactionCommand(true); RemoveTempRelations(myTempNamespace); - CommitTransactionCommand(); + CommitTransactionCommand(true); } } diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 4c7c5f2110..97e1dc17ae 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.88 2002/08/05 03:29:16 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.89 2002/08/30 22:18:05 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -400,9 +400,9 @@ Async_UnlistenOnExit(void) */ AbortOutOfAnyTransaction(); /* Now we can do the unlisten */ - StartTransactionCommand(); + StartTransactionCommand(true); Async_UnlistenAll(); - CommitTransactionCommand(); + CommitTransactionCommand(true); } /* @@ -749,7 +749,7 @@ ProcessIncomingNotify(void) notifyInterruptOccurred = 0; - StartTransactionCommand(); + StartTransactionCommand(true); lRel = heap_openr(ListenerRelationName, AccessExclusiveLock); tdesc = RelationGetDescr(lRel); @@ -803,7 +803,7 @@ ProcessIncomingNotify(void) */ heap_close(lRel, NoLock); - CommitTransactionCommand(); + CommitTransactionCommand(true); /* * Must flush the notify messages to ensure frontend gets them diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index ec7e148279..b951fccb98 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.85 2002/08/29 15:56:20 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.86 2002/08/30 22:18:05 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -735,15 +735,16 @@ ReindexDatabase(const char *dbname, bool force, bool all) heap_close(relationRelation, AccessShareLock); /* Now reindex each rel in a separate transaction */ - CommitTransactionCommand(); + CommitTransactionCommand(true); for (i = 0; i < relcnt; i++) { - StartTransactionCommand(); + StartTransactionCommand(true); if (reindex_relation(relids[i], force)) elog(NOTICE, "relation %u was reindexed", relids[i]); - CommitTransactionCommand(); + CommitTransactionCommand(true); } - StartTransactionCommand(); + /* Tell xact.c not to chain the upcoming commit */ + StartTransactionCommand(true); MemoryContextDelete(private_context); } diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 4fc3b1d3d9..cda893fab7 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -13,7 +13,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.234 2002/08/13 20:14:24 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.235 2002/08/30 22:18:05 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -273,7 +273,7 @@ vacuum(VacuumStmt *vacstmt) } /* matches the StartTransaction in PostgresMain() */ - CommitTransactionCommand(); + CommitTransactionCommand(true); } /* @@ -296,14 +296,14 @@ vacuum(VacuumStmt *vacstmt) * return (else we leak memory while processing multiple tables). */ if (vacstmt->vacuum) - StartTransactionCommand(); + StartTransactionCommand(true); else old_context = MemoryContextSwitchTo(anl_context); analyze_rel(relid, vacstmt); if (vacstmt->vacuum) - CommitTransactionCommand(); + CommitTransactionCommand(true); else { MemoryContextSwitchTo(old_context); @@ -319,8 +319,12 @@ vacuum(VacuumStmt *vacstmt) { /* here, we are not in a transaction */ - /* matches the CommitTransaction in PostgresMain() */ - StartTransactionCommand(); + /* + * This matches the CommitTransaction waiting for us in PostgresMain(). + * We tell xact.c not to chain the upcoming commit, so that a VACUUM + * doesn't start a transaction block, even when autocommit is off. + */ + StartTransactionCommand(true); /* * If we did a database-wide VACUUM, update the database's pg_database @@ -703,7 +707,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind) Oid toast_relid; /* Begin a transaction for vacuuming this relation */ - StartTransactionCommand(); + StartTransactionCommand(true); /* * Check for user-requested abort. Note we want this to be inside a @@ -719,7 +723,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind) ObjectIdGetDatum(relid), 0, 0, 0)) { - CommitTransactionCommand(); + CommitTransactionCommand(true); return; } @@ -750,7 +754,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind) elog(WARNING, "Skipping \"%s\" --- only table or database owner can VACUUM it", RelationGetRelationName(onerel)); relation_close(onerel, lmode); - CommitTransactionCommand(); + CommitTransactionCommand(true); return; } @@ -763,7 +767,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind) elog(WARNING, "Skipping \"%s\" --- can not process indexes, views or special system tables", RelationGetRelationName(onerel)); relation_close(onerel, lmode); - CommitTransactionCommand(); + CommitTransactionCommand(true); return; } @@ -799,7 +803,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind) /* * Complete the transaction and free all temporary memory used. */ - CommitTransactionCommand(); + CommitTransactionCommand(true); /* * If the relation has a secondary toast rel, vacuum that too while we diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 6988972e1d..3947755a2e 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.286 2002/08/29 23:39:05 inoue Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.287 2002/08/30 22:18:06 tgl Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -860,7 +860,7 @@ static void start_xact_command(void) { elog(DEBUG1, "StartTransactionCommand"); - StartTransactionCommand(); + StartTransactionCommand(false); } static void @@ -872,7 +872,7 @@ finish_xact_command(void) /* Now commit the command */ elog(DEBUG1, "CommitTransactionCommand"); - CommitTransactionCommand(); + CommitTransactionCommand(false); #ifdef SHOW_MEMORY_STATS /* Print mem stats at each commit for leak tracking */ @@ -1664,7 +1664,7 @@ PostgresMain(int argc, char *argv[], const char *username) if (!IsUnderPostmaster) { puts("\nPOSTGRES backend interactive interface "); - puts("$Revision: 1.286 $ $Date: 2002/08/29 23:39:05 $\n"); + puts("$Revision: 1.287 $ $Date: 2002/08/30 22:18:06 $\n"); } /* diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index b02e371a81..82f4f632e5 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.111 2002/08/29 21:02:12 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.112 2002/08/30 22:18:06 tgl Exp $ * * *------------------------------------------------------------------------- @@ -330,7 +330,7 @@ InitPostgres(const char *dbname, const char *username) /* start a new transaction here before access to db */ if (!bootstrap) - StartTransactionCommand(); + StartTransactionCommand(true); /* * It's now possible to do real access to the system catalogs. @@ -394,7 +394,7 @@ InitPostgres(const char *dbname, const char *username) /* close the transaction we started above */ if (!bootstrap) - CommitTransactionCommand(); + CommitTransactionCommand(true); /* * Check a normal user hasn't connected to a superuser reserved slot. diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index e394e2cd87..6000493a85 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -5,7 +5,7 @@ * command, configuration file, and command line options. * See src/backend/utils/misc/README for more information. * - * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.88 2002/08/30 16:50:50 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.89 2002/08/30 22:18:07 tgl Exp $ * * Copyright 2000 by PostgreSQL Global Development Group * Written by Peter Eisentraut . @@ -58,6 +58,7 @@ extern int PreAuthDelay; extern int AuthenticationTimeout; extern int StatementTimeout; extern int CheckPointTimeout; +extern bool autocommit; extern int CommitDelay; extern int CommitSiblings; extern bool FixBTree; @@ -487,6 +488,10 @@ static struct config_bool { "db_user_namespace", PGC_SIGHUP }, &Db_user_namespace, false, NULL, NULL }, + { + { "autocommit", PGC_USERSET }, &autocommit, + true, NULL, NULL + }, { { NULL, 0 }, NULL, false, NULL, NULL diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index 11e9caaabc..1141e3c604 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -68,8 +68,6 @@ #checkpoint_segments = 3 # in logfile segments, min 1, 16MB each #checkpoint_timeout = 300 # range 30-3600, in seconds # -#wal_files = 0 # range 0-64 -# #commit_delay = 0 # range 0-100000, in microseconds #commit_siblings = 5 # range 1-1000 # @@ -186,6 +184,7 @@ # # Misc # +#autocommit = true #dynamic_library_path = '$libdir' #search_path = '$user,public' #datestyle = 'iso, us' diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index 98dfce1792..0ff42b5ee3 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -3,7 +3,7 @@ * * Copyright 2000-2002 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.59 2002/08/30 18:15:23 momjian Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.60 2002/08/30 22:18:07 tgl Exp $ */ /*---------------------------------------------------------------------- @@ -246,6 +246,7 @@ psql_completion(char *text, int start, int end) "australian_timezones", "password_encryption", "transform_null_equals", + "autocommit", "default_statistics_target", "geqo_threshold", diff --git a/src/include/access/xact.h b/src/include/access/xact.h index 5448b68f72..b74b9d4cdc 100644 --- a/src/include/access/xact.h +++ b/src/include/access/xact.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: xact.h,v 1.44 2002/06/20 20:29:43 momjian Exp $ + * $Id: xact.h,v 1.45 2002/08/30 22:18:07 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -105,8 +105,8 @@ extern AbsoluteTime GetCurrentTransactionStartTimeUsec(int *usec); extern bool TransactionIdIsCurrentTransactionId(TransactionId xid); extern bool CommandIdIsCurrentCommandId(CommandId cid); extern void CommandCounterIncrement(void); -extern void StartTransactionCommand(void); -extern void CommitTransactionCommand(void); +extern void StartTransactionCommand(bool preventChain); +extern void CommitTransactionCommand(bool forceCommit); extern void AbortCurrentTransaction(void); extern void BeginTransactionBlock(void); extern void EndTransactionBlock(void);