From: drh Date: Mon, 20 Apr 2009 17:43:03 +0000 (+0000) Subject: Change the journal_mode pragma so that it always returns the current X-Git-Tag: version-3.6.15~224 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8a939190824f7198026c08253587fd152bf5cae6;p=thirdparty%2Fsqlite.git Change the journal_mode pragma so that it always returns the current journal mode, even on a failed attempt to change the journal mode. Allow the journal mode to be changed as long as there is not a pending transaction. Ticket #3811. (CVS 6526) FossilOrigin-Name: 419e320ae51639794335d19699f8e1189e524e7d --- diff --git a/manifest b/manifest index 7c014b8bb8..d79431efc6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\snew\stests\sto\sshow\sthat\sjournal_mode=OFF\sworks\swith\slocking_mode=EXCLUSIVE\nas\slong\sas\sthe\sjournal_mode\sis\sset\sprior\sto\sthe\sfirst\stransaction.\nTicket\s#3811.\s(CVS\s6525) -D 2009-04-20T13:32:33 +C Change\sthe\sjournal_mode\spragma\sso\sthat\sit\salways\sreturns\sthe\scurrent\njournal\smode,\seven\son\sa\sfailed\sattempt\sto\schange\sthe\sjournal\smode.\nAllow\sthe\sjournal\smode\sto\sbe\schanged\sas\slong\sas\sthere\sis\snot\sa\spending\ntransaction.\s\sTicket\s#3811.\s(CVS\s6526) +D 2009-04-20T17:43:03 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in 583e87706abc3026960ed759aff6371faf84c211 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -106,7 +106,7 @@ F src/btmutex.c 9b899c0d8df3bd68f527b0afe03088321b696d3c F src/btree.c b4ec46b3adc3e2d82704c949d4b654b031a64ad6 F src/btree.h 99fcc7e8c4a1e35afe271bcb38de1a698dfc904e F src/btreeInt.h df64030d632f8c8ac217ed52e8b6b3eacacb33a5 -F src/build.c 2882f22078db1c3f887b1aca77ff460cf9461c62 +F src/build.c 18c5e51c2cbaab95b1d90d38f5a15005a430d047 F src/callback.c 73016376d6848ba987709e8c9048d4f0e0776036 F src/complete.c cb14e06dbe79dee031031f0d9e686ff306afe07c F src/date.c d327ec7bb2f64b08d32b1035de82b9ba8675de91 @@ -143,14 +143,14 @@ F src/os_common.h 8c61457df58f1a4bd5f5adc3e90e01b37bf7afbc F src/os_os2.c bed77dc26e3a95ce4a204936b9a1ca6fe612fcc5 F src/os_unix.c 9ad9f45049a3c9eb0b0713b162ff0d7024ff7259 F src/os_win.c c3d0354b9a7ae75e3e993e6c17f5deb061acbc36 -F src/pager.c 2ad6a948040f802508acddf4052f29b04802b3db +F src/pager.c adfdf98f92bcab88246aaa5079df49f9441ebd81 F src/pager.h 0c9f3520c00d8a3b8e792ca56c9a11b6b02b4b0f F src/parse.y b7e4341b21736a90b952aa6bb663ec98529b778e F src/pcache.c 395f752a13574120bd7513a400ba02a265aaa76d F src/pcache.h 9b927ccc5a538e31b4c3bc7eec4f976db42a1324 F src/pcache1.c 35f8601c91c09a1e887a1914ebca07bb5afc7b89 F src/pragma.c c26c16c49a80d03c8597f0e6c7daba53f283428f -F src/prepare.c 0ad1ba3290e0626aa4e7589ed6ab6af2572875b0 +F src/prepare.c 72d74e6d3b9c8eb0663b33ec6438aa718096ac79 F src/printf.c ea2d76000cc5f4579d7e9cb2f5460433eec0d384 F src/random.c 676b9d7ac820fe81e6fb2394ac8c10cff7f38628 F src/resolve.c 094e44450371fb27869eb8bf679aacbe51fdc56d @@ -420,9 +420,9 @@ F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0 F test/join4.test 1a352e4e267114444c29266ce79e941af5885916 F test/join5.test 86675fc2919269aa923c84dd00ee4249b97990fe F test/journal1.test 36f2d1bb9bf03f790f43fbdb439e44c0657fab19 -F test/jrnlmode.test 05e1e187c5b64022e832761674ee2395f3267d01 +F test/jrnlmode.test 0584cbd11bf8999501abf1b991979f8aa69c265b F test/jrnlmode2.test bd846e10d463c0b6f8bded674cb07f94a0277097 -F test/jrnlmode3.test 4e9a1f6099a13ec863720de981e3044f735f02bf +F test/jrnlmode3.test cfcdb12b90e640a23b92785a002d96c0624c8710 F test/keyword1.test a2400977a2e4fde43bf33754c2929fda34dbca05 F test/lastinsert.test 474d519c68cb79d07ecae56a763aa7f322c72f51 F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200 @@ -718,7 +718,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e -P 3182e8bf69eb4e5e4070930cb9c750942b1dc735 -R 63b3c0e9e8b9bff8f84a79194299cadb +P e62ac26f72224a4ba6c7dc5c32b7e4370461764d +R 39db01b2d3bd255afa6f732be2b5d532 U drh -Z b0e0f5d2013af325cce1fe669e1d8579 +Z d037c0a2ce0411a3e53db40f26904a65 diff --git a/manifest.uuid b/manifest.uuid index 24829e0b6b..bcccd3f9fb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e62ac26f72224a4ba6c7dc5c32b7e4370461764d \ No newline at end of file +419e320ae51639794335d19699f8e1189e524e7d \ No newline at end of file diff --git a/src/build.c b/src/build.c index a54efcf5d2..987a90c998 100644 --- a/src/build.c +++ b/src/build.c @@ -22,7 +22,7 @@ ** COMMIT ** ROLLBACK ** -** $Id: build.c,v 1.528 2009/04/08 13:51:51 drh Exp $ +** $Id: build.c,v 1.529 2009/04/20 17:43:03 drh Exp $ */ #include "sqliteInt.h" @@ -158,7 +158,9 @@ void sqlite3FinishCoding(Parse *pParse){ if( (mask & pParse->cookieMask)==0 ) continue; sqlite3VdbeUsesBtree(v, iDb); sqlite3VdbeAddOp2(v,OP_Transaction, iDb, (mask & pParse->writeMask)!=0); - sqlite3VdbeAddOp2(v,OP_VerifyCookie, iDb, pParse->cookieValue[iDb]); + if( db->init.busy==0 ){ + sqlite3VdbeAddOp2(v,OP_VerifyCookie, iDb, pParse->cookieValue[iDb]); + } } #ifndef SQLITE_OMIT_VIRTUALTABLE { diff --git a/src/pager.c b/src/pager.c index b42f299e24..aef663c958 100644 --- a/src/pager.c +++ b/src/pager.c @@ -18,7 +18,7 @@ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.581 2009/04/20 11:34:27 drh Exp $ +** @(#) $Id: pager.c,v 1.582 2009/04/20 17:43:03 drh Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" @@ -5195,11 +5195,14 @@ int sqlite3PagerLockingMode(Pager *pPager, int eMode){ ** PAGER_JOURNALMODE_OFF ** PAGER_JOURNALMODE_MEMORY ** -** If the parameter is not _QUERY, then the journal-mode is set to the -** value specified. Except, an in-memory database can only have its -** journal mode set to _OFF or _MEMORY. Attempts to change the journal -** mode of an in-memory database to something other than _OFF or _MEMORY -** are silently ignored. +** If the parameter is not _QUERY, then the journal_mode is set to the +** value specified if the change is allowed. The change is disallowed +** for the following reasons: +** +** * An in-memory database can only have its journal_mode set to _OFF +** or _MEMORY. +** +** * The journal mode may not be changed while a transaction is active. ** ** The returned indicate the current (possibly updated) journal-mode. */ @@ -5211,8 +5214,14 @@ int sqlite3PagerJournalMode(Pager *pPager, int eMode){ || eMode==PAGER_JOURNALMODE_OFF || eMode==PAGER_JOURNALMODE_MEMORY ); assert( PAGER_JOURNALMODE_QUERY<0 ); - if( eMode>=0 && (!MEMDB || eMode==PAGER_JOURNALMODE_MEMORY - || eMode==PAGER_JOURNALMODE_OFF) ){ + if( eMode>=0 + && (!MEMDB || eMode==PAGER_JOURNALMODE_MEMORY + || eMode==PAGER_JOURNALMODE_OFF) + && !pPager->dbModified + ){ + if( isOpen(pPager->jfd) ){ + sqlite3OsClose(pPager->jfd); + } pPager->journalMode = (u8)eMode; } return (int)pPager->journalMode; diff --git a/src/prepare.c b/src/prepare.c index e3479f3b89..c5f4de9042 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -13,7 +13,7 @@ ** interface, and routines that contribute to loading the database schema ** from disk. ** -** $Id: prepare.c,v 1.116 2009/04/02 18:32:27 drh Exp $ +** $Id: prepare.c,v 1.117 2009/04/20 17:43:03 drh Exp $ */ #include "sqliteInt.h" @@ -127,6 +127,7 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){ */ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ int rc; + int i; BtCursor *curMain; int size; Table *pTab; @@ -216,7 +217,8 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ } sqlite3BtreeEnter(pDb->pBt); rc = sqlite3BtreeCursor(pDb->pBt, MASTER_ROOT, 0, 0, curMain); - if( rc!=SQLITE_OK && rc!=SQLITE_EMPTY ){ + if( rc==SQLITE_EMPTY ) rc = SQLITE_OK; + if( rc!=SQLITE_OK ){ sqlite3SetString(pzErrMsg, db, "%s", sqlite3ErrStr(rc)); goto initone_error_out; } @@ -238,17 +240,12 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ ** Note: The #defined SQLITE_UTF* symbols in sqliteInt.h correspond to ** the possible values of meta[4]. */ - if( rc==SQLITE_OK ){ - int i; - for(i=0; ipBt, i+1, (u32 *)&meta[i]); - if( rc ){ - sqlite3SetString(pzErrMsg, db, "%s", sqlite3ErrStr(rc)); - goto initone_error_out; - } + for(i=0; ipBt, i+1, (u32 *)&meta[i]); + if( rc ){ + sqlite3SetString(pzErrMsg, db, "%s", sqlite3ErrStr(rc)); + goto initone_error_out; } - }else{ - memset(meta, 0, sizeof(meta)); } pDb->pSchema->schema_cookie = meta[0]; diff --git a/test/jrnlmode.test b/test/jrnlmode.test index 900a77ff6e..114b255eca 100644 --- a/test/jrnlmode.test +++ b/test/jrnlmode.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The focus # of these tests is the journal mode pragma. # -# $Id: jrnlmode.test,v 1.14 2009/04/10 15:02:44 danielk1977 Exp $ +# $Id: jrnlmode.test,v 1.15 2009/04/20 17:43:03 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -282,6 +282,7 @@ ifcapable autovacuum&&pragma { } {3} do_test jrnlmode-4.2 { +breakpoint execsql { PRAGMA journal_mode = off } } {off} @@ -464,7 +465,7 @@ ifcapable pragma { INSERT INTO t4 VALUES(1, 2); PRAGMA journal_mode = memory; } - } {truncate memory} + } {truncate truncate} do_test jrnlmode-6.2 { file exists test.db-journal } {1} @@ -476,14 +477,15 @@ ifcapable pragma { } {1 2} do_test jrnlmode-6.4 { file exists test.db-journal - } {0} + } {1} do_test jrnlmode-6.5 { execsql { + PRAGMA journal_mode = MEMORY; BEGIN; INSERT INTO t4 VALUES(3, 4); } file exists test.db-journal - } {0} + } {1} do_test jrnlmode-6.7 { execsql { COMMIT; @@ -492,6 +494,13 @@ ifcapable pragma { } {1 2 3 4} do_test jrnlmode-6.8 { file exists test.db-journal + } {1} + do_test jrnlmode-6.9 { + execsql { + PRAGMA journal_mode = DELETE; + BEGIN IMMEDIATE; COMMIT; + } + file exists test.db-journal } {0} } } diff --git a/test/jrnlmode3.test b/test/jrnlmode3.test index 7756104e81..7a6f4c3adc 100644 --- a/test/jrnlmode3.test +++ b/test/jrnlmode3.test @@ -9,7 +9,11 @@ # #*********************************************************************** # -# $Id: jrnlmode3.test,v 1.4 2009/04/20 13:32:33 drh Exp $ +# Test cases inspired by ticket #3811. Tests to make sure that +# the journal_mode can only be changed at appropriate times and that +# all reported changes are effective. +# +# $Id: jrnlmode3.test,v 1.5 2009/04/20 17:43:03 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -19,7 +23,6 @@ ifcapable {!pager_pragmas} { return } -# Ticket #3811 # # Verify that journal_mode=OFF works as long as it occurs before the first # transaction, even if locking_mode=EXCLUSIVE is enabled. The behavior if @@ -66,5 +69,82 @@ do_test jrnlmode3-2.2 { } } {1 2} +# Test cases to verify that we can move from any journal_mode +# to any other, as long as we are not in a transaction. Verify +# that we cannot change journal_mode while a transaction is active. +# +set all_journal_modes {delete persist truncate memory off} +set cnt 0 +foreach fromjmode $all_journal_modes { + foreach tojmode $all_journal_modes { + + # Skip the no-change cases + if {$fromjmode==$tojmode} continue + incr cnt + + # Start with a fresh database connection an empty database file. + # + db close + file delete -force test.db test.db-journal + sqlite3 db test.db + + # Initialize the journal mode. + # + do_test jrnlmode3-3.$cnt.1-($fromjmode-to-$tojmode) { + db eval "PRAGMA journal_mode = $fromjmode;" + } $fromjmode + + # Verify that the initial journal mode takes. + # + do_test jrnlmode3-3.$cnt.2 { + db eval {PRAGMA main.journal_mode} + } $fromjmode + + # Start a transaction and try to change the journal mode within + # the transaction. This should fail. + # + do_test jrnlmode3-3.$cnt.3 { + db eval { + CREATE TABLE t1(x); + BEGIN; + INSERT INTO t1 VALUES($cnt); + } + db eval "PRAGMA journal_mode=$tojmode" + } $fromjmode + + # Rollback the transaction. Verify that the rollback occurred + # if journal_mode!=OFF. + # + do_test jrnlmode3-3.$cnt.4 { + db eval { + ROLLBACK; + SELECT * FROM t1; + } + } [expr {$fromjmode=="off"?$cnt:""}] + + # Now change the journal mode again. This time the new mode + # should take. + # + do_test jrnlmode3-3.$cnt.5 { + db eval "PRAGMA journal_mode=$tojmode" + } $tojmode + + # Do a the transaction. Verify that the rollback occurred + # if journal_mode!=OFF. + # + do_test jrnlmode3-3.$cnt.6 { + db eval { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(x); + BEGIN; + INSERT INTO t1 VALUES(1); + } + db eval ROLLBACK + db eval { + SELECT * FROM t1; + } + } [expr {$tojmode=="off"?"1":""}] + } +} finish_test