From: danielk1977 Date: Thu, 20 Mar 2008 11:04:21 +0000 (+0000) Subject: Allow a VACUUM operation to change the page-size in the same way as it can be used... X-Git-Tag: version-3.6.10~1281 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f653d78282b61b9ea5940453d0065cbdbdd6ffb2;p=thirdparty%2Fsqlite.git Allow a VACUUM operation to change the page-size in the same way as it can be used to change a database between auto-vacuum and normal mode. (CVS 4896) FossilOrigin-Name: 871df0e7c36a88f175cfc63797745e52a1b1796b --- diff --git a/manifest b/manifest index 5799b5ed93..aad0e4530f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C stick\severything\sthat\ssqlite\slinks\sagainst\sinto\sLibs.private\s(CVS\s4895) -D 2008-03-20T10:44:43 +C Allow\sa\sVACUUM\soperation\sto\schange\sthe\spage-size\sin\sthe\ssame\sway\sas\sit\scan\sbe\sused\sto\schange\sa\sdatabase\sbetween\sauto-vacuum\sand\snormal\smode.\s(CVS\s4896) +D 2008-03-20T11:04:21 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7 F Makefile.in cf434ce8ca902e69126ae0f94fc9f7dc7428a5fa F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -86,7 +86,7 @@ F src/attach.c e7cf4ae2a2c8ebd554dc6ca06859b587fa7197c2 F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627 F src/bitvec.c fac68429a9916a50229c4ab88abb69c00c438f7f F src/btmutex.c 483ced3c52205b04b97df69161fadbf87f4f1ea2 -F src/btree.c 439e2684892d2b70996dc3c5fba25e07949e1d84 +F src/btree.c 77304a2086a9089fe5e5ee8861248b72d6cca5d6 F src/btree.h 19dcf5ad23c17b98855da548e9a8e3eb4429d5eb F src/btreeInt.h d7d2f4d9d7f2e72c455326d48b2b478b842a81f6 F src/build.c fa70bc0fb02e4d08202dd6a752ab5f5df5676e50 @@ -105,7 +105,7 @@ F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2 F src/legacy.c cb1939fdeb91ea88fb44fbd2768a10e14bc44650 F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35 F src/loadext.c f26b22f7c84153c9d5dbd7c240848823c6e6b6dc -F src/main.c bb31f65f7b1870825a4c9a31f19354d566b7633c +F src/main.c 9dd4646a7dadcde7efa36c2904792f992872b2bc F src/malloc.c 60e392a4c12c839517f9b0db7b995f825444fb35 F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217 F src/mem1.c fc716ff521b6dd3e43eaa211967383308800e70a @@ -129,10 +129,10 @@ F src/os_unix.c fdec4e5ee5dd555a6ad4a69f38ab35f0788536b4 F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e F src/os_win.c 3a60bddd07ea6f8adb2314dd5996ac97b988f403 F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b -F src/pager.c d3448e060afc840be75b09c83501e5f8c13bac54 -F src/pager.h 8174615ffd14ccc2cad2b081b919a398fa95e3f9 +F src/pager.c 22241b59c80ca083a96816df434adb8c097afcd4 +F src/pager.h b1e2258f03878c14b06a95bfa362e8c5c9638170 F src/parse.y 00f2698c8ae84f315be5e3f10b63c94f531fdd6d -F src/pragma.c 09128fe3e2b5108d322a66b19a6f2974dac64479 +F src/pragma.c f64eed914518c28d1863356163dea1e6f58e28f2 F src/prepare.c 88e32e985921e9fb5d3ca22ccc74e054ebfe49f2 F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910 F src/random.c 8b6ab5418cf0f4dde551730825d67da1457c2b3c @@ -141,12 +141,12 @@ F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96 F src/shell.c 22297fffa6f00a6c6d44020fa13b1184a1bb372d F src/sqlite.h.in c82088b99b3262c017ddadc14d45b2d5877cbeae F src/sqlite3ext.h faacd0e6a81aabee0861c6d7883c9172e74ef5b3 -F src/sqliteInt.h ed823fb087e57a09762bc1f4e0935761a8d57c7b +F src/sqliteInt.h 160aadae3b44b53b9176d615bbada6b0ba7d00c4 F src/sqliteLimit.h ee4430f88f69bf63527967bb35ca52af7b0ccb1e F src/table.c 2c48c575dd59b3a6c5c306bc55f51a9402cf429a F src/tclsqlite.c d42912617d4734b8f9195416badf5b27e512ded2 F src/test1.c 935f327fe989694a3aa07ab78ae5c00705651b34 -F src/test2.c 443ccc1bd5717b1001e5558b6f6b33bd34f8b81b +F src/test2.c da3c4016fc1e08fa1a133ca81591ee8ca99ce8e7 F src/test3.c 5c7452038ab27aa698070799b10132f26cdd2a80 F src/test4.c c2c0f5dc907f1346f5d4b65eb5799f11eb9e4071 F src/test5.c 3a6a5717a149d7ca2e6d14f5be72cf7555d54dc4 @@ -174,7 +174,7 @@ F src/trigger.c 9bd3b6fa0beff4a02d262c96466f752ec15a7fc3 F src/update.c d2c59643af98f966c2a04d392463089b715ca18f F src/utf.c 32b00d6e19010025e58f2ecb2f921d5e126771b4 F src/util.c dba9e04121eb17ec4643d6ca231ff859452cf0e2 -F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0 +F src/vacuum.c 3524411bfb58aac0d87eadd3e5b7cd532772af30 F src/vdbe.c 86033e43d89892ea6a817e8bcd4e6273bc1ebdf5 F src/vdbe.h 58a7d931ffb704e034b2a725981cfa5bd406fad9 F src/vdbeInt.h 76c81d057a39813de0fda3cad1498655d53ec69d @@ -625,7 +625,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 -P 79f573cc7be89b3dd5540c45ef132b5cedc98e9b -R 9c4651c8bf3b341af0787aed67123442 -U vapier -Z edba339a7453fff69aec5101a9514ca7 +P 8b198617f572d35f04d119ba688e0f5c67f81144 +R a308dd47ecbf55342f9cd3c4b73f760c +U danielk1977 +Z ca52892929aebf794b5fd5229c74cc6b diff --git a/manifest.uuid b/manifest.uuid index 10e3b3e73f..d46cbbceff 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8b198617f572d35f04d119ba688e0f5c67f81144 \ No newline at end of file +871df0e7c36a88f175cfc63797745e52a1b1796b \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 82085eb3af..023e5a1aa6 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.440 2008/03/04 17:45:01 mlcreech Exp $ +** $Id: btree.c,v 1.441 2008/03/20 11:04:21 danielk1977 Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. @@ -1635,20 +1635,21 @@ int sqlite3BtreeGetAutoVacuum(Btree *p){ ** is returned if we run out of memory. */ static int lockBtree(BtShared *pBt){ - int rc, pageSize; + int rc; MemPage *pPage1; assert( sqlite3_mutex_held(pBt->mutex) ); if( pBt->pPage1 ) return SQLITE_OK; rc = sqlite3BtreeGetPage(pBt, 1, &pPage1, 0); if( rc!=SQLITE_OK ) return rc; - /* Do some checking to help insure the file we opened really is ** a valid database file. */ rc = SQLITE_NOTADB; if( sqlite3PagerPagecount(pBt->pPager)>0 ){ + int pageSize; + int usableSize; u8 *page1 = pPage1->aData; if( memcmp(page1, zMagicHeader, 16)!=0 ){ goto page1_init_failed; @@ -1666,11 +1667,25 @@ static int lockBtree(BtShared *pBt){ goto page1_init_failed; } assert( (pageSize & 7)==0 ); - pBt->pageSize = pageSize; - pBt->usableSize = pageSize - page1[20]; - if( pBt->usableSize<500 ){ + usableSize = pageSize - page1[20]; + if( pageSize!=pBt->pageSize ){ + /* After reading the first page of the database assuming a page size + ** of BtShared.pageSize, we have discovered that the page-size is + ** actually pageSize. Unlock the database, leave pBt->pPage1 at + ** zero and return SQLITE_OK. The caller will call this function + ** again with the correct page-size. + */ + releasePage(pPage1); + pBt->usableSize = usableSize; + pBt->pageSize = pageSize; + sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize); + return SQLITE_OK; + } + if( usableSize<500 ){ goto page1_init_failed; } + pBt->pageSize = pageSize; + pBt->usableSize = usableSize; pBt->maxEmbedFrac = page1[21]; pBt->minEmbedFrac = page1[22]; pBt->minLeafFrac = page1[23]; @@ -1879,7 +1894,7 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag){ #endif do { - if( pBt->pPage1==0 ){ + while( rc==SQLITE_OK && pBt->pPage1==0 ){ rc = lockBtree(pBt); } @@ -2359,7 +2374,7 @@ int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){ } } #endif - rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, nTrunc); + rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, nTrunc, 0); sqlite3BtreeLeave(p); } return rc; @@ -6729,62 +6744,209 @@ const char *sqlite3BtreeGetJournalname(Btree *p){ ** Copy the complete content of pBtFrom into pBtTo. A transaction ** must be active for both files. ** -** The size of file pBtFrom may be reduced by this operation. -** If anything goes wrong, the transaction on pBtFrom is rolled back. +** The size of file pTo may be reduced by this operation. +** If anything goes wrong, the transaction on pTo is rolled back. +** +** If successful, CommitPhaseOne() may be called on pTo before returning. +** The caller should finish committing the transaction on pTo by calling +** sqlite3BtreeCommit(). */ static int btreeCopyFile(Btree *pTo, Btree *pFrom){ int rc = SQLITE_OK; - Pgno i, nPage, nToPage, iSkip; + Pgno i; + + Pgno nFromPage; /* Number of pages in pFrom */ + Pgno nToPage; /* Number of pages in pTo */ + Pgno nNewPage; /* Number of pages in pTo after the copy */ + + Pgno iSkip; /* Pending byte page in pTo */ + int nToPageSize; /* Page size of pTo in bytes */ + int nFromPageSize; /* Page size of pFrom in bytes */ BtShared *pBtTo = pTo->pBt; BtShared *pBtFrom = pFrom->pBt; pBtTo->db = pTo->db; pBtFrom->db = pFrom->db; - + + nToPageSize = pBtTo->pageSize; + nFromPageSize = pBtFrom->pageSize; if( pTo->inTrans!=TRANS_WRITE || pFrom->inTrans!=TRANS_WRITE ){ return SQLITE_ERROR; } - if( pBtTo->pCursor ) return SQLITE_BUSY; + if( pBtTo->pCursor ){ + return SQLITE_BUSY; + } + nToPage = sqlite3PagerPagecount(pBtTo->pPager); - nPage = sqlite3PagerPagecount(pBtFrom->pPager); + nFromPage = sqlite3PagerPagecount(pBtFrom->pPager); iSkip = PENDING_BYTE_PAGE(pBtTo); - for(i=1; rc==SQLITE_OK && i<=nPage; i++){ - DbPage *pDbPage; - if( i==iSkip ) continue; - rc = sqlite3PagerGet(pBtFrom->pPager, i, &pDbPage); - if( rc ) break; - rc = sqlite3PagerOverwrite(pBtTo->pPager, i, sqlite3PagerGetData(pDbPage)); - sqlite3PagerUnref(pDbPage); - } - /* If the file is shrinking, journal the pages that are being truncated - ** so that they can be rolled back if the commit fails. + /* Variable nNewPage is the number of pages required to store the + ** contents of pFrom using the current page-size of pTo. */ - for(i=nPage+1; rc==SQLITE_OK && i<=nToPage; i++){ - DbPage *pDbPage; - if( i==iSkip ) continue; - rc = sqlite3PagerGet(pBtTo->pPager, i, &pDbPage); - if( rc ) break; - rc = sqlite3PagerWrite(pDbPage); - sqlite3PagerDontWrite(pDbPage); - /* Yeah. It seems wierd to call DontWrite() right after Write(). But - ** that is because the names of those procedures do not exactly - ** represent what they do. Write() really means "put this page in the - ** rollback journal and mark it as dirty so that it will be written - ** to the database file later." DontWrite() undoes the second part of - ** that and prevents the page from being written to the database. The - ** page is still on the rollback journal, though. And that is the whole - ** point of this loop: to put pages on the rollback journal. */ - sqlite3PagerUnref(pDbPage); + nNewPage = ((i64)nFromPage * (i64)nFromPageSize + (i64)nToPageSize - 1) / + (i64)nToPageSize; + + for(i=1; rc==SQLITE_OK && (i<=nToPage || i<=nNewPage); i++){ + + /* Journal the original page. + ** + ** iSkip is the page number of the locking page (PENDING_BYTE_PAGE) + ** in database *pTo (before the copy). This page is never written + ** into the journal file. Unless i==iSkip or the page was not + ** present in pTo before the copy operation, journal page i from pTo. + */ + if( i!=iSkip && i<=nToPage ){ + DbPage *pDbPage; + rc = sqlite3PagerGet(pBtTo->pPager, i, &pDbPage); + if( rc ){ + break; + } + rc = sqlite3PagerWrite(pDbPage); + if( rc ){ + break; + } + if( i>nFromPage ){ + /* Yeah. It seems wierd to call DontWrite() right after Write(). But + ** that is because the names of those procedures do not exactly + ** represent what they do. Write() really means "put this page in the + ** rollback journal and mark it as dirty so that it will be written + ** to the database file later." DontWrite() undoes the second part of + ** that and prevents the page from being written to the database. The + ** page is still on the rollback journal, though. And that is the + ** whole point of this block: to put pages on the rollback journal. + */ + sqlite3PagerDontWrite(pDbPage); + } + sqlite3PagerUnref(pDbPage); + } + + /* Overwrite the data in page i of the target database */ + if( rc==SQLITE_OK && i!=iSkip && i<=nNewPage ){ + + DbPage *pToPage = 0; + sqlite3_int64 iOff; + + rc = sqlite3PagerGet(pBtTo->pPager, i, &pToPage); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerWrite(pToPage); + } + + for( + iOff=(i-1)*nToPageSize; + rc==SQLITE_OK && iOffpPager, iFrom, &pFromPage); + if( rc==SQLITE_OK ){ + char *zTo = sqlite3PagerGetData(pToPage); + char *zFrom = sqlite3PagerGetData(pFromPage); + int nCopy; + + if( nFromPageSize>=nToPageSize ){ + zFrom += ((i-1)*nToPageSize - ((iFrom-1)*nFromPageSize)); + nCopy = nToPageSize; + }else{ + zTo += (((iFrom-1)*nFromPageSize) - (i-1)*nToPageSize); + nCopy = nFromPageSize; + } + + memcpy(zTo, zFrom, nCopy); + sqlite3PagerUnref(pFromPage); + } + } + + if( pToPage ) sqlite3PagerUnref(pToPage); + } } - if( !rc && nPagepPager, nPage); + + /* If things have worked so far, the database file may need to be + ** truncated. The complex part is that it may need to be truncated to + ** a size that is not an integer multiple of nToPageSize - the current + ** page size used by the pager associated with B-Tree pTo. + ** + ** For example, say the page-size of pTo is 2048 bytes and the original + ** number of pages is 5 (10 KB file). If pFrom has a page size of 1024 + ** bytes and 9 pages, then the file needs to be truncated to 9KB. + */ + if( rc==SQLITE_OK ){ + if( nFromPageSize!=nToPageSize ){ + sqlite3_file *pFile = sqlite3PagerFile(pBtTo->pPager); + i64 iSize = (i64)nFromPageSize * (i64)nFromPage; + i64 iNow = (i64)((nToPage>nNewPage)?nToPage:nNewPage) * (i64)nToPageSize; + i64 iPending = ((i64)PENDING_BYTE_PAGE(pBtTo)-1) *(i64)nToPageSize; + + assert( iSize<=iNow ); + + /* Commit phase one syncs the journal file associated with pTo + ** containing the original data. It does not sync the database file + ** itself. After doing this it is safe to use OsTruncate() and other + ** file APIs on the database file directly. + */ + pBtTo->db = pTo->db; + rc = sqlite3PagerCommitPhaseOne(pBtTo->pPager, 0, 0, 1); + if( iSizeiPending){ + i64 iOff; + for( + iOff=iPending; + rc==SQLITE_OK && iOff<(iPending+nToPageSize); + iOff += nFromPageSize + ){ + DbPage *pFromPage = 0; + Pgno iFrom = (iOff/nFromPageSize)+1; + + if( iFrom==PENDING_BYTE_PAGE(pBtFrom) || iFrom>nFromPage ){ + continue; + } + + rc = sqlite3PagerGet(pBtFrom->pPager, iFrom, &pFromPage); + if( rc==SQLITE_OK ){ + char *zFrom = sqlite3PagerGetData(pFromPage); + rc = sqlite3OsWrite(pFile, zFrom, nFromPageSize, iOff); + sqlite3PagerUnref(pFromPage); + } + } + } + + /* Sync the database file */ + if( rc==SQLITE_OK ){ + rc = sqlite3PagerSync(pBtTo->pPager); + } + }else{ + rc = sqlite3PagerTruncate(pBtTo->pPager, nNewPage); + } + if( rc==SQLITE_OK ){ + pBtTo->pageSizeFixed = 0; + } } if( rc ){ sqlite3BtreeRollback(pTo); } + return rc; } int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){ diff --git a/src/main.c b/src/main.c index dd9999e537..4fef038b23 100644 --- a/src/main.c +++ b/src/main.c @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.424 2008/03/19 16:08:54 drh Exp $ +** $Id: main.c,v 1.425 2008/03/20 11:04:21 danielk1977 Exp $ */ #include "sqliteInt.h" #include @@ -971,6 +971,7 @@ static int openDatabase( db->aDb = db->aDbStatic; db->autoCommit = 1; db->nextAutovac = -1; + db->nextPagesize = 0; db->flags |= SQLITE_ShortColNames #if SQLITE_DEFAULT_FILE_FORMAT<4 | SQLITE_LegacyFileFmt diff --git a/src/pager.c b/src/pager.c index 5313404ccb..7f76c13d5a 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.419 2008/03/20 04:45:49 danielk1977 Exp $ +** @(#) $Id: pager.c,v 1.420 2008/03/20 11:04:21 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" @@ -4501,6 +4501,17 @@ static int pager_incr_changecounter(Pager *pPager, int isDirect){ return rc; } +/* +** Sync the pager file to disk. +*/ +int sqlite3PagerSync(Pager *pPager){ + int rc; + pagerEnter(pPager); + rc = sqlite3OsSync(pPager->fd, pPager->sync_flags); + pagerLeave(pPager); + return rc; +} + /* ** Sync the database file for the pager pPager. zMaster points to the name ** of a master journal file that should be written into the individual @@ -4517,8 +4528,18 @@ static int pager_incr_changecounter(Pager *pPager, int isDirect){ ** ** If parameter nTrunc is non-zero, then the pager file is truncated to ** nTrunc pages (this is used by auto-vacuum databases). +** +** If the final parameter - noSync - is true, then the database file itself +** is not synced. The caller must call sqlite3PagerSync() directly to +** sync the database file before calling CommitPhaseTwo() to delete the +** journal file in this case. */ -int sqlite3PagerCommitPhaseOne(Pager *pPager, const char *zMaster, Pgno nTrunc){ +int sqlite3PagerCommitPhaseOne( + Pager *pPager, + const char *zMaster, + Pgno nTrunc, + int noSync +){ int rc = SQLITE_OK; PAGERTRACE4("DATABASE SYNC: File=%s zMaster=%s nTrunc=%d\n", @@ -4630,7 +4651,7 @@ int sqlite3PagerCommitPhaseOne(Pager *pPager, const char *zMaster, Pgno nTrunc){ pPager->pDirty = 0; /* Sync the database file. */ - if( !pPager->noSync ){ + if( !pPager->noSync && !noSync ){ rc = sqlite3OsSync(pPager->fd, pPager->sync_flags); } IOTRACE(("DBSYNC %p\n", pPager)) diff --git a/src/pager.h b/src/pager.h index c864a1501c..a6bd54c977 100644 --- a/src/pager.h +++ b/src/pager.h @@ -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.69 2008/02/02 20:47:38 drh Exp $ +** @(#) $Id: pager.h,v 1.70 2008/03/20 11:04:21 danielk1977 Exp $ */ #ifndef _PAGER_H_ @@ -73,7 +73,7 @@ int sqlite3PagerOverwrite(Pager *pPager, Pgno pgno, void*); int sqlite3PagerPagecount(Pager*); int sqlite3PagerTruncate(Pager*,Pgno); int sqlite3PagerBegin(DbPage*, int exFlag); -int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, Pgno); +int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, Pgno, int); int sqlite3PagerCommitPhaseTwo(Pager*); int sqlite3PagerRollback(Pager*); int sqlite3PagerIsreadonly(Pager*); @@ -95,6 +95,7 @@ void *sqlite3PagerGetData(DbPage *); void *sqlite3PagerGetExtra(DbPage *); int sqlite3PagerLockingMode(Pager *, int); void *sqlite3PagerTempSpace(Pager*); +int sqlite3PagerSync(Pager *pPager); #if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO) int sqlite3PagerReleaseMemory(int); diff --git a/src/pragma.c b/src/pragma.c index 067426d11c..98d7d2a0ff 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** -** $Id: pragma.c,v 1.171 2008/03/19 00:21:31 drh Exp $ +** $Id: pragma.c,v 1.172 2008/03/20 11:04:21 danielk1977 Exp $ */ #include "sqliteInt.h" #include @@ -350,7 +350,8 @@ void sqlite3Pragma( /* Malloc may fail when setting the page-size, as there is an internal ** buffer that the pager module resizes using sqlite3_realloc(). */ - if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, atoi(zRight), -1) ){ + db->nextPagesize = atoi(zRight); + if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1) ){ db->mallocFailed = 1; } } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index b27971ae1c..fdf4d7879c 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.675 2008/03/20 00:32:20 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.676 2008/03/20 11:04:21 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -575,6 +575,7 @@ struct sqlite3 { u8 temp_store; /* 1: file 2: memory 0: default */ u8 mallocFailed; /* True if we have seen a malloc failure */ signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ + int nextPagesize; /* Pagesize after VACUUM if >0 */ int nTable; /* Number of tables in the database */ CollSeq *pDfltColl; /* The default collating sequence (BINARY) */ i64 lastRowid; /* ROWID of most recent insert (see above) */ diff --git a/src/test2.c b/src/test2.c index d326a91d88..a8457efb33 100644 --- a/src/test2.c +++ b/src/test2.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test2.c,v 1.55 2008/03/19 00:21:31 drh Exp $ +** $Id: test2.c,v 1.56 2008/03/20 11:04:21 danielk1977 Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -164,7 +164,7 @@ static int pager_commit( return TCL_ERROR; } pPager = sqlite3TextToPtr(argv[1]); - rc = sqlite3PagerCommitPhaseOne(pPager, 0, 0); + rc = sqlite3PagerCommitPhaseOne(pPager, 0, 0, 0); if( rc!=SQLITE_OK ){ Tcl_AppendResult(interp, errorName(rc), 0); return TCL_ERROR; diff --git a/src/vacuum.c b/src/vacuum.c index c6544ac57b..2bfd7aea9b 100644 --- a/src/vacuum.c +++ b/src/vacuum.c @@ -14,7 +14,7 @@ ** Most of the code in this file may be omitted by defining the ** SQLITE_OMIT_VACUUM macro. ** -** $Id: vacuum.c,v 1.76 2008/01/03 00:01:25 drh Exp $ +** $Id: vacuum.c,v 1.77 2008/03/20 11:04:21 danielk1977 Exp $ */ #include "sqliteInt.h" #include "vdbeInt.h" @@ -85,6 +85,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ char *zSql = 0; /* SQL statements */ int saved_flags; /* Saved value of the db->flags */ Db *pDb = 0; /* Database to detach at end of vacuum */ + int nRes; /* Save the current value of the write-schema flag before setting it. */ saved_flags = db->flags; @@ -112,13 +113,15 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ pDb = &db->aDb[db->nDb-1]; assert( strcmp(db->aDb[db->nDb-1].zName,"vacuum_db")==0 ); pTemp = db->aDb[db->nDb-1].pBt; - sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), - sqlite3BtreeGetReserve(pMain)); - if( db->mallocFailed ){ + + nRes = sqlite3BtreeGetReserve(pMain); + if( sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), nRes) + || sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes) + || db->mallocFailed + ){ rc = SQLITE_NOMEM; goto end_of_vacuum; } - assert( sqlite3BtreeGetPageSize(pTemp)==sqlite3BtreeGetPageSize(pMain) ); rc = execSql(db, "PRAGMA vacuum_db.synchronous=OFF"); if( rc!=SQLITE_OK ){ goto end_of_vacuum; @@ -237,6 +240,10 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ rc = sqlite3BtreeCommit(pMain); } + if( rc==SQLITE_OK ){ + rc = sqlite3BtreeSetPageSize(pMain, sqlite3BtreeGetPageSize(pTemp), nRes); + } + end_of_vacuum: /* Restore the original value of db->flags */ db->flags = saved_flags;