diff --git a/manifest b/manifest index 889e49894b..f289413a0f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Get\sLIMIT\s0\sworking\son\ssubqueries.\s\sTicket\s#1784.\s(CVS\s3177) -D 2006-04-26T17:39:34 +C Faster\s:memory:\sdatabase\sCOMMITs.\s\sTicket\s#1790.\s(CVS\s3178) +D 2006-05-03T23:34:06 F Makefile.in 5d8dff443383918b700e495de42ec65bc1c8865b F Makefile.linux-gcc 74ba0eadf88748a9ce3fd03d2a3ede2e6715baec F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -59,7 +59,7 @@ F src/os_unix.c 17d91581a0ab478a06cb6f257b707a4c4a93e5a7 F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e F src/os_win.c 8ced9ac82670bbf77492961a2f7ff80a87f1404f F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b -F src/pager.c ca7112635ac51779c44f93e562e811df939fb402 +F src/pager.c 57348b21910450b47cdb7ab7a9a4e6bac68f6a5f F src/pager.h 43f32f3847421f7502cfbb66f4eb2302b8033818 F src/parse.y ee1887ce0e6eea15cc728913ad3462898f88e9b0 F src/pragma.c 27d5e395c5d950931c7ac4fe610e7c2993e2fa55 @@ -98,7 +98,7 @@ F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5 F src/vdbemem.c 5f0afe3b92bb2c037f8d5d697f7c151fa50783a3 F src/where.c dc626f8c0fcff56ab7b08c9fb579d8ac33b0fbd9 F tclinstaller.tcl 046e3624671962dc50f0481d7c25b38ef803eb42 -F test/aggerror.test b854de90f530ae37be68fbfe6de40e111358cbb2 +F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/all.test 5df90d015ca63fcef2a4b62c24f7316b66c4bfd4 F test/alter.test 29234396d738966d512dcb0d71c137a2315d38d7 F test/alter2.test cc0b8832e4e98605dbc26910efd4bb89abe59cb2 @@ -355,7 +355,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513 -P 39dd969527a107b2a6bb94dfc35d93850917faa8 -R f4f7a2878489bcdf7e5731c09d18d35d +P 7f3ef7ddba22d69a23e656836ba76738c9652b4d +R 44ec6e5db6ad334f233b7b64f878721e U drh -Z 6e77e754e7e04c0ab1946a636756db5c +Z d5ea3db4b30df259b8b3ffa443e2426d diff --git a/manifest.uuid b/manifest.uuid index cb4caba4a1..cf2c224ca5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7f3ef7ddba22d69a23e656836ba76738c9652b4d \ No newline at end of file +8f820e435272c0a4861421508c7e6f2979c2750f \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index d6c2d32994..4a438c0dc4 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.266 2006/04/07 13:54:47 drh Exp $ +** @(#) $Id: pager.c,v 1.267 2006/05/03 23:34:06 drh Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" @@ -161,7 +161,8 @@ struct PgHdr { u8 needSync; /* Sync journal before writing this page */ u8 alwaysRollback; /* Disable dont_rollback() for this page */ short int nRef; /* Number of users of this page */ - PgHdr *pDirty; /* Dirty pages sorted by PgHdr.pgno */ + PgHdr *pDirty, *pPrevDirty; /* Dirty pages sorted by PgHdr.pgno */ + u32 notUsed; /* Buffer space */ #ifdef SQLITE_CHECK_PAGES u32 pageHash; #endif @@ -280,6 +281,7 @@ struct Pager { PgHdr *pFirstSynced; /* First free page with PgHdr.needSync==0 */ PgHdr *pAll; /* List of all pages */ PgHdr *pStmt; /* List of pages in the statement subjournal */ + PgHdr *pDirty; /* List of all dirty pages */ i64 journalOff; /* Current byte offset in the journal file */ i64 journalHdr; /* Byte offset to previous journal header */ i64 stmtHdrOff; /* First journal header written this statement */ @@ -892,6 +894,7 @@ static int pager_unwritelock(Pager *pPager){ pPg->pageHash = pager_pagehash(pPg); #endif } + pPager->pDirty = 0; pPager->dirtyCache = 0; pPager->nRec = 0; }else{ @@ -937,6 +940,9 @@ static u32 pager_cksum(Pager *pPager, const u8 *aData){ return cksum; } +/* Forward declaration */ +static void makeClean(PgHdr*); + /* ** Read a single page from the journal file opened on file descriptor ** jfd. Playback this one page. @@ -1014,7 +1020,9 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){ if( rc==SQLITE_OK ){ rc = sqlite3OsWrite(pPager->fd, aData, pPager->pageSize); } - if( pPg ) pPg->dirty = 0; + if( pPg ){ + makeClean(pPg); + } } if( pPg ){ /* No page should ever be explicitly rolled back that is in use, except @@ -1164,6 +1172,7 @@ static int pager_reload_cache(Pager *pPager){ pPg->pageHash = pager_pagehash(pPg); #endif } + pPager->pDirty = 0; return rc; } @@ -1908,6 +1917,7 @@ static void memoryTruncate(Pager *pPager){ }else{ *ppPg = pPg->pNextAll; unlinkPage(pPg); + makeClean(pPg); sqliteFree(pPg); pPager->nPage--; } @@ -2305,15 +2315,7 @@ static int pager_write_pagelist(PgHdr *pList){ ** collected even if they are still in use. */ static PgHdr *pager_get_all_dirty_pages(Pager *pPager){ - PgHdr *p, *pList; - pList = 0; - for(p=pPager->pAll; p; p=p->pNextAll){ - if( p->dirty ){ - p->pDirty = pList; - pList = p; - } - } - return pList; + return pPager->pDirty; } /* @@ -2388,6 +2390,8 @@ static int pager_recycle(Pager *pPager, int syncOk, PgHdr **ppPg){ if( pPg->dirty ){ int rc; assert( pPg->needSync==0 ); + makeClean(pPg); + pPg->dirty = 1; pPg->pDirty = 0; rc = pager_write_pagelist( pPg ); if( rc!=SQLITE_OK ){ @@ -2659,7 +2663,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ }else{ page_remove_from_stmt_list(pPg); } - pPg->dirty = 0; + makeClean(pPg); pPg->nRef = 1; REFINFO(pPg); @@ -2935,6 +2939,42 @@ int sqlite3pager_begin(void *pData, int exFlag){ return rc; } +/* +** Make a page dirty. Set its dirty flag and add it to the dirty +** page list. +*/ +static void makeDirty(PgHdr *pPg){ + if( pPg->dirty==0 ){ + Pager *pPager = pPg->pPager; + pPg->dirty = 1; + pPg->pDirty = pPager->pDirty; + if( pPager->pDirty ){ + pPager->pDirty->pPrevDirty = pPg; + } + pPg->pPrevDirty = 0; + pPager->pDirty = pPg; + } +} + +/* +** Make a page clean. Clear its dirty bit and remove it from the +** dirty page list. +*/ +static void makeClean(PgHdr *pPg){ + if( pPg->dirty ){ + pPg->dirty = 0; + if( pPg->pDirty ){ + pPg->pDirty->pPrevDirty = pPg->pPrevDirty; + } + if( pPg->pPrevDirty ){ + pPg->pPrevDirty->pDirty = pPg->pDirty; + }else{ + pPg->pPager->pDirty = pPg->pDirty; + } + } +} + + /* ** Mark a data page as writeable. The page is written into the journal ** if it is not there already. This routine must be called before making @@ -2973,7 +3013,7 @@ int sqlite3pager_write(void *pData){ /* Mark the page as dirty. If the page has already been written ** to the journal then we can return right away. */ - pPg->dirty = 1; + makeDirty(pPg); if( pPg->inJournal && (pPg->inStmt || pPager->stmtInUse==0) ){ pPager->dirtyCache = 1; }else{ @@ -3180,7 +3220,7 @@ void sqlite3pager_dont_write(Pager *pPager, Pgno pgno){ */ }else{ TRACE3("DONT_WRITE page %d of %d\n", pgno, PAGERID(pPager)); - pPg->dirty = 0; + makeClean(pPg); #ifdef SQLITE_CHECK_PAGES pPg->pageHash = pager_pagehash(pPg); #endif @@ -3248,6 +3288,7 @@ int sqlite3pager_commit(Pager *pPager){ pPg->pPrevStmt = pPg->pNextStmt = 0; pPg = pPg->pDirty; } + pPager->pDirty = 0; #ifndef NDEBUG for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); @@ -3315,12 +3356,11 @@ int sqlite3pager_rollback(Pager *pPager){ p->inJournal = 0; p->inStmt = 0; p->pPrevStmt = p->pNextStmt = 0; - if( pPager->xReiniter ){ pPager->xReiniter(PGHDR_TO_DATA(p), pPager->pageSize); } - } + pPager->pDirty = 0; pPager->pStmt = 0; pPager->dbSize = pPager->origDbSize; memoryTruncate(pPager); @@ -3715,7 +3755,7 @@ int sqlite3pager_movepage(Pager *pPager, void *pData, Pgno pgno){ if( pPgOld ){ assert( pPgOld->nRef==0 ); unlinkHashChain(pPager, pPgOld); - pPgOld->dirty = 0; + makeClean(pPgOld); if( pPgOld->needSync ){ assert( pPgOld->inJournal ); pPg->inJournal = 1; @@ -3735,7 +3775,7 @@ int sqlite3pager_movepage(Pager *pPager, void *pData, Pgno pgno){ pPager->aHash[h] = pPg; pPg->pPrevHash = 0; - pPg->dirty = 1; + makeDirty(pPg); pPager->dirtyCache = 1; if( needSyncPgno ){ @@ -3756,7 +3796,7 @@ int sqlite3pager_movepage(Pager *pPager, void *pData, Pgno pgno){ pPager->needSync = 1; DATA_TO_PGHDR(pNeedSync)->needSync = 1; DATA_TO_PGHDR(pNeedSync)->inJournal = 1; - DATA_TO_PGHDR(pNeedSync)->dirty = 1; + makeDirty(DATA_TO_PGHDR(pNeedSync)); sqlite3pager_unref(pNeedSync); } diff --git a/test/aggerror.test b/test/aggerror.test index 470395ebef..f95d8b220a 100644 --- a/test/aggerror.test +++ b/test/aggerror.test @@ -13,7 +13,7 @@ # This file implements tests for calling sqlite3_result_error() # from within an aggregate function implementation. # -# $Id: aggerror.test,v 1.2 2006/01/23 07:52:41 danielk1977 Exp $ +# $Id: aggerror.test,v 1.3 2006/05/03 23:34:06 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -24,7 +24,7 @@ source $testdir/tester.tcl # final results is 42. Make sure that such errors are handled # appropriately. # -do_test aggfunc-1.1 { +do_test aggerror-1.1 { set DB [sqlite3_connection_pointer db] sqlite3_create_aggregate $DB execsql { @@ -39,19 +39,19 @@ do_test aggfunc-1.1 { SELECT x_count(*) FROM t1; } } {39} -do_test aggfunc-1.2 { +do_test aggerror-1.2 { execsql { INSERT INTO t1 VALUES(40); SELECT x_count(*) FROM t1; } } {40} -do_test aggfunc-1.3 { +do_test aggerror-1.3 { catchsql { SELECT x_count(a) FROM t1; } } {1 {value of 40 handed to x_count}} ifcapable utf16 { - do_test aggfunc-1.4 { + do_test aggerror-1.4 { execsql { UPDATE t1 SET a=41 WHERE a=40 } @@ -60,12 +60,12 @@ ifcapable utf16 { } } {1 abc} } -do_test aggfunc-1.5 { +do_test aggerror-1.5 { execsql { SELECT x_count(*) FROM t1 } } 40 -do_test aggfunc-1.6 { +do_test aggerror-1.6 { execsql { INSERT INTO t1 VALUES(40); INSERT INTO t1 VALUES(42);