1# 2022 August 28 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 13source [file join [file dirname [info script]] recover_common.tcl] 14set testprefix recover1 15 16proc compare_result {db1 db2 sql} { 17 set r1 [$db1 eval $sql] 18 set r2 [$db2 eval $sql] 19 if {$r1 != $r2} { 20 puts "r1: $r1" 21 puts "r2: $r2" 22 error "mismatch for $sql" 23 } 24 return "" 25} 26 27proc compare_dbs {db1 db2} { 28 compare_result $db1 $db2 "SELECT sql FROM sqlite_master ORDER BY 1" 29 foreach tbl [$db1 eval {SELECT name FROM sqlite_master WHERE type='table'}] { 30 compare_result $db1 $db2 "SELECT * FROM $tbl" 31 } 32 33 compare_result $db1 $db2 "PRAGMA page_size" 34 compare_result $db1 $db2 "PRAGMA auto_vacuum" 35 compare_result $db1 $db2 "PRAGMA encoding" 36 compare_result $db1 $db2 "PRAGMA user_version" 37 compare_result $db1 $db2 "PRAGMA application_id" 38} 39 40proc do_recover_test {tn} { 41 forcedelete test.db2 42 forcedelete rstate.db 43 44 uplevel [list do_test $tn.1 { 45 set R [sqlite3_recover_init db main test.db2] 46 $R config testdb rstate.db 47 $R run 48 $R finish 49 } {}] 50 51 sqlite3 db2 test.db2 52 uplevel [list do_test $tn.2 [list compare_dbs db db2] {}] 53 db2 close 54 55 forcedelete test.db2 56 forcedelete rstate.db 57 58 uplevel [list do_test $tn.3 { 59 set ::sqlhook [list] 60 set R [sqlite3_recover_init_sql db main my_sql_hook] 61 $R config testdb rstate.db 62 $R config rowids 1 63 $R run 64 $R finish 65 } {}] 66 67 sqlite3 db2 test.db2 68 execsql [join $::sqlhook ";"] db2 69 db2 close 70 sqlite3 db2 test.db2 71 uplevel [list do_test $tn.4 [list compare_dbs db db2] {}] 72 db2 close 73} 74 75proc my_sql_hook {sql} { 76 lappend ::sqlhook $sql 77 return 0 78} 79 80do_execsql_test 1.0 { 81 CREATE TABLE t1(a INTEGER PRIMARY KEY, b); 82 CREATE TABLE t2(a INTEGER PRIMARY KEY, b) WITHOUT ROWID; 83 WITH s(i) AS ( 84 SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<10 85 ) 86 INSERT INTO t1 SELECT i*2, hex(randomblob(250)) FROM s; 87 INSERT INTO t2 SELECT * FROM t1; 88} 89 90do_recover_test 1 91 92do_execsql_test 2.0 { 93 ALTER TABLE t1 ADD COLUMN c DEFAULT 'xyz' 94} 95do_recover_test 2 96 97do_execsql_test 3.0 { 98 CREATE INDEX i1 ON t1(c); 99} 100do_recover_test 3 101 102do_execsql_test 4.0 { 103 CREATE VIEW v1 AS SELECT * FROM t2; 104} 105do_recover_test 4 106 107do_execsql_test 5.0 { 108 CREATE UNIQUE INDEX i2 ON t1(c, b); 109} 110do_recover_test 5 111 112#-------------------------------------------------------------------------- 113# 114reset_db 115do_execsql_test 6.0 { 116 CREATE TABLE t1( 117 a INTEGER PRIMARY KEY, 118 b INT, 119 c TEXT, 120 d INT GENERATED ALWAYS AS (a*abs(b)) VIRTUAL, 121 e TEXT GENERATED ALWAYS AS (substr(c,b,b+1)) STORED, 122 f TEXT GENERATED ALWAYS AS (substr(c,b,b+1)) STORED 123 ); 124 125 INSERT INTO t1 VALUES(1, 2, 'hello world'); 126} 127do_recover_test 6 128 129do_execsql_test 7.0 { 130 CREATE TABLE t2(i, j GENERATED ALWAYS AS (i+1) STORED, k); 131 INSERT INTO t2 VALUES(10, 'ten'); 132} 133do_execsql_test 7.1 { 134 SELECT * FROM t2 135} {10 11 ten} 136 137do_recover_test 7.2 138 139#-------------------------------------------------------------------------- 140# 141reset_db 142do_execsql_test 8.0 { 143 CREATE TABLE x1(a INTEGER PRIMARY KEY AUTOINCREMENT, b, c); 144 WITH s(i) AS ( 145 SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<2 146 ) 147 INSERT INTO x1(b, c) SELECT hex(randomblob(100)), hex(randomblob(100)) FROM s; 148 149 CREATE INDEX x1b ON x1(b); 150 CREATE INDEX x1cb ON x1(c, b); 151 DELETE FROM x1 WHERE a>50; 152 153 ANALYZE; 154} 155 156do_recover_test 8 157 158#------------------------------------------------------------------------- 159reset_db 160ifcapable fts5 { 161 do_execsql_test 9.1 { 162 CREATE VIRTUAL TABLE ft5 USING fts5(a, b); 163 INSERT INTO ft5 VALUES('hello', 'world'); 164 } 165 do_recover_test 9 166} 167 168#------------------------------------------------------------------------- 169reset_db 170do_execsql_test 10.1 { 171 CREATE TABLE x1(a PRIMARY KEY, str TEXT) WITHOUT ROWID; 172 INSERT INTO x1 VALUES(1, ' 173 \nhello\012world(\n0)(\n1) 174 '); 175 INSERT INTO x1 VALUES(2, ' 176 \nhello 177 '); 178} 179do_execsql_test 10.2 " 180 INSERT INTO x1 VALUES(3, '\012hello there\015world'); 181 INSERT INTO x1 VALUES(4, '\015hello there\015world'); 182" 183do_recover_test 10 184 185#------------------------------------------------------------------------- 186reset_db 187do_execsql_test 11.1 { 188 PRAGMA page_size = 4096; 189 PRAGMA encoding='utf16'; 190 PRAGMA auto_vacuum = 2; 191 PRAGMA user_version = 45; 192 PRAGMA application_id = 22; 193 194 CREATE TABLE u1(u, v); 195 INSERT INTO u1 VALUES('edvin marton', 'bond'); 196 INSERT INTO u1 VALUES(1, 4.0); 197} 198do_execsql_test 11.1a { 199 PRAGMA auto_vacuum; 200} {2} 201 202do_recover_test 11 203 204do_test 12.1 { 205 set R [sqlite3_recover_init db "" test.db2] 206 $R config lostandfound "" 207 $R config invalid xyz 208} {12} 209do_test 12.2 { 210 $R run 211 $R run 212} {0} 213 214do_test 12.3 { 215 $R finish 216} {} 217 218 219 220#------------------------------------------------------------------------- 221reset_db 222file_control_reservebytes db 16 223do_execsql_test 12.1 { 224 PRAGMA auto_vacuum = 2; 225 PRAGMA user_version = 45; 226 PRAGMA application_id = 22; 227 228 CREATE TABLE u1(u, v); 229 CREATE UNIQUE INDEX i1 ON u1(u, v); 230 INSERT INTO u1 VALUES(1, 2), (3, 4); 231 232 CREATE TABLE u2(u, v); 233 CREATE UNIQUE INDEX i2 ON u1(u, v); 234 INSERT INTO u2 VALUES(hex(randomblob(500)), hex(randomblob(1000))); 235 INSERT INTO u2 VALUES(hex(randomblob(500)), hex(randomblob(1000))); 236 INSERT INTO u2 VALUES(hex(randomblob(500)), hex(randomblob(1000))); 237 INSERT INTO u2 VALUES(hex(randomblob(50000)), hex(randomblob(20000))); 238} 239 240do_recover_test 12 241 242#------------------------------------------------------------------------- 243reset_db 244sqlite3 db "" 245do_recover_test 13 246 247do_execsql_test 14.1 { 248 PRAGMA auto_vacuum = 2; 249 PRAGMA user_version = 45; 250 PRAGMA application_id = 22; 251 252 CREATE TABLE u1(u, v); 253 CREATE UNIQUE INDEX i1 ON u1(u, v); 254 INSERT INTO u1 VALUES(1, 2), (3, 4); 255 256 CREATE TABLE u2(u, v); 257 CREATE UNIQUE INDEX i2 ON u1(u, v); 258 INSERT INTO u2 VALUES(hex(randomblob(500)), hex(randomblob(1000))); 259 INSERT INTO u2 VALUES(hex(randomblob(500)), hex(randomblob(1000))); 260 INSERT INTO u2 VALUES(hex(randomblob(500)), hex(randomblob(1000))); 261 INSERT INTO u2 VALUES(hex(randomblob(50000)), hex(randomblob(20000))); 262} 263do_recover_test 14 264 265#------------------------------------------------------------------------- 266reset_db 267execsql { 268 PRAGMA journal_mode=OFF; 269 PRAGMA mmap_size=10; 270} 271do_execsql_test 15.1 { 272 CREATE TABLE t1(x); 273} {} 274do_recover_test 15 275 276finish_test 277 278