Index: src/pager.c ================================================================== --- src/pager.c +++ src/pager.c @@ -16,11 +16,11 @@ ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.45 2002/04/18 01:56:58 drh Exp $ +** @(#) $Id: pager.c,v 1.46 2002/05/30 12:27:03 drh Exp $ */ #include "sqliteInt.h" #include "pager.h" #include "os.h" #include @@ -112,10 +112,11 @@ int nRef; /* Number of in-memory pages with PgHdr.nRef>0 */ int mxPage; /* Maximum number of pages to hold in cache */ int nHit, nMiss, nOvfl; /* Cache hits, missing, and LRU overflows */ u8 journalOpen; /* True if journal file descriptors is valid */ u8 ckptOpen; /* True if the checkpoint journal is open */ + u8 ckptInUse; /* True we are in a checkpoint */ u8 noSync; /* Do not sync the journal if true */ u8 state; /* SQLITE_UNLOCK, _READLOCK or _WRITELOCK */ u8 errMask; /* One of several kinds of errors */ u8 tempFile; /* zFilename is a temporary file */ u8 readOnly; /* True for a read-only database */ @@ -241,10 +242,14 @@ static int pager_unwritelock(Pager *pPager){ int rc; PgHdr *pPg; if( pPager->stateckptOpen ){ + sqliteOsClose(&pPager->cpfd); + pPager->ckptOpen = 0; + } sqliteOsClose(&pPager->jfd); pPager->journalOpen = 0; sqliteOsDelete(pPager->zJournal); rc = sqliteOsReadLock(&pPager->fd); assert( rc==SQLITE_OK ); @@ -389,11 +394,11 @@ rc = sqliteOsTruncate(&pPager->fd, pPager->ckptSize*SQLITE_PAGE_SIZE); pPager->dbSize = pPager->ckptSize; /* Figure out how many records are in the checkpoint journal. */ - assert( pPager->ckptOpen && pPager->journalOpen ); + assert( pPager->ckptInUse && pPager->journalOpen ); sqliteOsSeek(&pPager->cpfd, 0); rc = sqliteOsFileSize(&pPager->cpfd, &nRec); if( rc!=SQLITE_OK ){ goto end_ckpt_playback; } @@ -526,10 +531,11 @@ strcpy(pPager->zJournal, zFilename); strcpy(&pPager->zJournal[nameLen], "-journal"); pPager->fd = fd; pPager->journalOpen = 0; pPager->ckptOpen = 0; + pPager->ckptInUse = 0; pPager->nRef = 0; pPager->dbSize = -1; pPager->ckptSize = 0; pPager->ckptJSize = 0; pPager->nPage = 0; @@ -612,13 +618,15 @@ pNext = pPg->pNextAll; sqliteFree(pPg); } sqliteOsClose(&pPager->fd); assert( pPager->journalOpen==0 ); - if( pPager->tempFile ){ - /* sqliteOsDelete(pPager->zFilename); */ - } + /* Temp files are automatically deleted by the OS + ** if( pPager->tempFile ){ + ** sqliteOsDelete(pPager->zFilename); + ** } + */ sqliteFree(pPager); return SQLITE_OK; } /* @@ -1088,11 +1096,11 @@ /* Mark the page as dirty. If the page has already been written ** to the journal then we can return right away. */ pPg->dirty = 1; - if( pPg->inJournal && (pPg->inCkpt || pPager->ckptOpen==0) ){ + if( pPg->inJournal && (pPg->inCkpt || pPager->ckptInUse==0) ){ pPager->dirtyFile = 1; return SQLITE_OK; } /* If we get this far, it means that the page needs to be @@ -1125,20 +1133,20 @@ } assert( pPager->aInJournal!=0 ); pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7); pPager->needSync = !pPager->noSync; pPg->inJournal = 1; - if( pPager->ckptOpen ){ + if( pPager->ckptInUse ){ pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7); pPg->inCkpt = 1; } } /* If the checkpoint journal is open and the page is not in it, ** then write the current page to the checkpoint journal. */ - if( pPager->ckptOpen && !pPg->inCkpt && (int)pPg->pgno<=pPager->ckptSize ){ + if( pPager->ckptInUse && !pPg->inCkpt && (int)pPg->pgno<=pPager->ckptSize ){ assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize ); rc = sqliteOsWrite(&pPager->cpfd, &pPg->pgno, sizeof(Pgno)); if( rc==SQLITE_OK ){ rc = sqliteOsWrite(&pPager->cpfd, pData, SQLITE_PAGE_SIZE); } @@ -1204,16 +1212,16 @@ if( pPager->state!=SQLITE_WRITELOCK || pPager->journalOpen==0 ) return; if( !pPg->inJournal && (int)pPg->pgno <= pPager->origDbSize ){ assert( pPager->aInJournal!=0 ); pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7); pPg->inJournal = 1; - if( pPager->ckptOpen ){ + if( pPager->ckptInUse ){ pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7); pPg->inCkpt = 1; } } - if( pPager->ckptOpen && !pPg->inCkpt && (int)pPg->pgno<=pPager->ckptSize ){ + if( pPager->ckptInUse && !pPg->inCkpt && (int)pPg->pgno<=pPager->ckptSize ){ assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize ); assert( pPager->aInCkpt!=0 ); pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7); pPg->inCkpt = 1; } @@ -1343,22 +1351,25 @@ */ int sqlitepager_ckpt_begin(Pager *pPager){ int rc; char zTemp[SQLITE_TEMPNAME_SIZE]; assert( pPager->journalOpen ); - assert( !pPager->ckptOpen ); + assert( !pPager->ckptInUse ); pPager->aInCkpt = sqliteMalloc( pPager->dbSize/8 + 1 ); if( pPager->aInCkpt==0 ){ sqliteOsReadLock(&pPager->fd); return SQLITE_NOMEM; } rc = sqliteOsFileSize(&pPager->jfd, &pPager->ckptJSize); if( rc ) goto ckpt_begin_failed; pPager->ckptSize = pPager->dbSize; - rc = sqlitepager_opentemp(zTemp, &pPager->cpfd); - if( rc ) goto ckpt_begin_failed; - pPager->ckptOpen = 1; + if( !pPager->ckptOpen ){ + rc = sqlitepager_opentemp(zTemp, &pPager->cpfd); + if( rc ) goto ckpt_begin_failed; + pPager->ckptOpen = 1; + } + pPager->ckptInUse = 1; return SQLITE_OK; ckpt_begin_failed: if( pPager->aInCkpt ){ sqliteFree(pPager->aInCkpt); @@ -1369,14 +1380,14 @@ /* ** Commit a checkpoint. */ int sqlitepager_ckpt_commit(Pager *pPager){ - if( pPager->ckptOpen ){ + if( pPager->ckptInUse ){ PgHdr *pPg; - sqliteOsClose(&pPager->cpfd); - pPager->ckptOpen = 0; + sqliteOsTruncate(&pPager->cpfd, 0); + pPager->ckptInUse = 0; sqliteFree( pPager->aInCkpt ); pPager->aInCkpt = 0; for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ pPg->inCkpt = 0; } @@ -1387,11 +1398,11 @@ /* ** Rollback a checkpoint. */ int sqlitepager_ckpt_rollback(Pager *pPager){ int rc; - if( pPager->ckptOpen ){ + if( pPager->ckptInUse ){ rc = pager_ckpt_playback(pPager); sqlitepager_ckpt_commit(pPager); }else{ rc = SQLITE_OK; } Index: test/expr.test ================================================================== --- test/expr.test +++ test/expr.test @@ -9,11 +9,11 @@ # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing expressions. # -# $Id: expr.test,v 1.22 2002/05/30 02:35:12 drh Exp $ +# $Id: expr.test,v 1.23 2002/05/30 12:27:03 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Create a table to work with. @@ -352,11 +352,13 @@ {CASE i1 WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 'error' END} error test_expr expr-case.10 {i1=3} \ {CASE i1 WHEN 1 THEN 'one' WHEN 2 THEN 'two' END} {{}} test_expr expr-case.11 {i1=null} \ {CASE i1 WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 3 END} {{}} -test_expr expr-case.12 {i1=7} \ +test_expr expr-case.12 {i1=1} \ + {CASE i1 WHEN 1 THEN null WHEN 2 THEN 'two' ELSE 3 END} {{}} +test_expr expr-case.13 {i1=7} \ { CASE WHEN i1 < 5 THEN 'low' WHEN i1 < 10 THEN 'medium' WHEN i1 < 15 THEN 'high' ELSE 'error' END} medium