return nRet;
}
-static void *recoverMalloc(sqlite3_recover *p, sqlite3_int64 nByte){
+static void *recoverMalloc(sqlite3_recover *p, i64 nByte){
void *pRet = 0;
assert( nByte>0 );
if( p->errCode==SQLITE_OK ){
return nPg;
}
+/*
+** Scalar function "read_i32". The first argument to this function
+** must be a blob. The second a non-negative integer. This function
+** reads and returns a 32-bit big-endian integer from byte
+** offset (4*<arg2>) of the blob.
+*/
+static void recoverReadI32(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ const unsigned char *pBlob;
+ int nBlob;
+ int iInt;
+
+ assert( argc==2 );
+ nBlob = sqlite3_value_bytes(argv[0]);
+ pBlob = (const unsigned char*)sqlite3_value_blob(argv[0]);
+ iInt = sqlite3_value_int(argv[1]);
+
+ if( iInt>=0 && (iInt+1)*4<=nBlob ){
+ const unsigned char *a = &pBlob[iInt*4];
+ i64 iVal = ((i64)a[0]<<24)
+ + ((i64)a[1]<<16)
+ + ((i64)a[2]<< 8)
+ + ((i64)a[3]<< 0);
+ sqlite3_result_int64(context, iVal);
+ }
+}
+
/*
** SELECT page_is_used(pgno);
*/
sqlite3_value **apArg
){
sqlite3_recover *p = (sqlite3_recover*)sqlite3_user_data(pCtx);
- sqlite3_int64 pgno = sqlite3_value_int64(apArg[0]);
+ i64 pgno = sqlite3_value_int64(apArg[0]);
sqlite3_stmt *pStmt = 0;
int bRet;
sqlite3_value **apArg
){
sqlite3_recover *p = (sqlite3_recover*)sqlite3_user_data(pCtx);
- sqlite3_int64 pgno = sqlite3_value_int64(apArg[0]);
+ i64 pgno = sqlite3_value_int64(apArg[0]);
sqlite3_stmt *pStmt = 0;
assert( nArg==1 );
db, "page_is_used", 1, SQLITE_UTF8, (void*)p, recoverPageIsUsed, 0, 0
);
}
+ if( rc==SQLITE_OK ){
+ rc = sqlite3_create_function(
+ db, "read_i32", 2, SQLITE_UTF8, (void*)p, recoverReadI32, 0, 0
+ );
+ }
if( rc!=SQLITE_OK ){
if( p->errCode==SQLITE_OK ) rc = recoverDbError(p, db);
}
recoverFinalize(p, pStmt);
+ /* Add all pages that appear to be part of the freelist to the bitmap. */
+ pStmt = recoverPrepare(p, p->dbOut,
+ "WITH trunk(pgno) AS ("
+ " SELECT read_i32(getpage(1), 8) AS x WHERE x>0"
+ " UNION"
+ " SELECT read_i32(getpage(trunk.pgno), 0) AS x FROM trunk WHERE x>0"
+ "),"
+ "trunkdata(pgno, data) AS ("
+ " SELECT pgno, getpage(pgno) FROM trunk"
+ "),"
+ "freelist(data, n, freepgno) AS ("
+ " SELECT data, min(16384, read_i32(data, 1)-1), pgno FROM trunkdata"
+ " UNION ALL"
+ " SELECT data, n-1, read_i32(data, 2+n) FROM freelist WHERE n>=0"
+ ")"
+ "SELECT freepgno FROM freelist"
+ );
+ while( pStmt && SQLITE_ROW==sqlite3_step(pStmt) ){
+ i64 iPg = sqlite3_column_int64(pStmt, 0);
+ recoverBitmapSet(pMap, iPg);
+ }
+ recoverFinalize(p, pStmt);
+
/* Add an entry for each page not already added to the bitmap to
** the recovery.map table. This loop leaves the "parent" column
** of each recovery.map row set to NULL - to be filled in below. */
-C Further\swork\son\smaking\sthe\srecover\sextension\scompatible\swith\sthe\s.recover\scommand.
-D 2022-09-03T20:07:39.011
+C Take\sthe\sfreelist\sinto\saccount\swhen\srecovering\sdata\sthat\sis\snot\slinked\sin\sto\sany\stree\sassociated\swith\sa\sschema\sentry.
+D 2022-09-03T20:31:36.832
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F ext/rbu/test_rbu.c 03f6f177096a5f822d68d8e4069ad8907fe572c62ff2d19b141f59742821828a
F ext/recover/recover1.test a848af8c82fe0731af835ff99475724f8654d2f24f772cc4e6f7ec4eb2ab71ea
F ext/recover/recover_common.tcl 6679af7dffc858e345053a91c9b0a897595b4a13007aceffafca75304ccb137c
-F ext/recover/recoverold.test 33ccbe2393af0e82f292c135b725e3eca1e803960681cf6da41fc00d28bd8683
-F ext/recover/sqlite3recover.c 8d93b9aa056c3fae9a5e2736a4ffa71414bdb502863ef879e55bec7b37030266
+F ext/recover/recoverold.test 7578e9b938db15dc469a4af247e15866226f366bde0cbe09a40b0aef4a0506c8
+F ext/recover/sqlite3recover.c 6c9cbc993a970060f9fb881d78f6c7e182ec988a5e48acbf15bb4a5f05ce2902
F ext/recover/sqlite3recover.h b82974790b528480163d87dcd84afffe7568393194c9ec8241cfbc3ee6bbdd1b
F ext/recover/test_recover.c b8dddd96ccd4a62bc14cb3a8d5696407892e184fe7d45ecbedde954577857de2
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 8df7c7d0dcd1b2fcdad00e765a9868407f0ced02ac4432ee2cdf25d83b130759
-R 93788fe8081a2011cde8fac3142d518f
+P f2ac315844d8db1bd1c6950a4fef7c459ddd37cc21a8f3daafa5639fad8118e2
+R 471b646b541e0fcab850e84cb036ac46
U dan
-Z 21514150d144c868f0bbea27057fe308
+Z 9f579b130a06a2078244b88aebbd5365
# Remove this line to create a well-formed Fossil manifest.