-C Enhance\sthe\s".recover"\scommand.\sFix\sa\sproblem\swith\soverflow\spages\sin\sdbdata.c.
-D 2019-04-22T20:52:12.850
+C Fixes\sfor\sthe\s".recover"\sshell\scommand.
+D 2019-04-23T18:03:02.318
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F src/resolve.c 567888ee3faec14dae06519b4306201771058364a37560186a3e0e755ebc4cb8
F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
F src/select.c 9263f5c30dd44c7ac2eb29f40a7ec64322a96885b71c00de6bc30b756c2e1c49
-F src/shell.c.in 7dd0babc42bc136b8dd070152981ee2325b787571f58326e68e6ad35d764aa33
+F src/shell.c.in 6c02cbd1de3b878abc04b08f2f74cc4d65d0a8e52dd3e78194db2a79d686b841
F src/sqlite.h.in 38390767acc1914d58930e03149595ee4710afa4e3c43ab6c3a8aea3f1a6b8cd
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 9ecc93b8493bd20c0c07d52e2ac0ed8bab9b549c7f7955b59869597b650dd8b5
F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
F test/rbu.test 168573d353cd0fd10196b87b0caa322c144ef736
F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
+F test/recover.test a8fed5acf2742268e366abb76a01de6ddce278aae01658488b950c968ebef638
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 7461d2e120f2149315ddac2676d51d7445bcdb8e97543effd9c30603517ef9da
-R 14050e9b3d7e7a784dc8a127e6275222
+P f193ca587f9e4f925f4f2343b0b07053bd6f93dd87fc6f8f41cf4479e90cf562
+R 73bcd5cc8a48367ff5a018a5ccb0a79d
U dan
-Z abcbf2aebf4cbfcbf65f71e558364487
+Z e408dc486ac689ec1d61c890dc79708f
-f193ca587f9e4f925f4f2343b0b07053bd6f93dd87fc6f8f41cf4479e90cf562
\ No newline at end of file
+8dcc1d89d955bf58c80a8c30a37960f0cf95719953951a92626cc332cc75ec60
\ No newline at end of file
sqlite3_stmt *pStmt = 0;
rc = sqlite3_open("", &dbtmp);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3_exec(dbtmp, "PRAGMA writable_schema = on", 0, 0, 0);
+ }
if( rc==SQLITE_OK ){
rc = sqlite3_exec(dbtmp, zSql, 0, 0, 0);
if( rc==SQLITE_ERROR ){
if( rc==SQLITE_OK ){
sqlite3_stmt *pStmt = 0;
raw_printf(pState->out, "BEGIN;\n");
- shellPrepare(pState->db, &rc,
+ raw_printf(pState->out, "PRAGMA writable_schema = on;\n");
+ shellPrepare(pState->db, &rc,
"SELECT sql FROM recovery.schema "
- "WHERE type='table' "
- " AND length(sql)>6"
- " AND sql LIKE 'create table%'"
- " AND name NOT LIKE 'sqliteX_%' ESCAPE 'X'", &pStmt
+ "WHERE type='table' AND sql LIKE 'create table%'", &pStmt
);
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
const char *zCreateTable = (const char*)sqlite3_column_text(pStmt, 0);
- raw_printf(pState->out, "%s;\n", zCreateTable);
+ raw_printf(pState->out, "CREATE TABLE IF NOT EXISTS %s;\n",
+ &zCreateTable[12]
+ );
}
shellFinalize(&rc, pStmt);
}
/* Loop through each root page. */
shellPrepare(pState->db, &rc,
"SELECT root, intkey, max(maxlen) FROM recovery.map"
- " WHERE root>1 GROUP BY root, intkey", &pLoop
+ " WHERE root>1 GROUP BY root, intkey ORDER BY root=("
+ " SELECT rootpage FROM recovery.schema WHERE name='sqlite_sequence'"
+ ")", &pLoop
);
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
int iRoot = sqlite3_column_int(pLoop, 0);
pTab = recoverNewTable(pState, &rc, iRoot, bIntkey, nCol);
if( pTab ){
sqlite3_stmt *pData = 0;
+ if( 0==sqlite3_stricmp(pTab->zName, "sqlite_sequence") ){
+ raw_printf(pState->out, "DELETE FROM sqlite_sequence;\n");
+ }
shellPreparePrintf(pState->db, &rc, &pData,
"SELECT max(field), group_concat(quote(value), ', ') "
"FROM sqlite_dbdata WHERE pgno IN ("
}
shellFinalize(&rc, pLoop);
+ /* The rest of the schema */
+ if( rc==SQLITE_OK ){
+ sqlite3_stmt *pStmt = 0;
+ shellPrepare(pState->db, &rc,
+ "SELECT sql, name FROM recovery.schema "
+ "WHERE (type='table' AND sql LIKE 'create table%') IS NOT TRUE", &pStmt
+ );
+ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
+ const char *zSql = (const char*)sqlite3_column_text(pStmt, 0);
+ if( sqlite3_strnicmp(zSql, "create virt", 11)==0 ){
+ const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
+ char *zPrint = shellMPrintf(&rc,
+ "INSERT INTO sqlite_master VALUES('table', %Q, %Q, 0, %Q)",
+ zName, zName, zSql
+ );
+ raw_printf(pState->out, "%s;\n", zPrint);
+ sqlite3_free(zPrint);
+ }else{
+ raw_printf(pState->out, "%s;\n", zSql);
+ }
+ }
+ shellFinalize(&rc, pStmt);
+ }
+
if( rc==SQLITE_OK ){
+ raw_printf(pState->out, "PRAGMA writable_schema = off;\n");
raw_printf(pState->out, "COMMIT;\n");
}
sqlite3_exec(pState->db, "DETACH recovery", 0, 0, 0);
--- /dev/null
+# 2019 April 23
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+# Test the shell tool ".ar" command.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set testprefix recover
+
+ifcapable !vtab {
+ finish_test; return
+}
+set CLI [test_find_cli]
+
+proc compare_result {db1 db2 sql} {
+ set r1 [$db1 eval $sql]
+ set r2 [$db2 eval $sql]
+ if {$r1 != $r2} {
+ puts "r1: $r1"
+ puts "r2: $r2"
+ error "mismatch for $sql"
+ }
+ return ""
+}
+
+proc compare_dbs {db1 db2} {
+ compare_result $db1 $db2 "SELECT sql FROM sqlite_master ORDER BY 1"
+ foreach tbl [$db1 eval {SELECT name FROM sqlite_master WHERE type='table'}] {
+ compare_result $db1 $db2 "SELECT * FROM $tbl"
+ }
+}
+
+proc do_recover_test {tn} {
+ set fd [open "|$::CLI test.db .recover"]
+ fconfigure $fd -encoding binary
+ fconfigure $fd -translation binary
+ set sql [read $fd]
+ close $fd
+
+ forcedelete test.db2
+ sqlite3 db2 test.db2
+ breakpoint
+ execsql $sql db2
+ uplevel [list do_test $tn [list compare_dbs db db2] {}]
+ db2 close
+}
+
+set doc {
+ hello
+ world
+}
+do_execsql_test 1.1.1 {
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
+ INSERT INTO t1 VALUES(1, 4, X'1234567800');
+ INSERT INTO t1 VALUES(2, 'test', 8.1);
+ INSERT INTO t1 VALUES(3, $doc, 8.4);
+}
+do_recover_test 1.1.2
+
+do_execsql_test 1.2.1 "
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES(13, 'hello\r\nworld', 13);
+"
+do_recover_test 1.2.2
+
+do_execsql_test 1.3.1 "
+ CREATE TABLE t2(i INTEGER PRIMARY KEY AUTOINCREMENT, b, c);
+ INSERT INTO t2 VALUES(NULL, 1, 2);
+ INSERT INTO t2 VALUES(NULL, 3, 4);
+ INSERT INTO t2 VALUES(NULL, 5, 6);
+ CREATE TABLE t3(i INTEGER PRIMARY KEY AUTOINCREMENT, b, c);
+ INSERT INTO t3 VALUES(NULL, 1, 2);
+ INSERT INTO t3 VALUES(NULL, 3, 4);
+ INSERT INTO t3 VALUES(NULL, 5, 6);
+ DELETE FROM t2;
+"
+do_recover_test 1.3.2
+
+finish_test