diff --git a/manifest b/manifest index 233eb87ec3..6bc092dab1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,8 @@ -C Increase\sthe\sestimated\scost\sof\susing\sa\svirtual\stable\sas\sthe\souter\sloop\sof\sa\sjoin\swhen\sthere\sexists\san\sORDER\sBY\sclause\sthat\sis\snot\ssatisfied\sby\sthe\svirtual\stable.\sFix\sfor\s[775b39dd3c]. -D 2010-03-27T09:44:42 +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + +C Experimental\schanges\sthat\scause\sSQLite\sto\suse\sbytes\s28..31\sof\sthe\sdatabase\nheader\sto\sdetermine\sthe\sdatabase\ssize,\srather\sthan\susing\sthe\sactual\sdatabase\nsize.\s\sThis\sallows\sdatabase\sspace\sto\sbe\spreallocated. +D 2010-03-27T17:12:36 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in 4f2f967b7e58a35bb74fb7ec8ae90e0f4ca7868b F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -109,9 +112,9 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c b293534bc2df23c57668a585b17ee7faaaef0939 F src/bitvec.c 06ad2c36a9c3819c0b9cbffec7b15f58d5d834e0 F src/btmutex.c 96a12f50f7a17475155971a241d85ec5171573ff -F src/btree.c 0d6e44d664b1775b269ea7e6f66fdffcfc32ceb3 +F src/btree.c 28c3975060209dc5c5ca91abaa5e034dab03539f F src/btree.h 0e193b7e90f1d78b79c79474040e3d66a553a4fa -F src/btreeInt.h 71ed5e7f009caf17b7dc304350b3cb64b5970135 +F src/btreeInt.h 132d750db5d86b75344cec870501fa09a67b1f96 F src/build.c 11100b66fb97638d2d874c1d34d8db90650bb1d7 F src/callback.c 908f3e0172c3d4058f4ca0acd42c637c52e9669f F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac @@ -152,7 +155,7 @@ F src/os_common.h 240c88b163b02c21a9f21f87d49678a0aa21ff30 F src/os_os2.c 75a8c7b9a00a2cf1a65f9fa4afbc27d46634bb2f F src/os_unix.c 148d2f625db3727250c0b880481ae7630b6d0eb0 F src/os_win.c 1c7453c2df4dab26d90ff6f91272aea18bcf7053 -F src/pager.c 2a374f72e6c87150d043173b8041dc537f926b02 +F src/pager.c af1c58b7b884839853cc553681f771297de56049 F src/pager.h ef8a2cf10084f60ab45ee2dfded8bf8b0c655ddf F src/parse.y ace5c7a125d9f2a410e431ee3209034105045f7e F src/pcache.c ace8f6a5ecd4711cc66a1b23053be7109bd437cf @@ -293,7 +296,7 @@ F test/colmeta.test 087c42997754b8c648819832241daf724f813322 F test/colname.test 08948a4809d22817e0e5de89c7c0a8bd90cb551b F test/conflict.test 0ed68b11f22721052d880ee80bd528a0e0828236 F test/corrupt.test 0d346c9fe064ca71281685a8a732fcc83461bb99 -F test/corrupt2.test a571e30ea4e82318f319a24b6cc55935ce862079 +F test/corrupt2.test 576122d756feda40e63ef1c1ff6c4720a927d126 F test/corrupt3.test 263e8bb04e2728df832fddf6973cf54c91db0c32 F test/corrupt4.test acdb01afaedf529004b70e55de1a6f5a05ae7fff F test/corrupt5.test c23da7bfb20917cc7fdbb13ee25c7cc4e9fffeff @@ -528,7 +531,7 @@ F test/pagesize.test 76aa9f23ecb0741a4ed9d2e16c5fa82671f28efb F test/pcache.test eebc4420b37cb07733ae9b6e99c9da7c40dd6d58 F test/pcache2.test 0d85f2ab6963aee28c671d4c71bec038c00a1d16 F test/permutations.test 91928573ca2db2c88dbc50ab34e4a585d912b580 -F test/pragma.test 5aeb48a442dba3c3e8e38773b121371814ab3b17 +F test/pragma.test 6960f9efbce476f70ba9ee2171daf5042f9e3d8a F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47 F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 @@ -794,7 +797,18 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P c33b38b59f733494ca0bce3f59a669fe7ed76b9f -R 1048b4f005b8cf985bff319e6cd284fa -U dan -Z 25a9f1889e9ba9dd674533c69390c60b +P 9e075e70f0e2a1ad302d17150cd58f91669a97a6 +R 8d4f88bef4d5dad0eb6446592a8450b9 +T *bgcolor * #c0ffc0 +T *branch * experimental +T *sym-experimental * +T -sym-trunk * +U drh +Z 4146840317f4bfa6058f588cd6ed7701 +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.6 (GNU/Linux) + +iD8DBQFLrjyHoxKgR168RlERArtLAKCJtnFICZRpFQj18diXIg+u0uOi3ACgh4j0 +mhbXREy6ig+7NdEp5dlms38= +=ITwY +-----END PGP SIGNATURE----- diff --git a/manifest.uuid b/manifest.uuid index cefdd79cc5..35e921ca95 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9e075e70f0e2a1ad302d17150cd58f91669a97a6 \ No newline at end of file +b844ac6fcb72595a71e5c5283ec461309a87ba79 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index dbcdf65ec8..b8c41674a2 100644 --- a/src/btree.c +++ b/src/btree.c @@ -516,11 +516,8 @@ static void invalidateIncrblobCursors( static int btreeSetHasContent(BtShared *pBt, Pgno pgno){ int rc = SQLITE_OK; if( !pBt->pHasContent ){ - int nPage = 100; - sqlite3PagerPagecount(pBt->pPager, &nPage); - /* If sqlite3PagerPagecount() fails there is no harm because the - ** nPage variable is unchanged from its default value of 100 */ - pBt->pHasContent = sqlite3BitvecCreate((u32)nPage); + assert( pgno<=pBt->nPage ); + pBt->pHasContent = sqlite3BitvecCreate(pBt->nPage); if( !pBt->pHasContent ){ rc = SQLITE_NOMEM; } @@ -1564,12 +1561,8 @@ static MemPage *btreePageLookup(BtShared *pBt, Pgno pgno){ ** error, return ((unsigned int)-1). */ static Pgno pagerPagecount(BtShared *pBt){ - int nPage = -1; - int rc; - assert( pBt->pPage1 ); - rc = sqlite3PagerPagecount(pBt->pPager, &nPage); - assert( rc==SQLITE_OK || nPage==-1 ); - return (Pgno)nPage; + int nPage = (int)pBt->nPage; + return nPage; } /* @@ -2254,8 +2247,8 @@ static int lockBtree(BtShared *pBt){ /* Do some checking to help insure the file we opened really is ** a valid database file. */ - rc = sqlite3PagerPagecount(pBt->pPager, &nPage); - if( rc!=SQLITE_OK ){ + nPage = get4byte(28+(u8*)pPage1->aData); + if( nPage==0 && (rc = sqlite3PagerPagecount(pBt->pPager, &nPage))!=0 ){ goto page1_init_failed; }else if( nPage>0 ){ int pageSize; @@ -2333,6 +2326,7 @@ static int lockBtree(BtShared *pBt){ pBt->minLeaf = (pBt->usableSize-12)*32/255 - 23; assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) ); pBt->pPage1 = pPage1; + pBt->nPage = nPage; return SQLITE_OK; page1_init_failed: @@ -2370,12 +2364,10 @@ static int newDatabase(BtShared *pBt){ MemPage *pP1; unsigned char *data; int rc; - int nPage; assert( sqlite3_mutex_held(pBt->mutex) ); - rc = sqlite3PagerPagecount(pBt->pPager, &nPage); - if( rc!=SQLITE_OK || nPage>0 ){ - return rc; + if( pBt->nPage>0 ){ + return SQLITE_OK; } pP1 = pBt->pPage1; assert( pP1!=0 ); @@ -2401,6 +2393,8 @@ static int newDatabase(BtShared *pBt){ put4byte(&data[36 + 4*4], pBt->autoVacuum); put4byte(&data[36 + 7*4], pBt->incrVacuum); #endif + pBt->nPage = 1; + data[31] = 1; return SQLITE_OK; } @@ -2769,12 +2763,12 @@ static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8); */ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){ Pgno nFreeList; /* Number of pages still on the free-list */ + int rc; assert( sqlite3_mutex_held(pBt->mutex) ); assert( iLastPg>nFin ); if( !PTRMAP_ISPAGE(pBt, iLastPg) && iLastPg!=PENDING_BYTE_PAGE(pBt) ){ - int rc; u8 eType; Pgno iPtrPage; @@ -2850,7 +2844,7 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){ while( iLastPg==PENDING_BYTE_PAGE(pBt)||PTRMAP_ISPAGE(pBt, iLastPg) ){ if( PTRMAP_ISPAGE(pBt, iLastPg) ){ MemPage *pPg; - int rc = btreeGetPage(pBt, iLastPg, &pPg, 0); + rc = btreeGetPage(pBt, iLastPg, &pPg, 0); if( rc!=SQLITE_OK ){ return rc; } @@ -2863,6 +2857,7 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){ iLastPg--; } sqlite3PagerTruncateImage(pBt->pPager, iLastPg); + pBt->nPage = iLastPg; } return SQLITE_OK; } @@ -2886,6 +2881,10 @@ int sqlite3BtreeIncrVacuum(Btree *p){ }else{ invalidateAllOverflowCache(pBt); rc = incrVacuumStep(pBt, 0, pagerPagecount(pBt)); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); + put4byte(&pBt->pPage1->aData[28], pBt->nPage); + } } sqlite3BtreeLeave(p); return rc; @@ -2941,11 +2940,12 @@ static int autoVacuumCommit(BtShared *pBt){ rc = incrVacuumStep(pBt, nFin, iFree); } if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){ - rc = SQLITE_OK; rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); put4byte(&pBt->pPage1->aData[32], 0); put4byte(&pBt->pPage1->aData[36], 0); + put4byte(&pBt->pPage1->aData[28], nFin); sqlite3PagerTruncateImage(pBt->pPager, nFin); + pBt->nPage = nFin; } if( rc!=SQLITE_OK ){ sqlite3PagerRollback(pPager); @@ -3269,6 +3269,7 @@ int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){ rc = sqlite3PagerSavepoint(pBt->pPager, op, iSavepoint); if( rc==SQLITE_OK ){ rc = newDatabase(pBt); + pBt->nPage = get4byte(28 + pBt->pPage1->aData); } sqlite3BtreeLeave(p); } @@ -4833,32 +4834,32 @@ static int allocateBtreePage( }else{ /* There are no pages on the freelist, so create a new page at the ** end of the file */ - int nPage = pagerPagecount(pBt); - *pPgno = nPage + 1; - - if( *pPgno==PENDING_BYTE_PAGE(pBt) ){ - (*pPgno)++; - } + rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); + if( rc ) return rc; + pBt->nPage++; + if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ) pBt->nPage++; #ifndef SQLITE_OMIT_AUTOVACUUM - if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt, *pPgno) ){ + if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt, pBt->nPage) ){ /* If *pPgno refers to a pointer-map page, allocate two new pages ** at the end of the file instead of one. The first allocated page ** becomes a new pointer-map page, the second is used by the caller. */ MemPage *pPg = 0; - TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", *pPgno)); - assert( *pPgno!=PENDING_BYTE_PAGE(pBt) ); - rc = btreeGetPage(pBt, *pPgno, &pPg, 0); + TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", pBt->nPage)); + assert( pBt->nPage!=PENDING_BYTE_PAGE(pBt) ); + rc = btreeGetPage(pBt, pBt->nPage, &pPg, 0); if( rc==SQLITE_OK ){ rc = sqlite3PagerWrite(pPg->pDbPage); releasePage(pPg); } if( rc ) return rc; - (*pPgno)++; - if( *pPgno==PENDING_BYTE_PAGE(pBt) ){ (*pPgno)++; } + pBt->nPage++; + if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ){ pBt->nPage++; } } #endif + put4byte(28 + (u8*)pBt->pPage1->aData, pBt->nPage); + *pPgno = pBt->nPage; assert( *pPgno!=PENDING_BYTE_PAGE(pBt) ); rc = btreeGetPage(pBt, *pPgno, ppPage, 0); diff --git a/src/btreeInt.h b/src/btreeInt.h index f6d95e5047..ddb8e932e4 100644 --- a/src/btreeInt.h +++ b/src/btreeInt.h @@ -420,6 +420,7 @@ struct BtShared { u16 minLeaf; /* Minimum local payload in a LEAFDATA table */ u8 inTransaction; /* Transaction state */ int nTransaction; /* Number of open transactions (read + write) */ + u32 nPage; /* Number of pages in the database */ void *pSchema; /* Pointer to space allocated by sqlite3BtreeSchema() */ void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */ sqlite3_mutex *mutex; /* Non-recursive mutex required to access this struct */ diff --git a/src/pager.c b/src/pager.c index 56becfcec2..ced997b4e2 100644 --- a/src/pager.c +++ b/src/pager.c @@ -4156,10 +4156,10 @@ static int pager_write(PgHdr *pPg){ */ assert( pPager->state>=PAGER_RESERVED ); - /* If an error has been previously detected, we should not be - ** calling this routine. Repeat the error for robustness. + /* If an error has been previously detected, report the same error + ** again. */ - if( NEVER(pPager->errCode) ) return pPager->errCode; + if( pPager->errCode ) return pPager->errCode; /* Higher-level routines never call this function if database is not ** writable. But check anyway, just for robustness. */ @@ -4489,10 +4489,6 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){ change_counter++; put32bits(((char*)pPgHdr->pData)+24, change_counter); - /* Also store the current database size in bytes 28..31 */ - assert( pPager->dbSizeValid ); - put32bits(((char*)pPgHdr->pData)+28, pPager->dbSize); - /* Also store the SQLite version number in bytes 96..99 */ assert( pPager->dbSizeValid ); put32bits(((char*)pPgHdr->pData)+96, SQLITE_VERSION_NUMBER); @@ -4570,10 +4566,8 @@ int sqlite3PagerCommitPhaseOne( /* The dbOrigSize is never set if journal_mode=OFF */ assert( pPager->journalMode!=PAGER_JOURNALMODE_OFF || pPager->dbOrigSize==0 ); - /* If a prior error occurred, this routine should not be called. ROLLBACK - ** is the appropriate response to an error, not COMMIT. Guard against - ** coding errors by repeating the prior error. */ - if( NEVER(pPager->errCode) ) return pPager->errCode; + /* If a prior error occurred, report that error again. */ + if( pPager->errCode ) return pPager->errCode; PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n", pPager->zFilename, zMaster, pPager->dbSize)); @@ -4925,6 +4919,9 @@ int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){ int ii; /* Iterator variable */ PagerSavepoint *aNew; /* New Pager.aSavepoint array */ + rc = sqlite3PagerPagecount(pPager, 0); + if( rc ) return rc; + /* Grow the Pager.aSavepoint array using realloc(). Return SQLITE_NOMEM ** if the allocation fails. Otherwise, zero the new portion in case a ** malloc failure occurs while populating it in the for(...) loop below. diff --git a/test/corrupt2.test b/test/corrupt2.test index acda25436d..12437c72a2 100644 --- a/test/corrupt2.test +++ b/test/corrupt2.test @@ -334,6 +334,7 @@ ifcapable autovacuum { seek $fd 0 end puts -nonewline $fd [string repeat x $nAppend] close $fd + hexio_write corrupt.db 28 00000000 } -test { do_test corrupt2-6.4 { catchsql { @@ -522,6 +523,7 @@ ifcapable autovacuum { file size corrupt.db } $::sqlite_pending_byte hexio_write corrupt.db [expr $::sqlite_pending_byte+1023] 00 + hexio_write corrupt.db 28 00000000 } -test { do_test corrupt2-13.2 { file size corrupt.db diff --git a/test/pragma.test b/test/pragma.test index 46f7d6d516..380a59e707 100644 --- a/test/pragma.test +++ b/test/pragma.test @@ -317,6 +317,7 @@ ifcapable attach { puts -nonewline $out [read $in] close $in close $out + hexio_write testerr.db 28 00000000 execsql {REINDEX t2} execsql {PRAGMA integrity_check} } {ok}