sl@0
|
1 |
# 2003 April 4
|
sl@0
|
2 |
#
|
sl@0
|
3 |
# The author disclaims copyright to this source code. In place of
|
sl@0
|
4 |
# a legal notice, here is a blessing:
|
sl@0
|
5 |
#
|
sl@0
|
6 |
# May you do good and not evil.
|
sl@0
|
7 |
# May you find forgiveness for yourself and forgive others.
|
sl@0
|
8 |
# May you share freely, never taking more than you give.
|
sl@0
|
9 |
#
|
sl@0
|
10 |
#***********************************************************************
|
sl@0
|
11 |
# This file implements regression tests for SQLite library. The
|
sl@0
|
12 |
# focus of this script is testing the ATTACH and DETACH commands
|
sl@0
|
13 |
# and related functionality.
|
sl@0
|
14 |
#
|
sl@0
|
15 |
# $Id: attach.test,v 1.49 2008/07/12 14:52:20 drh Exp $
|
sl@0
|
16 |
#
|
sl@0
|
17 |
|
sl@0
|
18 |
set testdir [file dirname $argv0]
|
sl@0
|
19 |
source $testdir/tester.tcl
|
sl@0
|
20 |
|
sl@0
|
21 |
ifcapable !attach {
|
sl@0
|
22 |
finish_test
|
sl@0
|
23 |
return
|
sl@0
|
24 |
}
|
sl@0
|
25 |
|
sl@0
|
26 |
for {set i 2} {$i<=15} {incr i} {
|
sl@0
|
27 |
file delete -force test$i.db
|
sl@0
|
28 |
file delete -force test$i.db-journal
|
sl@0
|
29 |
}
|
sl@0
|
30 |
|
sl@0
|
31 |
do_test attach-1.1 {
|
sl@0
|
32 |
execsql {
|
sl@0
|
33 |
CREATE TABLE t1(a,b);
|
sl@0
|
34 |
INSERT INTO t1 VALUES(1,2);
|
sl@0
|
35 |
INSERT INTO t1 VALUES(3,4);
|
sl@0
|
36 |
SELECT * FROM t1;
|
sl@0
|
37 |
}
|
sl@0
|
38 |
} {1 2 3 4}
|
sl@0
|
39 |
do_test attach-1.2 {
|
sl@0
|
40 |
sqlite3 db2 test2.db
|
sl@0
|
41 |
execsql {
|
sl@0
|
42 |
CREATE TABLE t2(x,y);
|
sl@0
|
43 |
INSERT INTO t2 VALUES(1,'x');
|
sl@0
|
44 |
INSERT INTO t2 VALUES(2,'y');
|
sl@0
|
45 |
SELECT * FROM t2;
|
sl@0
|
46 |
} db2
|
sl@0
|
47 |
} {1 x 2 y}
|
sl@0
|
48 |
do_test attach-1.3 {
|
sl@0
|
49 |
execsql {
|
sl@0
|
50 |
ATTACH DATABASE 'test2.db' AS two;
|
sl@0
|
51 |
SELECT * FROM two.t2;
|
sl@0
|
52 |
}
|
sl@0
|
53 |
} {1 x 2 y}
|
sl@0
|
54 |
do_test attach-1.4 {
|
sl@0
|
55 |
execsql {
|
sl@0
|
56 |
SELECT * FROM t2;
|
sl@0
|
57 |
}
|
sl@0
|
58 |
} {1 x 2 y}
|
sl@0
|
59 |
do_test attach-1.5 {
|
sl@0
|
60 |
execsql {
|
sl@0
|
61 |
DETACH DATABASE two;
|
sl@0
|
62 |
SELECT * FROM t1;
|
sl@0
|
63 |
}
|
sl@0
|
64 |
} {1 2 3 4}
|
sl@0
|
65 |
do_test attach-1.6 {
|
sl@0
|
66 |
catchsql {
|
sl@0
|
67 |
SELECT * FROM t2;
|
sl@0
|
68 |
}
|
sl@0
|
69 |
} {1 {no such table: t2}}
|
sl@0
|
70 |
do_test attach-1.7 {
|
sl@0
|
71 |
catchsql {
|
sl@0
|
72 |
SELECT * FROM two.t2;
|
sl@0
|
73 |
}
|
sl@0
|
74 |
} {1 {no such table: two.t2}}
|
sl@0
|
75 |
do_test attach-1.8 {
|
sl@0
|
76 |
catchsql {
|
sl@0
|
77 |
ATTACH DATABASE 'test3.db' AS three;
|
sl@0
|
78 |
}
|
sl@0
|
79 |
} {0 {}}
|
sl@0
|
80 |
do_test attach-1.9 {
|
sl@0
|
81 |
catchsql {
|
sl@0
|
82 |
SELECT * FROM three.sqlite_master;
|
sl@0
|
83 |
}
|
sl@0
|
84 |
} {0 {}}
|
sl@0
|
85 |
do_test attach-1.10 {
|
sl@0
|
86 |
catchsql {
|
sl@0
|
87 |
DETACH DATABASE [three];
|
sl@0
|
88 |
}
|
sl@0
|
89 |
} {0 {}}
|
sl@0
|
90 |
do_test attach-1.11 {
|
sl@0
|
91 |
execsql {
|
sl@0
|
92 |
ATTACH 'test.db' AS db2;
|
sl@0
|
93 |
ATTACH 'test.db' AS db3;
|
sl@0
|
94 |
ATTACH 'test.db' AS db4;
|
sl@0
|
95 |
ATTACH 'test.db' AS db5;
|
sl@0
|
96 |
ATTACH 'test.db' AS db6;
|
sl@0
|
97 |
ATTACH 'test.db' AS db7;
|
sl@0
|
98 |
ATTACH 'test.db' AS db8;
|
sl@0
|
99 |
ATTACH 'test.db' AS db9;
|
sl@0
|
100 |
}
|
sl@0
|
101 |
} {}
|
sl@0
|
102 |
proc db_list {db} {
|
sl@0
|
103 |
set list {}
|
sl@0
|
104 |
foreach {idx name file} [execsql {PRAGMA database_list} $db] {
|
sl@0
|
105 |
lappend list $idx $name
|
sl@0
|
106 |
}
|
sl@0
|
107 |
return $list
|
sl@0
|
108 |
}
|
sl@0
|
109 |
ifcapable schema_pragmas {
|
sl@0
|
110 |
do_test attach-1.11b {
|
sl@0
|
111 |
db_list db
|
sl@0
|
112 |
} {0 main 2 db2 3 db3 4 db4 5 db5 6 db6 7 db7 8 db8 9 db9}
|
sl@0
|
113 |
} ;# ifcapable schema_pragmas
|
sl@0
|
114 |
do_test attach-1.12 {
|
sl@0
|
115 |
catchsql {
|
sl@0
|
116 |
ATTACH 'test.db' as db2;
|
sl@0
|
117 |
}
|
sl@0
|
118 |
} {1 {database db2 is already in use}}
|
sl@0
|
119 |
do_test attach-1.12.2 {
|
sl@0
|
120 |
db errorcode
|
sl@0
|
121 |
} {1}
|
sl@0
|
122 |
do_test attach-1.13 {
|
sl@0
|
123 |
catchsql {
|
sl@0
|
124 |
ATTACH 'test.db' as db5;
|
sl@0
|
125 |
}
|
sl@0
|
126 |
} {1 {database db5 is already in use}}
|
sl@0
|
127 |
do_test attach-1.14 {
|
sl@0
|
128 |
catchsql {
|
sl@0
|
129 |
ATTACH 'test.db' as db9;
|
sl@0
|
130 |
}
|
sl@0
|
131 |
} {1 {database db9 is already in use}}
|
sl@0
|
132 |
do_test attach-1.15 {
|
sl@0
|
133 |
catchsql {
|
sl@0
|
134 |
ATTACH 'test.db' as main;
|
sl@0
|
135 |
}
|
sl@0
|
136 |
} {1 {database main is already in use}}
|
sl@0
|
137 |
ifcapable tempdb {
|
sl@0
|
138 |
do_test attach-1.16 {
|
sl@0
|
139 |
catchsql {
|
sl@0
|
140 |
ATTACH 'test.db' as temp;
|
sl@0
|
141 |
}
|
sl@0
|
142 |
} {1 {database temp is already in use}}
|
sl@0
|
143 |
}
|
sl@0
|
144 |
do_test attach-1.17 {
|
sl@0
|
145 |
catchsql {
|
sl@0
|
146 |
ATTACH 'test.db' as MAIN;
|
sl@0
|
147 |
}
|
sl@0
|
148 |
} {1 {database MAIN is already in use}}
|
sl@0
|
149 |
do_test attach-1.18 {
|
sl@0
|
150 |
catchsql {
|
sl@0
|
151 |
ATTACH 'test.db' as db10;
|
sl@0
|
152 |
ATTACH 'test.db' as db11;
|
sl@0
|
153 |
}
|
sl@0
|
154 |
} {0 {}}
|
sl@0
|
155 |
do_test attach-1.19 {
|
sl@0
|
156 |
catchsql {
|
sl@0
|
157 |
ATTACH 'test.db' as db12;
|
sl@0
|
158 |
}
|
sl@0
|
159 |
} {1 {too many attached databases - max 10}}
|
sl@0
|
160 |
do_test attach-1.19.1 {
|
sl@0
|
161 |
db errorcode
|
sl@0
|
162 |
} {1}
|
sl@0
|
163 |
do_test attach-1.20.1 {
|
sl@0
|
164 |
execsql {
|
sl@0
|
165 |
DETACH db5;
|
sl@0
|
166 |
}
|
sl@0
|
167 |
} {}
|
sl@0
|
168 |
ifcapable schema_pragmas {
|
sl@0
|
169 |
do_test attach-1.20.2 {
|
sl@0
|
170 |
db_list db
|
sl@0
|
171 |
} {0 main 2 db2 3 db3 4 db4 5 db6 6 db7 7 db8 8 db9 9 db10 10 db11}
|
sl@0
|
172 |
} ;# ifcapable schema_pragmas
|
sl@0
|
173 |
integrity_check attach-1.20.3
|
sl@0
|
174 |
ifcapable tempdb {
|
sl@0
|
175 |
execsql {select * from sqlite_temp_master}
|
sl@0
|
176 |
}
|
sl@0
|
177 |
do_test attach-1.21 {
|
sl@0
|
178 |
catchsql {
|
sl@0
|
179 |
ATTACH 'test.db' as db12;
|
sl@0
|
180 |
}
|
sl@0
|
181 |
} {0 {}}
|
sl@0
|
182 |
do_test attach-1.22 {
|
sl@0
|
183 |
catchsql {
|
sl@0
|
184 |
ATTACH 'test.db' as db13;
|
sl@0
|
185 |
}
|
sl@0
|
186 |
} {1 {too many attached databases - max 10}}
|
sl@0
|
187 |
do_test attach-1.22.1 {
|
sl@0
|
188 |
db errorcode
|
sl@0
|
189 |
} {1}
|
sl@0
|
190 |
do_test attach-1.23 {
|
sl@0
|
191 |
catchsql {
|
sl@0
|
192 |
DETACH "db14";
|
sl@0
|
193 |
}
|
sl@0
|
194 |
} {1 {no such database: db14}}
|
sl@0
|
195 |
do_test attach-1.24 {
|
sl@0
|
196 |
catchsql {
|
sl@0
|
197 |
DETACH db12;
|
sl@0
|
198 |
}
|
sl@0
|
199 |
} {0 {}}
|
sl@0
|
200 |
do_test attach-1.25 {
|
sl@0
|
201 |
catchsql {
|
sl@0
|
202 |
DETACH db12;
|
sl@0
|
203 |
}
|
sl@0
|
204 |
} {1 {no such database: db12}}
|
sl@0
|
205 |
do_test attach-1.26 {
|
sl@0
|
206 |
catchsql {
|
sl@0
|
207 |
DETACH main;
|
sl@0
|
208 |
}
|
sl@0
|
209 |
} {1 {cannot detach database main}}
|
sl@0
|
210 |
|
sl@0
|
211 |
ifcapable tempdb {
|
sl@0
|
212 |
do_test attach-1.27 {
|
sl@0
|
213 |
catchsql {
|
sl@0
|
214 |
DETACH Temp;
|
sl@0
|
215 |
}
|
sl@0
|
216 |
} {1 {cannot detach database Temp}}
|
sl@0
|
217 |
} else {
|
sl@0
|
218 |
do_test attach-1.27 {
|
sl@0
|
219 |
catchsql {
|
sl@0
|
220 |
DETACH Temp;
|
sl@0
|
221 |
}
|
sl@0
|
222 |
} {1 {no such database: Temp}}
|
sl@0
|
223 |
}
|
sl@0
|
224 |
|
sl@0
|
225 |
do_test attach-1.28 {
|
sl@0
|
226 |
catchsql {
|
sl@0
|
227 |
DETACH db11;
|
sl@0
|
228 |
DETACH db10;
|
sl@0
|
229 |
DETACH db9;
|
sl@0
|
230 |
DETACH db8;
|
sl@0
|
231 |
DETACH db7;
|
sl@0
|
232 |
DETACH db6;
|
sl@0
|
233 |
DETACH db4;
|
sl@0
|
234 |
DETACH db3;
|
sl@0
|
235 |
DETACH db2;
|
sl@0
|
236 |
}
|
sl@0
|
237 |
} {0 {}}
|
sl@0
|
238 |
ifcapable schema_pragmas {
|
sl@0
|
239 |
ifcapable tempdb {
|
sl@0
|
240 |
do_test attach-1.29 {
|
sl@0
|
241 |
db_list db
|
sl@0
|
242 |
} {0 main 1 temp}
|
sl@0
|
243 |
} else {
|
sl@0
|
244 |
do_test attach-1.29 {
|
sl@0
|
245 |
db_list db
|
sl@0
|
246 |
} {0 main}
|
sl@0
|
247 |
}
|
sl@0
|
248 |
} ;# ifcapable schema_pragmas
|
sl@0
|
249 |
|
sl@0
|
250 |
ifcapable {trigger} { # Only do the following tests if triggers are enabled
|
sl@0
|
251 |
do_test attach-2.1 {
|
sl@0
|
252 |
execsql {
|
sl@0
|
253 |
CREATE TABLE tx(x1,x2,y1,y2);
|
sl@0
|
254 |
CREATE TRIGGER r1 AFTER UPDATE ON t2 FOR EACH ROW BEGIN
|
sl@0
|
255 |
INSERT INTO tx(x1,x2,y1,y2) VALUES(OLD.x,NEW.x,OLD.y,NEW.y);
|
sl@0
|
256 |
END;
|
sl@0
|
257 |
SELECT * FROM tx;
|
sl@0
|
258 |
} db2;
|
sl@0
|
259 |
} {}
|
sl@0
|
260 |
do_test attach-2.2 {
|
sl@0
|
261 |
execsql {
|
sl@0
|
262 |
UPDATE t2 SET x=x+10;
|
sl@0
|
263 |
SELECT * FROM tx;
|
sl@0
|
264 |
} db2;
|
sl@0
|
265 |
} {1 11 x x 2 12 y y}
|
sl@0
|
266 |
do_test attach-2.3 {
|
sl@0
|
267 |
execsql {
|
sl@0
|
268 |
CREATE TABLE tx(x1,x2,y1,y2);
|
sl@0
|
269 |
SELECT * FROM tx;
|
sl@0
|
270 |
}
|
sl@0
|
271 |
} {}
|
sl@0
|
272 |
do_test attach-2.4 {
|
sl@0
|
273 |
execsql {
|
sl@0
|
274 |
ATTACH 'test2.db' AS db2;
|
sl@0
|
275 |
}
|
sl@0
|
276 |
} {}
|
sl@0
|
277 |
do_test attach-2.5 {
|
sl@0
|
278 |
execsql {
|
sl@0
|
279 |
UPDATE db2.t2 SET x=x+10;
|
sl@0
|
280 |
SELECT * FROM db2.tx;
|
sl@0
|
281 |
}
|
sl@0
|
282 |
} {1 11 x x 2 12 y y 11 21 x x 12 22 y y}
|
sl@0
|
283 |
do_test attach-2.6 {
|
sl@0
|
284 |
execsql {
|
sl@0
|
285 |
SELECT * FROM main.tx;
|
sl@0
|
286 |
}
|
sl@0
|
287 |
} {}
|
sl@0
|
288 |
do_test attach-2.7 {
|
sl@0
|
289 |
execsql {
|
sl@0
|
290 |
SELECT type, name, tbl_name FROM db2.sqlite_master;
|
sl@0
|
291 |
}
|
sl@0
|
292 |
} {table t2 t2 table tx tx trigger r1 t2}
|
sl@0
|
293 |
|
sl@0
|
294 |
ifcapable schema_pragmas&&tempdb {
|
sl@0
|
295 |
do_test attach-2.8 {
|
sl@0
|
296 |
db_list db
|
sl@0
|
297 |
} {0 main 1 temp 2 db2}
|
sl@0
|
298 |
} ;# ifcapable schema_pragmas&&tempdb
|
sl@0
|
299 |
ifcapable schema_pragmas&&!tempdb {
|
sl@0
|
300 |
do_test attach-2.8 {
|
sl@0
|
301 |
db_list db
|
sl@0
|
302 |
} {0 main 2 db2}
|
sl@0
|
303 |
} ;# ifcapable schema_pragmas&&!tempdb
|
sl@0
|
304 |
|
sl@0
|
305 |
do_test attach-2.9 {
|
sl@0
|
306 |
execsql {
|
sl@0
|
307 |
CREATE INDEX i2 ON t2(x);
|
sl@0
|
308 |
SELECT * FROM t2 WHERE x>5;
|
sl@0
|
309 |
} db2
|
sl@0
|
310 |
} {21 x 22 y}
|
sl@0
|
311 |
do_test attach-2.10 {
|
sl@0
|
312 |
execsql {
|
sl@0
|
313 |
SELECT type, name, tbl_name FROM sqlite_master;
|
sl@0
|
314 |
} db2
|
sl@0
|
315 |
} {table t2 t2 table tx tx trigger r1 t2 index i2 t2}
|
sl@0
|
316 |
#do_test attach-2.11 {
|
sl@0
|
317 |
# catchsql {
|
sl@0
|
318 |
# SELECT * FROM t2 WHERE x>5;
|
sl@0
|
319 |
# }
|
sl@0
|
320 |
#} {1 {database schema has changed}}
|
sl@0
|
321 |
ifcapable schema_pragmas {
|
sl@0
|
322 |
ifcapable tempdb {
|
sl@0
|
323 |
do_test attach-2.12 {
|
sl@0
|
324 |
db_list db
|
sl@0
|
325 |
} {0 main 1 temp 2 db2}
|
sl@0
|
326 |
} else {
|
sl@0
|
327 |
do_test attach-2.12 {
|
sl@0
|
328 |
db_list db
|
sl@0
|
329 |
} {0 main 2 db2}
|
sl@0
|
330 |
}
|
sl@0
|
331 |
} ;# ifcapable schema_pragmas
|
sl@0
|
332 |
do_test attach-2.13 {
|
sl@0
|
333 |
catchsql {
|
sl@0
|
334 |
SELECT * FROM t2 WHERE x>5;
|
sl@0
|
335 |
}
|
sl@0
|
336 |
} {0 {21 x 22 y}}
|
sl@0
|
337 |
do_test attach-2.14 {
|
sl@0
|
338 |
execsql {
|
sl@0
|
339 |
SELECT type, name, tbl_name FROM sqlite_master;
|
sl@0
|
340 |
}
|
sl@0
|
341 |
} {table t1 t1 table tx tx}
|
sl@0
|
342 |
do_test attach-2.15 {
|
sl@0
|
343 |
execsql {
|
sl@0
|
344 |
SELECT type, name, tbl_name FROM db2.sqlite_master;
|
sl@0
|
345 |
}
|
sl@0
|
346 |
} {table t2 t2 table tx tx trigger r1 t2 index i2 t2}
|
sl@0
|
347 |
do_test attach-2.16 {
|
sl@0
|
348 |
db close
|
sl@0
|
349 |
sqlite3 db test.db
|
sl@0
|
350 |
execsql {
|
sl@0
|
351 |
ATTACH 'test2.db' AS db2;
|
sl@0
|
352 |
SELECT type, name, tbl_name FROM db2.sqlite_master;
|
sl@0
|
353 |
}
|
sl@0
|
354 |
} {table t2 t2 table tx tx trigger r1 t2 index i2 t2}
|
sl@0
|
355 |
} ;# End of ifcapable {trigger}
|
sl@0
|
356 |
|
sl@0
|
357 |
do_test attach-3.1 {
|
sl@0
|
358 |
db close
|
sl@0
|
359 |
db2 close
|
sl@0
|
360 |
sqlite3 db test.db
|
sl@0
|
361 |
sqlite3 db2 test2.db
|
sl@0
|
362 |
execsql {
|
sl@0
|
363 |
SELECT * FROM t1
|
sl@0
|
364 |
}
|
sl@0
|
365 |
} {1 2 3 4}
|
sl@0
|
366 |
|
sl@0
|
367 |
# If we are testing a version of the code that lacks trigger support,
|
sl@0
|
368 |
# adjust the database contents so that they are the same if triggers
|
sl@0
|
369 |
# had been enabled.
|
sl@0
|
370 |
ifcapable {!trigger} {
|
sl@0
|
371 |
db2 eval {
|
sl@0
|
372 |
DELETE FROM t2;
|
sl@0
|
373 |
INSERT INTO t2 VALUES(21, 'x');
|
sl@0
|
374 |
INSERT INTO t2 VALUES(22, 'y');
|
sl@0
|
375 |
CREATE TABLE tx(x1,x2,y1,y2);
|
sl@0
|
376 |
INSERT INTO tx VALUES(1, 11, 'x', 'x');
|
sl@0
|
377 |
INSERT INTO tx VALUES(2, 12, 'y', 'y');
|
sl@0
|
378 |
INSERT INTO tx VALUES(11, 21, 'x', 'x');
|
sl@0
|
379 |
INSERT INTO tx VALUES(12, 22, 'y', 'y');
|
sl@0
|
380 |
CREATE INDEX i2 ON t2(x);
|
sl@0
|
381 |
}
|
sl@0
|
382 |
}
|
sl@0
|
383 |
|
sl@0
|
384 |
do_test attach-3.2 {
|
sl@0
|
385 |
catchsql {
|
sl@0
|
386 |
SELECT * FROM t2
|
sl@0
|
387 |
}
|
sl@0
|
388 |
} {1 {no such table: t2}}
|
sl@0
|
389 |
do_test attach-3.3 {
|
sl@0
|
390 |
catchsql {
|
sl@0
|
391 |
ATTACH DATABASE 'test2.db' AS db2;
|
sl@0
|
392 |
SELECT * FROM t2
|
sl@0
|
393 |
}
|
sl@0
|
394 |
} {0 {21 x 22 y}}
|
sl@0
|
395 |
|
sl@0
|
396 |
# Even though 'db' has started a transaction, it should not yet have
|
sl@0
|
397 |
# a lock on test2.db so 'db2' should be readable.
|
sl@0
|
398 |
do_test attach-3.4 {
|
sl@0
|
399 |
execsql BEGIN
|
sl@0
|
400 |
catchsql {
|
sl@0
|
401 |
SELECT * FROM t2;
|
sl@0
|
402 |
} db2;
|
sl@0
|
403 |
} {0 {21 x 22 y}}
|
sl@0
|
404 |
|
sl@0
|
405 |
# Reading from test2.db from db within a transaction should not
|
sl@0
|
406 |
# prevent test2.db from being read by db2.
|
sl@0
|
407 |
do_test attach-3.5 {
|
sl@0
|
408 |
execsql {SELECT * FROM t2}
|
sl@0
|
409 |
catchsql {
|
sl@0
|
410 |
SELECT * FROM t2;
|
sl@0
|
411 |
} db2;
|
sl@0
|
412 |
} {0 {21 x 22 y}}
|
sl@0
|
413 |
|
sl@0
|
414 |
# Making a change to test2.db through db causes test2.db to get
|
sl@0
|
415 |
# a reserved lock. It should still be accessible through db2.
|
sl@0
|
416 |
do_test attach-3.6 {
|
sl@0
|
417 |
execsql {
|
sl@0
|
418 |
UPDATE t2 SET x=x+1 WHERE x=50;
|
sl@0
|
419 |
}
|
sl@0
|
420 |
catchsql {
|
sl@0
|
421 |
SELECT * FROM t2;
|
sl@0
|
422 |
} db2;
|
sl@0
|
423 |
} {0 {21 x 22 y}}
|
sl@0
|
424 |
|
sl@0
|
425 |
do_test attach-3.7 {
|
sl@0
|
426 |
execsql ROLLBACK
|
sl@0
|
427 |
execsql {SELECT * FROM t2} db2
|
sl@0
|
428 |
} {21 x 22 y}
|
sl@0
|
429 |
|
sl@0
|
430 |
# Start transactions on both db and db2. Once again, just because
|
sl@0
|
431 |
# we make a change to test2.db using db2, only a RESERVED lock is
|
sl@0
|
432 |
# obtained, so test2.db should still be readable using db.
|
sl@0
|
433 |
#
|
sl@0
|
434 |
do_test attach-3.8 {
|
sl@0
|
435 |
execsql BEGIN
|
sl@0
|
436 |
execsql BEGIN db2
|
sl@0
|
437 |
execsql {UPDATE t2 SET x=0 WHERE 0} db2
|
sl@0
|
438 |
catchsql {SELECT * FROM t2}
|
sl@0
|
439 |
} {0 {21 x 22 y}}
|
sl@0
|
440 |
|
sl@0
|
441 |
# It is also still accessible from db2.
|
sl@0
|
442 |
do_test attach-3.9 {
|
sl@0
|
443 |
catchsql {SELECT * FROM t2} db2
|
sl@0
|
444 |
} {0 {21 x 22 y}}
|
sl@0
|
445 |
|
sl@0
|
446 |
do_test attach-3.10 {
|
sl@0
|
447 |
execsql {SELECT * FROM t1}
|
sl@0
|
448 |
} {1 2 3 4}
|
sl@0
|
449 |
|
sl@0
|
450 |
do_test attach-3.11 {
|
sl@0
|
451 |
catchsql {UPDATE t1 SET a=a+1}
|
sl@0
|
452 |
} {0 {}}
|
sl@0
|
453 |
do_test attach-3.12 {
|
sl@0
|
454 |
execsql {SELECT * FROM t1}
|
sl@0
|
455 |
} {2 2 4 4}
|
sl@0
|
456 |
|
sl@0
|
457 |
# db2 has a RESERVED lock on test2.db, so db cannot write to any tables
|
sl@0
|
458 |
# in test2.db.
|
sl@0
|
459 |
do_test attach-3.13 {
|
sl@0
|
460 |
catchsql {UPDATE t2 SET x=x+1 WHERE x=50}
|
sl@0
|
461 |
} {1 {database is locked}}
|
sl@0
|
462 |
|
sl@0
|
463 |
# Change for version 3. Transaction is no longer rolled back
|
sl@0
|
464 |
# for a locked database.
|
sl@0
|
465 |
execsql {ROLLBACK}
|
sl@0
|
466 |
|
sl@0
|
467 |
# db is able to reread its schema because db2 still only holds a
|
sl@0
|
468 |
# reserved lock.
|
sl@0
|
469 |
do_test attach-3.14 {
|
sl@0
|
470 |
catchsql {SELECT * FROM t1}
|
sl@0
|
471 |
} {0 {1 2 3 4}}
|
sl@0
|
472 |
do_test attach-3.15 {
|
sl@0
|
473 |
execsql COMMIT db2
|
sl@0
|
474 |
execsql {SELECT * FROM t1}
|
sl@0
|
475 |
} {1 2 3 4}
|
sl@0
|
476 |
|
sl@0
|
477 |
# Ticket #323
|
sl@0
|
478 |
do_test attach-4.1 {
|
sl@0
|
479 |
execsql {DETACH db2}
|
sl@0
|
480 |
db2 close
|
sl@0
|
481 |
sqlite3 db2 test2.db
|
sl@0
|
482 |
execsql {
|
sl@0
|
483 |
CREATE TABLE t3(x,y);
|
sl@0
|
484 |
CREATE UNIQUE INDEX t3i1 ON t3(x);
|
sl@0
|
485 |
INSERT INTO t3 VALUES(1,2);
|
sl@0
|
486 |
SELECT * FROM t3;
|
sl@0
|
487 |
} db2;
|
sl@0
|
488 |
} {1 2}
|
sl@0
|
489 |
do_test attach-4.2 {
|
sl@0
|
490 |
execsql {
|
sl@0
|
491 |
CREATE TABLE t3(a,b);
|
sl@0
|
492 |
CREATE UNIQUE INDEX t3i1b ON t3(a);
|
sl@0
|
493 |
INSERT INTO t3 VALUES(9,10);
|
sl@0
|
494 |
SELECT * FROM t3;
|
sl@0
|
495 |
}
|
sl@0
|
496 |
} {9 10}
|
sl@0
|
497 |
do_test attach-4.3 {
|
sl@0
|
498 |
execsql {
|
sl@0
|
499 |
ATTACH DATABASE 'test2.db' AS db2;
|
sl@0
|
500 |
SELECT * FROM db2.t3;
|
sl@0
|
501 |
}
|
sl@0
|
502 |
} {1 2}
|
sl@0
|
503 |
do_test attach-4.4 {
|
sl@0
|
504 |
execsql {
|
sl@0
|
505 |
SELECT * FROM main.t3;
|
sl@0
|
506 |
}
|
sl@0
|
507 |
} {9 10}
|
sl@0
|
508 |
do_test attach-4.5 {
|
sl@0
|
509 |
execsql {
|
sl@0
|
510 |
INSERT INTO db2.t3 VALUES(9,10);
|
sl@0
|
511 |
SELECT * FROM db2.t3;
|
sl@0
|
512 |
}
|
sl@0
|
513 |
} {1 2 9 10}
|
sl@0
|
514 |
execsql {
|
sl@0
|
515 |
DETACH db2;
|
sl@0
|
516 |
}
|
sl@0
|
517 |
ifcapable {trigger} {
|
sl@0
|
518 |
do_test attach-4.6 {
|
sl@0
|
519 |
execsql {
|
sl@0
|
520 |
CREATE TABLE t4(x);
|
sl@0
|
521 |
CREATE TRIGGER t3r3 AFTER INSERT ON t3 BEGIN
|
sl@0
|
522 |
INSERT INTO t4 VALUES('db2.' || NEW.x);
|
sl@0
|
523 |
END;
|
sl@0
|
524 |
INSERT INTO t3 VALUES(6,7);
|
sl@0
|
525 |
SELECT * FROM t4;
|
sl@0
|
526 |
} db2
|
sl@0
|
527 |
} {db2.6}
|
sl@0
|
528 |
do_test attach-4.7 {
|
sl@0
|
529 |
execsql {
|
sl@0
|
530 |
CREATE TABLE t4(y);
|
sl@0
|
531 |
CREATE TRIGGER t3r3 AFTER INSERT ON t3 BEGIN
|
sl@0
|
532 |
INSERT INTO t4 VALUES('main.' || NEW.a);
|
sl@0
|
533 |
END;
|
sl@0
|
534 |
INSERT INTO main.t3 VALUES(11,12);
|
sl@0
|
535 |
SELECT * FROM main.t4;
|
sl@0
|
536 |
}
|
sl@0
|
537 |
} {main.11}
|
sl@0
|
538 |
}
|
sl@0
|
539 |
ifcapable {!trigger} {
|
sl@0
|
540 |
# When we do not have trigger support, set up the table like they
|
sl@0
|
541 |
# would have been had triggers been there. The tests that follow need
|
sl@0
|
542 |
# this setup.
|
sl@0
|
543 |
execsql {
|
sl@0
|
544 |
CREATE TABLE t4(x);
|
sl@0
|
545 |
INSERT INTO t3 VALUES(6,7);
|
sl@0
|
546 |
INSERT INTO t4 VALUES('db2.6');
|
sl@0
|
547 |
INSERT INTO t4 VALUES('db2.13');
|
sl@0
|
548 |
} db2
|
sl@0
|
549 |
execsql {
|
sl@0
|
550 |
CREATE TABLE t4(y);
|
sl@0
|
551 |
INSERT INTO main.t3 VALUES(11,12);
|
sl@0
|
552 |
INSERT INTO t4 VALUES('main.11');
|
sl@0
|
553 |
}
|
sl@0
|
554 |
}
|
sl@0
|
555 |
|
sl@0
|
556 |
|
sl@0
|
557 |
# This one is tricky. On the UNION ALL select, we have to make sure
|
sl@0
|
558 |
# the schema for both main and db2 is valid before starting to execute
|
sl@0
|
559 |
# the first query of the UNION ALL. If we wait to test the validity of
|
sl@0
|
560 |
# the schema for main until after the first query has run, that test will
|
sl@0
|
561 |
# fail and the query will abort but we will have already output some
|
sl@0
|
562 |
# results. When the query is retried, the results will be repeated.
|
sl@0
|
563 |
#
|
sl@0
|
564 |
ifcapable compound {
|
sl@0
|
565 |
do_test attach-4.8 {
|
sl@0
|
566 |
execsql {
|
sl@0
|
567 |
ATTACH DATABASE 'test2.db' AS db2;
|
sl@0
|
568 |
INSERT INTO db2.t3 VALUES(13,14);
|
sl@0
|
569 |
SELECT * FROM db2.t4 UNION ALL SELECT * FROM main.t4;
|
sl@0
|
570 |
}
|
sl@0
|
571 |
} {db2.6 db2.13 main.11}
|
sl@0
|
572 |
|
sl@0
|
573 |
do_test attach-4.9 {
|
sl@0
|
574 |
ifcapable {!trigger} {execsql {INSERT INTO main.t4 VALUES('main.15')}}
|
sl@0
|
575 |
execsql {
|
sl@0
|
576 |
INSERT INTO main.t3 VALUES(15,16);
|
sl@0
|
577 |
SELECT * FROM db2.t4 UNION ALL SELECT * FROM main.t4;
|
sl@0
|
578 |
}
|
sl@0
|
579 |
} {db2.6 db2.13 main.11 main.15}
|
sl@0
|
580 |
} ;# ifcapable compound
|
sl@0
|
581 |
|
sl@0
|
582 |
ifcapable !compound {
|
sl@0
|
583 |
ifcapable {!trigger} {execsql {INSERT INTO main.t4 VALUES('main.15')}}
|
sl@0
|
584 |
execsql {
|
sl@0
|
585 |
ATTACH DATABASE 'test2.db' AS db2;
|
sl@0
|
586 |
INSERT INTO db2.t3 VALUES(13,14);
|
sl@0
|
587 |
INSERT INTO main.t3 VALUES(15,16);
|
sl@0
|
588 |
}
|
sl@0
|
589 |
} ;# ifcapable !compound
|
sl@0
|
590 |
|
sl@0
|
591 |
ifcapable view {
|
sl@0
|
592 |
do_test attach-4.10 {
|
sl@0
|
593 |
execsql {
|
sl@0
|
594 |
DETACH DATABASE db2;
|
sl@0
|
595 |
}
|
sl@0
|
596 |
execsql {
|
sl@0
|
597 |
CREATE VIEW v3 AS SELECT x*100+y FROM t3;
|
sl@0
|
598 |
SELECT * FROM v3;
|
sl@0
|
599 |
} db2
|
sl@0
|
600 |
} {102 910 607 1314}
|
sl@0
|
601 |
do_test attach-4.11 {
|
sl@0
|
602 |
execsql {
|
sl@0
|
603 |
CREATE VIEW v3 AS SELECT a*100+b FROM t3;
|
sl@0
|
604 |
SELECT * FROM v3;
|
sl@0
|
605 |
}
|
sl@0
|
606 |
} {910 1112 1516}
|
sl@0
|
607 |
do_test attach-4.12 {
|
sl@0
|
608 |
execsql {
|
sl@0
|
609 |
ATTACH DATABASE 'test2.db' AS db2;
|
sl@0
|
610 |
SELECT * FROM db2.v3;
|
sl@0
|
611 |
}
|
sl@0
|
612 |
} {102 910 607 1314}
|
sl@0
|
613 |
do_test attach-4.13 {
|
sl@0
|
614 |
execsql {
|
sl@0
|
615 |
SELECT * FROM main.v3;
|
sl@0
|
616 |
}
|
sl@0
|
617 |
} {910 1112 1516}
|
sl@0
|
618 |
} ;# ifcapable view
|
sl@0
|
619 |
|
sl@0
|
620 |
# Tests for the sqliteFix...() routines in attach.c
|
sl@0
|
621 |
#
|
sl@0
|
622 |
ifcapable {trigger} {
|
sl@0
|
623 |
do_test attach-5.1 {
|
sl@0
|
624 |
db close
|
sl@0
|
625 |
sqlite3 db test.db
|
sl@0
|
626 |
db2 close
|
sl@0
|
627 |
file delete -force test2.db
|
sl@0
|
628 |
sqlite3 db2 test2.db
|
sl@0
|
629 |
catchsql {
|
sl@0
|
630 |
ATTACH DATABASE 'test.db' AS orig;
|
sl@0
|
631 |
CREATE TRIGGER r1 AFTER INSERT ON orig.t1 BEGIN
|
sl@0
|
632 |
SELECT 'no-op';
|
sl@0
|
633 |
END;
|
sl@0
|
634 |
} db2
|
sl@0
|
635 |
} {1 {trigger r1 cannot reference objects in database orig}}
|
sl@0
|
636 |
do_test attach-5.2 {
|
sl@0
|
637 |
catchsql {
|
sl@0
|
638 |
CREATE TABLE t5(x,y);
|
sl@0
|
639 |
CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
|
sl@0
|
640 |
SELECT 'no-op';
|
sl@0
|
641 |
END;
|
sl@0
|
642 |
} db2
|
sl@0
|
643 |
} {0 {}}
|
sl@0
|
644 |
do_test attach-5.3 {
|
sl@0
|
645 |
catchsql {
|
sl@0
|
646 |
DROP TRIGGER r5;
|
sl@0
|
647 |
CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
|
sl@0
|
648 |
SELECT 'no-op' FROM orig.t1;
|
sl@0
|
649 |
END;
|
sl@0
|
650 |
} db2
|
sl@0
|
651 |
} {1 {trigger r5 cannot reference objects in database orig}}
|
sl@0
|
652 |
ifcapable tempdb {
|
sl@0
|
653 |
do_test attach-5.4 {
|
sl@0
|
654 |
catchsql {
|
sl@0
|
655 |
CREATE TEMP TABLE t6(p,q,r);
|
sl@0
|
656 |
CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
|
sl@0
|
657 |
SELECT 'no-op' FROM temp.t6;
|
sl@0
|
658 |
END;
|
sl@0
|
659 |
} db2
|
sl@0
|
660 |
} {1 {trigger r5 cannot reference objects in database temp}}
|
sl@0
|
661 |
}
|
sl@0
|
662 |
ifcapable subquery {
|
sl@0
|
663 |
do_test attach-5.5 {
|
sl@0
|
664 |
catchsql {
|
sl@0
|
665 |
CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
|
sl@0
|
666 |
SELECT 'no-op' || (SELECT * FROM temp.t6);
|
sl@0
|
667 |
END;
|
sl@0
|
668 |
} db2
|
sl@0
|
669 |
} {1 {trigger r5 cannot reference objects in database temp}}
|
sl@0
|
670 |
do_test attach-5.6 {
|
sl@0
|
671 |
catchsql {
|
sl@0
|
672 |
CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
|
sl@0
|
673 |
SELECT 'no-op' FROM t1 WHERE x<(SELECT min(x) FROM temp.t6);
|
sl@0
|
674 |
END;
|
sl@0
|
675 |
} db2
|
sl@0
|
676 |
} {1 {trigger r5 cannot reference objects in database temp}}
|
sl@0
|
677 |
do_test attach-5.7 {
|
sl@0
|
678 |
catchsql {
|
sl@0
|
679 |
CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
|
sl@0
|
680 |
SELECT 'no-op' FROM t1 GROUP BY 1 HAVING x<(SELECT min(x) FROM temp.t6);
|
sl@0
|
681 |
END;
|
sl@0
|
682 |
} db2
|
sl@0
|
683 |
} {1 {trigger r5 cannot reference objects in database temp}}
|
sl@0
|
684 |
do_test attach-5.7 {
|
sl@0
|
685 |
catchsql {
|
sl@0
|
686 |
CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
|
sl@0
|
687 |
SELECT max(1,x,(SELECT min(x) FROM temp.t6)) FROM t1;
|
sl@0
|
688 |
END;
|
sl@0
|
689 |
} db2
|
sl@0
|
690 |
} {1 {trigger r5 cannot reference objects in database temp}}
|
sl@0
|
691 |
do_test attach-5.8 {
|
sl@0
|
692 |
catchsql {
|
sl@0
|
693 |
CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
|
sl@0
|
694 |
INSERT INTO t1 VALUES((SELECT min(x) FROM temp.t6),5);
|
sl@0
|
695 |
END;
|
sl@0
|
696 |
} db2
|
sl@0
|
697 |
} {1 {trigger r5 cannot reference objects in database temp}}
|
sl@0
|
698 |
do_test attach-5.9 {
|
sl@0
|
699 |
catchsql {
|
sl@0
|
700 |
CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
|
sl@0
|
701 |
DELETE FROM t1 WHERE x<(SELECT min(x) FROM temp.t6);
|
sl@0
|
702 |
END;
|
sl@0
|
703 |
} db2
|
sl@0
|
704 |
} {1 {trigger r5 cannot reference objects in database temp}}
|
sl@0
|
705 |
} ;# endif subquery
|
sl@0
|
706 |
} ;# endif trigger
|
sl@0
|
707 |
|
sl@0
|
708 |
# Check to make sure we get a sensible error if unable to open
|
sl@0
|
709 |
# the file that we are trying to attach.
|
sl@0
|
710 |
#
|
sl@0
|
711 |
do_test attach-6.1 {
|
sl@0
|
712 |
catchsql {
|
sl@0
|
713 |
ATTACH DATABASE 'no-such-file' AS nosuch;
|
sl@0
|
714 |
}
|
sl@0
|
715 |
} {0 {}}
|
sl@0
|
716 |
if {$tcl_platform(platform)=="unix"} {
|
sl@0
|
717 |
do_test attach-6.2 {
|
sl@0
|
718 |
sqlite3 dbx cannot-read
|
sl@0
|
719 |
dbx eval {CREATE TABLE t1(a,b,c)}
|
sl@0
|
720 |
dbx close
|
sl@0
|
721 |
file attributes cannot-read -permission 0000
|
sl@0
|
722 |
if {[file writable cannot-read]} {
|
sl@0
|
723 |
puts "\n**** Tests do not work when run as root ****"
|
sl@0
|
724 |
file delete -force cannot-read
|
sl@0
|
725 |
exit 1
|
sl@0
|
726 |
}
|
sl@0
|
727 |
catchsql {
|
sl@0
|
728 |
ATTACH DATABASE 'cannot-read' AS noread;
|
sl@0
|
729 |
}
|
sl@0
|
730 |
} {1 {unable to open database: cannot-read}}
|
sl@0
|
731 |
do_test attach-6.2.2 {
|
sl@0
|
732 |
db errorcode
|
sl@0
|
733 |
} {14}
|
sl@0
|
734 |
file delete -force cannot-read
|
sl@0
|
735 |
}
|
sl@0
|
736 |
|
sl@0
|
737 |
# Check the error message if we try to access a database that has
|
sl@0
|
738 |
# not been attached.
|
sl@0
|
739 |
do_test attach-6.3 {
|
sl@0
|
740 |
catchsql {
|
sl@0
|
741 |
CREATE TABLE no_such_db.t1(a, b, c);
|
sl@0
|
742 |
}
|
sl@0
|
743 |
} {1 {unknown database no_such_db}}
|
sl@0
|
744 |
for {set i 2} {$i<=15} {incr i} {
|
sl@0
|
745 |
catch {db$i close}
|
sl@0
|
746 |
}
|
sl@0
|
747 |
db close
|
sl@0
|
748 |
file delete -force test2.db
|
sl@0
|
749 |
file delete -force no-such-file
|
sl@0
|
750 |
|
sl@0
|
751 |
ifcapable subquery {
|
sl@0
|
752 |
do_test attach-7.1 {
|
sl@0
|
753 |
file delete -force test.db test.db-journal
|
sl@0
|
754 |
sqlite3 db test.db
|
sl@0
|
755 |
catchsql {
|
sl@0
|
756 |
DETACH RAISE ( IGNORE ) IN ( SELECT "AAAAAA" . * ORDER BY
|
sl@0
|
757 |
REGISTER LIMIT "AAAAAA" . "AAAAAA" OFFSET RAISE ( IGNORE ) NOT NULL )
|
sl@0
|
758 |
}
|
sl@0
|
759 |
} {1 {invalid name: "RAISE ( IGNORE ) IN ( SELECT "AAAAAA" . * ORDER BY
|
sl@0
|
760 |
REGISTER LIMIT "AAAAAA" . "AAAAAA" OFFSET RAISE ( IGNORE ) NOT NULL )"}}
|
sl@0
|
761 |
}
|
sl@0
|
762 |
|
sl@0
|
763 |
# Create a malformed file (a file that is not a valid database)
|
sl@0
|
764 |
# and try to attach it
|
sl@0
|
765 |
#
|
sl@0
|
766 |
do_test attach-8.1 {
|
sl@0
|
767 |
set fd [open test2.db w]
|
sl@0
|
768 |
puts $fd "This file is not a valid SQLite database"
|
sl@0
|
769 |
close $fd
|
sl@0
|
770 |
catchsql {
|
sl@0
|
771 |
ATTACH 'test2.db' AS t2;
|
sl@0
|
772 |
}
|
sl@0
|
773 |
} {1 {file is encrypted or is not a database}}
|
sl@0
|
774 |
do_test attach-8.2 {
|
sl@0
|
775 |
db errorcode
|
sl@0
|
776 |
} {26}
|
sl@0
|
777 |
file delete -force test2.db
|
sl@0
|
778 |
do_test attach-8.3 {
|
sl@0
|
779 |
sqlite3 db2 test2.db
|
sl@0
|
780 |
db2 eval {CREATE TABLE t1(x); BEGIN EXCLUSIVE}
|
sl@0
|
781 |
catchsql {
|
sl@0
|
782 |
ATTACH 'test2.db' AS t2;
|
sl@0
|
783 |
}
|
sl@0
|
784 |
} {1 {database is locked}}
|
sl@0
|
785 |
do_test attach-8.4 {
|
sl@0
|
786 |
db errorcode
|
sl@0
|
787 |
} {5}
|
sl@0
|
788 |
db2 close
|
sl@0
|
789 |
file delete -force test2.db
|
sl@0
|
790 |
|
sl@0
|
791 |
|
sl@0
|
792 |
finish_test
|