From a3125b1a4e1bf064bb73fe9fe54323b766297e75 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 9 Mar 2017 16:32:39 +0000 Subject: [PATCH] Add the --recovery-mode option to the CLI ".dump" command. This involves enhancing the "PRAGMA reverse_unordered_selects" command to accept a "TOGGLE" option. Recovery mode used to be always on. Now it is opt-in. Not sure this is the correct approach. Also not sure if TOGGLE is a good feature to have on boolean PRAGMA statements. FossilOrigin-Name: 5dc82a155dee76e4c8c12e8e62284a10a52a43c8 --- manifest | 17 ++++++++++------- manifest.uuid | 2 +- src/pragma.c | 9 ++++++--- src/shell.c | 47 +++++++++++++++++++++++++++++++++-------------- 4 files changed, 50 insertions(+), 25 deletions(-) diff --git a/manifest b/manifest index c8aad6cfb1..0e6980af07 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Begin\smoving\sseparate\sboolean\svariables\sin\sthe\sShellState\sobject\sof\sthe\sCLI\ninto\sthe\sshellFlgs\sbitmask. -D 2017-03-09T13:50:49.349 +C Add\sthe\s--recovery-mode\soption\sto\sthe\sCLI\s".dump"\scommand.\s\sThis\sinvolves\nenhancing\sthe\s"PRAGMA\sreverse_unordered_selects"\scommand\sto\saccept\sa\s"TOGGLE"\noption.\s\sRecovery\smode\sused\sto\sbe\salways\son.\s\sNow\sit\sis\sopt-in.\s\sNot\ssure\sthis\nis\sthe\scorrect\sapproach.\s\sAlso\snot\ssure\sif\sTOGGLE\sis\sa\sgood\sfeature\sto\shave\non\sboolean\sPRAGMA\sstatements. +D 2017-03-09T16:32:39.526 F Makefile.in edb6bcdd37748d2b1c3422ff727c748df7ffe918 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc a89ea37ab5928026001569f056973b9059492fe2 @@ -392,7 +392,7 @@ F src/parse.y 48b03113704ee8bd78ee6996d81de7fbee22e105 F src/pcache.c 62835bed959e2914edd26afadfecce29ece0e870 F src/pcache.h 2cedcd8407eb23017d92790b112186886e179490 F src/pcache1.c e3967219b2a92b9edcb9324a4ba75009090d3953 -F src/pragma.c b7bf4f1dd9cdcdd3f72f0bdbce3502d69d0f48ba +F src/pragma.c 6d0dd6879a9a8f18a2aad9c0cf34ccaa66bf3de9 F src/pragma.h c9c763958fec92b04125571472c9500b351c5f7f F src/prepare.c b1140c3d0cf59bc85ace00ce363153041b424b7a F src/printf.c 67427bbee66d891fc6f6f5aada857e9cdb368c1c @@ -400,7 +400,7 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 3e518b962d932a997fae373366880fc028c75706 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c d12f3539f80db38b09015561b569e0eb1c4b6c5f -F src/shell.c 397e51c3eeb3a9dc21667a0a384eb14403cc5eea +F src/shell.c 9eb1fe6b682d86b5af82aa745132f436a2525a83 F src/sqlite.h.in 4d0c08f8640c586564a7032b259c5f69bf397850 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 8648034aa702469afb553231677306cc6492a1ae @@ -1564,7 +1564,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 2ea300fb8f7c497f3f092dc91f4305d8431c27d9 -R 193fb708e3eeb9be14d6692d9fad8ed4 +P 50eec5d9aa38fab1a85d788356ffdaf6c35d9ece +R 51880737be8d6b044d8d1303684ea6d0 +T *branch * dump-recovery +T *sym-dump-recovery * +T -sym-trunk * U drh -Z 6ea8a21fbd5a369fc4273386c415b1f4 +Z f19b0ff5084fef69a5f8e22c2e8f27d1 diff --git a/manifest.uuid b/manifest.uuid index 2f86d48c03..7f979cbcee 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -50eec5d9aa38fab1a85d788356ffdaf6c35d9ece \ No newline at end of file +5dc82a155dee76e4c8c12e8e62284a10a52a43c8 \ No newline at end of file diff --git a/src/pragma.c b/src/pragma.c index 2901f4bdc5..1ba9ab9c60 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1045,12 +1045,15 @@ void sqlite3Pragma( mask &= ~(SQLITE_WriteSchema); } #endif - - if( sqlite3GetBoolean(zRight, 0) ){ + if( sqlite3StrICmp(zRight, "toggle")==0 ){ + db->flags ^= mask; + }else if( sqlite3GetBoolean(zRight, 0) ){ db->flags |= mask; }else{ db->flags &= ~mask; - if( mask==SQLITE_DeferFKs ) db->nDeferredImmCons = 0; + } + if( mask==SQLITE_DeferFKs && (db->flags & mask)==0 ){ + db->nDeferredImmCons = 0; } /* Many of the flag-pragmas modify the code generated by the SQL diff --git a/src/shell.c b/src/shell.c index 1de72f8997..dbba1fb6fe 100644 --- a/src/shell.c +++ b/src/shell.c @@ -1410,6 +1410,7 @@ struct ShellState { #define SHFLG_PreserveRowid 0x00000010 /* .dump preserves rowid values */ #define SHFLG_CountChanges 0x00000020 /* .changes setting */ #define SHFLG_Echo 0x00000040 /* .echo or --echo setting */ +#define SHFLG_RecoveryMode 0x00000080 /* The --recovery-mode flag for .dump */ /* ** Macros for testing and setting shellFlgs @@ -2219,7 +2220,7 @@ static int display_stats( sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, bReset); raw_printf(pArg->out, "Number of Outstanding Allocations: %d (max %d)\n", iCur, iHiwtr); - if( pArg->shellFlgs & SHFLG_Pagecache ){ + if( ShellHasFlag(pArg, SHFLG_Pagecache) ){ iHiwtr = iCur = -1; sqlite3_status(SQLITE_STATUS_PAGECACHE_USED, &iCur, &iHiwtr, bReset); raw_printf(pArg->out, @@ -2231,7 +2232,7 @@ static int display_stats( raw_printf(pArg->out, "Number of Pcache Overflow Bytes: %d (max %d) bytes\n", iCur, iHiwtr); - if( pArg->shellFlgs & SHFLG_Scratch ){ + if( ShellHasFlag(pArg, SHFLG_Scratch) ){ iHiwtr = iCur = -1; sqlite3_status(SQLITE_STATUS_SCRATCH_USED, &iCur, &iHiwtr, bReset); raw_printf(pArg->out, @@ -2264,7 +2265,7 @@ static int display_stats( } if( pArg && pArg->out && db ){ - if( pArg->shellFlgs & SHFLG_Lookaside ){ + if( ShellHasFlag(pArg, SHFLG_Lookaside) ){ iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED, &iCur, &iHiwtr, bReset); @@ -2946,6 +2947,14 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){ p->zDestTable = sTable.z; p->mode = p->cMode = MODE_Insert; rc = shell_exec(p->db, sSelect.z, shell_callback, p, 0); + if( (rc&0xff)==SQLITE_CORRUPT ){ + raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n"); + if( ShellHasFlag(p, SHFLG_RecoveryMode) ){ + sqlite3_exec(p->db, "PRAGMA reverse_unordered_selects=TOGGLE",0,0,0); + shell_exec(p->db, sSelect.z, shell_callback, p, 0); + sqlite3_exec(p->db, "PRAGMA reverse_unordered_selects=TOGGLE",0,0,0); + } + } p->zDestTable = savedDestTable; p->mode = savedMode; freeText(&sTable); @@ -2959,8 +2968,9 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){ ** Run zQuery. Use dump_callback() as the callback routine so that ** the contents of the query are output as SQL statements. ** -** If we get a SQLITE_CORRUPT error, rerun the query after appending -** "ORDER BY rowid DESC" to the end. +** If we get a SQLITE_CORRUPT error and the --recovery-mode flag is +** set, then rerun the query in reverse order to try to get more +** data. */ static int run_schema_dump_query( ShellState *p, @@ -2969,7 +2979,7 @@ static int run_schema_dump_query( int rc; char *zErr = 0; rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr); - if( rc==SQLITE_CORRUPT ){ + if( rc==SQLITE_CORRUPT && ShellHasFlag(p, SHFLG_RecoveryMode) ){ char *zQ2; int len = strlen30(zQuery); raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n"); @@ -4570,7 +4580,7 @@ static int do_meta_command(char *zLine, ShellState *p){ if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){ const char *zLike = 0; int i; - ShellClearFlag(p, SHFLG_PreserveRowid); + ShellClearFlag(p, SHFLG_PreserveRowid|SHFLG_RecoveryMode); for(i=1; iout, "PRAGMA foreign_keys=OFF;\n"); raw_printf(p->out, "BEGIN TRANSACTION;\n"); p->writableSchema = 0; - /* Set writable_schema=ON since doing so forces SQLite to initialize - ** as much of the schema as it can even if the sqlite_master table is - ** corrupt. */ - sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0); + if( ShellHasFlag(p, SHFLG_RecoveryMode) ){ + /* Set writable_schema=ON since doing so forces SQLite to initialize + ** as much of the schema as it can even if the sqlite_master table is + ** corrupt. */ + sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0); + } p->nErr = 0; if( zLike==0 ){ run_schema_dump_query(p, @@ -4636,8 +4653,10 @@ static int do_meta_command(char *zLine, ShellState *p){ raw_printf(p->out, "PRAGMA writable_schema=OFF;\n"); p->writableSchema = 0; } - sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0); - sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0); + if( ShellHasFlag(p, SHFLG_RecoveryMode) ){ + sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0); + sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0); + } raw_printf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n"); }else -- 2.39.5