1 # 2012 January 11 {} 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 # This file implements regression tests for SQLite library. 12 # 13 # This file implements tests for the recover module, which can read 14 # through corrupt rows and pages. 15 # 16 # $Id$ 17 18 # TODO(shess): These all test that the module correctly reads good 19 # data. It would be good to implement tests of corrupt data. 20 21 set testdir [file dirname $argv0] 22 source $testdir/tester.tcl 23 24 db eval { 25 DROP TABLE IF EXISTS altered; 26 CREATE TABLE altered ( 27 c TEXT 28 ); 29 INSERT INTO altered VALUES ('a'); 30 INSERT INTO altered VALUES ('b'); 31 INSERT INTO altered VALUES ('c'); 32 ALTER TABLE altered ADD COLUMN i INTEGER NOT NULL DEFAULT 10; 33 INSERT INTO altered VALUES ('d', 5); 34 } 35 36 # SQLite will fill the earlier rows with the default. 37 do_test recover-alter-1.0 { 38 execsql {SELECT c, i FROM altered ORDER BY rowid} 39 } {a 10 b 10 c 10 d 5} 40 41 # recover sees NULL for those rows. 42 do_test recover-alter-1.1 { 43 db eval { 44 DROP TABLE IF EXISTS temp.altered_recover; 45 CREATE VIRTUAL TABLE temp.altered_recover USING recover( 46 altered, 47 c TEXT, 48 i INTEGER 49 ); 50 } 51 execsql {SELECT c, i FROM altered_recover ORDER BY rowid} 52 } {a {} b {} c {} d 5} 53 54 # Can skip those NULL columns like if they contained a real NULL. 55 do_test recover-alter-1.2 { 56 db eval { 57 DROP TABLE IF EXISTS temp.altered_recover; 58 CREATE VIRTUAL TABLE temp.altered_recover USING recover( 59 altered, 60 c TEXT, 61 i INTEGER NOT NULL 62 ); 63 } 64 execsql {SELECT c, i FROM altered_recover ORDER BY rowid} 65 } {d 5} 66 67 if {0} { 68 # It would be neat if this could work. I tried putting "DEFAULT ..." 69 # in the schema exposed by the recover table, but it doesn't do the 70 # trick. 71 do_test recover-alter-1.2 { 72 db eval { 73 DROP TABLE IF EXISTS temp.altered_recover; 74 CREATE VIRTUAL TABLE temp.altered_recover USING recover( 75 altered, 76 c TEXT, 77 i INTEGER NOT NULL DEFAULT 10 78 ); 79 } 80 execsql {SELECT c, i FROM altered_recover ORDER BY rowid} 81 } {a 10 b 10 c 10 d 5} 82 } 83 84 # Helper function to generate an arbitrarily-sized table. 85 proc generate {table base count} { 86 db eval "DROP TABLE IF EXISTS $table" 87 db transaction immediate { 88 db eval "CREATE TABLE $table (t TEXT,n INT)" 89 for {set i 0} {$i<$count} {incr i} { 90 set t [concat $base $i] 91 db eval [concat {INSERT INTO} $table {VALUES ($t, $i)}] 92 } 93 } 94 } 95 96 # Leaf-only database parses. 97 do_test recover-leaf-1.0 { 98 db close 99 sqlite3 db test.db 100 generate "leaf" "Leaf-node-generating line " 10 101 102 db eval { 103 DROP TABLE IF EXISTS temp.leaf_recover; 104 CREATE VIRTUAL TABLE temp.leaf_recover USING recover( 105 leaf, 106 t TEXT, 107 n INTEGER 108 ); 109 } 110 execsql {SELECT t, n FROM leaf_recover ORDER BY rowid} 111 } {{Leaf-node-generating line 0} 0 {Leaf-node-generating line 1} 1 {Leaf-node-generating line 2} 2 {Leaf-node-generating line 3} 3 {Leaf-node-generating line 4} 4 {Leaf-node-generating line 5} 5 {Leaf-node-generating line 6} 6 {Leaf-node-generating line 7} 7 {Leaf-node-generating line 8} 8 {Leaf-node-generating line 9} 9} 112 113 # Single level of interior node. 114 do_test recover-interior-1.0 { 115 db close 116 sqlite3 db test.db 117 generate "interior" "Interior-node-generating line " 100 118 119 db eval { 120 DROP TABLE IF EXISTS temp.interior_recover; 121 CREATE VIRTUAL TABLE temp.interior_recover USING recover( 122 interior, 123 t TEXT, 124 n INTEGER 125 ); 126 } 127 execsql {SELECT t, n FROM interior_recover WHERE (rowid%10)=0 ORDER BY rowid} 128 } {{Interior-node-generating line 9} 9 {Interior-node-generating line 19} 19 {Interior-node-generating line 29} 29 {Interior-node-generating line 39} 39 {Interior-node-generating line 49} 49 {Interior-node-generating line 59} 59 {Interior-node-generating line 69} 69 {Interior-node-generating line 79} 79 {Interior-node-generating line 89} 89 {Interior-node-generating line 99} 99} 129 130 # Multiple levels of interior node. 131 do_test recover-interior-2.0 { 132 db close 133 sqlite3 db test.db 134 generate "interior2" "Interior-node-generating line " 5000 135 136 db eval { 137 DROP TABLE IF EXISTS temp.interior2_recover; 138 CREATE VIRTUAL TABLE temp.interior2_recover USING recover( 139 interior2, 140 t TEXT, 141 n INTEGER 142 ); 143 } 144 execsql {SELECT t, n FROM interior2_recover WHERE (rowid%500)=0 ORDER BY rowid} 145 } {{Interior-node-generating line 499} 499 {Interior-node-generating line 999} 999 {Interior-node-generating line 1499} 1499 {Interior-node-generating line 1999} 1999 {Interior-node-generating line 2499} 2499 {Interior-node-generating line 2999} 2999 {Interior-node-generating line 3499} 3499 {Interior-node-generating line 3999} 3999 {Interior-node-generating line 4499} 4499 {Interior-node-generating line 4999} 4999} 146 147 finish_test 148