diff --git a/ext/misc/cksumvfs.c b/ext/misc/cksumvfs.c index 8c340889fe..e7c2c9d5c0 100644 --- a/ext/misc/cksumvfs.c +++ b/ext/misc/cksumvfs.c @@ -47,7 +47,7 @@ ** ** sqlite3 *db; ** sqlite3_open(":memory:", &db); -** sqlite3_load_extention(db, "./cksumvfs"); +** sqlite3_load_extension(db, "./cksumvfs"); ** sqlite3_close(db); ** ** If this extension is compiled with -DSQLITE_CKSUMVFS_STATIC and diff --git a/ext/recover/recover1.test b/ext/recover/recover1.test index 99ddc1f4b3..ed921b7e91 100644 --- a/ext/recover/recover1.test +++ b/ext/recover/recover1.test @@ -222,5 +222,29 @@ do_test 12.3 { $R finish } {} + + +#------------------------------------------------------------------------- +reset_db +file_control_reservebytes db 16 +do_execsql_test 12.1 { + PRAGMA auto_vacuum = 2; + PRAGMA user_version = 45; + PRAGMA application_id = 22; + + CREATE TABLE u1(u, v); + CREATE UNIQUE INDEX i1 ON u1(u, v); + INSERT INTO u1 VALUES(1, 2), (3, 4); + + CREATE TABLE u2(u, v); + CREATE UNIQUE INDEX i2 ON u1(u, v); + INSERT INTO u2 VALUES(hex(randomblob(500)), hex(randomblob(1000))); + INSERT INTO u2 VALUES(hex(randomblob(500)), hex(randomblob(1000))); + INSERT INTO u2 VALUES(hex(randomblob(500)), hex(randomblob(1000))); + INSERT INTO u2 VALUES(hex(randomblob(50000)), hex(randomblob(20000))); +} + +do_recover_test 12 + finish_test diff --git a/ext/recover/sqlite3recover.c b/ext/recover/sqlite3recover.c index 6e5db516c9..70f3386924 100644 --- a/ext/recover/sqlite3recover.c +++ b/ext/recover/sqlite3recover.c @@ -194,6 +194,7 @@ struct sqlite3_recover { int pgsz; int detected_pgsz; + int nReserve; u8 *pPage1Disk; u8 *pPage1Cache; @@ -667,20 +668,13 @@ static void recoverGetPage( if( pStmt ){ sqlite3_bind_int64(pStmt, 1, pgno); if( SQLITE_ROW==sqlite3_step(pStmt) ){ - int bDone = 0; assert( p->errCode==SQLITE_OK ); - if( pgno==1 ){ - const u8 *aPg = sqlite3_column_blob(pStmt, 0); - int nPg = sqlite3_column_bytes(pStmt, 0); - if( nPg==p->pgsz && 0==memcmp(p->pPage1Cache, aPg, nPg) ){ - sqlite3_result_blob(pCtx, p->pPage1Disk, nPg, SQLITE_STATIC); - bDone = 1; - } - } - - if( !bDone ){ - sqlite3_result_value(pCtx, sqlite3_column_value(pStmt, 0)); + const u8 *aPg = sqlite3_column_blob(pStmt, 0); + int nPg = sqlite3_column_bytes(pStmt, 0); + if( pgno==1 && nPg==p->pgsz && 0==memcmp(p->pPage1Cache, aPg, nPg) ){ + aPg = p->pPage1Disk; } + sqlite3_result_blob(pCtx, aPg, nPg-p->nReserve, SQLITE_TRANSIENT); } recoverReset(p, pStmt); } @@ -2097,6 +2091,7 @@ static void recoverPutU32(u8 *a, u32 v){ static int recoverVfsDetectPagesize( sqlite3_recover *p, sqlite3_file *pFd, + u32 nReserve, /* Possible nReserve value */ i64 nSz ){ int rc = SQLITE_OK; @@ -2116,23 +2111,31 @@ static int recoverVfsDetectPagesize( nBlk = (nSz+nMax-1)/nMax; if( nBlk>nMaxBlk ) nBlk = nMaxBlk; - for(iBlk=0; rc==SQLITE_OK && iBlk=((iBlk+1)*nMax)) ? nMax : (nSz % nMax); - memset(aPg, 0, nMax); - rc = pFd->pMethods->xRead(pFd, aPg, nByte, iBlk*nMax); - if( rc==SQLITE_OK ){ - int pgsz2; - for(pgsz2=(pgsz ? pgsz*2 : nMin); pgsz2<=nMax; pgsz2=pgsz2*2){ - int iOff; - for(iOff=0; iOff=((iBlk+1)*nMax)) ? nMax : (nSz % nMax); + memset(aPg, 0, nMax); + rc = pFd->pMethods->xRead(pFd, aPg, nByte, iBlk*nMax); + if( rc==SQLITE_OK ){ + int pgsz2; + for(pgsz2=(pgsz ? pgsz*2 : nMin); pgsz2<=nMax; pgsz2=pgsz2*2){ + int iOff; + for(iOff=0; iOffp->detected_pgsz ){ + p->detected_pgsz = pgsz; + p->nReserve = nReserve; + } + if( nReserve==0 ) break; + nReserve = 0; + }while( 1 ); p->detected_pgsz = pgsz; sqlite3_free(aPg); @@ -2188,6 +2191,7 @@ static int recoverVfsRead(sqlite3_file *pFd, void *aBuf, int nByte, i64 iOff){ u8 *a = (u8*)aBuf; u32 pgsz = recoverGetU16(&a[16]); + u32 nReserve = a[20]; u32 enc = recoverGetU32(&a[56]); u32 dbsz = 0; i64 dbFileSize = 0; @@ -2199,10 +2203,11 @@ static int recoverVfsRead(sqlite3_file *pFd, void *aBuf, int nByte, i64 iOff){ if( rc==SQLITE_OK && p->detected_pgsz==0 ){ u32 pgsz2 = 0; - rc = recoverVfsDetectPagesize(p, pFd, dbFileSize); + rc = recoverVfsDetectPagesize(p, pFd, nReserve, dbFileSize); } if( p->detected_pgsz ){ pgsz = p->detected_pgsz; + nReserve = p->nReserve; } if( pgsz ){ @@ -2224,9 +2229,10 @@ static int recoverVfsRead(sqlite3_file *pFd, void *aBuf, int nByte, i64 iOff){ recoverPutU32(&aHdr[28], dbsz); recoverPutU32(&aHdr[56], enc); - recoverPutU16(&aHdr[105], pgsz); + recoverPutU16(&aHdr[105], pgsz-nReserve); if( pgsz==65536 ) pgsz = 1; recoverPutU16(&aHdr[16], pgsz); + aHdr[20] = nReserve; for(ii=0; ii