1# 2019 April 23 2# 3# The author disclaims copyright to this source code. In place of 4# a legal notice, here is a blessing: 5# 6# May you do good and not evil. 7# May you find forgiveness for yourself and forgive others. 8# May you share freely, never taking more than you give. 9# 10#*********************************************************************** 11# 12# 13 14source [file join [file dirname [info script]] recover_common.tcl] 15set testprefix recoverold 16 17proc compare_result {db1 db2 sql} { 18 set r1 [$db1 eval $sql] 19 set r2 [$db2 eval $sql] 20 if {$r1 != $r2} { 21 puts "sql: $sql" 22 puts "r1: $r1" 23 puts "r2: $r2" 24 error "mismatch for $sql" 25 } 26 return "" 27} 28 29proc compare_dbs {db1 db2} { 30 compare_result $db1 $db2 "SELECT sql FROM sqlite_master ORDER BY 1" 31 foreach tbl [$db1 eval {SELECT name FROM sqlite_master WHERE type='table'}] { 32 compare_result $db1 $db2 "SELECT * FROM $tbl" 33 } 34} 35 36proc do_recover_test {tn {tsql {}} {res {}}} { 37 forcedelete test.db2 38 forcedelete rstate.db 39 40 set R [sqlite3_recover_init db main test.db2] 41 $R config lostandfound lost_and_found 42 $R run 43 $R finish 44 45 sqlite3 db2 test.db2 46 47 if {$tsql==""} { 48 uplevel [list do_test $tn.1 [list compare_dbs db db2] {}] 49 } else { 50 uplevel [list do_execsql_test -db db2 $tn.1 $tsql $res] 51 } 52 db2 close 53 54 forcedelete test.db2 55 forcedelete rstate.db 56 57 set ::sqlhook [list] 58 set R [sqlite3_recover_init_sql db main my_sql_hook] 59 $R config lostandfound lost_and_found 60 $R run 61 $R finish 62 63 sqlite3 db2 test.db2 64 db2 eval [join $::sqlhook ";"] 65 66 67 db cache flush 68 if {$tsql==""} { 69 compare_dbs db db2 70 uplevel [list do_test $tn.sql [list compare_dbs db db2] {}] 71 } else { 72 uplevel [list do_execsql_test -db db2 $tn.sql $tsql $res] 73 } 74 db2 close 75} 76 77proc my_sql_hook {sql} { 78 lappend ::sqlhook $sql 79 return 0 80} 81 82 83set doc { 84 hello 85 world 86} 87do_execsql_test 1.1.1 { 88 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); 89 INSERT INTO t1 VALUES(1, 4, X'1234567800'); 90 INSERT INTO t1 VALUES(2, 'test', 8.1); 91 INSERT INTO t1 VALUES(3, $doc, 8.4); 92} 93do_recover_test 1.1.2 94 95do_execsql_test 1.2.1 " 96 DELETE FROM t1; 97 INSERT INTO t1 VALUES(13, 'hello\r\nworld', 13); 98" 99do_recover_test 1.2.2 100 101do_execsql_test 1.3.1 " 102 CREATE TABLE t2(i INTEGER PRIMARY KEY AUTOINCREMENT, b, c); 103 INSERT INTO t2 VALUES(NULL, 1, 2); 104 INSERT INTO t2 VALUES(NULL, 3, 4); 105 INSERT INTO t2 VALUES(NULL, 5, 6); 106 CREATE TABLE t3(i INTEGER PRIMARY KEY AUTOINCREMENT, b, c); 107 INSERT INTO t3 VALUES(NULL, 1, 2); 108 INSERT INTO t3 VALUES(NULL, 3, 4); 109 INSERT INTO t3 VALUES(NULL, 5, 6); 110 DELETE FROM t2; 111" 112do_recover_test 1.3.2 113 114#------------------------------------------------------------------------- 115reset_db 116do_execsql_test 2.1.0 { 117 PRAGMA auto_vacuum = 0; 118 CREATE TABLE t1(a, b, c, PRIMARY KEY(b, c)) WITHOUT ROWID; 119 INSERT INTO t1 VALUES(1, 2, 3); 120 INSERT INTO t1 VALUES(4, 5, 6); 121 INSERT INTO t1 VALUES(7, 8, 9); 122} 123 124do_recover_test 2.1.1 125 126do_execsql_test 2.2.0 { 127 PRAGMA writable_schema = 1; 128 DELETE FROM sqlite_master WHERE name='t1'; 129} 130do_recover_test 2.2.1 { 131 SELECT name FROM sqlite_master 132} {lost_and_found} 133 134do_execsql_test 2.3.0 { 135 CREATE TABLE lost_and_found(a, b, c); 136} 137do_recover_test 2.3.1 { 138 SELECT name FROM sqlite_master 139} {lost_and_found lost_and_found_0} 140 141do_execsql_test 2.4.0 { 142 CREATE TABLE lost_and_found_0(a, b, c); 143} 144do_recover_test 2.4.1 { 145 SELECT name FROM sqlite_master; 146 SELECT * FROM lost_and_found_1; 147} {lost_and_found lost_and_found_0 lost_and_found_1 148 2 2 3 {} 2 3 1 149 2 2 3 {} 5 6 4 150 2 2 3 {} 8 9 7 151} 152 153do_execsql_test 2.5 { 154 CREATE TABLE x1(a, b, c); 155 WITH s(i) AS ( 156 SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<100 157 ) 158 INSERT INTO x1 SELECT i, i, hex(randomblob(500)) FROM s; 159 DROP TABLE x1; 160} 161do_recover_test 2.5.1 { 162 SELECT name FROM sqlite_master; 163 SELECT * FROM lost_and_found_1; 164} {lost_and_found lost_and_found_0 lost_and_found_1 165 2 2 3 {} 2 3 1 166 2 2 3 {} 5 6 4 167 2 2 3 {} 8 9 7 168} 169 170ifcapable !secure_delete { 171 do_test 2.6 { 172 forcedelete test.db2 173 set R [sqlite3_recover_init db main test.db2] 174 $R config lostandfound lost_and_found 175 $R config freelistcorrupt 1 176 $R run 177 $R finish 178 sqlite3 db2 test.db2 179 execsql { SELECT count(*) FROM lost_and_found_1; } db2 180 } {103} 181 db2 close 182} 183 184#------------------------------------------------------------------------- 185breakpoint 186reset_db 187do_recover_test 3.0 188 189finish_test 190