aboutsummaryrefslogtreecommitdiff
path: root/ext/recover/sqlite3recover.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/recover/sqlite3recover.c')
-rw-r--r--ext/recover/sqlite3recover.c46
1 files changed, 31 insertions, 15 deletions
diff --git a/ext/recover/sqlite3recover.c b/ext/recover/sqlite3recover.c
index 58d726f59..b13719083 100644
--- a/ext/recover/sqlite3recover.c
+++ b/ext/recover/sqlite3recover.c
@@ -2574,37 +2574,53 @@ 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");
+ recoverSqlCallback(p, "PRAGMA foreign_keys = off");
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);
-
- recoverUninstallWrapper(p);
- recoverLeaveMutex();
+ /* 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)
+ );
+ }
+ recoverLeaveMutex();
recoverExec(p, p->dbOut, "BEGIN");
-
recoverWriteSchema1(p);
p->eState = RECOVER_STATE_WRITING;
break;
+ }
case RECOVER_STATE_WRITING: {
if( p->w1.pTbls==0 ){