-C All\sthe\scode\sis\snow\sin\splace\sfor\sSQLite\sto\sdistinguish\sbetween\sNUMERIC\sand\nTEXT\sdatatypes.\s\sStill\sneed\sto\sturn\son\sthe\snew\scode\sand\stest\sit.\s(CVS\s659)
-D 2002-07-05T21:42:36
+C Fix\sfor\sbug\s#94:\sBe\ssure\sto\sjournal\spages\sthat\sare\sadded\sto\sthe\sfreelist\sthen\nremoved\sfrom\sthe\sfreelist\sand\sreused\sduring\sthe\ssame\stransaction.\s(CVS\s660)
+D 2002-07-06T16:28:48
F Makefile.in 6291a33b87d2a395aafd7646ee1ed562c6f2c28c
F Makefile.template 4e11752e0b5c7a043ca50af4296ec562857ba495
F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0
F src/md5.c 0ae1f3e2cac92d06fc6246d1b4b8f61a2fe66d3b
F src/os.c 9cc40c5384baba4a85e160e67807645ca98ba3cc
F src/os.h 4a361fccfbc4e7609b3e1557f604f94c1e96ad10
-F src/pager.c 58ae9f569b3c664ea9205c6f6da432e3ae180f56
+F src/pager.c 103341600b4044e41b5bd95cd3850f046b976ff2
F src/pager.h 6fddfddd3b73aa8abc081b973886320e3c614f0e
F src/parse.y 35437ac29441ce2d34904d8e93f40b7d112147a9
F src/printf.c 236ed7a79386feed4456fa728fff8be793f1547c
F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098
F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
-P 85793a4f03250166c21007cab3525709592d0866
-R f77acd757b229f1cdb42ab7cac78b933
+P b4737a16c997a6c139d616211fb6bc4b0fae181c
+R 253a44e4b92ce398170a14aa4989c608
U drh
-Z 6c4c383ead0a1302c4ea68955c9a4a90
+Z 4750e3634de2bc1c9f7bbad93ace444e
** file simultaneously, or one process from reading the database while
** another is writing.
**
-** @(#) $Id: pager.c,v 1.47 2002/06/25 14:43:58 drh Exp $
+** @(#) $Id: pager.c,v 1.48 2002/07/06 16:28:48 drh Exp $
*/
#include "sqliteInt.h"
#include "pager.h"
char inJournal; /* TRUE if has been written to journal */
char inCkpt; /* TRUE if written to the checkpoint journal */
char dirty; /* TRUE if we need to write back changes */
+ char alwaysRollback; /* Ignore dont_rollback() calls if true */
/* SQLITE_PAGE_SIZE bytes of page data follow this header */
/* Pager.nExtra bytes of local data follow the page data */
};
pPager->journalOpen = 0;
sqliteOsDelete(pPager->zJournal);
rc = sqliteOsReadLock(&pPager->fd);
- assert( rc==SQLITE_OK );
sqliteFree( pPager->aInJournal );
pPager->aInJournal = 0;
for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
pPg->inJournal = 0;
pPg->dirty = 0;
}
- pPager->state = SQLITE_READLOCK;
+ if( rc==SQLITE_OK ){
+ pPager->state = SQLITE_READLOCK;
+ }else{
+ /* This can only happen if a process does a BEGIN, then forks and the
+ ** child process does the COMMIT. Because of the semantics of unix
+ ** file locking, the unlock will fail.
+ */
+ pPager->state = SQLITE_UNLOCK;
+ }
return rc;
}
sqliteOsReadLock(&pPager->fd);
return SQLITE_NOMEM;
}
- rc = sqliteOsOpenExclusive(pPager->zJournal, &pPager->jfd, 0);
+ rc = sqliteOsOpenExclusive(pPager->zJournal, &pPager->jfd,pPager->tempFile);
if( rc!=SQLITE_OK ){
sqliteFree(pPager->aInJournal);
pPager->aInJournal = 0;
** Tests show that this optimization, together with the
** sqlitepager_dont_rollback() below, more than double the speed
** of large INSERT operations and quadruple the speed of large DELETEs.
+**
+** When this routine is called, set the alwaysRollback flag to true.
+** Subsequent calls to sqlitepager_dont_rollback() for the same page
+** will thereafter be ignored. This is necessary to avoid a problem
+** where a page with data is added to the freelist during one part of
+** a transaction then removed from the freelist during a later part
+** of the same transaction and reused for some other purpose. When it
+** is first added to the freelist, this routine is called. When reused,
+** the dont_rollback() routine is called. But because the page contains
+** critical data, we still need to be sure it gets rolled back in spite
+** of the dont_rollback() call.
*/
void sqlitepager_dont_write(Pager *pPager, Pgno pgno){
PgHdr *pPg;
+
pPg = pager_lookup(pPager, pgno);
+ pPg->alwaysRollback = 1;
if( pPg && pPg->dirty ){
if( pPager->dbSize==(int)pPg->pgno && pPager->origDbSize<pPager->dbSize ){
/* If this pages is the last page in the file and the file has grown
Pager *pPager = pPg->pPager;
if( pPager->state!=SQLITE_WRITELOCK || pPager->journalOpen==0 ) return;
+ if( pPg->alwaysRollback ) return;
if( !pPg->inJournal && (int)pPg->pgno <= pPager->origDbSize ){
assert( pPager->aInJournal!=0 );
pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7);