1 # 2003 July 1 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. The 12 # focus of this script is testing the ATTACH and DETACH commands 13 # and schema changes to attached databases. 14 # 15 # $Id: attach3.test,v 1.18 2007/10/09 08:29:32 danielk1977 Exp $ 16 # 17 18 set testdir [file dirname $argv0] 19 source $testdir/tester.tcl 20 21 ifcapable !attach { 22 finish_test 23 return 24 } 25 26 # The tests in this file were written before SQLite supported recursive 27 # trigger invocation, and some tests depend on that to pass. So disable 28 # recursive triggers for this file. 29 catchsql { pragma recursive_triggers = off } 30 31 # Create tables t1 and t2 in the main database 32 execsql { 33 CREATE TABLE t1(a, b); 34 CREATE TABLE t2(c, d); 35 } 36 37 # Create tables t1 and t2 in database file test2.db 38 file delete -force test2.db 39 file delete -force test2.db-journal 40 sqlite3 db2 test2.db 41 execsql { 42 CREATE TABLE t1(a, b); 43 CREATE TABLE t2(c, d); 44 } db2 45 db2 close 46 47 # Create a table in the auxilary database. 48 do_test attach3-1.1 { 49 execsql { 50 ATTACH 'test2.db' AS aux; 51 } 52 } {} 53 do_test attach3-1.2 { 54 execsql { 55 CREATE TABLE aux.t3(e, f); 56 } 57 } {} 58 do_test attach3-1.3 { 59 execsql { 60 SELECT * FROM sqlite_master WHERE name = 't3'; 61 } 62 } {} 63 do_test attach3-1.4 { 64 execsql { 65 SELECT * FROM aux.sqlite_master WHERE name = 't3'; 66 } 67 } "table t3 t3 [expr $AUTOVACUUM?5:4] {CREATE TABLE t3(e, f)}" 68 do_test attach3-1.5 { 69 execsql { 70 INSERT INTO t3 VALUES(1, 2); 71 SELECT * FROM t3; 72 } 73 } {1 2} 74 75 # Create an index on the auxilary database table. 76 do_test attach3-2.1 { 77 execsql { 78 CREATE INDEX aux.i1 on t3(e); 79 } 80 } {} 81 do_test attach3-2.2 { 82 execsql { 83 SELECT * FROM sqlite_master WHERE name = 'i1'; 84 } 85 } {} 86 do_test attach3-2.3 { 87 execsql { 88 SELECT * FROM aux.sqlite_master WHERE name = 'i1'; 89 } 90 } "index i1 t3 [expr $AUTOVACUUM?6:5] {CREATE INDEX i1 on t3(e)}" 91 92 # Drop the index on the aux database table. 93 do_test attach3-3.1 { 94 execsql { 95 DROP INDEX aux.i1; 96 SELECT * FROM aux.sqlite_master WHERE name = 'i1'; 97 } 98 } {} 99 do_test attach3-3.2 { 100 execsql { 101 CREATE INDEX aux.i1 on t3(e); 102 SELECT * FROM aux.sqlite_master WHERE name = 'i1'; 103 } 104 } "index i1 t3 [expr $AUTOVACUUM?6:5] {CREATE INDEX i1 on t3(e)}" 105 do_test attach3-3.3 { 106 execsql { 107 DROP INDEX i1; 108 SELECT * FROM aux.sqlite_master WHERE name = 'i1'; 109 } 110 } {} 111 112 # Drop tables t1 and t2 in the auxilary database. 113 do_test attach3-4.1 { 114 execsql { 115 DROP TABLE aux.t1; 116 SELECT name FROM aux.sqlite_master; 117 } 118 } {t2 t3} 119 do_test attach3-4.2 { 120 # This will drop main.t2 121 execsql { 122 DROP TABLE t2; 123 SELECT name FROM aux.sqlite_master; 124 } 125 } {t2 t3} 126 do_test attach3-4.3 { 127 execsql { 128 DROP TABLE t2; 129 SELECT name FROM aux.sqlite_master; 130 } 131 } {t3} 132 133 # Create a view in the auxilary database. 134 ifcapable view { 135 do_test attach3-5.1 { 136 execsql { 137 CREATE VIEW aux.v1 AS SELECT * FROM t3; 138 } 139 } {} 140 do_test attach3-5.2 { 141 execsql { 142 SELECT * FROM aux.sqlite_master WHERE name = 'v1'; 143 } 144 } {view v1 v1 0 {CREATE VIEW v1 AS SELECT * FROM t3}} 145 do_test attach3-5.3 { 146 execsql { 147 INSERT INTO aux.t3 VALUES('hello', 'world'); 148 SELECT * FROM v1; 149 } 150 } {1 2 hello world} 151 152 # Drop the view 153 do_test attach3-6.1 { 154 execsql { 155 DROP VIEW aux.v1; 156 } 157 } {} 158 do_test attach3-6.2 { 159 execsql { 160 SELECT * FROM aux.sqlite_master WHERE name = 'v1'; 161 } 162 } {} 163 } ;# ifcapable view 164 165 ifcapable {trigger} { 166 # Create a trigger in the auxilary database. 167 do_test attach3-7.1 { 168 execsql { 169 CREATE TRIGGER aux.tr1 AFTER INSERT ON t3 BEGIN 170 INSERT INTO t3 VALUES(new.e*2, new.f*2); 171 END; 172 } 173 } {} 174 do_test attach3-7.2 { 175 execsql { 176 DELETE FROM t3; 177 INSERT INTO t3 VALUES(10, 20); 178 SELECT * FROM t3; 179 } 180 } {10 20 20 40} 181 do_test attach3-5.3 { 182 execsql { 183 SELECT * FROM aux.sqlite_master WHERE name = 'tr1'; 184 } 185 } {trigger tr1 t3 0 {CREATE TRIGGER tr1 AFTER INSERT ON t3 BEGIN 186 INSERT INTO t3 VALUES(new.e*2, new.f*2); 187 END}} 188 189 # Drop the trigger 190 do_test attach3-8.1 { 191 execsql { 192 DROP TRIGGER aux.tr1; 193 } 194 } {} 195 do_test attach3-8.2 { 196 execsql { 197 SELECT * FROM aux.sqlite_master WHERE name = 'tr1'; 198 } 199 } {} 200 201 ifcapable tempdb { 202 # Try to trick SQLite into dropping the wrong temp trigger. 203 do_test attach3-9.0 { 204 execsql { 205 CREATE TABLE main.t4(a, b, c); 206 CREATE TABLE aux.t4(a, b, c); 207 CREATE TEMP TRIGGER tst_trigger BEFORE INSERT ON aux.t4 BEGIN 208 SELECT 'hello world'; 209 END; 210 SELECT count(*) FROM sqlite_temp_master; 211 } 212 } {1} 213 do_test attach3-9.1 { 214 execsql { 215 DROP TABLE main.t4; 216 SELECT count(*) FROM sqlite_temp_master; 217 } 218 } {1} 219 do_test attach3-9.2 { 220 execsql { 221 DROP TABLE aux.t4; 222 SELECT count(*) FROM sqlite_temp_master; 223 } 224 } {0} 225 } 226 } ;# endif trigger 227 228 # Make sure the aux.sqlite_master table is read-only 229 do_test attach3-10.0 { 230 catchsql { 231 INSERT INTO aux.sqlite_master VALUES(1, 2, 3, 4, 5); 232 } 233 } {1 {table sqlite_master may not be modified}} 234 235 # Failure to attach leaves us in a workable state. 236 # Ticket #811 237 # 238 do_test attach3-11.0 { 239 catchsql { 240 ATTACH DATABASE '/nodir/nofile.x' AS notadb; 241 } 242 } {1 {unable to open database: /nodir/nofile.x}} 243 do_test attach3-11.1 { 244 catchsql { 245 ATTACH DATABASE ':memory:' AS notadb; 246 } 247 } {0 {}} 248 do_test attach3-11.2 { 249 catchsql { 250 DETACH DATABASE notadb; 251 } 252 } {0 {}} 253 254 # Return a list of attached databases 255 # 256 proc db_list {} { 257 set x [execsql { 258 PRAGMA database_list; 259 }] 260 set y {} 261 foreach {n id file} $x {lappend y $id} 262 return $y 263 } 264 265 ifcapable schema_pragmas&&tempdb { 266 267 ifcapable !trigger { 268 execsql {create temp table dummy(dummy)} 269 } 270 271 # Ticket #1825 272 # 273 do_test attach3-12.1 { 274 db_list 275 } {main temp aux} 276 do_test attach3-12.2 { 277 execsql { 278 ATTACH DATABASE ? AS ? 279 } 280 db_list 281 } {main temp aux {}} 282 do_test attach3-12.3 { 283 execsql { 284 DETACH aux 285 } 286 db_list 287 } {main temp {}} 288 do_test attach3-12.4 { 289 execsql { 290 DETACH ? 291 } 292 db_list 293 } {main temp} 294 do_test attach3-12.5 { 295 execsql { 296 ATTACH DATABASE '' AS '' 297 } 298 db_list 299 } {main temp {}} 300 do_test attach3-12.6 { 301 execsql { 302 DETACH '' 303 } 304 db_list 305 } {main temp} 306 do_test attach3-12.7 { 307 execsql { 308 ATTACH DATABASE '' AS ? 309 } 310 db_list 311 } {main temp {}} 312 do_test attach3-12.8 { 313 execsql { 314 DETACH '' 315 } 316 db_list 317 } {main temp} 318 do_test attach3-12.9 { 319 execsql { 320 ATTACH DATABASE '' AS NULL 321 } 322 db_list 323 } {main temp {}} 324 do_test attach3-12.10 { 325 breakpoint 326 execsql { 327 DETACH ? 328 } 329 db_list 330 } {main temp} 331 do_test attach3-12.11 { 332 catchsql { 333 DETACH NULL 334 } 335 } {1 {no such database: }} 336 do_test attach3-12.12 { 337 catchsql { 338 ATTACH null AS null; 339 ATTACH '' AS ''; 340 } 341 } {1 {database is already in use}} 342 do_test attach3-12.13 { 343 db_list 344 } {main temp {}} 345 do_test attach3-12.14 { 346 execsql { 347 DETACH ''; 348 } 349 db_list 350 } {main temp} 351 352 } ;# ifcapable pragma 353 354 finish_test 355