]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add "pragma journal_mode=memory". Change the way rollback works for in-memory databas...
authordanielk1977 <danielk1977@noemail.net>
Fri, 17 Oct 2008 18:51:52 +0000 (18:51 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Fri, 17 Oct 2008 18:51:52 +0000 (18:51 +0000)
FossilOrigin-Name: 39ebf01addf9d0867daafd06a38719e725128f9c

15 files changed:
main.mk
manifest
manifest.uuid
src/pager.c
src/pager.h
src/pcache.c
src/pcache.h
src/pragma.c
src/sqliteInt.h
test/jrnlmode.test
test/pager.test
test/pager2.test
test/permutations.test
test/rollback.test
tool/mksqlite3c.tcl

diff --git a/main.mk b/main.mk
index 423f429aee45bc0c23953413c4893b524e7ed43a..ee8d2d00643d0090a05bae117913485721e744f4 100644 (file)
--- a/main.mk
+++ b/main.mk
@@ -57,6 +57,7 @@ LIBOBJ+= alter.o analyze.o attach.o auth.o \
          func.o global.o hash.o \
          icu.o insert.o journal.o legacy.o loadext.o \
          main.o malloc.o mem1.o mem2.o mem3.o mem4.o mem5.o mem6.o \
+         memjournal.o \
          mutex.o mutex_noop.o mutex_os2.o mutex_unix.o mutex_w32.o \
          opcodes.o os.o os_os2.o os_unix.o os_win.o \
          pager.o parse.o pcache.o pragma.o prepare.o printf.o \
@@ -104,6 +105,7 @@ SRC = \
   $(TOP)/src/mem4.c \
   $(TOP)/src/mem5.c \
   $(TOP)/src/mem6.c \
+  $(TOP)/src/memjournal.c \
   $(TOP)/src/mutex.c \
   $(TOP)/src/mutex.h \
   $(TOP)/src/mutex_noop.c \
index 8a99e9a0d1fc35d05733a3f7175c9a8dcd713be9..860104d4eb4f90c6af2860cc1316665bd1394688 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sa\stypo\sin\sdocumentation.\s\sTicket\s#3447.\s(CVS\s5829)
-D 2008-10-17T15:10:37
+C Add\s"pragma\sjournal_mode=memory".\sChange\sthe\sway\srollback\sworks\sfor\sin-memory\sdatabases\sso\sthat\sit\sreuses\sthe\sjournal_mode=memory\scode.\s(CVS\s5830)
+D 2008-10-17T18:51:52
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in 2014e5a4010ad5ebbcaedff98240b3d14ee83838
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -79,7 +79,7 @@ F ext/rtree/tkt3363.test 6662237ea75bb431cd5d262dfc9535e1023315fc
 F ext/rtree/viewrtree.tcl 09526398dae87a5a87c5aac2b3854dbaf8376869
 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
 F ltmain.sh 09fe5815427dc7d0abb188bbcdf0e34896577210
-F main.mk 725b8b0ee2c1a7e53adb172984c43165eca61be1
+F main.mk c0baa7e57584ce3666a854015ad8743c5fe38dec
 F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a
 F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
 F mkextw.sh 4123480947681d9b434a5e7b1ee08135abe409ac
@@ -138,12 +138,12 @@ F src/os_common.h 24525d8b7bce66c374dfc1810a6c9043f3359b60
 F src/os_os2.c 24221ff5ab20cf3472e3ec7eec595f759de55298
 F src/os_unix.c 5e3b3c9a54546249c1317cff5343e965192f7f2b
 F src/os_win.c 13bed718f62d64031b17bb3685adcf994dbf0232
-F src/pager.c d98f56128e849083f2f612196efebd982c491fea
-F src/pager.h 9c1917be28fff58118e1fe0ddbc7adfb8dd4f44d
+F src/pager.c fd11076a5a2f46a831688f036f03c57bd730dff5
+F src/pager.h 4a57b219c0765fe1870238064e3f46e4eb2cf5af
 F src/parse.y f4620f42b5e0141e20243b5f963d0fc9c180ab9b
-F src/pcache.c f8d7beceba164a34441ac37e88abb3a404f968a7
-F src/pcache.h 974d8ba609c7069af7c050cd3de698cadd090405
-F src/pragma.c f0f48d0d50e9d8fa785178fc2410244c06f6a287
+F src/pcache.c 5b80676e664019c1ebc8356cc25332dd69da6269
+F src/pcache.h 2caf2deb6cbaa75c423b8b96fc1411069ee77c75
+F src/pragma.c 10d61f211d819acd97174a41acc56394bd5bde7e
 F src/prepare.c c7e00ed1b0bdcf699b1aad651247d4dc3d281b0b
 F src/printf.c 785f87120589c1db672e37c6eb1087c456e6f84d
 F src/random.c a87afbd598aa877e23ac676ee92fd8ee5c786a51
@@ -152,7 +152,7 @@ F src/select.c d910d7350df0d918e22286c5bfd39d4ea68ec813
 F src/shell.c d83b578a8ccdd3e0e7fef4388a0887ce9f810967
 F src/sqlite.h.in ee95eeed2196e5fa98fdad007301b8d5d3733b6d
 F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17
-F src/sqliteInt.h 69ad0023756cc738d2a5f9def8a0b21d90350667
+F src/sqliteInt.h e5e3909f565fb020a820ccce11abca040902f075
 F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8
 F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
 F src/table.c 22744786199c9195720c15a7a42cb97b2e2728d8
@@ -393,7 +393,7 @@ F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
 F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
 F test/join5.test 86675fc2919269aa923c84dd00ee4249b97990fe
 F test/journal1.test 36f2d1bb9bf03f790f43fbdb439e44c0657fab19
-F test/jrnlmode.test 54469696db41e185a37aed3b3848998cca4e0c37
+F test/jrnlmode.test c2e8212a6f6d32f8fd8f869b93553154eaf2244c
 F test/lastinsert.test 474d519c68cb79d07ecae56a763aa7f322c72f51
 F test/laststmtchanges.test 18ead86c8a87ade949a1d5658f6dc4bb111d1b02
 F test/like.test fef924922828d5a2a5bff80b9bdd9ff57a1ca500
@@ -450,14 +450,14 @@ F test/nan.test c627d79b3d36ea892563fd67584b3e8a18f0618a
 F test/notnull.test 44d600f916b770def8b095a9962dbe3be5a70d82
 F test/null.test a8b09b8ed87852742343b33441a9240022108993
 F test/openv2.test f5dd6b23e4dce828eb211649b600763c42a668df
-F test/pager.test 1e1832795e9e07a359c959ffdddcf7275a88f54c
-F test/pager2.test 070983b89a308adaba525a2f9c1ba0592c72fa3d
+F test/pager.test fd3f5009985728ef7bf0dfe32a1bbc112e6895c5
+F test/pager2.test d84c59ae4a803e03d19d72cbb5b14c71850c6163
 F test/pager3.test 2323bf27fd5bd887b580247e5bce500ceee994b4
 F test/pageropt.test 3ee6578891baaca967f0bd349e4abfa736229e1a
 F test/pagesize.test 0d9ff3fedfce6e5ffe8fa7aca9b6d3433a2e843b
 F test/pcache.test 515b4c26e9f57660357dfff5b6b697acac1abc5f
 F test/pcache2.test e2260293e892190be65de89526dbc4f92c8b5a7c
-F test/permutations.test a80a319ed2e825fa828af086d322b47fc9d9c664
+F test/permutations.test 3f24cf55e9646b138a6980f78f18190f318af9a3
 F test/pragma.test 583937903d01cad823ae195573d90c02ea945717
 F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47
 F test/printf.test 262a5acd3158f788e9bdf7f18d718f3af32ff6ef
@@ -467,7 +467,7 @@ F test/quick.test 70695607082b3e1ca54023b2c856991604b07703
 F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6
 F test/rdonly.test bd054831f8a3078e765a0657e247182486f0cb47
 F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
-F test/rollback.test d67022e8f99fdb1f115de7e8ea65139263b4bd40
+F test/rollback.test 1f70ab4301d8d105d41438a436cad1fc8897f5e5
 F test/rowid.test 1c8fc43c60d273e6ea44dfb992db587f3164312c
 F test/rtree.test b85fd4f0861a40ca366ac195e363be2528dcfadf
 F test/safety.test b69e2b2dd5d52a3f78e216967086884bbc1a09c6
@@ -633,7 +633,7 @@ F tool/memleak3.tcl 7707006ee908cffff210c98158788d85bb3fcdbf
 F tool/mkkeywordhash.c c219ee2b8b5b8e7011cccfa1caec62d9812e82e7
 F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x
 F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
-F tool/mksqlite3c.tcl 8aff2d49beb7d94a63841e86f3ffd4770e5054aa
+F tool/mksqlite3c.tcl ab98a8321f292b4871e362bb4435be234993d46b
 F tool/mksqlite3internalh.tcl 7b43894e21bcb1bb39e11547ce7e38a063357e87
 F tool/omittest.tcl 27d6f6e3b1e95aeb26a1c140e6eb57771c6d794a
 F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
@@ -648,7 +648,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
-P 8065a92f705dfa04863ba4a828f5bd2803901be8
-R 4bd0b87e5fdde7ed86abc759091ffc21
-U drh
-Z 9251407651b2b71ae84b77628eaaa866
+P 5ce2ddffea807d45318619cc9e259a99dfa14346
+R d3d208ea9f507cd99d0a55a9424ad33c
+U danielk1977
+Z e1e732a777069a84074d19c41d686a93
index 801027e17b6911ca911d468c10abce7480b82c1b..48f94588a2ee96feadea4ce2b703974eec7517be 100644 (file)
@@ -1 +1 @@
-5ce2ddffea807d45318619cc9e259a99dfa14346
\ No newline at end of file
+39ebf01addf9d0867daafd06a38719e725128f9c
\ No newline at end of file
index 900aa1618d0fca05aaa359c677db2f4b350353f3..6932ab96df44426c5a692f9ad9a3e589627d3104 100644 (file)
@@ -18,7 +18,7 @@
 ** file simultaneously, or one process from reading the database while
 ** another is writing.
 **
-** @(#) $Id: pager.c,v 1.497 2008/10/07 11:51:20 danielk1977 Exp $
+** @(#) $Id: pager.c,v 1.498 2008/10/17 18:51:52 danielk1977 Exp $
 */
 #ifndef SQLITE_OMIT_DISKIO
 #include "sqliteInt.h"
@@ -309,11 +309,7 @@ static const unsigned char aJournalMagic[] = {
 */
 static int pageInStatement(PgHdr *pPg){
   Pager *pPager = pPg->pPager;
-  if( MEMDB ){
-    return pPg->apSave[1]!=0;
-  }else{
-    return sqlite3BitvecTest(pPager->pInStmt, pPg->pgno);
-  }
+  return sqlite3BitvecTest(pPager->pInStmt, pPg->pgno);
 }
 
 /*
@@ -470,7 +466,7 @@ static u32 pager_set_pagehash(PgHdr *pPage){
 #define CHECK_PAGE(x) checkPage(x)
 static void checkPage(PgHdr *pPg){
   Pager *pPager = pPg->pPager;
-  assert( !pPg->pageHash || pPager->errCode || MEMDB 
+  assert( !pPg->pageHash || pPager->errCode
       || (pPg->flags&PGHDR_DIRTY) || pPg->pageHash==pager_pagehash(pPg) );
 }
 
@@ -664,7 +660,7 @@ static int writeJournalHdr(Pager *pPager){
   **     that garbage data is never appended to the journal file.
   */
   assert(pPager->fd->pMethods||pPager->noSync);
-  if( (pPager->noSync) 
+  if( (pPager->noSync) || (pPager->journalMode==PAGER_JOURNALMODE_MEMORY)
    || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND) 
   ){
     put32bits(&zHeader[sizeof(aJournalMagic)], 0xffffffff);
@@ -796,7 +792,8 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){
   u32 cksum = 0;
   char zBuf[sizeof(aJournalMagic)+2*4];
 
-  if( !zMaster || pPager->setMaster) return SQLITE_OK;
+  if( !zMaster || pPager->setMaster ) return SQLITE_OK;
+  if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ) return SQLITE_OK;
   pPager->setMaster = 1;
 
   len = strlen(zMaster);
@@ -880,50 +877,46 @@ static void pager_reset(Pager *pPager){
 */
 static void pager_unlock(Pager *pPager){
   if( !pPager->exclusiveMode ){
-    if( !MEMDB ){
-      int rc = osUnlock(pPager->fd, NO_LOCK);
-      if( rc ) pPager->errCode = rc;
-      pPager->dbSize = -1;
-      IOTRACE(("UNLOCK %p\n", pPager))
+    int rc = osUnlock(pPager->fd, NO_LOCK);
+    if( rc ) pPager->errCode = rc;
+    pPager->dbSize = -1;
+    IOTRACE(("UNLOCK %p\n", pPager))
 
-      /* Always close the journal file when dropping the database lock.
-      ** Otherwise, another connection with journal_mode=delete might
-      ** delete the file out from under us.
-      */
-      if( pPager->journalOpen ){
-        sqlite3OsClose(pPager->jfd);
-        pPager->journalOpen = 0;
-        sqlite3BitvecDestroy(pPager->pInJournal);
-        pPager->pInJournal = 0;
-        sqlite3BitvecDestroy(pPager->pAlwaysRollback);
-        pPager->pAlwaysRollback = 0;
-      }
+    /* Always close the journal file when dropping the database lock.
+    ** Otherwise, another connection with journal_mode=delete might
+    ** delete the file out from under us.
+    */
+    if( pPager->journalOpen ){
+      sqlite3OsClose(pPager->jfd);
+      pPager->journalOpen = 0;
+      sqlite3BitvecDestroy(pPager->pInJournal);
+      pPager->pInJournal = 0;
+      sqlite3BitvecDestroy(pPager->pAlwaysRollback);
+      pPager->pAlwaysRollback = 0;
+    }
 
-      /* If Pager.errCode is set, the contents of the pager cache cannot be
-      ** trusted. Now that the pager file is unlocked, the contents of the
-      ** cache can be discarded and the error code safely cleared.
-      */
-      if( pPager->errCode ){
-        if( rc==SQLITE_OK ) pPager->errCode = SQLITE_OK;
-        pager_reset(pPager);
-        if( pPager->stmtOpen ){
-          sqlite3OsClose(pPager->stfd);
-          sqlite3BitvecDestroy(pPager->pInStmt);
-          pPager->pInStmt = 0;
-        }
-        pPager->stmtOpen = 0;
-        pPager->stmtInUse = 0;
-        pPager->journalOff = 0;
-        pPager->journalStarted = 0;
-        pPager->stmtAutoopen = 0;
-        pPager->origDbSize = 0;
+    /* If Pager.errCode is set, the contents of the pager cache cannot be
+    ** trusted. Now that the pager file is unlocked, the contents of the
+    ** cache can be discarded and the error code safely cleared.
+    */
+    if( pPager->errCode ){
+      if( rc==SQLITE_OK ) pPager->errCode = SQLITE_OK;
+      pager_reset(pPager);
+      if( pPager->stmtOpen ){
+        sqlite3OsClose(pPager->stfd);
+        sqlite3BitvecDestroy(pPager->pInStmt);
+        pPager->pInStmt = 0;
       }
+      pPager->stmtOpen = 0;
+      pPager->stmtInUse = 0;
+      pPager->journalOff = 0;
+      pPager->journalStarted = 0;
+      pPager->stmtAutoopen = 0;
+      pPager->origDbSize = 0;
     }
 
-    if( !MEMDB || pPager->errCode==SQLITE_OK ){
-      pPager->state = PAGER_UNLOCK;
-      pPager->changeCountDone = 0;
-    }
+    pPager->state = PAGER_UNLOCK;
+    pPager->changeCountDone = 0;
   }
 }
 
@@ -961,7 +954,6 @@ static void pagerUnlockAndRollback(Pager *p){
 static int pager_end_transaction(Pager *pPager, int hasMaster){
   int rc = SQLITE_OK;
   int rc2 = SQLITE_OK;
-  assert( !MEMDB );
   if( pPager->state<PAGER_RESERVED ){
     return SQLITE_OK;
   }
@@ -971,7 +963,14 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
     pPager->stmtOpen = 0;
   }
   if( pPager->journalOpen ){
-    if( pPager->journalMode==PAGER_JOURNALMODE_TRUNCATE
+    if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){
+      int isMemoryJournal = sqlite3IsMemJournal(pPager->jfd);
+      sqlite3OsClose(pPager->jfd);
+      pPager->journalOpen = 0;
+      if( !isMemoryJournal ){
+        rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
+      }
+    }else if( pPager->journalMode==PAGER_JOURNALMODE_TRUNCATE
          && (rc = sqlite3OsTruncate(pPager->jfd, 0))==SQLITE_OK ){
       pPager->journalOff = 0;
       pPager->journalStarted = 0;
@@ -1017,7 +1016,9 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
   pPager->setMaster = 0;
   pPager->needSync = 0;
   /* lruListSetFirstSynced(pPager); */
-  pPager->dbSize = -1;
+  if( !MEMDB ){
+    pPager->dbSize = -1;
+  }
   pPager->dbModified = 0;
 
   return (rc==SQLITE_OK?rc2:rc);
@@ -1667,7 +1668,7 @@ void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){
 */
 #ifndef SQLITE_OMIT_PAGER_PRAGMAS
 void sqlite3PagerSetSafetyLevel(Pager *pPager, int level, int bFullFsync){
-  pPager->noSync =  level==1 || pPager->tempFile || MEMDB;
+  pPager->noSync =  level==1 || pPager->tempFile;
   pPager->fullSync = level==3 && !pPager->tempFile;
   pPager->sync_flags = (bFullFsync?SQLITE_SYNC_FULL:SQLITE_SYNC_NORMAL);
   if( pPager->noSync ) pPager->needSync = 0;
@@ -1741,12 +1742,18 @@ int sqlite3PagerOpen(
   int readOnly = 0;
   int useJournal = (flags & PAGER_OMIT_JOURNAL)==0;
   int noReadlock = (flags & PAGER_NO_READLOCK)!=0;
-  int journalFileSize = sqlite3JournalSize(pVfs);
+  int journalFileSize;
   int pcacheSize = sqlite3PcacheSize();
   int szPageDflt = SQLITE_DEFAULT_PAGE_SIZE;
   char *zPathname = 0;
   int nPathname = 0;
 
+  if( sqlite3JournalSize(pVfs)>sqlite3MemJournalSize() ){
+    journalFileSize = sqlite3JournalSize(pVfs);
+  }else{
+    journalFileSize = sqlite3MemJournalSize();
+  }
+
   /* The default return is a NULL pointer */
   *ppPager = 0;
 
@@ -1764,7 +1771,6 @@ int sqlite3PagerOpen(
     if( strcmp(zFilename,":memory:")==0 ){
       memDb = 1;
       zPathname[0] = 0;
-      useJournal = 0;
     }else
 #endif
     {
@@ -1782,7 +1788,8 @@ int sqlite3PagerOpen(
     sizeof(*pPager) +           /* Pager structure */
     pcacheSize      +           /* PCache object */
     journalFileSize +           /* The journal file structure */ 
-    pVfs->szOsFile * 3 +        /* The main db and two journal files */ 
+    pVfs->szOsFile  +           /* The main db file */
+    journalFileSize * 2 +       /* The two journal files */ 
     3*nPathname + 40            /* zFilename, zDirectory, zJournal */
   );
   if( !pPager ){
@@ -1793,9 +1800,9 @@ int sqlite3PagerOpen(
   pPtr = ((u8 *)&pPager[1]) + pcacheSize;
   pPager->vfsFlags = vfsFlags;
   pPager->fd = (sqlite3_file*)&pPtr[pVfs->szOsFile*0];
-  pPager->stfd = (sqlite3_file*)&pPtr[pVfs->szOsFile*1];
-  pPager->jfd = (sqlite3_file*)&pPtr[pVfs->szOsFile*2];
-  pPager->zFilename = (char*)&pPtr[pVfs->szOsFile*2+journalFileSize];
+  pPager->stfd = (sqlite3_file*)&pPtr[pVfs->szOsFile];
+  pPager->jfd = (sqlite3_file*)&pPtr[pVfs->szOsFile+journalFileSize];
+  pPager->zFilename = (char*)&pPtr[pVfs->szOsFile+2*journalFileSize];
   pPager->zDirectory = &pPager->zFilename[nPathname+1];
   pPager->zJournal = &pPager->zDirectory[nPathname+1];
   pPager->pVfs = pVfs;
@@ -1845,10 +1852,14 @@ int sqlite3PagerOpen(
         }
       }
     }
-  }else if( !memDb ){
+  }else{
     /* If a temporary file is requested, it is not opened immediately.
     ** In this case we accept the default page size and delay actually
     ** opening the file until the first call to OsWrite().
+    **
+    ** This branch is also run for an in-memory database. An in-memory
+    ** database is the same as a temp-file that is never written out to
+    ** disk and uses an in-memory rollback journal.
     */ 
     tempFile = 1;
     pPager->state = PAGER_EXCLUSIVE;
@@ -1920,9 +1931,10 @@ int sqlite3PagerOpen(
   /* pPager->pLast = 0; */
   pPager->nExtra = nExtra;
   pPager->journalSizeLimit = SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT;
-  assert(pPager->fd->pMethods||memDb||tempFile);
-  if( !memDb ){
-    setSectorSize(pPager);
+  assert(pPager->fd->pMethods||tempFile);
+  setSectorSize(pPager);
+  if( memDb ){
+    pPager->journalMode = PAGER_JOURNALMODE_MEMORY;
   }
   /* pPager->pBusyHandler = 0; */
   /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
@@ -2043,7 +2055,7 @@ void enable_simulated_io_errors(void){
 int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned char *pDest){
   int rc = SQLITE_OK;
   memset(pDest, 0, N);
-  assert(MEMDB||pPager->fd->pMethods||pPager->tempFile);
+  assert(pPager->fd->pMethods||pPager->tempFile);
   if( pPager->fd->pMethods ){
     IOTRACE(("DBHDR %p 0 %d\n", pPager, N))
     rc = sqlite3OsRead(pPager->fd, pDest, N, 0);
@@ -2139,7 +2151,7 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
   assert( PAGER_EXCLUSIVE==EXCLUSIVE_LOCK );
 
   /* If the file is currently unlocked then the size must be unknown */
-  assert( pPager->state>=PAGER_SHARED || pPager->dbSize<0 || MEMDB );
+  assert( pPager->state>=PAGER_SHARED || pPager->dbSize<0 );
 
   if( pPager->state>=locktype ){
     rc = SQLITE_OK;
@@ -2161,25 +2173,19 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
 */
 int sqlite3PagerTruncate(Pager *pPager, Pgno nPage){
   int rc = SQLITE_OK;
-  assert( pPager->state>=PAGER_SHARED || MEMDB );
-
+  assert( pPager->state>=PAGER_SHARED );
 
   sqlite3PagerPagecount(pPager, 0);
   if( pPager->errCode ){
     rc = pPager->errCode;
   }else if( nPage<(unsigned)pPager->dbSize ){
-    if( MEMDB ){
-      pPager->dbSize = nPage;
-      pager_truncate_cache(pPager);
-    }else{
-      rc = syncJournal(pPager);
-      if( rc==SQLITE_OK ){
-        /* Get an exclusive lock on the database before truncating. */
-        rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
-      }
-      if( rc==SQLITE_OK ){
-        rc = pager_truncate(pPager, nPage);
-      }
+    rc = syncJournal(pPager);
+    if( rc==SQLITE_OK ){
+      /* Get an exclusive lock on the database before truncating. */
+      rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
+    }
+    if( rc==SQLITE_OK ){
+      rc = pager_truncate(pPager, nPage);
     }
   }
 
@@ -2207,7 +2213,9 @@ int sqlite3PagerClose(Pager *pPager){
   pPager->errCode = 0;
   pPager->exclusiveMode = 0;
   pager_reset(pPager);
-  pagerUnlockAndRollback(pPager);
+  if( !MEMDB ){
+    pagerUnlockAndRollback(pPager);
+  }
   enable_simulated_io_errors();
   sqlite3EndBenignMalloc();
   PAGERTRACE2("CLOSE %d\n", PAGERID(pPager));
@@ -2283,7 +2291,8 @@ static int syncJournal(Pager *pPager){
   ** (assuming there is a journal and it needs to be synced.)
   */
   if( pPager->needSync ){
-    if( !pPager->tempFile ){
+    assert( !pPager->tempFile );
+    if( pPager->journalMode!=PAGER_JOURNALMODE_MEMORY ){
       int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
       assert( pPager->journalOpen );
 
@@ -2439,6 +2448,7 @@ static int pagerStress(void *p, PgHdr *pPg){
     if( pPg->flags&PGHDR_NEED_SYNC ){
       rc = syncJournal(pPager);
       if( rc==SQLITE_OK && pPager->fullSync && 
+        !(pPager->journalMode==PAGER_JOURNALMODE_MEMORY) &&
         !(sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND)
       ){
         pPager->nRec = 0;
@@ -2572,140 +2582,139 @@ static int pagerSharedLock(Pager *pPager){
 
   if( pPager->state==PAGER_UNLOCK || isErrorReset ){
     sqlite3_vfs *pVfs = pPager->pVfs;
-    if( !MEMDB ){
-      int isHotJournal;
-      assert( sqlite3PcacheRefCount(pPager->pPCache)==0 );
-      if( !pPager->noReadlock ){
-        rc = pager_wait_on_lock(pPager, SHARED_LOCK);
-        if( rc!=SQLITE_OK ){
-          assert( pPager->state==PAGER_UNLOCK );
-          return pager_error(pPager, rc);
-        }
-        assert( pPager->state>=SHARED_LOCK );
+    assert( !MEMDB );
+    int isHotJournal;
+    assert( sqlite3PcacheRefCount(pPager->pPCache)==0 );
+    if( !pPager->noReadlock ){
+      rc = pager_wait_on_lock(pPager, SHARED_LOCK);
+      if( rc!=SQLITE_OK ){
+        assert( pPager->state==PAGER_UNLOCK );
+        return pager_error(pPager, rc);
       }
-  
-      /* If a journal file exists, and there is no RESERVED lock on the
-      ** database file, then it either needs to be played back or deleted.
+      assert( pPager->state>=SHARED_LOCK );
+    }
+
+    /* If a journal file exists, and there is no RESERVED lock on the
+    ** database file, then it either needs to be played back or deleted.
+    */
+    if( !isErrorReset ){
+      rc = hasHotJournal(pPager, &isHotJournal);
+      if( rc!=SQLITE_OK ){
+        goto failed;
+      }
+    }
+    if( isErrorReset || isHotJournal ){
+      /* Get an EXCLUSIVE lock on the database file. At this point it is
+      ** important that a RESERVED lock is not obtained on the way to the
+      ** EXCLUSIVE lock. If it were, another process might open the
+      ** database file, detect the RESERVED lock, and conclude that the
+      ** database is safe to read while this process is still rolling it 
+      ** back.
+      ** 
+      ** Because the intermediate RESERVED lock is not requested, the
+      ** second process will get to this point in the code and fail to
+      ** obtain its own EXCLUSIVE lock on the database file.
       */
-      if( !isErrorReset ){
-        rc = hasHotJournal(pPager, &isHotJournal);
+      if( pPager->state<EXCLUSIVE_LOCK ){
+        rc = sqlite3OsLock(pPager->fd, EXCLUSIVE_LOCK);
         if( rc!=SQLITE_OK ){
+          rc = pager_error(pPager, rc);
           goto failed;
         }
+        pPager->state = PAGER_EXCLUSIVE;
       }
-      if( isErrorReset || isHotJournal ){
-        /* Get an EXCLUSIVE lock on the database file. At this point it is
-        ** important that a RESERVED lock is not obtained on the way to the
-        ** EXCLUSIVE lock. If it were, another process might open the
-        ** database file, detect the RESERVED lock, and conclude that the
-        ** database is safe to read while this process is still rolling it 
-        ** back.
-        ** 
-        ** Because the intermediate RESERVED lock is not requested, the
-        ** second process will get to this point in the code and fail to
-        ** obtain its own EXCLUSIVE lock on the database file.
-        */
-        if( pPager->state<EXCLUSIVE_LOCK ){
-          rc = sqlite3OsLock(pPager->fd, EXCLUSIVE_LOCK);
-          if( rc!=SQLITE_OK ){
-            rc = pager_error(pPager, rc);
-            goto failed;
-          }
-          pPager->state = PAGER_EXCLUSIVE;
-        }
  
-        /* Open the journal for read/write access. This is because in 
-        ** exclusive-access mode the file descriptor will be kept open and
-        ** possibly used for a transaction later on. On some systems, the
-        ** OsTruncate() call used in exclusive-access mode also requires
-        ** a read/write file handle.
-        */
-        if( !isErrorReset && pPager->journalOpen==0 ){
-          int res;
-          rc = sqlite3OsAccess(pVfs,pPager->zJournal,SQLITE_ACCESS_EXISTS,&res);
-          if( rc==SQLITE_OK ){
-            if( res ){
-              int fout = 0;
-              int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL;
-              assert( !pPager->tempFile );
-              rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout);
-              assert( rc!=SQLITE_OK || pPager->jfd->pMethods );
-              if( fout&SQLITE_OPEN_READONLY ){
-                rc = SQLITE_BUSY;
-                sqlite3OsClose(pPager->jfd);
-              }
-            }else{
-              /* If the journal does not exist, that means some other process
-              ** has already rolled it back */
+      /* Open the journal for read/write access. This is because in 
+      ** exclusive-access mode the file descriptor will be kept open and
+      ** possibly used for a transaction later on. On some systems, the
+      ** OsTruncate() call used in exclusive-access mode also requires
+      ** a read/write file handle.
+      */
+      if( !isErrorReset && pPager->journalOpen==0 ){
+        int res;
+        rc = sqlite3OsAccess(pVfs,pPager->zJournal,SQLITE_ACCESS_EXISTS,&res);
+        if( rc==SQLITE_OK ){
+          if( res ){
+            int fout = 0;
+            int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL;
+            assert( !pPager->tempFile );
+            rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout);
+            assert( rc!=SQLITE_OK || pPager->jfd->pMethods );
+            if( fout&SQLITE_OPEN_READONLY ){
               rc = SQLITE_BUSY;
+              sqlite3OsClose(pPager->jfd);
             }
-          }
-        }
-        if( rc!=SQLITE_OK ){
-          if( rc!=SQLITE_NOMEM && rc!=SQLITE_IOERR_UNLOCK 
-           && rc!=SQLITE_IOERR_NOMEM 
-          ){
+          }else{
+            /* If the journal does not exist, that means some other process
+            ** has already rolled it back */
             rc = SQLITE_BUSY;
           }
-          goto failed;
         }
-        pPager->journalOpen = 1;
-        pPager->journalStarted = 0;
-        pPager->journalOff = 0;
-        pPager->setMaster = 0;
-        pPager->journalHdr = 0;
-        /* Playback and delete the journal.  Drop the database write
-        ** lock and reacquire the read lock.
-        */
-        rc = pager_playback(pPager, 1);
-        if( rc!=SQLITE_OK ){
-          rc = pager_error(pPager, rc);
-          goto failed;
+      }
+      if( rc!=SQLITE_OK ){
+        if( rc!=SQLITE_NOMEM && rc!=SQLITE_IOERR_UNLOCK 
+         && rc!=SQLITE_IOERR_NOMEM 
+        ){
+          rc = SQLITE_BUSY;
         }
-        assert(pPager->state==PAGER_SHARED || 
-            (pPager->exclusiveMode && pPager->state>PAGER_SHARED)
-        );
+        goto failed;
+      }
+      pPager->journalOpen = 1;
+      pPager->journalStarted = 0;
+      pPager->journalOff = 0;
+      pPager->setMaster = 0;
+      pPager->journalHdr = 0;
+      /* Playback and delete the journal.  Drop the database write
+      ** lock and reacquire the read lock.
+      */
+      rc = pager_playback(pPager, 1);
+      if( rc!=SQLITE_OK ){
+        rc = pager_error(pPager, rc);
+        goto failed;
       }
+      assert(pPager->state==PAGER_SHARED || 
+          (pPager->exclusiveMode && pPager->state>PAGER_SHARED)
+      );
+    }
 
-      if( sqlite3PcachePagecount(pPager->pPCache)>0 ){
-        /* The shared-lock has just been acquired on the database file
-        ** and there are already pages in the cache (from a previous
-        ** read or write transaction).  Check to see if the database
-        ** has been modified.  If the database has changed, flush the
-        ** cache.
-        **
-        ** Database changes is detected by looking at 15 bytes beginning
-        ** at offset 24 into the file.  The first 4 of these 16 bytes are
-        ** a 32-bit counter that is incremented with each change.  The
-        ** other bytes change randomly with each file change when
-        ** a codec is in use.
-        ** 
-        ** There is a vanishingly small chance that a change will not be 
-        ** detected.  The chance of an undetected change is so small that
-        ** it can be neglected.
-        */
-        char dbFileVers[sizeof(pPager->dbFileVers)];
-        sqlite3PagerPagecount(pPager, 0);
+    if( sqlite3PcachePagecount(pPager->pPCache)>0 ){
+      /* The shared-lock has just been acquired on the database file
+      ** and there are already pages in the cache (from a previous
+      ** read or write transaction).  Check to see if the database
+      ** has been modified.  If the database has changed, flush the
+      ** cache.
+      **
+      ** Database changes is detected by looking at 15 bytes beginning
+      ** at offset 24 into the file.  The first 4 of these 16 bytes are
+      ** a 32-bit counter that is incremented with each change.  The
+      ** other bytes change randomly with each file change when
+      ** a codec is in use.
+      ** 
+      ** There is a vanishingly small chance that a change will not be 
+      ** detected.  The chance of an undetected change is so small that
+      ** it can be neglected.
+      */
+      char dbFileVers[sizeof(pPager->dbFileVers)];
+      sqlite3PagerPagecount(pPager, 0);
 
-        if( pPager->errCode ){
-          rc = pPager->errCode;
-          goto failed;
-        }
+      if( pPager->errCode ){
+        rc = pPager->errCode;
+        goto failed;
+      }
 
-        if( pPager->dbSize>0 ){
-          IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers)));
-          rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24);
-          if( rc!=SQLITE_OK ){
-            goto failed;
-          }
-        }else{
-          memset(dbFileVers, 0, sizeof(dbFileVers));
+      if( pPager->dbSize>0 ){
+        IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers)));
+        rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24);
+        if( rc!=SQLITE_OK ){
+          goto failed;
         }
+      }else{
+        memset(dbFileVers, 0, sizeof(dbFileVers));
+      }
 
-        if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){
-          pager_reset(pPager);
-        }
+      if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){
+        pager_reset(pPager);
       }
     }
     assert( pPager->exclusiveMode || pPager->state<=PAGER_SHARED );
@@ -2808,7 +2817,7 @@ int sqlite3PagerAcquire(
 
   assert( pPager->state==PAGER_UNLOCK 
        || sqlite3PcacheRefCount(pPager->pPCache)>0 
-       || pgno==1 
+       || pgno==1
   );
 
   /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page
@@ -2845,7 +2854,6 @@ int sqlite3PagerAcquire(
     PAGER_INCR(pPager->nMiss);
     pPg->pPager = pPager;
     if( sqlite3BitvecTest(pPager->pInJournal, pgno) ){
-      assert( !MEMDB );
       pPg->flags |= PGHDR_IN_JOURNAL;
     }
     memset(pPg->pExtra, 0, pPager->nExtra);
@@ -2948,7 +2956,6 @@ static int pager_open_journal(Pager *pPager){
   int flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_CREATE);
 
   int rc;
-  assert( !MEMDB );
   assert( pPager->state>=PAGER_RESERVED );
   assert( pPager->useJournal );
   assert( pPager->pInJournal==0 );
@@ -2965,13 +2972,18 @@ static int pager_open_journal(Pager *pPager){
     }else{
       flags |= (SQLITE_OPEN_MAIN_JOURNAL);
     }
+    if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){
+      sqlite3MemJournalOpen(pPager->jfd);
+      rc = SQLITE_OK;
+    }else{
 #ifdef SQLITE_ENABLE_ATOMIC_WRITE
-    rc = sqlite3JournalOpen(
-        pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager)
-    );
+      rc = sqlite3JournalOpen(
+          pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager)
+      );
 #else
-    rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0);
+      rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0);
 #endif
+    }
     assert( rc!=SQLITE_OK || pPager->jfd->pMethods );
     pPager->journalOff = 0;
     pPager->setMaster = 0;
@@ -3046,28 +3058,24 @@ int sqlite3PagerBegin(DbPage *pPg, int exFlag){
   assert( pPager->state!=PAGER_UNLOCK );
   if( pPager->state==PAGER_SHARED ){
     assert( pPager->pInJournal==0 );
+    assert( !MEMDB );
     sqlite3PcacheAssertFlags(pPager->pPCache, 0, PGHDR_IN_JOURNAL);
-    if( MEMDB ){
-      pPager->state = PAGER_EXCLUSIVE;
-      pPager->origDbSize = pPager->dbSize;
-    }else{
-      rc = sqlite3OsLock(pPager->fd, RESERVED_LOCK);
-      if( rc==SQLITE_OK ){
-        pPager->state = PAGER_RESERVED;
-        if( exFlag ){
-          rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
-        }
-      }
-      if( rc!=SQLITE_OK ){
-        return rc;
-      }
-      pPager->dirtyCache = 0;
-      PAGERTRACE2("TRANSACTION %d\n", PAGERID(pPager));
-      if( pPager->useJournal && !pPager->tempFile
-             && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
-        rc = pager_open_journal(pPager);
+    rc = sqlite3OsLock(pPager->fd, RESERVED_LOCK);
+    if( rc==SQLITE_OK ){
+      pPager->state = PAGER_RESERVED;
+      if( exFlag ){
+        rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
       }
     }
+    if( rc!=SQLITE_OK ){
+      return rc;
+    }
+    pPager->dirtyCache = 0;
+    PAGERTRACE2("TRANSACTION %d\n", PAGERID(pPager));
+    if( pPager->useJournal && !pPager->tempFile
+           && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
+      rc = pager_open_journal(pPager);
+    }
   }else if( pPager->journalOpen && pPager->journalOff==0 ){
     /* This happens when the pager was in exclusive-access mode the last
     ** time a (read or write) transaction was successfully concluded
@@ -3192,57 +3200,49 @@ static int pager_write(PgHdr *pPg){
     ** EXCLUSIVE lock on the main database file.  Write the current page to
     ** the transaction journal if it is not there already.
     */
-    if( !(pPg->flags&PGHDR_IN_JOURNAL) && (pPager->journalOpen || MEMDB) ){
+    if( !(pPg->flags&PGHDR_IN_JOURNAL) && pPager->journalOpen ){
       if( (int)pPg->pgno <= pPager->origDbSize ){
-        if( MEMDB ){
-          PAGERTRACE3("JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
-          rc = sqlite3PcachePreserve(pPg, 0);
-          if( rc!=SQLITE_OK ){
-            return rc;
-          }
-        }else{
-          u32 cksum;
-          char *pData2;
-
-          /* We should never write to the journal file the page that
-          ** contains the database locks.  The following assert verifies
-          ** that we do not. */
-          assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) );
-          pData2 = CODEC2(pPager, pData, pPg->pgno, 7);
-          cksum = pager_cksum(pPager, (u8*)pData2);
-          rc = write32bits(pPager->jfd, pPager->journalOff, pPg->pgno);
-          if( rc==SQLITE_OK ){
-            rc = sqlite3OsWrite(pPager->jfd, pData2, pPager->pageSize,
-                                pPager->journalOff + 4);
-            pPager->journalOff += pPager->pageSize+4;
-          }
-          if( rc==SQLITE_OK ){
-            rc = write32bits(pPager->jfd, pPager->journalOff, cksum);
-            pPager->journalOff += 4;
-          }
-          IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno, 
-                   pPager->journalOff, pPager->pageSize));
-          PAGER_INCR(sqlite3_pager_writej_count);
-          PAGERTRACE5("JOURNAL %d page %d needSync=%d hash(%08x)\n",
-               PAGERID(pPager), pPg->pgno, 
-               ((pPg->flags&PGHDR_NEED_SYNC)?1:0), pager_pagehash(pPg));
-
-          /* An error has occured writing to the journal file. The 
-          ** transaction will be rolled back by the layer above.
-          */
-          if( rc!=SQLITE_OK ){
-            return rc;
-          }
+        u32 cksum;
+        char *pData2;
+
+        /* We should never write to the journal file the page that
+        ** contains the database locks.  The following assert verifies
+        ** that we do not. */
+        assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) );
+        pData2 = CODEC2(pPager, pData, pPg->pgno, 7);
+        cksum = pager_cksum(pPager, (u8*)pData2);
+        rc = write32bits(pPager->jfd, pPager->journalOff, pPg->pgno);
+        if( rc==SQLITE_OK ){
+          rc = sqlite3OsWrite(pPager->jfd, pData2, pPager->pageSize,
+                              pPager->journalOff + 4);
+          pPager->journalOff += pPager->pageSize+4;
+        }
+        if( rc==SQLITE_OK ){
+          rc = write32bits(pPager->jfd, pPager->journalOff, cksum);
+          pPager->journalOff += 4;
+        }
+        IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno, 
+                 pPager->journalOff, pPager->pageSize));
+        PAGER_INCR(sqlite3_pager_writej_count);
+        PAGERTRACE5("JOURNAL %d page %d needSync=%d hash(%08x)\n",
+             PAGERID(pPager), pPg->pgno, 
+             ((pPg->flags&PGHDR_NEED_SYNC)?1:0), pager_pagehash(pPg));
+
+        /* An error has occured writing to the journal file. The 
+        ** transaction will be rolled back by the layer above.
+        */
+        if( rc!=SQLITE_OK ){
+          return rc;
+        }
 
-          pPager->nRec++;
-          assert( pPager->pInJournal!=0 );
-          sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
-          if( !pPager->noSync ){
-            pPg->flags |= PGHDR_NEED_SYNC;
-          }
-          if( pPager->stmtInUse ){
-            sqlite3BitvecSet(pPager->pInStmt, pPg->pgno);
-          }
+        pPager->nRec++;
+        assert( pPager->pInJournal!=0 );
+        sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
+        if( !pPager->noSync ){
+          pPg->flags |= PGHDR_NEED_SYNC;
+        }
+        if( pPager->stmtInUse ){
+          sqlite3BitvecSet(pPager->pInStmt, pPg->pgno);
         }
       }else{
         if( !pPager->journalStarted && !pPager->noSync ){
@@ -3269,27 +3269,19 @@ static int pager_write(PgHdr *pPg){
     ){
       assert( (pPg->flags&PGHDR_IN_JOURNAL) 
                  || (int)pPg->pgno>pPager->origDbSize );
-      if( MEMDB ){
-        rc = sqlite3PcachePreserve(pPg, 1);
-        if( rc!=SQLITE_OK ){
-          return rc;
-        }
-        PAGERTRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
-      }else{
-        i64 offset = pPager->stmtNRec*(4+pPager->pageSize);
-        char *pData2 = CODEC2(pPager, pData, pPg->pgno, 7);
-        rc = write32bits(pPager->stfd, offset, pPg->pgno);
-        if( rc==SQLITE_OK ){
-          rc = sqlite3OsWrite(pPager->stfd, pData2, pPager->pageSize, offset+4);
-        }
-        PAGERTRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
-        if( rc!=SQLITE_OK ){
-          return rc;
-        }
-        pPager->stmtNRec++;
-        assert( pPager->pInStmt!=0 );
-        sqlite3BitvecSet(pPager->pInStmt, pPg->pgno);
+      i64 offset = pPager->stmtNRec*(4+pPager->pageSize);
+      char *pData2 = CODEC2(pPager, pData, pPg->pgno, 7);
+      rc = write32bits(pPager->stfd, offset, pPg->pgno);
+      if( rc==SQLITE_OK ){
+        rc = sqlite3OsWrite(pPager->stfd, pData2, pPager->pageSize, offset+4);
+      }
+      PAGERTRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
+      if( rc!=SQLITE_OK ){
+        return rc;
       }
+      pPager->stmtNRec++;
+      assert( pPager->pInStmt!=0 );
+      sqlite3BitvecSet(pPager->pInStmt, pPg->pgno);
     }
   }
 
@@ -3298,7 +3290,7 @@ static int pager_write(PgHdr *pPg){
   assert( pPager->state>=PAGER_SHARED );
   if( pPager->dbSize<(int)pPg->pgno ){
     pPager->dbSize = pPg->pgno;
-    if( !MEMDB && pPager->dbSize==PENDING_BYTE/pPager->pageSize ){
+    if( pPager->dbSize==PENDING_BYTE/pPager->pageSize ){
       pPager->dbSize++;
     }
   }
@@ -3322,7 +3314,7 @@ int sqlite3PagerWrite(DbPage *pDbPage){
   Pager *pPager = pPg->pPager;
   Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);
 
-  if( !MEMDB && nPagePerSector>1 ){
+  if( nPagePerSector>1 ){
     Pgno nPageCount;          /* Total number of pages in database file */
     Pgno pg1;                 /* First page of the sector pPg is located on. */
     int nPage;                /* Number of pages starting at pg1 to journal */
@@ -3332,6 +3324,7 @@ int sqlite3PagerWrite(DbPage *pDbPage){
     /* Set the doNotSync flag to 1. This is because we cannot allow a journal
     ** header to be written between the pages journaled by this function.
     */
+    assert( !MEMDB );
     assert( pPager->doNotSync==0 );
     pPager->doNotSync = 1;
 
@@ -3439,7 +3432,7 @@ int sqlite3PagerDontWrite(DbPage *pDbPage){
   Pager *pPager = pPg->pPager;
   int rc;
 
-  if( MEMDB || pPg->pgno>pPager->origDbSize ){
+  if( pPg->pgno>pPager->origDbSize ){
     return SQLITE_OK;
   }
   if( pPager->pAlwaysRollback==0 ){
@@ -3500,7 +3493,6 @@ void sqlite3PagerDontRollback(DbPage *pPg){
   ){
     return;
   }
-  assert( !MEMDB );    /* For a memdb, pPager->journalOpen is always 0 */
 
 #ifdef SQLITE_SECURE_DELETE
   if( (pPg->flags & PGHDR_IN_JOURNAL)!=0 || (int)pPg->pgno>pPager->origDbSize ){
@@ -3792,16 +3784,9 @@ int sqlite3PagerCommitPhaseTwo(Pager *pPager){
     return SQLITE_OK;
   }
   PAGERTRACE2("COMMIT %d\n", PAGERID(pPager));
-  if( MEMDB ){
-    sqlite3PcacheCommit(pPager->pPCache, 0);
-    sqlite3PcacheCleanAll(pPager->pPCache);
-    sqlite3PcacheAssertFlags(pPager->pPCache, 0, PGHDR_IN_JOURNAL);
-    pPager->state = PAGER_SHARED;
-  }else{
-    assert( pPager->state==PAGER_SYNCED || !pPager->dirtyCache );
-    rc = pager_end_transaction(pPager, pPager->setMaster);
-    rc = pager_error(pPager, rc);
-  }
+  assert( pPager->state==PAGER_SYNCED || MEMDB || !pPager->dirtyCache );
+  rc = pager_end_transaction(pPager, pPager->setMaster);
+  rc = pager_error(pPager, rc);
   return rc;
 }
 
@@ -3820,16 +3805,7 @@ int sqlite3PagerCommitPhaseTwo(Pager *pPager){
 int sqlite3PagerRollback(Pager *pPager){
   int rc = SQLITE_OK;
   PAGERTRACE2("ROLLBACK %d\n", PAGERID(pPager));
-  if( MEMDB ){
-    sqlite3PcacheRollback(pPager->pPCache, 1, pPager->xReiniter);
-    sqlite3PcacheRollback(pPager->pPCache, 0, pPager->xReiniter);
-    sqlite3PcacheCleanAll(pPager->pPCache);
-    sqlite3PcacheAssertFlags(pPager->pPCache, 0, PGHDR_IN_JOURNAL);
-    pPager->dbSize = pPager->origDbSize;
-    pager_truncate_cache(pPager);
-    pPager->stmtInUse = 0;
-    pPager->state = PAGER_SHARED;
-  }else if( !pPager->dirtyCache || !pPager->journalOpen ){
+  if( !pPager->dirtyCache || !pPager->journalOpen ){
     rc = pager_end_transaction(pPager, pPager->setMaster);
   }else if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){
     if( pPager->state>=PAGER_EXCLUSIVE ){
@@ -3848,7 +3824,9 @@ int sqlite3PagerRollback(Pager *pPager){
       rc = pager_playback(pPager, 0);
     }
 
-    pPager->dbSize = -1;
+    if( !MEMDB ){
+      pPager->dbSize = -1;
+    }
 
     /* If an error occurs during a ROLLBACK, we can no longer trust the pager
     ** cache. So call pager_error() on the way out to make any error 
@@ -3918,11 +3896,6 @@ static int pagerStmtBegin(Pager *pPager){
   assert( pPager->state>=PAGER_SHARED );
   assert( pPager->dbSize>=0 );
   PAGERTRACE2("STMT-BEGIN %d\n", PAGERID(pPager));
-  if( MEMDB ){
-    pPager->stmtInUse = 1;
-    pPager->stmtSize = pPager->dbSize;
-    return SQLITE_OK;
-  }
   if( !pPager->journalOpen ){
     pPager->stmtAutoopen = 1;
     return SQLITE_OK;
@@ -3939,9 +3912,13 @@ static int pagerStmtBegin(Pager *pPager){
   pPager->stmtHdrOff = 0;
   pPager->stmtCksum = pPager->cksumInit;
   if( !pPager->stmtOpen ){
-    rc = sqlite3PagerOpentemp(pPager, pPager->stfd, SQLITE_OPEN_SUBJOURNAL);
-    if( rc ){
-      goto stmt_begin_failed;
+    if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){
+      sqlite3MemJournalOpen(pPager->stfd);
+    }else{
+      rc = sqlite3PagerOpentemp(pPager, pPager->stfd, SQLITE_OPEN_SUBJOURNAL);
+      if( rc ){
+        goto stmt_begin_failed;
+      }
     }
     pPager->stmtOpen = 1;
     pPager->stmtNRec = 0;
@@ -3968,14 +3945,13 @@ int sqlite3PagerStmtBegin(Pager *pPager){
 int sqlite3PagerStmtCommit(Pager *pPager){
   if( pPager->stmtInUse ){
     PAGERTRACE2("STMT-COMMIT %d\n", PAGERID(pPager));
-    if( !MEMDB ){
-      sqlite3BitvecDestroy(pPager->pInStmt);
-      pPager->pInStmt = 0;
-    }else{
-      sqlite3PcacheCommit(pPager->pPCache, 1);
-    }
+    sqlite3BitvecDestroy(pPager->pInStmt);
+    pPager->pInStmt = 0;
     pPager->stmtNRec = 0;
     pPager->stmtInUse = 0;
+    if( sqlite3IsMemJournal(pPager->stfd) ){
+      sqlite3OsTruncate(pPager->stfd, 0);
+    }
   }
   pPager->stmtAutoopen = 0;
   return SQLITE_OK;
@@ -3988,14 +3964,7 @@ int sqlite3PagerStmtRollback(Pager *pPager){
   int rc;
   if( pPager->stmtInUse ){
     PAGERTRACE2("STMT-ROLLBACK %d\n", PAGERID(pPager));
-    if( MEMDB ){
-      sqlite3PcacheRollback(pPager->pPCache, 1, pPager->xReiniter);
-      pPager->dbSize = pPager->stmtSize;
-      pager_truncate_cache(pPager);
-      rc = SQLITE_OK;
-    }else{
-      rc = pager_stmt_playback(pPager);
-    }
+    rc = pager_stmt_playback(pPager);
     sqlite3PagerStmtCommit(pPager);
   }else{
     rc = SQLITE_OK;
@@ -4124,7 +4093,6 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
     pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
   }
   if( sqlite3BitvecTest(pPager->pInJournal, pgno) ){
-    assert( !MEMDB );
     pPg->flags |= PGHDR_IN_JOURNAL;
   }
 
@@ -4233,16 +4201,19 @@ int sqlite3PagerLockingMode(Pager *pPager, int eMode){
 ** journal-mode.
 */
 int sqlite3PagerJournalMode(Pager *pPager, int eMode){
-  assert( eMode==PAGER_JOURNALMODE_QUERY
-            || eMode==PAGER_JOURNALMODE_DELETE
-            || eMode==PAGER_JOURNALMODE_TRUNCATE
-            || eMode==PAGER_JOURNALMODE_PERSIST
-            || eMode==PAGER_JOURNALMODE_OFF );
-  assert( PAGER_JOURNALMODE_QUERY<0 );
-  if( eMode>=0 ){
-    pPager->journalMode = eMode;
-  }else{
-    assert( eMode==PAGER_JOURNALMODE_QUERY );
+  if( !MEMDB ){
+    assert( eMode==PAGER_JOURNALMODE_QUERY
+              || eMode==PAGER_JOURNALMODE_DELETE
+              || eMode==PAGER_JOURNALMODE_TRUNCATE
+              || eMode==PAGER_JOURNALMODE_PERSIST
+              || eMode==PAGER_JOURNALMODE_OFF 
+              || eMode==PAGER_JOURNALMODE_MEMORY );
+    assert( PAGER_JOURNALMODE_QUERY<0 );
+    if( eMode>=0 ){
+      pPager->journalMode = eMode;
+    }else{
+      assert( eMode==PAGER_JOURNALMODE_QUERY );
+    }
   }
   return (int)pPager->journalMode;
 }
index accf049e9d3865f323add8a0f03afc88a3105b9b..822b62b18a3c99230068eb8efc438d5a550f8709 100644 (file)
@@ -13,7 +13,7 @@
 ** subsystem.  The page cache subsystem reads and writes a file a page
 ** at a time and provides a journal for rollback.
 **
-** @(#) $Id: pager.h,v 1.85 2008/09/29 11:49:48 danielk1977 Exp $
+** @(#) $Id: pager.h,v 1.86 2008/10/17 18:51:53 danielk1977 Exp $
 */
 
 #ifndef _PAGER_H_
@@ -66,6 +66,7 @@ typedef struct PgHdr DbPage;
 #define PAGER_JOURNALMODE_PERSIST     1   /* Commit by zeroing journal header */
 #define PAGER_JOURNALMODE_OFF         2   /* Journal omitted.  */
 #define PAGER_JOURNALMODE_TRUNCATE    3   /* Commit by truncating journal */
+#define PAGER_JOURNALMODE_MEMORY      4   /* In-memory journal file */
 
 /*
 ** See source code comments for a detailed description of the following
index f55049eb58a441d5b7ef236841cc63ad52037701..a3a1d50577d2b77c9ca28c80c026adb7f302e8b0 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file implements that page cache.
 **
-** @(#) $Id: pcache.c,v 1.33 2008/09/29 11:49:48 danielk1977 Exp $
+** @(#) $Id: pcache.c,v 1.34 2008/10/17 18:51:53 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 
@@ -491,8 +491,6 @@ static void pcachePageFree(PgHdr *p){
   if( p->pCache->bPurgeable ){
     pcache_g.nCurrentPage--;
   }
-  pcacheFree(p->apSave[0]);
-  pcacheFree(p->apSave[1]);
   pcacheFree(p);
 }
 
@@ -813,7 +811,6 @@ void sqlite3PcacheMakeDirty(PgHdr *p){
 
 static void pcacheMakeClean(PgHdr *p){
   PCache *pCache = p->pCache;
-  assert( p->apSave[0]==0 && p->apSave[1]==0 );
   assert( p->flags & PGHDR_DIRTY );
   pcacheRemoveFromList(&pCache->pDirty, p);
   pcacheAddToList(&pCache->pClean, p);
@@ -844,7 +841,6 @@ void sqlite3PcacheCleanAll(PCache *pCache){
   PgHdr *p;
   pcacheEnterMutex();
   while( (p = pCache->pDirty)!=0 ){
-    assert( p->apSave[0]==0 && p->apSave[1]==0 );
     pcacheRemoveFromList(&pCache->pDirty, p);
     p->flags &= ~PGHDR_DIRTY;
     pcacheAddToList(&pCache->pClean, p);
@@ -869,10 +865,6 @@ void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){
   pcacheRemoveFromHash(p);
   p->pgno = newPgno;
   if( newPgno==0 ){
-    pcacheFree(p->apSave[0]);
-    pcacheFree(p->apSave[1]);
-    p->apSave[0] = 0;
-    p->apSave[1] = 0;
     if( (p->flags & PGHDR_DIRTY) ){
       pcacheMakeClean(p);
     }
@@ -970,72 +962,6 @@ void sqlite3PcacheClose(PCache *pCache){
   pcacheExitMutex();
 }
 
-/*
-** Preserve the content of the page.  It is assumed that the content
-** has not been preserved already.
-**
-** If idJournal==0 then this is for the overall transaction.
-** If idJournal==1 then this is for the statement journal.
-**
-** This routine is used for in-memory databases only.
-**
-** Return SQLITE_OK or SQLITE_NOMEM if a memory allocation fails.
-*/
-int sqlite3PcachePreserve(PgHdr *p, int idJournal){
-  void *x;
-  int sz;
-  assert( p->pCache->bPurgeable==0 );
-  assert( p->apSave[idJournal]==0 );
-  sz = p->pCache->szPage;
-  p->apSave[idJournal] = x = sqlite3PageMalloc( sz );
-  if( x==0 ) return SQLITE_NOMEM;
-  memcpy(x, p->pData, sz);
-  return SQLITE_OK;
-}
-
-/*
-** Commit a change previously preserved.
-*/
-void sqlite3PcacheCommit(PCache *pCache, int idJournal){
-  PgHdr *p;
-  int mask = idJournal==0 ? ~PGHDR_IN_JOURNAL : 0xffffff;
-  pcacheEnterMutex();     /* Mutex is required to call pcacheFree() */
-  for(p=pCache->pDirty; p; p=p->pNext){
-    if( p->apSave[idJournal] ){
-      pcacheFree(p->apSave[idJournal]);
-      p->apSave[idJournal] = 0;
-    }
-    p->flags &= mask;
-  }
-  pcacheExitMutex();
-}
-
-/*
-** Rollback a change previously preserved.
-*/
-void sqlite3PcacheRollback(
-  PCache *pCache,                  /* Pager cache */
-  int idJournal,                   /* Which copy to rollback to */
-  void (*xReiniter)(PgHdr*)        /* Called on each rolled back page */
-){
-  PgHdr *p;
-  int sz;
-  int mask = idJournal==0 ? ~PGHDR_IN_JOURNAL : 0xffffff;
-  pcacheEnterMutex();     /* Mutex is required to call pcacheFree() */
-  sz = pCache->szPage;
-  for(p=pCache->pDirty; p; p=p->pNext){
-    if( p->apSave[idJournal] ){
-      memcpy(p->pData, p->apSave[idJournal], sz);
-      pcacheFree(p->apSave[idJournal]);
-      p->apSave[idJournal] = 0;
-      if( xReiniter ){
-        xReiniter(p);
-      }
-    }
-    p->flags &= mask;
-  }
-  pcacheExitMutex();
-}
 
 #ifndef NDEBUG
 /* 
index 835fee9189740864edbb228ef4d4367166185950..152d9e6cd50f6029eec9af9e35ae14c32389a822 100644 (file)
@@ -12,7 +12,7 @@
 ** This header file defines the interface that the sqlite page cache
 ** subsystem. 
 **
-** @(#) $Id: pcache.h,v 1.13 2008/10/11 17:42:29 drh Exp $
+** @(#) $Id: pcache.h,v 1.14 2008/10/17 18:51:53 danielk1977 Exp $
 */
 
 #ifndef _PCACHE_H_
@@ -40,7 +40,7 @@ struct PgHdr {
   */
   i16 nRef;                      /* Number of users of this page */
   PCache *pCache;                /* Cache that owns this page */
-  void *apSave[2];               /* Journal entries for in-memory databases */
+
   /**********************************************************************
   ** Elements above are accessible at any time by the owner of the cache
   ** without the need for a mutex.  The elements that follow can only be
@@ -109,11 +109,6 @@ void sqlite3PcacheMove(PgHdr*, Pgno);
 /* Remove all pages with pgno>x.  Reset the cache if x==0 */
 void sqlite3PcacheTruncate(PCache*, Pgno x);
 
-/* Routines used to implement transactions on memory-only databases. */
-int sqlite3PcachePreserve(PgHdr*, int);    /* Preserve current page content */
-void sqlite3PcacheCommit(PCache*, int);    /* Drop preserved copy */
-void sqlite3PcacheRollback(PCache*, int, void (*xReiniter)(PgHdr*));
-
 /* Get a list of all dirty pages in the cache, sorted by page number */
 PgHdr *sqlite3PcacheDirtyList(PCache*);
 
index 5a35099609e880fe60cae984841f41d0fb55de51..e8cfc52cc73b10219abb8ddc60b2157b132a5f11 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file contains code used to implement the PRAGMA command.
 **
-** $Id: pragma.c,v 1.189 2008/10/10 17:47:21 danielk1977 Exp $
+** $Id: pragma.c,v 1.190 2008/10/17 18:51:53 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -455,11 +455,13 @@ void sqlite3Pragma(
 
   /*
   **  PRAGMA [database.]journal_mode
-  **  PRAGMA [database.]journal_mode = (delete|persist|off)
+  **  PRAGMA [database.]journal_mode = (delete|persist|memory|off)
   */
   if( sqlite3StrICmp(zLeft,"journal_mode")==0 ){
     int eMode;
-    static char * const azModeName[] = {"delete", "persist", "off", "truncate"};
+    static char * const azModeName[] = {
+      "delete", "persist", "off", "truncate", "memory"
+    };
 
     if( zRight==0 ){
       eMode = PAGER_JOURNALMODE_QUERY;
@@ -503,7 +505,8 @@ void sqlite3Pragma(
     assert( eMode==PAGER_JOURNALMODE_DELETE
               || eMode==PAGER_JOURNALMODE_TRUNCATE
               || eMode==PAGER_JOURNALMODE_PERSIST
-              || eMode==PAGER_JOURNALMODE_OFF );
+              || eMode==PAGER_JOURNALMODE_OFF
+              || eMode==PAGER_JOURNALMODE_MEMORY );
     sqlite3VdbeSetNumCols(v, 1);
     sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "journal_mode", P4_STATIC);
     sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, 
index e4ef1d0b69a476d03b28b22358f243d0c4bf8697..405a5eb97033a6c93a0c3149b35bf1a8390928f4 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.784 2008/10/13 15:35:09 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.785 2008/10/17 18:51:53 danielk1977 Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -2505,6 +2505,10 @@ int sqlite3FindInIndex(Parse *, Expr *, int*);
   #define sqlite3JournalSize(pVfs) ((pVfs)->szOsFile)
 #endif
 
+void sqlite3MemJournalOpen(sqlite3_file *);
+int sqlite3MemJournalSize();
+int sqlite3IsMemJournal(sqlite3_file *);
+
 #if SQLITE_MAX_EXPR_DEPTH>0
   void sqlite3ExprSetHeight(Parse *pParse, Expr *p);
   int sqlite3SelectExprHeight(Select *);
index 6383299883a9f6a4b9aa2baadccd7103e5a084c6..29317220f61fff5c35cf4d1e35fa9cefca0bed4a 100644 (file)
@@ -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.6 2008/09/26 21:08:08 drh Exp $
+# $Id: jrnlmode.test,v 1.7 2008/10/17 18:51:53 danielk1977 Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -95,7 +95,7 @@ ifcapable attach {
       PRAGMA main.journal_mode;
       PRAGMA aux1.journal_mode;
     }
-  } {persist persist}
+  } {persist memory}
   do_test jrnlmode-1.10 {
     execsql {
       PRAGMA main.journal_mode = OFF;
@@ -105,7 +105,7 @@ ifcapable attach {
       PRAGMA temp.journal_mode;
       PRAGMA aux1.journal_mode;
     }
-  } {off persist persist}
+  } {off persist memory}
   do_test jrnlmode-1.11 {
     execsql {
       PRAGMA journal_mode;
@@ -120,8 +120,9 @@ ifcapable attach {
       PRAGMA aux1.journal_mode;
       PRAGMA aux2.journal_mode;
     }
-  } {off persist persist}
+  } {off memory memory}
   do_test jrnlmode-1.11 {
+    # The journal-mode used by in-memory databases cannot be changed.
     execsql {
       PRAGMA aux1.journal_mode = DELETE;
     }
@@ -130,7 +131,7 @@ ifcapable attach {
       PRAGMA aux1.journal_mode;
       PRAGMA aux2.journal_mode;
     }
-  } {off delete persist}
+  } {off memory memory}
   do_test jrnlmode-1.12 {
     execsql {
       PRAGMA journal_mode = delete;
@@ -141,7 +142,7 @@ ifcapable attach {
       PRAGMA aux1.journal_mode;
       PRAGMA aux2.journal_mode;
     }
-  } {delete delete delete delete}
+  } {delete delete memory memory}
   do_test jrnlmode-1.13 {
     execsql {
       ATTACH ':memory:' as aux3;
@@ -153,7 +154,7 @@ ifcapable attach {
       PRAGMA aux2.journal_mode;
       PRAGMA aux3.journal_mode;
     }
-  } {delete delete delete delete delete}
+  } {delete delete memory memory memory}
   do_test jrnlmode-1.14 {
     execsql {
       PRAGMA journal_mode = TRUNCATE;
@@ -165,7 +166,7 @@ ifcapable attach {
       PRAGMA aux2.journal_mode;
       PRAGMA aux3.journal_mode;
     }
-  } {truncate truncate truncate truncate truncate}
+  } {truncate truncate memory memory memory}
   
   do_test jrnlmode-1.99 {
     execsql {
index 3b199c4b4338418cd5ccf358d562df4167a4f0a2..32265a521198e1df5f56e0bdb825648a7b42a565 100644 (file)
@@ -11,7 +11,7 @@
 # This file implements regression tests for SQLite library.  The
 # focus of this script is page cache subsystem.
 #
-# $Id: pager.test,v 1.31 2008/08/20 14:49:25 danielk1977 Exp $
+# $Id: pager.test,v 1.32 2008/10/17 18:51:53 danielk1977 Exp $
 
 
 set testdir [file dirname $argv0]
@@ -415,12 +415,14 @@ ifcapable memorydb {
     pager_truncate $::p2 5
   } {}
   do_test pager-4.6.3 {
+    set page1 [page_get $::p2 1]
     for {set i 1} {$i<5} {incr i} {
       set p [page_get $::p2 $i]
       page_write $p "Page $i"
       pager_commit $::p2
       page_unref $p
     }
+    page_unref $page1
     # pager_truncate $::p2 3
   } {}
   do_test pager-4.6.4 {
index 5b65785a61321da3ccda933cefc2ed1c5ce13417..c20c355661fc5b5629c1c30fc9b590ad63302fad 100644 (file)
@@ -11,7 +11,7 @@
 # This file implements regression tests for SQLite library.  The
 # focus of this script is page cache subsystem.
 #
-# $Id: pager2.test,v 1.7 2008/08/20 14:49:25 danielk1977 Exp $
+# $Id: pager2.test,v 1.8 2008/10/17 18:51:53 danielk1977 Exp $
 
 
 set testdir [file dirname $argv0]
@@ -33,13 +33,13 @@ do_test pager2-1.0 {
 } {0}
 do_test pager2-1.1 {
   pager_stats $::p1
-} {ref 0 page 0 max 10 size 0 state 0 err 0 hit 0 miss 0 ovfl 0}
+} {ref 0 page 0 max 10 size 0 state 4 err 0 hit 0 miss 0 ovfl 0}
 do_test pager2-1.2 {
   pager_pagecount $::p1
 } {0}
 do_test pager2-1.3 {
   pager_stats $::p1
-} {ref 0 page 0 max 10 size 0 state 0 err 0 hit 0 miss 0 ovfl 0}
+} {ref 0 page 0 max 10 size 0 state 4 err 0 hit 0 miss 0 ovfl 0}
 do_test pager2-1.4 {
   pager_close $::p1
 } {}
@@ -62,7 +62,7 @@ do_test pager2-2.3.1 {
 } {}
 do_test pager2-2.3.2 {
   pager_stats $::p1
-} {ref 0 page 0 max 10 size 0 state 0 err 0 hit 0 miss 0 ovfl 0}
+} {ref 0 page 0 max 10 size 0 state 4 err 0 hit 0 miss 0 ovfl 0}
 do_test pager2-2.3.3 {
   set v [catch {
     set ::g1 [page_get $::p1 1]
@@ -72,7 +72,7 @@ do_test pager2-2.3.3 {
 } {0}
 do_test pager2-2.3.3 {
   pager_stats $::p1
-} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
+} {ref 1 page 1 max 10 size 0 state 4 err 0 hit 0 miss 1 ovfl 0}
 do_test pager2-2.3.4 {
   set ::gx [page_lookup $::p1 1]
   page_unref $::gx
@@ -80,22 +80,22 @@ do_test pager2-2.3.4 {
 } {1}
 do_test pager2-2.3.5 {
   pager_stats $::p1
-} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
+} {ref 1 page 1 max 10 size 0 state 4 err 0 hit 0 miss 1 ovfl 0}
 do_test pager2-2.3.6 {
   expr {$::g1==$::gx}
 } {1}
 do_test pager2-2.3.7 {
   pager_stats $::p1
-} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
+} {ref 1 page 1 max 10 size 0 state 4 err 0 hit 0 miss 1 ovfl 0}
 do_test pager2-2.4 {
   pager_stats $::p1
-} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
+} {ref 1 page 1 max 10 size 0 state 4 err 0 hit 0 miss 1 ovfl 0}
 do_test pager2-2.5 {
   pager_pagecount $::p1
 } {0}
 do_test pager2-2.6 {
   pager_stats $::p1
-} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
+} {ref 1 page 1 max 10 size 0 state 4 err 0 hit 0 miss 1 ovfl 0}
 do_test pager2-2.7 {
   page_number $::g1
 } {1}
@@ -107,7 +107,7 @@ do_test pager2-2.9 {
 } {}
 do_test pager2-2.10 {
   pager_stats $::p1
-} {ref 0 page 1 max 10 size 0 state 0 err 0 hit 0 miss 1 ovfl 0}
+} {ref 0 page 1 max 10 size 0 state 4 err 0 hit 0 miss 1 ovfl 0}
 do_test pager2-2.11 {
   set ::g1 [page_get $::p1 1]
   expr {$::g1!=0}
@@ -117,7 +117,7 @@ do_test pager2-2.12 {
 } {1}
 do_test pager2-2.13 {
   pager_stats $::p1
-} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 1 miss 1 ovfl 0}
+} {ref 1 page 1 max 10 size 0 state 4 err 0 hit 1 miss 1 ovfl 0}
 do_test pager2-2.14 {
   set v [catch {
     page_write $::g1 "Page-One"
@@ -138,19 +138,19 @@ do_test pager2-2.17 {
 } {0 {}}
 do_test pager2-2.20 {
   pager_stats $::p1
-} {ref 1 page 1 max 10 size 1 state 1 err 0 hit 1 miss 1 ovfl 0}
+} {ref 1 page 1 max 10 size 1 state 4 err 0 hit 1 miss 1 ovfl 0}
 do_test pager2-2.19 {
   pager_pagecount $::p1
 } {1}
 do_test pager2-2.21 {
   pager_stats $::p1
-} {ref 1 page 1 max 10 size 1 state 1 err 0 hit 1 miss 1 ovfl 0}
+} {ref 1 page 1 max 10 size 1 state 4 err 0 hit 1 miss 1 ovfl 0}
 do_test pager2-2.22 {
   page_unref $::g1
 } {}
 do_test pager2-2.23 {
   pager_stats $::p1
-} {ref 0 page 1 max 10 size 1 state 0 err 0 hit 1 miss 1 ovfl 0}
+} {ref 0 page 1 max 10 size 1 state 4 err 0 hit 1 miss 1 ovfl 0}
 do_test pager2-2.24 {
   set v [catch {
     page_get $::p1 1
@@ -215,14 +215,17 @@ do_test pager2-3.5 {
   page_unref $::g(1)
 } {}
 for {set i 2} {$i<=20} {incr i} {
+  set page1 [page_get $::p1 1]
   do_test pager2-3.6.[expr {$i-1}] [subst {
     set gx \[page_get $::p1 $i\]
     set v \[page_read \$gx\]
     page_unref \$gx
     set v
   }] "Page-$i"
+  page_unref $page1
 }
 for {set i 1} {$i<=20} {incr i} {
+  set page1 [page_get $::p1 1]
   regsub -all CNT {
     set ::g1 [page_get $::p1 CNT]
     set ::g2 [page_get $::p1 CNT]
@@ -244,6 +247,7 @@ for {set i 1} {$i<=20} {incr i} {
     expr {$vy==$::vx}
   } $i body;
   do_test pager2-3.7.$i.3 $body {1}
+  page_unref $page1
 }
 do_test pager2-3.99 {
   pager_close $::p1
@@ -281,7 +285,7 @@ do_test pager2-4.3 {
 } {ref 1}
 do_test pager2-4.4 {
   lrange [pager_stats $::p1] 8 9
-} {state 1}
+} {state 4}
 
 for {set i 1} {$i<20} {incr i} {
   do_test pager2-4.5.$i.0 {
@@ -396,7 +400,7 @@ breakpoint
   do_test pager2-4.5.$i.10 {
     pager_commit $p1
     lrange [pager_stats $p1] 8 9
-  } {state 1}
+  } {state 4}
 }
 
 do_test pager2-4.99 {
index 2abf67199a0f90585d7291a3861a176c185950a5..b459cd0a7fbda116203705b775eea7bc92eb0c65 100644 (file)
@@ -9,7 +9,7 @@
 #
 #***********************************************************************
 #
-# $Id: permutations.test,v 1.35 2008/10/11 17:04:04 danielk1977 Exp $
+# $Id: permutations.test,v 1.36 2008/10/17 18:51:53 danielk1977 Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -448,6 +448,24 @@ run_tests "autovacuum_ioerr" -description {
   pragma auto_vacuum = 1
 } -include ioerr.test
 
+# Run tests with an in-memory journal.
+#
+run_tests "inmemory_journal" -description {
+  Run tests with an in-memory journal file.
+} -presql {
+  pragma journal_mode = 'memory'
+} -exclude {
+  # Exclude all tests that simulate IO errors.
+  autovacuum_ioerr2.test incrvacuum_ioerr.test ioerr.test
+  ioerr.test ioerr2.test ioerr3.test ioerr4.test ioerr5.test
+  vacuum3.test incrblob_err.test diskfull.test 
+
+  # Exclude test scripts that use tcl IO to access journal files or count
+  # the number of fsync() calls.
+  pager.test exclusive.test jrnlmode.test sync.test misc1.test 
+  journal1.test conflict.test
+}
+
 ifcapable mem3 {
   run_tests "memsys3" -description {
     Run tests using the allocator in mem3.c.
index 54fdcb20260f7574346099e60bdccc6dc6adb501..b526a62a05af7f3b91310ad9924ce49fa89b5066 100644 (file)
@@ -13,7 +13,7 @@
 # caused by an ON CONFLICT ROLLBACK clause aborts any other pending
 # statements.
 #
-# $Id: rollback.test,v 1.9 2008/10/13 14:16:11 drh Exp $
+# $Id: rollback.test,v 1.10 2008/10/17 18:51:53 danielk1977 Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -81,7 +81,10 @@ do_test rollback-1.9 {
 
 set permutation ""
 catch {set permutation $::permutations_test_prefix}
-if {$tcl_platform(platform) == "unix" && $permutation ne "onefile"} {
+if {$tcl_platform(platform) == "unix" 
+ && $permutation ne "onefile"
+ && $permutation ne "inmemory_journal"
+} {
   do_test rollback-2.1 {
     execsql {
       BEGIN;
index 1dd54e4a04f975e2c0674abc046139d9cb22e6f8..9678c20a7e523ec6b47527e895f534691874cb20 100644 (file)
@@ -247,6 +247,7 @@ foreach file {
    vdbe.c
    vdbeblob.c
    journal.c
+   memjournal.c
 
    walker.c
    resolve.c