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