sl@0: # 2003 July 1 sl@0: # sl@0: # The author disclaims copyright to this source code. In place of sl@0: # a legal notice, here is a blessing: sl@0: # sl@0: # May you do good and not evil. sl@0: # May you find forgiveness for yourself and forgive others. sl@0: # May you share freely, never taking more than you give. sl@0: # sl@0: #*********************************************************************** sl@0: # This file implements regression tests for SQLite library. The sl@0: # focus of this script is testing the ATTACH and DETACH commands sl@0: # and schema changes to attached databases. sl@0: # sl@0: # $Id: attach3.test,v 1.18 2007/10/09 08:29:32 danielk1977 Exp $ sl@0: # sl@0: sl@0: set testdir [file dirname $argv0] sl@0: source $testdir/tester.tcl sl@0: sl@0: ifcapable !attach { sl@0: finish_test sl@0: return sl@0: } sl@0: sl@0: # Create tables t1 and t2 in the main database sl@0: execsql { sl@0: CREATE TABLE t1(a, b); sl@0: CREATE TABLE t2(c, d); sl@0: } sl@0: sl@0: # Create tables t1 and t2 in database file test2.db sl@0: file delete -force test2.db sl@0: file delete -force test2.db-journal sl@0: sqlite3 db2 test2.db sl@0: execsql { sl@0: CREATE TABLE t1(a, b); sl@0: CREATE TABLE t2(c, d); sl@0: } db2 sl@0: db2 close sl@0: sl@0: # Create a table in the auxilary database. sl@0: do_test attach3-1.1 { sl@0: execsql { sl@0: ATTACH 'test2.db' AS aux; sl@0: } sl@0: } {} sl@0: do_test attach3-1.2 { sl@0: execsql { sl@0: CREATE TABLE aux.t3(e, f); sl@0: } sl@0: } {} sl@0: do_test attach3-1.3 { sl@0: execsql { sl@0: SELECT * FROM sqlite_master WHERE name = 't3'; sl@0: } sl@0: } {} sl@0: do_test attach3-1.4 { sl@0: execsql { sl@0: SELECT * FROM aux.sqlite_master WHERE name = 't3'; sl@0: } sl@0: } "table t3 t3 [expr $AUTOVACUUM?5:4] {CREATE TABLE t3(e, f)}" sl@0: do_test attach3-1.5 { sl@0: execsql { sl@0: INSERT INTO t3 VALUES(1, 2); sl@0: SELECT * FROM t3; sl@0: } sl@0: } {1 2} sl@0: sl@0: # Create an index on the auxilary database table. sl@0: do_test attach3-2.1 { sl@0: execsql { sl@0: CREATE INDEX aux.i1 on t3(e); sl@0: } sl@0: } {} sl@0: do_test attach3-2.2 { sl@0: execsql { sl@0: SELECT * FROM sqlite_master WHERE name = 'i1'; sl@0: } sl@0: } {} sl@0: do_test attach3-2.3 { sl@0: execsql { sl@0: SELECT * FROM aux.sqlite_master WHERE name = 'i1'; sl@0: } sl@0: } "index i1 t3 [expr $AUTOVACUUM?6:5] {CREATE INDEX i1 on t3(e)}" sl@0: sl@0: # Drop the index on the aux database table. sl@0: do_test attach3-3.1 { sl@0: execsql { sl@0: DROP INDEX aux.i1; sl@0: SELECT * FROM aux.sqlite_master WHERE name = 'i1'; sl@0: } sl@0: } {} sl@0: do_test attach3-3.2 { sl@0: execsql { sl@0: CREATE INDEX aux.i1 on t3(e); sl@0: SELECT * FROM aux.sqlite_master WHERE name = 'i1'; sl@0: } sl@0: } "index i1 t3 [expr $AUTOVACUUM?6:5] {CREATE INDEX i1 on t3(e)}" sl@0: do_test attach3-3.3 { sl@0: execsql { sl@0: DROP INDEX i1; sl@0: SELECT * FROM aux.sqlite_master WHERE name = 'i1'; sl@0: } sl@0: } {} sl@0: sl@0: # Drop tables t1 and t2 in the auxilary database. sl@0: do_test attach3-4.1 { sl@0: execsql { sl@0: DROP TABLE aux.t1; sl@0: SELECT name FROM aux.sqlite_master; sl@0: } sl@0: } {t2 t3} sl@0: do_test attach3-4.2 { sl@0: # This will drop main.t2 sl@0: execsql { sl@0: DROP TABLE t2; sl@0: SELECT name FROM aux.sqlite_master; sl@0: } sl@0: } {t2 t3} sl@0: do_test attach3-4.3 { sl@0: execsql { sl@0: DROP TABLE t2; sl@0: SELECT name FROM aux.sqlite_master; sl@0: } sl@0: } {t3} sl@0: sl@0: # Create a view in the auxilary database. sl@0: ifcapable view { sl@0: do_test attach3-5.1 { sl@0: execsql { sl@0: CREATE VIEW aux.v1 AS SELECT * FROM t3; sl@0: } sl@0: } {} sl@0: do_test attach3-5.2 { sl@0: execsql { sl@0: SELECT * FROM aux.sqlite_master WHERE name = 'v1'; sl@0: } sl@0: } {view v1 v1 0 {CREATE VIEW v1 AS SELECT * FROM t3}} sl@0: do_test attach3-5.3 { sl@0: execsql { sl@0: INSERT INTO aux.t3 VALUES('hello', 'world'); sl@0: SELECT * FROM v1; sl@0: } sl@0: } {1 2 hello world} sl@0: sl@0: # Drop the view sl@0: do_test attach3-6.1 { sl@0: execsql { sl@0: DROP VIEW aux.v1; sl@0: } sl@0: } {} sl@0: do_test attach3-6.2 { sl@0: execsql { sl@0: SELECT * FROM aux.sqlite_master WHERE name = 'v1'; sl@0: } sl@0: } {} sl@0: } ;# ifcapable view sl@0: sl@0: ifcapable {trigger} { sl@0: # Create a trigger in the auxilary database. sl@0: do_test attach3-7.1 { sl@0: execsql { sl@0: CREATE TRIGGER aux.tr1 AFTER INSERT ON t3 BEGIN sl@0: INSERT INTO t3 VALUES(new.e*2, new.f*2); sl@0: END; sl@0: } sl@0: } {} sl@0: do_test attach3-7.2 { sl@0: execsql { sl@0: DELETE FROM t3; sl@0: INSERT INTO t3 VALUES(10, 20); sl@0: SELECT * FROM t3; sl@0: } sl@0: } {10 20 20 40} sl@0: do_test attach3-5.3 { sl@0: execsql { sl@0: SELECT * FROM aux.sqlite_master WHERE name = 'tr1'; sl@0: } sl@0: } {trigger tr1 t3 0 {CREATE TRIGGER tr1 AFTER INSERT ON t3 BEGIN sl@0: INSERT INTO t3 VALUES(new.e*2, new.f*2); sl@0: END}} sl@0: sl@0: # Drop the trigger sl@0: do_test attach3-8.1 { sl@0: execsql { sl@0: DROP TRIGGER aux.tr1; sl@0: } sl@0: } {} sl@0: do_test attach3-8.2 { sl@0: execsql { sl@0: SELECT * FROM aux.sqlite_master WHERE name = 'tr1'; sl@0: } sl@0: } {} sl@0: sl@0: ifcapable tempdb { sl@0: # Try to trick SQLite into dropping the wrong temp trigger. sl@0: do_test attach3-9.0 { sl@0: execsql { sl@0: CREATE TABLE main.t4(a, b, c); sl@0: CREATE TABLE aux.t4(a, b, c); sl@0: CREATE TEMP TRIGGER tst_trigger BEFORE INSERT ON aux.t4 BEGIN sl@0: SELECT 'hello world'; sl@0: END; sl@0: SELECT count(*) FROM sqlite_temp_master; sl@0: } sl@0: } {1} sl@0: do_test attach3-9.1 { sl@0: execsql { sl@0: DROP TABLE main.t4; sl@0: SELECT count(*) FROM sqlite_temp_master; sl@0: } sl@0: } {1} sl@0: do_test attach3-9.2 { sl@0: execsql { sl@0: DROP TABLE aux.t4; sl@0: SELECT count(*) FROM sqlite_temp_master; sl@0: } sl@0: } {0} sl@0: } sl@0: } ;# endif trigger sl@0: sl@0: # Make sure the aux.sqlite_master table is read-only sl@0: do_test attach3-10.0 { sl@0: catchsql { sl@0: INSERT INTO aux.sqlite_master VALUES(1, 2, 3, 4, 5); sl@0: } sl@0: } {1 {table sqlite_master may not be modified}} sl@0: sl@0: # Failure to attach leaves us in a workable state. sl@0: # Ticket #811 sl@0: # Symbian OS: '/' in the file name replaced with '\' sl@0: do_test attach3-11.0 { sl@0: catchsql { sl@0: ATTACH DATABASE '\nodir\nofile.x' AS notadb; sl@0: } sl@0: } {1 {unable to open database: \nodir\nofile.x}} sl@0: do_test attach3-11.1 { sl@0: catchsql { sl@0: ATTACH DATABASE ':memory:' AS notadb; sl@0: } sl@0: } {0 {}} sl@0: do_test attach3-11.2 { sl@0: catchsql { sl@0: DETACH DATABASE notadb; sl@0: } sl@0: } {0 {}} sl@0: sl@0: # Return a list of attached databases sl@0: # sl@0: proc db_list {} { sl@0: set x [execsql { sl@0: PRAGMA database_list; sl@0: }] sl@0: set y {} sl@0: foreach {n id file} $x {lappend y $id} sl@0: return $y sl@0: } sl@0: sl@0: ifcapable schema_pragmas&&tempdb { sl@0: sl@0: ifcapable !trigger { sl@0: execsql {create temp table dummy(dummy)} sl@0: } sl@0: sl@0: # Ticket #1825 sl@0: # sl@0: do_test attach3-12.1 { sl@0: db_list sl@0: } {main temp aux} sl@0: do_test attach3-12.2 { sl@0: execsql { sl@0: ATTACH DATABASE ? AS ? sl@0: } sl@0: db_list sl@0: } {main temp aux {}} sl@0: do_test attach3-12.3 { sl@0: execsql { sl@0: DETACH aux sl@0: } sl@0: db_list sl@0: } {main temp {}} sl@0: do_test attach3-12.4 { sl@0: execsql { sl@0: DETACH ? sl@0: } sl@0: db_list sl@0: } {main temp} sl@0: do_test attach3-12.5 { sl@0: execsql { sl@0: ATTACH DATABASE '' AS '' sl@0: } sl@0: db_list sl@0: } {main temp {}} sl@0: do_test attach3-12.6 { sl@0: execsql { sl@0: DETACH '' sl@0: } sl@0: db_list sl@0: } {main temp} sl@0: do_test attach3-12.7 { sl@0: execsql { sl@0: ATTACH DATABASE '' AS ? sl@0: } sl@0: db_list sl@0: } {main temp {}} sl@0: do_test attach3-12.8 { sl@0: execsql { sl@0: DETACH '' sl@0: } sl@0: db_list sl@0: } {main temp} sl@0: do_test attach3-12.9 { sl@0: execsql { sl@0: ATTACH DATABASE '' AS NULL sl@0: } sl@0: db_list sl@0: } {main temp {}} sl@0: do_test attach3-12.10 { sl@0: execsql { sl@0: DETACH ? sl@0: } sl@0: db_list sl@0: } {main temp} sl@0: do_test attach3-12.11 { sl@0: catchsql { sl@0: DETACH NULL sl@0: } sl@0: } {1 {no such database: }} sl@0: do_test attach3-12.12 { sl@0: catchsql { sl@0: ATTACH null AS null; sl@0: ATTACH '' AS ''; sl@0: } sl@0: } {1 {database is already in use}} sl@0: do_test attach3-12.13 { sl@0: db_list sl@0: } {main temp {}} sl@0: do_test attach3-12.14 { sl@0: execsql { sl@0: DETACH ''; sl@0: } sl@0: db_list sl@0: } {main temp} sl@0: sl@0: } ;# ifcapable pragma sl@0: sl@0: finish_test