return p->errCode;
}
-/*
-** For each table in the recovered schema, this function extracts as much
-** data as possible from the output database and writes it to the input
-** database. Or, if the recover handle is in SQL callback mode, issues
-** equivalent callbacks.
-**
-** It does not recover "orphaned" data into the lost-and-found table.
-** See recoverLostAndFound() for that.
-*/
-static int recoverWriteData(sqlite3_recover *p){
- recoverWriteDataInit(p);
- while( p->errCode==SQLITE_OK && SQLITE_OK==recoverWriteDataStep(p) );
- recoverWriteDataCleanup(p);
- return p->errCode;
-}
-
-/*
-** This function does the work of sqlite3_recover_run(). It is assumed that
-** no error has occurred when this is called. If an error occurs during
-** the recovery operation, an error code and error message are left in
-** the recovery handle.
-*/
-static void recoverRun(sqlite3_recover *p){
- RecoverTable *pTab = 0;
- RecoverTable *pNext = 0;
- int rc = SQLITE_OK;
-
- assert( p->errCode==SQLITE_OK );
- p->eState = 1;
-
- recoverSqlCallback(p, "BEGIN");
- recoverSqlCallback(p, "PRAGMA writable_schema = on");
-
- /* Open the output database. And register required virtual tables and
- ** user functions with the new handle. */
- recoverOpenOutput(p);
-
- /* Open transactions on both the input and output databases. */
- recoverExec(p, p->dbIn, "BEGIN");
- recoverExec(p, p->dbOut, "BEGIN");
-
- recoverCacheSchema(p);
- recoverWriteSchema1(p);
- recoverWriteData(p);
- if( p->zLostAndFound ) recoverLostAndFound(p);
- recoverWriteSchema2(p);
-
- /* If no error has occurred, commit the write transaction on the output
- ** database. Then end the read transaction on the input database, regardless
- ** of whether or not prior errors have occurred. */
- recoverExec(p, p->dbOut, "COMMIT");
- rc = sqlite3_exec(p->dbIn, "END", 0, 0, 0);
- if( p->errCode==SQLITE_OK ) p->errCode = rc;
-
- recoverSqlCallback(p, "PRAGMA writable_schema = off");
- recoverSqlCallback(p, "COMMIT");
-
- /* Clean up various resources allocated by this function. */
- for(pTab=p->pTblList; pTab; pTab=pNext){
- pNext = pTab->pNext;
- sqlite3_free(pTab);
- }
- p->pTblList = 0;
- sqlite3_finalize(p->pGetPage);
- p->pGetPage = 0;
- recoverBitmapFree(p->pUsed);
- p->pUsed = 0;
- sqlite3_close(p->dbOut);
-}
-
static void recoverFinalCleanup(sqlite3_recover *p){
RecoverTable *pTab = 0;
RecoverTable *pNext = 0;
*/
int sqlite3_recover_config(sqlite3_recover *p, int op, void *pArg){
int rc = SQLITE_OK;
-
- if( p==0 ) return SQLITE_NOMEM;
- switch( op ){
- case 789:
- sqlite3_free(p->zStateDb);
- p->zStateDb = recoverMPrintf(p, "%s", (char*)pArg);
- break;
-
- case SQLITE_RECOVER_LOST_AND_FOUND: {
- const char *zArg = (const char*)pArg;
- sqlite3_free(p->zLostAndFound);
- if( zArg ){
- p->zLostAndFound = recoverMPrintf(p, "%s", zArg);
- }else{
- p->zLostAndFound = 0;
+ if( p==0 ){
+ rc = SQLITE_NOMEM;
+ }else if( p->eState!=RECOVER_STATE_INIT ){
+ rc = SQLITE_MISUSE;
+ }else{
+ switch( op ){
+ case 789:
+ sqlite3_free(p->zStateDb);
+ p->zStateDb = recoverMPrintf(p, "%s", (char*)pArg);
+ break;
+
+ case SQLITE_RECOVER_LOST_AND_FOUND: {
+ const char *zArg = (const char*)pArg;
+ sqlite3_free(p->zLostAndFound);
+ if( zArg ){
+ p->zLostAndFound = recoverMPrintf(p, "%s", zArg);
+ }else{
+ p->zLostAndFound = 0;
+ }
+ break;
}
- break;
- }
- case SQLITE_RECOVER_FREELIST_CORRUPT:
- p->bFreelistCorrupt = *(int*)pArg;
- break;
+ case SQLITE_RECOVER_FREELIST_CORRUPT:
+ p->bFreelistCorrupt = *(int*)pArg;
+ break;
- case SQLITE_RECOVER_ROWIDS:
- p->bRecoverRowid = *(int*)pArg;
- break;
+ case SQLITE_RECOVER_ROWIDS:
+ p->bRecoverRowid = *(int*)pArg;
+ break;
- default:
- rc = SQLITE_NOTFOUND;
- break;
+ default:
+ rc = SQLITE_NOTFOUND;
+ break;
+ }
}
return rc;
}
+/*
+** Do a unit of work towards the recovery job. Return SQLITE_OK if
+** no error has occurred but database recovery is not finished, SQLITE_DONE
+** if database recovery has been successfully completed, or an SQLite
+** error code if an error has occurred.
+*/
int sqlite3_recover_step(sqlite3_recover *p){
if( p==0 ) return SQLITE_NOMEM;
if( p->errCode==SQLITE_OK ) recoverStep(p);
** Do the configured recovery operation. Return SQLITE_OK if successful, or
** else an SQLite error code.
*/
-#if 0
-int sqlite3_recover_run(sqlite3_recover *p){
- if( p ){
- recoverExec(p, p->dbIn, "PRAGMA writable_schema=1");
- if( p->eState ) return SQLITE_MISUSE; /* Has already run */
- if( p->errCode==SQLITE_OK ) recoverRun(p);
- if( sqlite3_exec(p->dbIn, "PRAGMA writable_schema=0", 0, 0, 0) ){
- recoverDbError(p, p->dbIn);
- }
- }
- return p ? p->errCode : SQLITE_NOMEM;
-}
-#else
int sqlite3_recover_run(sqlite3_recover *p){
- if( p==0 ) return SQLITE_NOMEM;
while( SQLITE_OK==sqlite3_recover_step(p) );
- return p->errCode;
+ return sqlite3_recover_errcode(p);
}
-#endif
/*
** To use the API to recover data from a corrupted database, an
** application:
**
-** 1) Creates an sqlite3_recover handle by calling either
-** sqlite3_recover_init() or sqlite3_recover_init_sql().
-**
-** 2) Configures the new handle using one or more calls to
-** sqlite3_recover_config().
-**
-** 3) Executes the recovery by calling sqlite3_recover_run() on the handle.
-**
-** 4) Retrieves any error code and English language error message using the
-** sqlite3_recover_errcode() and sqlite3_recover_errmsg() APIs,
-** respectively.
-**
-** 5) Destroys the sqlite3_recover handle and frees all resources
-** using sqlite3_recover_finish().
+** 1) Creates an sqlite3_recover handle by calling either
+** sqlite3_recover_init() or sqlite3_recover_init_sql().
+**
+** 2) Configures the new handle using one or more calls to
+** sqlite3_recover_config().
+**
+** 3) Executes the recovery by repeatedly calling sqlite3_recover_step() on
+** the handle until it returns something other than SQLITE_OK. If it
+** returns SQLITE_DONE, then the recovery operation completed without
+** error. If it returns some other non-SQLITE_OK value, then an error
+** has occurred.
+**
+** 4) Retrieves any error code and English language error message using the
+** sqlite3_recover_errcode() and sqlite3_recover_errmsg() APIs,
+** respectively.
+**
+** 5) Destroys the sqlite3_recover handle and frees all resources
+** using sqlite3_recover_finish().
+**
+** The application may abandon the recovery operation at any point
+** before it is finished by passing the sqlite3_recover handle to
+** sqlite3_recover_finish(). This is not an error, but the final state
+** of the output database, or the results of running the partial script
+** delivered to the SQL callback, are undefined.
*/
#ifndef _SQLITE_RECOVER_H
/*
** Configure an sqlite3_recover object that has just been created using
-** sqlite3_recover_init() or sqlite3_recover_init_sql(). The second
-** argument passed to this function must be one of the SQLITE_RECOVER_*
-** symbols defined below. Valid values for the third argument depend
-** on the specific SQLITE_RECOVER_* symbol in use.
+** sqlite3_recover_init() or sqlite3_recover_init_sql(). This function
+** may only be called before the first call to sqlite3_recover_step()
+** or sqlite3_recover_run() on the object.
+**
+** The second argument passed to this function must be one of the
+** SQLITE_RECOVER_* symbols defined below. Valid values for the third argument
+** depend on the specific SQLITE_RECOVER_* symbol in use.
**
** SQLITE_OK is returned if the configuration operation was successful,
** or an SQLite error code otherwise.
#define SQLITE_RECOVER_FREELIST_CORRUPT 2
#define SQLITE_RECOVER_ROWIDS 3
-/*
-** Run the recovery operation. This function does not return until the
-** recovery operation is completed - either the new database has been
-** created and populated (sqlite3_recover_init()) or all SQL statements have
-** been passed to the callback (sqlite3_recover_init_sql()) - or an error
-** occurs. If the recovery is completed without error, SQLITE_OK
-** is returned. It is not considered an error if data cannot be recovered
+/*
+** Perform a unit of work towards the recovery operation. This function
+** must normally be called multiple times to complete database recovery.
+**
+** If no error occurs but the recovery operation is not completed, this
+** function returns SQLITE_OK. If recovery has been completed successfully
+** then SQLITE_DONE is returned. If an error has occurred, then an SQLite
+** error code (e.g. SQLITE_IOERR or SQLITE_NOMEM) is returned. It is not
+** considered an error if some or all of the data cannot be recovered
** due to database corruption.
**
-** If an error (for example an out-of-memory or IO error) occurs, then
-** an SQLite error code is returned. The final state of the output database
-** or the results of running any SQL statements already passed to the
-** callback in this case are undefined. An English language error
-** message corresponding to the error may be available via the
-** sqlite3_recover_errmsg() API.
-**
-** This function may only be called once on an sqlite3_recover handle.
-** If it is called more than once, the second and subsequent calls
-** return SQLITE_MISUSE. The error code and error message returned
-** by sqlite3_recover_errcode() and sqlite3_recover_errmsg() are not
-** updated in this case.
+** Once sqlite3_recover_step() has returned a value other than SQLITE_OK,
+** all further such calls on the same recover handle are no-ops that return
+** the same non-SQLITE_OK value.
+*/
+int sqlite3_recover_step(sqlite3_recover*);
+
+/*
+** Run the recovery operation to completion. Return SQLITE_OK if successful,
+** or an SQLite error code otherwise. Calling this function is the same
+** as executing:
+**
+** while( SQLITE_OK==sqlite3_recover_step(p) );
+** return sqlite3_recover_errcode(p);
*/
int sqlite3_recover_run(sqlite3_recover*);
/*
-** If this is called on an sqlite3_recover handle before
-** sqlite3_recover_run() has been called, or if the call to
-** sqlite3_recover_run() returned SQLITE_OK, then this API always returns
-** a NULL pointer.
-**
-** Otherwise, an attempt is made to return a pointer to a buffer containing
-** an English language error message related to the error that occurred
-** within the sqlite3_recover_run() call. If no error message is available,
-** or if an out-of-memory error occurs while attempting to allocate a buffer
-** for one, NULL may still be returned.
-**
-** The buffer remains valid until the sqlite3_recover handle is destroyed
-** using sqlite3_recover_finish().
+** If an error has been encountered during a prior call to
+** sqlite3_recover_step(), then this function attempts to return a
+** pointer to a buffer containing an English language explanation of
+** the error. If no error message is available, or if an out-of memory
+** error occurs while attempting to allocate a buffer in which to format
+** the error message, NULL is returned.
+**
+** The returned buffer remains valid until the sqlite3_recover handle is
+** destroyed using sqlite3_recover_finish().
*/
const char *sqlite3_recover_errmsg(sqlite3_recover*);
/*
-** If this function is called on an sqlite3_recover handle before
-** sqlite3_recover_run() has been called, it always returns SQLITE_OK.
-** Otherwise, it returns a copy of the value returned by the first
-** sqlite3_recover_run() call made on the handle.
+** If this function is called on an sqlite3_recover handle after
+** an error occurs, an SQLite error code is returned. Otherwise, SQLITE_OK.
*/
int sqlite3_recover_errcode(sqlite3_recover*);
** The results of using a recovery object with any API after it has been
** passed to this function are undefined.
**
-** If this function is called on an sqlite3_recover handle before
-** sqlite3_recover_run() has been called, it always returns SQLITE_OK.
-** Otherwise, it returns a copy of the value returned by the first
-** sqlite3_recover_run() call made on the handle.
+** This function returns the same value as sqlite3_recover_errcode().
*/
int sqlite3_recover_finish(sqlite3_recover*);
-C Update\sthings\sto\suse\ssqlite3_recover_step()\sinternally.
-D 2022-09-24T18:05:52.914
+C Add\ssqlite3_recover_step()\sto\sheader\sfile\ssqlite3recover.h.\sUpdate\sthe\sAPI\sdocs\sin\sthis\sfile.
+D 2022-09-24T19:17:20.785
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F ext/recover/recoverold.test 46e9d99b595fac583d4c67f74d7d89c20a435c752ef6eeb3e918b599940c88e0
F ext/recover/recoverrowid.test 1694a1a5526d825f71279f3d02ab02a1ee4c5265de18858bf54cb8ec54487ac8
F ext/recover/recoversql.test f9872ff2114e13ffd8ee31e1de06919f62b9b48bc080191b5bd076d10becb60f
-F ext/recover/sqlite3recover.c efed077977b195d2ac6c12f1485abf9c7e8c8d282834b05beee7151dabf21e88
-F ext/recover/sqlite3recover.h 81108efb8c4618d3d9c6da4df785212b0e4501aa0d25edfc463405fe839a6640
+F ext/recover/sqlite3recover.c 7752d374356a2346b5959161d5512d6f8a0bd7fb259ea81fd2473ad00dd39132
+F ext/recover/sqlite3recover.h 09a0f70b821954fc219d7583d74871e8578e4f1e9267304ec029c2bfc02bd27a
F ext/recover/test_recover.c 72a765616a3fa9dae2ed537d79b00f365d9f639d347858341b71bda7a3a45f56
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
F ext/repair/checkfreelist.c e21f06995ff4efdc1622dcceaea4dcba2caa83ca2f31a1607b98a8509168a996
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 73926d5c8cd1ecece134b5a73b44ee1dfca74dc200606e3f009b06cdecf8cee9
-R 0646ea13d6a7cac9dceb7b54cdbc6bf0
+P f4b15aad3005237b7ac507eed2b9b07e0f5c9407ab28f2656a21c9845f13d35f
+R b60fe138c3457719a54bec9e37633f69
U dan
-Z 958e4f167968f03754a4ebdb81e44d68
+Z c514b2b66b0aba624f215b19ab2fba51
# Remove this line to create a well-formed Fossil manifest.
-f4b15aad3005237b7ac507eed2b9b07e0f5c9407ab28f2656a21c9845f13d35f
\ No newline at end of file
+47f416153035d6bf0ae27587583d2957c87c02caecbd4e7f363bcb2bc27cf159
\ No newline at end of file