1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-30 19:03:16 +03:00

Update the recovery extension so that it works with encrypted databases.

FossilOrigin-Name: b0b66f21159b47e1950ca63a01f92fe4f621efb9a2962b310d65fa7ebdbb43b3
This commit is contained in:
dan
2025-03-05 17:26:56 +00:00
parent 427e0076a9
commit c27c61586f
3 changed files with 37 additions and 22 deletions

View File

@ -2574,37 +2574,52 @@ static void recoverUninstallWrapper(sqlite3_recover *p){
static void recoverStep(sqlite3_recover *p){
assert( p && p->errCode==SQLITE_OK );
switch( p->eState ){
case RECOVER_STATE_INIT:
case RECOVER_STATE_INIT: {
int bUseWrapper = 1;
/* This is the very first call to sqlite3_recover_step() on this object.
*/
recoverSqlCallback(p, "BEGIN");
recoverSqlCallback(p, "PRAGMA writable_schema = on");
recoverEnterMutex();
recoverInstallWrapper(p);
/* 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. */
sqlite3_file_control(p->dbIn, p->zDb, SQLITE_FCNTL_RESET_CACHE, 0);
recoverExec(p, p->dbIn, "PRAGMA writable_schema = on");
recoverExec(p, p->dbIn, "BEGIN");
if( p->errCode==SQLITE_OK ) p->bCloseTransaction = 1;
recoverExec(p, p->dbIn, "SELECT 1 FROM sqlite_schema");
recoverTransferSettings(p);
recoverOpenRecovery(p);
recoverCacheSchema(p);
/* Attempt to open a transaction and read page 1 of the input database.
** Two attempts may be made - one with a wrapper installed to ensure
** that the database header is sane, and then if that attempt returns
** SQLITE_NOTADB, then again with no wrapper. The second attempt is
** required for encrypted databases. */
if( p->errCode==SQLITE_OK ){
do{
p->errCode = SQLITE_OK;
if( bUseWrapper ) recoverInstallWrapper(p);
/* Open a transaction on the input database. */
sqlite3_file_control(p->dbIn, p->zDb, SQLITE_FCNTL_RESET_CACHE, 0);
recoverExec(p, p->dbIn, "PRAGMA writable_schema = on");
recoverExec(p, p->dbIn, "BEGIN");
if( p->errCode==SQLITE_OK ) p->bCloseTransaction = 1;
recoverExec(p, p->dbIn, "SELECT 1 FROM sqlite_schema");
recoverTransferSettings(p);
recoverOpenRecovery(p);
recoverCacheSchema(p);
if( bUseWrapper ) recoverUninstallWrapper(p);
}while( p->errCode==SQLITE_NOTADB
&& (bUseWrapper--)
&& SQLITE_OK==sqlite3_exec(p->dbIn, "ROLLBACK", 0, 0, 0)
);
}
recoverUninstallWrapper(p);
recoverLeaveMutex();
recoverExec(p, p->dbOut, "BEGIN");
recoverWriteSchema1(p);
p->eState = RECOVER_STATE_WRITING;
break;
}
case RECOVER_STATE_WRITING: {
if( p->w1.pTbls==0 ){