** This function is called to recover data from the database. A script ** to construct a new database containing all recovered data is output ** on stream pState->out. */
| 17219 | ** on stream pState->out. |
| 17220 | */ |
| 17221 | static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){ |
| 17222 | int rc = SQLITE_OK; |
| 17223 | sqlite3_stmt *pLoop = 0; /* Loop through all root pages */ |
| 17224 | sqlite3_stmt *pPages = 0; /* Loop through all pages in a group */ |
| 17225 | sqlite3_stmt *pCells = 0; /* Loop through all cells in a page */ |
| 17226 | const char *zRecoveryDb = ""; /* Name of "recovery" database */ |
| 17227 | const char *zLostAndFound = "lost_and_found"; |
| 17228 | int i; |
| 17229 | int nOrphan = -1; |
| 17230 | RecoverTable *pOrphan = 0; |
| 17231 | |
| 17232 | int bFreelist = 1; /* 0 if --freelist-corrupt is specified */ |
| 17233 | int bRowids = 1; /* 0 if --no-rowids */ |
| 17234 | for(i=1; i<nArg; i++){ |
| 17235 | char *z = azArg[i]; |
| 17236 | int n; |
| 17237 | if( z[0]=='-' && z[1]=='-' ) z++; |
| 17238 | n = strlen30(z); |
| 17239 | if( n<=17 && memcmp("-freelist-corrupt", z, n)==0 ){ |
| 17240 | bFreelist = 0; |
| 17241 | }else |
| 17242 | if( n<=12 && memcmp("-recovery-db", z, n)==0 && i<(nArg-1) ){ |
| 17243 | i++; |
| 17244 | zRecoveryDb = azArg[i]; |
| 17245 | }else |
| 17246 | if( n<=15 && memcmp("-lost-and-found", z, n)==0 && i<(nArg-1) ){ |
| 17247 | i++; |
| 17248 | zLostAndFound = azArg[i]; |
| 17249 | }else |
| 17250 | if( n<=10 && memcmp("-no-rowids", z, n)==0 ){ |
| 17251 | bRowids = 0; |
| 17252 | } |
| 17253 | else{ |
| 17254 | utf8_printf(stderr, "unexpected option: %s\n", azArg[i]); |
| 17255 | showHelp(pState->out, azArg[0]); |
| 17256 | return 1; |
| 17257 | } |
| 17258 | } |
| 17259 | |
| 17260 | shellExecPrintf(pState->db, &rc, |
| 17261 | /* Attach an in-memory database named 'recovery'. Create an indexed |
| 17262 | ** cache of the sqlite_dbptr virtual table. */ |
| 17263 | "PRAGMA writable_schema = on;" |
| 17264 | "ATTACH %Q AS recovery;" |
| 17265 | "DROP TABLE IF EXISTS recovery.dbptr;" |
| 17266 | "DROP TABLE IF EXISTS recovery.freelist;" |
| 17267 | "DROP TABLE IF EXISTS recovery.map;" |
| 17268 | "DROP TABLE IF EXISTS recovery.schema;" |
| 17269 | "CREATE TABLE recovery.freelist(pgno INTEGER PRIMARY KEY);", zRecoveryDb |
| 17270 | ); |
| 17271 | |
| 17272 | if( bFreelist ){ |
| 17273 | shellExec(pState->db, &rc, |
| 17274 | "WITH trunk(pgno) AS (" |
| 17275 | " SELECT shell_int32(" |
| 17276 | " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 8) AS x " |
| 17277 | " WHERE x>0" |
| 17278 | " UNION" |
no test coverage detected