1cbb18d22Sdanielk1977# 2003 July 1 2cbb18d22Sdanielk1977# 3cbb18d22Sdanielk1977# The author disclaims copyright to this source code. In place of 4cbb18d22Sdanielk1977# a legal notice, here is a blessing: 5cbb18d22Sdanielk1977# 6cbb18d22Sdanielk1977# May you do good and not evil. 7cbb18d22Sdanielk1977# May you find forgiveness for yourself and forgive others. 8cbb18d22Sdanielk1977# May you share freely, never taking more than you give. 9cbb18d22Sdanielk1977# 10cbb18d22Sdanielk1977#*********************************************************************** 11cbb18d22Sdanielk1977# This file implements regression tests for SQLite library. The 12cbb18d22Sdanielk1977# focus of this script is testing the ATTACH and DETACH commands 13cbb18d22Sdanielk1977# and schema changes to attached databases. 14cbb18d22Sdanielk1977# 155a8f9374Sdanielk1977# $Id: attach3.test,v 1.18 2007/10/09 08:29:32 danielk1977 Exp $ 16cbb18d22Sdanielk1977# 17cbb18d22Sdanielk1977 18cbb18d22Sdanielk1977set testdir [file dirname $argv0] 19cbb18d22Sdanielk1977source $testdir/tester.tcl 20cbb18d22Sdanielk1977 215a8f9374Sdanielk1977ifcapable !attach { 225a8f9374Sdanielk1977 finish_test 235a8f9374Sdanielk1977 return 245a8f9374Sdanielk1977} 255a8f9374Sdanielk1977 26523a087bSdan# The tests in this file were written before SQLite supported recursive 27523a087bSdan# trigger invocation, and some tests depend on that to pass. So disable 28523a087bSdan# recursive triggers for this file. 295bde73c4Sdancatchsql { pragma recursive_triggers = off } 30523a087bSdan 31cbb18d22Sdanielk1977# Create tables t1 and t2 in the main database 32cbb18d22Sdanielk1977execsql { 33cbb18d22Sdanielk1977 CREATE TABLE t1(a, b); 34cbb18d22Sdanielk1977 CREATE TABLE t2(c, d); 35cbb18d22Sdanielk1977} 36cbb18d22Sdanielk1977 37cbb18d22Sdanielk1977# Create tables t1 and t2 in database file test2.db 38fda06befSmistachkinforcedelete test2.db 39fda06befSmistachkinforcedelete test2.db-journal 40ef4ac8f9Sdrhsqlite3 db2 test2.db 41cbb18d22Sdanielk1977execsql { 42cbb18d22Sdanielk1977 CREATE TABLE t1(a, b); 43cbb18d22Sdanielk1977 CREATE TABLE t2(c, d); 44cbb18d22Sdanielk1977} db2 45cbb18d22Sdanielk1977db2 close 46cbb18d22Sdanielk1977 47cbb18d22Sdanielk1977# Create a table in the auxilary database. 48a8858103Sdanielk1977do_test attach3-1.1 { 49cbb18d22Sdanielk1977 execsql { 50cbb18d22Sdanielk1977 ATTACH 'test2.db' AS aux; 51cbb18d22Sdanielk1977 } 52cbb18d22Sdanielk1977} {} 53a8858103Sdanielk1977do_test attach3-1.2 { 54cbb18d22Sdanielk1977 execsql { 55cbb18d22Sdanielk1977 CREATE TABLE aux.t3(e, f); 56cbb18d22Sdanielk1977 } 57cbb18d22Sdanielk1977} {} 58a8858103Sdanielk1977do_test attach3-1.3 { 59cbb18d22Sdanielk1977 execsql { 60cbb18d22Sdanielk1977 SELECT * FROM sqlite_master WHERE name = 't3'; 61cbb18d22Sdanielk1977 } 62cbb18d22Sdanielk1977} {} 63a8858103Sdanielk1977do_test attach3-1.4 { 64cbb18d22Sdanielk1977 execsql { 65cbb18d22Sdanielk1977 SELECT * FROM aux.sqlite_master WHERE name = 't3'; 66cbb18d22Sdanielk1977 } 6745901d62Sdanielk1977} "table t3 t3 [expr $AUTOVACUUM?5:4] {CREATE TABLE t3(e, f)}" 68a8858103Sdanielk1977do_test attach3-1.5 { 69cbb18d22Sdanielk1977 execsql { 70cbb18d22Sdanielk1977 INSERT INTO t3 VALUES(1, 2); 71cbb18d22Sdanielk1977 SELECT * FROM t3; 72cbb18d22Sdanielk1977 } 73cbb18d22Sdanielk1977} {1 2} 74cbb18d22Sdanielk1977 75cbb18d22Sdanielk1977# Create an index on the auxilary database table. 76ef2cb63eSdanielk1977do_test attach3-2.1 { 77cbb18d22Sdanielk1977 execsql { 78cbb18d22Sdanielk1977 CREATE INDEX aux.i1 on t3(e); 79cbb18d22Sdanielk1977 } 80cbb18d22Sdanielk1977} {} 81ef2cb63eSdanielk1977do_test attach3-2.2 { 82cbb18d22Sdanielk1977 execsql { 83cbb18d22Sdanielk1977 SELECT * FROM sqlite_master WHERE name = 'i1'; 84cbb18d22Sdanielk1977 } 85cbb18d22Sdanielk1977} {} 86ef2cb63eSdanielk1977do_test attach3-2.3 { 87cbb18d22Sdanielk1977 execsql { 88cbb18d22Sdanielk1977 SELECT * FROM aux.sqlite_master WHERE name = 'i1'; 89cbb18d22Sdanielk1977 } 9045901d62Sdanielk1977} "index i1 t3 [expr $AUTOVACUUM?6:5] {CREATE INDEX i1 on t3(e)}" 91cbb18d22Sdanielk1977 92a8858103Sdanielk1977# Drop the index on the aux database table. 93ef2cb63eSdanielk1977do_test attach3-3.1 { 94a8858103Sdanielk1977 execsql { 95a8858103Sdanielk1977 DROP INDEX aux.i1; 96a8858103Sdanielk1977 SELECT * FROM aux.sqlite_master WHERE name = 'i1'; 97a8858103Sdanielk1977 } 98a8858103Sdanielk1977} {} 99ef2cb63eSdanielk1977do_test attach3-3.2 { 100a8858103Sdanielk1977 execsql { 101a8858103Sdanielk1977 CREATE INDEX aux.i1 on t3(e); 102a8858103Sdanielk1977 SELECT * FROM aux.sqlite_master WHERE name = 'i1'; 103a8858103Sdanielk1977 } 10445901d62Sdanielk1977} "index i1 t3 [expr $AUTOVACUUM?6:5] {CREATE INDEX i1 on t3(e)}" 105ef2cb63eSdanielk1977do_test attach3-3.3 { 106a8858103Sdanielk1977 execsql { 107a8858103Sdanielk1977 DROP INDEX i1; 108a8858103Sdanielk1977 SELECT * FROM aux.sqlite_master WHERE name = 'i1'; 109a8858103Sdanielk1977 } 110a8858103Sdanielk1977} {} 111a8858103Sdanielk1977 11248dec7e2Sdanielk1977# Drop tables t1 and t2 in the auxilary database. 113ef2cb63eSdanielk1977do_test attach3-4.1 { 114a8858103Sdanielk1977 execsql { 115a8858103Sdanielk1977 DROP TABLE aux.t1; 116a8858103Sdanielk1977 SELECT name FROM aux.sqlite_master; 117a8858103Sdanielk1977 } 118a8858103Sdanielk1977} {t2 t3} 119ef2cb63eSdanielk1977do_test attach3-4.2 { 120a8858103Sdanielk1977 # This will drop main.t2 121a8858103Sdanielk1977 execsql { 122a8858103Sdanielk1977 DROP TABLE t2; 123a8858103Sdanielk1977 SELECT name FROM aux.sqlite_master; 124a8858103Sdanielk1977 } 125a8858103Sdanielk1977} {t2 t3} 126ef2cb63eSdanielk1977do_test attach3-4.3 { 127a8858103Sdanielk1977 execsql { 128a8858103Sdanielk1977 DROP TABLE t2; 129a8858103Sdanielk1977 SELECT name FROM aux.sqlite_master; 130a8858103Sdanielk1977 } 131a8858103Sdanielk1977} {t3} 13248dec7e2Sdanielk1977 13348dec7e2Sdanielk1977# Create a view in the auxilary database. 1340fa8ddbdSdanielk1977ifcapable view { 135ef2cb63eSdanielk1977do_test attach3-5.1 { 136a8858103Sdanielk1977 execsql { 13748dec7e2Sdanielk1977 CREATE VIEW aux.v1 AS SELECT * FROM t3; 13848dec7e2Sdanielk1977 } 13948dec7e2Sdanielk1977} {} 140ef2cb63eSdanielk1977do_test attach3-5.2 { 14148dec7e2Sdanielk1977 execsql { 14248dec7e2Sdanielk1977 SELECT * FROM aux.sqlite_master WHERE name = 'v1'; 14348dec7e2Sdanielk1977 } 14448dec7e2Sdanielk1977} {view v1 v1 0 {CREATE VIEW v1 AS SELECT * FROM t3}} 145ef2cb63eSdanielk1977do_test attach3-5.3 { 14648dec7e2Sdanielk1977 execsql { 14748dec7e2Sdanielk1977 INSERT INTO aux.t3 VALUES('hello', 'world'); 14848dec7e2Sdanielk1977 SELECT * FROM v1; 14948dec7e2Sdanielk1977 } 15048dec7e2Sdanielk1977} {1 2 hello world} 15148dec7e2Sdanielk1977 15248dec7e2Sdanielk1977# Drop the view 153ef2cb63eSdanielk1977do_test attach3-6.1 { 15448dec7e2Sdanielk1977 execsql { 15548dec7e2Sdanielk1977 DROP VIEW aux.v1; 15648dec7e2Sdanielk1977 } 15748dec7e2Sdanielk1977} {} 158ef2cb63eSdanielk1977do_test attach3-6.2 { 15948dec7e2Sdanielk1977 execsql { 16048dec7e2Sdanielk1977 SELECT * FROM aux.sqlite_master WHERE name = 'v1'; 161a8858103Sdanielk1977 } 162a8858103Sdanielk1977} {} 1630fa8ddbdSdanielk1977} ;# ifcapable view 164a8858103Sdanielk1977 165798da52cSdrhifcapable {trigger} { 166ef2cb63eSdanielk1977# Create a trigger in the auxilary database. 167ef2cb63eSdanielk1977do_test attach3-7.1 { 168ef2cb63eSdanielk1977 execsql { 169ef2cb63eSdanielk1977 CREATE TRIGGER aux.tr1 AFTER INSERT ON t3 BEGIN 170ef2cb63eSdanielk1977 INSERT INTO t3 VALUES(new.e*2, new.f*2); 171ef2cb63eSdanielk1977 END; 172ef2cb63eSdanielk1977 } 173ef2cb63eSdanielk1977} {} 174ef2cb63eSdanielk1977do_test attach3-7.2 { 175ef2cb63eSdanielk1977 execsql { 176ef2cb63eSdanielk1977 DELETE FROM t3; 177ef2cb63eSdanielk1977 INSERT INTO t3 VALUES(10, 20); 178ef2cb63eSdanielk1977 SELECT * FROM t3; 179ef2cb63eSdanielk1977 } 180ef2cb63eSdanielk1977} {10 20 20 40} 181ef2cb63eSdanielk1977do_test attach3-5.3 { 182ef2cb63eSdanielk1977 execsql { 183ef2cb63eSdanielk1977 SELECT * FROM aux.sqlite_master WHERE name = 'tr1'; 184ef2cb63eSdanielk1977 } 1853df6b257Sdanielk1977} {trigger tr1 t3 0 {CREATE TRIGGER tr1 AFTER INSERT ON t3 BEGIN 186ef2cb63eSdanielk1977 INSERT INTO t3 VALUES(new.e*2, new.f*2); 187ef2cb63eSdanielk1977 END}} 188ef2cb63eSdanielk1977 189ef2cb63eSdanielk1977# Drop the trigger 190ef2cb63eSdanielk1977do_test attach3-8.1 { 191ef2cb63eSdanielk1977 execsql { 192ef2cb63eSdanielk1977 DROP TRIGGER aux.tr1; 193ef2cb63eSdanielk1977 } 194ef2cb63eSdanielk1977} {} 195ef2cb63eSdanielk1977do_test attach3-8.2 { 196ef2cb63eSdanielk1977 execsql { 197ef2cb63eSdanielk1977 SELECT * FROM aux.sqlite_master WHERE name = 'tr1'; 198ef2cb63eSdanielk1977 } 199ef2cb63eSdanielk1977} {} 200ef2cb63eSdanielk1977 20153c0f748Sdanielk1977ifcapable tempdb { 2028e227875Sdanielk1977 # Try to trick SQLite into dropping the wrong temp trigger. 2038e227875Sdanielk1977 do_test attach3-9.0 { 2048e227875Sdanielk1977 execsql { 2058e227875Sdanielk1977 CREATE TABLE main.t4(a, b, c); 2068e227875Sdanielk1977 CREATE TABLE aux.t4(a, b, c); 2078e227875Sdanielk1977 CREATE TEMP TRIGGER tst_trigger BEFORE INSERT ON aux.t4 BEGIN 2088e227875Sdanielk1977 SELECT 'hello world'; 2098e227875Sdanielk1977 END; 210*e0a04a36Sdrh SELECT count(*) FROM temp.sqlite_master; 2118e227875Sdanielk1977 } 2128e227875Sdanielk1977 } {1} 2138e227875Sdanielk1977 do_test attach3-9.1 { 2148e227875Sdanielk1977 execsql { 2158e227875Sdanielk1977 DROP TABLE main.t4; 2168e227875Sdanielk1977 SELECT count(*) FROM sqlite_temp_master; 2178e227875Sdanielk1977 } 2188e227875Sdanielk1977 } {1} 2198e227875Sdanielk1977 do_test attach3-9.2 { 2208e227875Sdanielk1977 execsql { 2218e227875Sdanielk1977 DROP TABLE aux.t4; 222*e0a04a36Sdrh SELECT count(*) FROM temp.sqlite_master; 2238e227875Sdanielk1977 } 2248e227875Sdanielk1977 } {0} 22553c0f748Sdanielk1977} 226798da52cSdrh} ;# endif trigger 2278e227875Sdanielk1977 228d008cfe3Sdanielk1977# Make sure the aux.sqlite_master table is read-only 229d008cfe3Sdanielk1977do_test attach3-10.0 { 230d008cfe3Sdanielk1977 catchsql { 231d008cfe3Sdanielk1977 INSERT INTO aux.sqlite_master VALUES(1, 2, 3, 4, 5); 232d008cfe3Sdanielk1977 } 233d008cfe3Sdanielk1977} {1 {table sqlite_master may not be modified}} 234d008cfe3Sdanielk1977 235755b6ba9Sdrh# Failure to attach leaves us in a workable state. 236755b6ba9Sdrh# Ticket #811 237755b6ba9Sdrh# 238755b6ba9Sdrhdo_test attach3-11.0 { 239755b6ba9Sdrh catchsql { 240755b6ba9Sdrh ATTACH DATABASE '/nodir/nofile.x' AS notadb; 241755b6ba9Sdrh } 242755b6ba9Sdrh} {1 {unable to open database: /nodir/nofile.x}} 243755b6ba9Sdrhdo_test attach3-11.1 { 244755b6ba9Sdrh catchsql { 245755b6ba9Sdrh ATTACH DATABASE ':memory:' AS notadb; 246755b6ba9Sdrh } 247755b6ba9Sdrh} {0 {}} 248755b6ba9Sdrhdo_test attach3-11.2 { 249755b6ba9Sdrh catchsql { 250755b6ba9Sdrh DETACH DATABASE notadb; 251755b6ba9Sdrh } 252755b6ba9Sdrh} {0 {}} 253d008cfe3Sdanielk1977 254ea063f5bSdrh# Return a list of attached databases 255ea063f5bSdrh# 256ea063f5bSdrhproc db_list {} { 257ea063f5bSdrh set x [execsql { 258ea063f5bSdrh PRAGMA database_list; 259ea063f5bSdrh }] 260ea063f5bSdrh set y {} 261ea063f5bSdrh foreach {n id file} $x {lappend y $id} 262ea063f5bSdrh return $y 263ea063f5bSdrh} 264ea063f5bSdrh 2654b2688abSdanielk1977ifcapable schema_pragmas&&tempdb { 2664b2688abSdanielk1977 2674b2688abSdanielk1977ifcapable !trigger { 2684b2688abSdanielk1977 execsql {create temp table dummy(dummy)} 2694b2688abSdanielk1977} 2704b2688abSdanielk1977 271ea063f5bSdrh# Ticket #1825 272ea063f5bSdrh# 273ea063f5bSdrhdo_test attach3-12.1 { 274ea063f5bSdrh db_list 275ea063f5bSdrh} {main temp aux} 276ea063f5bSdrhdo_test attach3-12.2 { 277ea063f5bSdrh execsql { 278ea063f5bSdrh ATTACH DATABASE ? AS ? 279ea063f5bSdrh } 280ea063f5bSdrh db_list 281ea063f5bSdrh} {main temp aux {}} 282ea063f5bSdrhdo_test attach3-12.3 { 283ea063f5bSdrh execsql { 284ea063f5bSdrh DETACH aux 285ea063f5bSdrh } 286ea063f5bSdrh db_list 287ea063f5bSdrh} {main temp {}} 288ea063f5bSdrhdo_test attach3-12.4 { 289ea063f5bSdrh execsql { 290ea063f5bSdrh DETACH ? 291ea063f5bSdrh } 292ea063f5bSdrh db_list 293ea063f5bSdrh} {main temp} 294ea063f5bSdrhdo_test attach3-12.5 { 295ea063f5bSdrh execsql { 296ea063f5bSdrh ATTACH DATABASE '' AS '' 297ea063f5bSdrh } 298ea063f5bSdrh db_list 299ea063f5bSdrh} {main temp {}} 300ea063f5bSdrhdo_test attach3-12.6 { 301ea063f5bSdrh execsql { 302ea063f5bSdrh DETACH '' 303ea063f5bSdrh } 304ea063f5bSdrh db_list 305ea063f5bSdrh} {main temp} 306ea063f5bSdrhdo_test attach3-12.7 { 307ea063f5bSdrh execsql { 308ea063f5bSdrh ATTACH DATABASE '' AS ? 309ea063f5bSdrh } 310ea063f5bSdrh db_list 311ea063f5bSdrh} {main temp {}} 312ea063f5bSdrhdo_test attach3-12.8 { 313ea063f5bSdrh execsql { 314ea063f5bSdrh DETACH '' 315ea063f5bSdrh } 316ea063f5bSdrh db_list 317ea063f5bSdrh} {main temp} 318ea063f5bSdrhdo_test attach3-12.9 { 319ea063f5bSdrh execsql { 320ea063f5bSdrh ATTACH DATABASE '' AS NULL 321ea063f5bSdrh } 322ea063f5bSdrh db_list 323ea063f5bSdrh} {main temp {}} 324ea063f5bSdrhdo_test attach3-12.10 { 325ea063f5bSdrh execsql { 326ea063f5bSdrh DETACH ? 327ea063f5bSdrh } 328ea063f5bSdrh db_list 329ea063f5bSdrh} {main temp} 330ea063f5bSdrhdo_test attach3-12.11 { 331ea063f5bSdrh catchsql { 332ea063f5bSdrh DETACH NULL 333ea063f5bSdrh } 334ea063f5bSdrh} {1 {no such database: }} 335ea063f5bSdrhdo_test attach3-12.12 { 336ea063f5bSdrh catchsql { 337ea063f5bSdrh ATTACH null AS null; 338ea063f5bSdrh ATTACH '' AS ''; 339ea063f5bSdrh } 340ea063f5bSdrh} {1 {database is already in use}} 341ea063f5bSdrhdo_test attach3-12.13 { 342ea063f5bSdrh db_list 343ea063f5bSdrh} {main temp {}} 344ea063f5bSdrhdo_test attach3-12.14 { 345ea063f5bSdrh execsql { 346ea063f5bSdrh DETACH ''; 347ea063f5bSdrh } 348ea063f5bSdrh db_list 349ea063f5bSdrh} {main temp} 350ea063f5bSdrh 3514b2688abSdanielk1977} ;# ifcapable pragma 3524b2688abSdanielk1977 353cbb18d22Sdanielk1977finish_test 354