u32 aElem[1]; /* Array of 32-bit bitmasks */
};
+/*
+** State variables (part of the sqlite3_recover structure) used while
+** recovering data for tables identified in the recovered schema (state
+** RECOVER_STATE_WRITING).
+*/
typedef struct RecoverStateW1 RecoverStateW1;
struct RecoverStateW1 {
sqlite3_stmt *pTbls;
int iPrevCell;
};
+/*
+** State variables (part of the sqlite3_recover structure) used while
+** recovering data destined for the lost and found table (states
+** RECOVER_STATE_LOSTANDFOUND[123]).
+*/
typedef struct RecoverStateLAF RecoverStateLAF;
struct RecoverStateLAF {
RecoverBitmap *pUsed;
/* Variables used with eState==RECOVER_STATE_WRITING */
RecoverStateW1 w1;
- /* Variables used with states RECOVER_STATE_LOSTANDFOUND* */
+ /* Variables used with states RECOVER_STATE_LOSTANDFOUND[123] */
RecoverStateLAF laf;
/* Fields used within sqlite3_recover_run() */
#define RECOVER_MUTEX_ID SQLITE_MUTEX_STATIC_APP2
-
/*
** Default value for SQLITE_RECOVER_ROWIDS (sqlite3_recover.bRecoverRowid).
*/
return p->errCode;
}
+/*
+** Attach the auxiliary database 'recovery' to the output database handle.
+** This temporary database is used during the recovery process and then
+** discarded.
+*/
static void recoverOpenRecovery(sqlite3_recover *p){
char *zSql = recoverMPrintf(p, "ATTACH %Q AS recovery;", p->zStateDb);
recoverExec(p, p->dbOut, zSql);
return pRet;
}
+/*
+** Input database page iPg contains data that will be written to the
+** lost-and-found table of the output database. This function attempts
+** to identify the root page of the tree that page iPg belonged to.
+** If successful, it sets output variable (*piRoot) to the page number
+** of the root page and returns SQLITE_OK. Otherwise, if an error occurs,
+** an SQLite error code is returned and the final value of *piRoot
+** undefined.
+*/
static int recoverLostAndFoundFindRoot(
sqlite3_recover *p,
i64 iPg,
return p->errCode;
}
+/*
+** Recover data from page iPage of the input database and write it to
+** the lost-and-found table in the output database.
+*/
static void recoverLostAndFoundOnePage(sqlite3_recover *p, i64 iPage){
RecoverStateLAF *pLaf = &p->laf;
sqlite3_value **apVal = pLaf->apVal;
}
}
+/*
+** Perform one step (sqlite3_recover_step()) of work for the connection
+** passed as the only argument, which is guaranteed to be in
+** RECOVER_STATE_LOSTANDFOUND3 state - during which the lost-and-found
+** table of the output database is populated with recovered data that can
+** not be assigned to any recovered schema object.
+*/
static int recoverLostAndFound3Step(sqlite3_recover *p){
RecoverStateLAF *pLaf = &p->laf;
if( p->errCode==SQLITE_OK ){
return SQLITE_OK;
}
+/*
+** Initialize resources required in RECOVER_STATE_LOSTANDFOUND3
+** state - during which the lost-and-found table of the output database
+** is populated with recovered data that can not be assigned to any
+** recovered schema object.
+*/
static void recoverLostAndFound3Init(sqlite3_recover *p){
RecoverStateLAF *pLaf = &p->laf;
}
}
+/*
+** Initialize resources required in RECOVER_STATE_WRITING state - during which
+** tables recovered from the schema of the input database are populated with
+** recovered data.
+*/
static int recoverWriteDataInit(sqlite3_recover *p){
RecoverStateW1 *p1 = &p->w1;
RecoverTable *pTbl = 0;
memset(p1, 0, sizeof(*p1));
}
+/*
+** Perform one step (sqlite3_recover_step()) of work for the connection
+** passed as the only argument, which is guaranteed to be in
+** RECOVER_STATE_WRITING state - during which tables recovered from the
+** schema of the input database are populated with recovered data.
+*/
static int recoverWriteDataStep(sqlite3_recover *p){
RecoverStateW1 *p1 = &p->w1;
sqlite3_stmt *pSel = p1->pSel;
return p->errCode;
}
+/*
+** Initialize resources required by sqlite3_recover_step() in
+** RECOVER_STATE_LOSTANDFOUND1 state - during which the set of pages not
+** already allocated to a recovered schema element is determined.
+*/
static void recoverLostAndFound1Init(sqlite3_recover *p){
RecoverStateLAF *pLaf = &p->laf;
sqlite3_stmt *pStmt = 0;
pLaf->pUsedPages = pStmt;
}
+/*
+** Perform one step (sqlite3_recover_step()) of work for the connection
+** passed as the only argument, which is guaranteed to be in
+** RECOVER_STATE_LOSTANDFOUND1 state - during which the set of pages not
+** already allocated to a recovered schema element is determined.
+*/
static int recoverLostAndFound1Step(sqlite3_recover *p){
RecoverStateLAF *pLaf = &p->laf;
int rc = p->errCode;
return rc;
}
+/*
+** Initialize resources required by RECOVER_STATE_LOSTANDFOUND2
+** state - during which the pages identified in RECOVER_STATE_LOSTANDFOUND1
+** are sorted into sets that likely belonged to the same database tree.
+*/
static void recoverLostAndFound2Init(sqlite3_recover *p){
RecoverStateLAF *pLaf = &p->laf;
);
}
+/*
+** Perform one step (sqlite3_recover_step()) of work for the connection
+** passed as the only argument, which is guaranteed to be in
+** RECOVER_STATE_LOSTANDFOUND2 state - during which the pages identified
+** in RECOVER_STATE_LOSTANDFOUND1 are sorted into sets that likely belonged
+** to the same database tree.
+*/
static int recoverLostAndFound2Step(sqlite3_recover *p){
RecoverStateLAF *pLaf = &p->laf;
if( p->errCode==SQLITE_OK ){
return p->errCode;
}
+/*
+** Free all resources allocated as part of sqlite3_recover_step() calls
+** in one of the RECOVER_STATE_LOSTANDFOUND[123] states.
+*/
static void recoverLostAndFoundCleanup(sqlite3_recover *p){
recoverBitmapFree(p->laf.pUsed);
p->laf.pUsed = 0;
p->laf.apVal = 0;
}
+/*
+** Free all resources allocated as part of sqlite3_recover_step() calls.
+*/
static void recoverFinalCleanup(sqlite3_recover *p){
RecoverTable *pTab = 0;
RecoverTable *pNext = 0;
p->dbOut = 0;
}
+/*
+** Decode and return an unsigned 16-bit big-endian integer value from
+** buffer a[].
+*/
static u32 recoverGetU16(const u8 *a){
return (((u32)a[0])<<8) + ((u32)a[1]);
}
+
+/*
+** Decode and return an unsigned 32-bit big-endian integer value from
+** buffer a[].
+*/
static u32 recoverGetU32(const u8 *a){
return (((u32)a[0])<<24) + (((u32)a[1])<<16) + (((u32)a[2])<<8) + ((u32)a[3]);
}
+
+/*
+** Decode an SQLite varint from buffer a[]. Write the decoded value to (*pVal)
+** and return the number of bytes consumed.
+*/
static int recoverGetVarint(const u8 *a, i64 *pVal){
sqlite3_int64 v = 0;
int i;
return pFd->pMethods->xClose(pFd);
}
+/*
+** Write value v to buffer a[] as a 16-bit big-endian unsigned integer.
+*/
static void recoverPutU16(u8 *a, u32 v){
a[0] = (v>>8) & 0x00FF;
a[1] = (v>>0) & 0x00FF;
}
+
+/*
+** Write value v to buffer a[] as a 32-bit big-endian unsigned integer.
+*/
static void recoverPutU32(u8 *a, u32 v){
a[0] = (v>>24) & 0x00FF;
a[1] = (v>>16) & 0x00FF;
a[3] = (v>>0) & 0x00FF;
}
+/*
+** Detect the page-size of the database opened by file-handle pFd by
+** searching the first part of the file for a well-formed SQLite b-tree
+** page. If parameter nReserve is non-zero, then as well as searching for
+** a b-tree page with zero reserved bytes, this function searches for one
+** with nReserve reserved bytes at the end of it.
+**
+** If successful, set variable p->detected_pgsz to the detected page-size
+** in bytes and return SQLITE_OK. Or, if no error occurs but no valid page
+** can be found, return SQLITE_OK but leave p->detected_pgsz set to 0. Or,
+** if an error occurs (e.g. an IO or OOM error), then an SQLite error code
+** is returned. The final value of p->detected_pgsz is undefined in this
+** case.
+*/
static int recoverVfsDetectPagesize(
- sqlite3_recover *p,
- sqlite3_file *pFd,
+ sqlite3_recover *p, /* Recover handle */
+ sqlite3_file *pFd, /* File-handle open on input database */
u32 nReserve, /* Possible nReserve value */
- i64 nSz
+ i64 nSz /* Size of database file in bytes */
){
int rc = SQLITE_OK;
const int nMin = 512;
return rc;
}
+/*
+** The xRead() method of the wrapper VFS. This is used to intercept calls
+** to read page 1 of the input database.
+*/
static int recoverVfsRead(sqlite3_file *pFd, void *aBuf, int nByte, i64 iOff){
int rc = SQLITE_OK;
if( pFd->pMethods==&recover_methods ){
return rc;
}
+/*
+** Used to make sqlite3_io_methods wrapper methods less verbose.
+*/
#define RECOVER_VFS_WRAPPER(code) \
int rc = SQLITE_OK; \
if( pFd->pMethods==&recover_methods ){ \
} \
return rc;
+/*
+** Methods of the wrapper VFS. All methods except for xRead() and xClose()
+** simply uninstall the sqlite3_io_methods wrapper, invoke the equivalent
+** method on the lower level VFS, then reinstall the wrapper before returning.
+** Those that return an integer value use the RECOVER_VFS_WRAPPER macro.
+*/
static int recoverVfsWrite(
sqlite3_file *pFd, const void *aBuf, int nByte, i64 iOff
){
pFd->pMethods->xTruncate(pFd, size)
);
}
-
static int recoverVfsSync(sqlite3_file *pFd, int flags){
RECOVER_VFS_WRAPPER (
pFd->pMethods->xSync(pFd, flags)
);
}
+/*
+** Install the VFS wrapper around the file-descriptor open on the input
+** database for recover handle p. Mutex RECOVER_MUTEX_ID must be held
+** when this function is called.
+*/
static void recoverInstallWrapper(sqlite3_recover *p){
sqlite3_file *pFd = 0;
assert( recover_g.pMethods==0 );
+ assert( sqlite3_mutex_held( sqlite3_mutex_alloc(RECOVER_MUTEX_ID) ) );
sqlite3_file_control(p->dbIn, p->zDb, SQLITE_FCNTL_FILE_POINTER, (void*)&pFd);
if( pFd ){
recover_g.pMethods = pFd->pMethods;
pFd->pMethods = &recover_methods;
}
}
+
+/*
+** Uninstall the VFS wrapper that was installed around the file-descriptor open
+** on the input database for recover handle p. Mutex RECOVER_MUTEX_ID must be
+** held when this function is called.
+*/
static void recoverUninstallWrapper(sqlite3_recover *p){
+ assert( sqlite3_mutex_held( sqlite3_mutex_alloc(RECOVER_MUTEX_ID) ) );
if( recover_g.pMethods ){
sqlite3_file *pFd = 0;
sqlite3_file_control(p->dbIn, p->zDb,SQLITE_FCNTL_FILE_POINTER,(void*)&pFd);
}
}
+/*
+** This function does the work of a single sqlite3_recover_step() call. It
+** is guaranteed that the handle is not in an error state when this
+** function is called.
+*/
static void recoverStep(sqlite3_recover *p){
assert( p && p->errCode==SQLITE_OK );
switch( p->eState ){
recoverSqlCallback(p, "BEGIN");
recoverSqlCallback(p, "PRAGMA writable_schema = on");
- sqlite3_mutex_enter( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_APP2) );
+ sqlite3_mutex_enter( sqlite3_mutex_alloc(RECOVER_MUTEX_ID) );
recoverInstallWrapper(p);
/* Open the output database. And register required virtual tables and
recoverCacheSchema(p);
recoverUninstallWrapper(p);
- sqlite3_mutex_leave( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_APP2) );
+ sqlite3_mutex_leave( sqlite3_mutex_alloc(RECOVER_MUTEX_ID) );
recoverExec(p, p->dbOut, "BEGIN");
-C Merge\slatest\strunk\schanges.
-D 2022-10-15T15:39:46.578
+C Add\smissing\scomments\sand\sfix\sother\scode\sissues.
+D 2022-10-15T18:26:30.696
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F ext/recover/recoverrowid.test 1694a1a5526d825f71279f3d02ab02a1ee4c5265de18858bf54cb8ec54487ac8
F ext/recover/recoverslowidx.test f356bb9fba7ffd6fc50e045e419464f0129ac6e24decf6e919584f79c3493727
F ext/recover/recoversql.test f9872ff2114e13ffd8ee31e1de06919f62b9b48bc080191b5bd076d10becb60f
-F ext/recover/sqlite3recover.c 3ab2017a947fa8c9286aa6257d0b19443ec04e557af9d989227b89f36ff50dd6
+F ext/recover/sqlite3recover.c db8f2166dbbdfc09a58a85f51f8e848858858ca8b4915a2f9c8cd5fd5ca536a8
F ext/recover/sqlite3recover.h f698ccc94bd4da38761035415ad08c4549a408491ff9fd5f52d34d2214f64e36
F ext/recover/test_recover.c 61ec931e47abca6b2210f46239cafd9f3060741605e3d3c45a7c7a53f63dd957
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
-F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c w ext/wasm/EXPORTED_FUNCTIONS.fiddle
+F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
F ext/wasm/EXPORTED_RUNTIME_METHODS.fiddle 0e88c8cfc3719e4b7e74980d9da664c709e68acf863e48386cda376edfd3bfb0
F ext/wasm/GNUmakefile 4ec270532b921c7c4b437fbdb06f6a0ce41f3bd874395ce70dbc933c8553efa9
F ext/wasm/README.md 1e5b28158b74ab3ffc9d54fcbc020f0bbeb82c2ff8bbd904214c86c70e8a3066
F ext/wasm/api/sqlite3-api-oo1.js 00f5cfce0989d2e08d7b21765d703c69234245d03a0cce8fcb32ccfcd53ffdbb
F ext/wasm/api/sqlite3-api-opfs.js 5a8ab3b76880c8ada8710ca9ba1ca5b160872edfd8bd5322e4f179a7f41cc616
F ext/wasm/api/sqlite3-api-prologue.js b7c82a22d50658a48463fa646a23135273bc2cfa843aedda32627ff281c12e4d
-F ext/wasm/api/sqlite3-api-worker1.js 7f4f46cb6b512a48572d7567233896e6a9c46570c44bdc3d13419730c7c221c8 w ext/wasm/api/sqlite3-api-worker.js
+F ext/wasm/api/sqlite3-api-worker1.js 7f4f46cb6b512a48572d7567233896e6a9c46570c44bdc3d13419730c7c221c8
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
F ext/wasm/api/sqlite3-wasm.c 4c131945ced4b08a694d287abcdb066b896d961ef79ee5241805ecc37e83d63a
F ext/wasm/batch-runner.html cf1a410c92bad50fcec2ddc71390b4e9df63a6ea1bef12a5163a66a0af4d78d9
F ext/wasm/sql/001-sudoku.sql 35b7cb7239ba5d5f193bc05ec379bcf66891bce6f2a5b3879f2f78d0917299b5
F ext/wasm/sqlite3-opfs-async-proxy.js 206ce6bbc3c30ad51a37d9c25e3a2712e70b586e0f9a2cf8cb0b9619017c2671
F ext/wasm/sqlite3-worker1-promiser.js 307d7837420ca6a9d3780dfc81194f1c0715637e6d9540e935514086b96913d8
-F ext/wasm/sqlite3-worker1.js 466e9bd39409ab03f3e00999887aaffc11e95b416e2689596e3d7f1516673fdf w ext/wasm/api/sqlite3-worker.js
+F ext/wasm/sqlite3-worker1.js 466e9bd39409ab03f3e00999887aaffc11e95b416e2689596e3d7f1516673fdf
F ext/wasm/test-opfs-vfs.html eb69dda21eb414b8f5e3f7c1cc0f774103cc9c0f87b2d28a33419e778abfbab5
F ext/wasm/test-opfs-vfs.js 56c3d725044c668fa7910451e96c1195d25ad95825f9ac79f747a7759d1973d0
F ext/wasm/tester1-worker.html 0af7a22025ff1da72a84765d64f8f221844a57c6e6e314acf3a30f176101fd3f
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 52d0235ef3f21683daadf2343514f7b95a67c3589266f75c1e00e04f11dc6214 ed14863dd72e35fa3a23320c3d5a8166515faea39a555c28a27b2d35e701eac4
-R 67f4b2d0a660b4df4f4f8911e9f69960
+P 42255ead8e44b24a8abc04aca49f170c55f3b52f42366a0d8ef248ee65fcc7ce
+R ba398a54428773327d217095fdca83a1
U dan
-Z 2f155b3b54b3254ee16d85f44719ac5e
+Z 9c11c46950d6b0a76e0307ada9a3c264
# Remove this line to create a well-formed Fossil manifest.