OLD | NEW |
| (Empty) |
1 # 2001 October 7 | |
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. | |
12 # | |
13 # This file implements tests for temporary tables and indices. | |
14 # | |
15 # $Id: temptable.test,v 1.21 2009/06/16 17:49:36 drh Exp $ | |
16 | |
17 set testdir [file dirname $argv0] | |
18 source $testdir/tester.tcl | |
19 | |
20 ifcapable !tempdb { | |
21 finish_test | |
22 return | |
23 } | |
24 | |
25 # Create an alternative connection to the database | |
26 # | |
27 do_test temptable-1.0 { | |
28 sqlite3 db2 ./test.db | |
29 set dummy {} | |
30 } {} | |
31 | |
32 # Create a permanent table. | |
33 # | |
34 do_test temptable-1.1 { | |
35 execsql {CREATE TABLE t1(a,b,c);} | |
36 execsql {INSERT INTO t1 VALUES(1,2,3);} | |
37 execsql {SELECT * FROM t1} | |
38 } {1 2 3} | |
39 do_test temptable-1.2 { | |
40 catch {db2 eval {SELECT * FROM sqlite_master}} | |
41 db2 eval {SELECT * FROM t1} | |
42 } {1 2 3} | |
43 do_test temptable-1.3 { | |
44 execsql {SELECT name FROM sqlite_master} | |
45 } {t1} | |
46 do_test temptable-1.4 { | |
47 db2 eval {SELECT name FROM sqlite_master} | |
48 } {t1} | |
49 | |
50 # Create a temporary table. Verify that only one of the two | |
51 # processes can see it. | |
52 # | |
53 do_test temptable-1.5 { | |
54 db2 eval { | |
55 CREATE TEMP TABLE t2(x,y,z); | |
56 INSERT INTO t2 VALUES(4,5,6); | |
57 } | |
58 db2 eval {SELECT * FROM t2} | |
59 } {4 5 6} | |
60 do_test temptable-1.6 { | |
61 catch {execsql {SELECT * FROM sqlite_master}} | |
62 catchsql {SELECT * FROM t2} | |
63 } {1 {no such table: t2}} | |
64 do_test temptable-1.7 { | |
65 catchsql {INSERT INTO t2 VALUES(8,9,0);} | |
66 } {1 {no such table: t2}} | |
67 do_test temptable-1.8 { | |
68 db2 eval {INSERT INTO t2 VALUES(8,9,0);} | |
69 db2 eval {SELECT * FROM t2 ORDER BY x} | |
70 } {4 5 6 8 9 0} | |
71 do_test temptable-1.9 { | |
72 db2 eval {DELETE FROM t2 WHERE x==8} | |
73 db2 eval {SELECT * FROM t2 ORDER BY x} | |
74 } {4 5 6} | |
75 do_test temptable-1.10 { | |
76 db2 eval {DELETE FROM t2} | |
77 db2 eval {SELECT * FROM t2} | |
78 } {} | |
79 do_test temptable-1.11 { | |
80 db2 eval { | |
81 INSERT INTO t2 VALUES(7,6,5); | |
82 INSERT INTO t2 VALUES(4,3,2); | |
83 SELECT * FROM t2 ORDER BY x; | |
84 } | |
85 } {4 3 2 7 6 5} | |
86 do_test temptable-1.12 { | |
87 db2 eval {DROP TABLE t2;} | |
88 set r [catch {db2 eval {SELECT * FROM t2}} msg] | |
89 lappend r $msg | |
90 } {1 {no such table: t2}} | |
91 | |
92 # Make sure temporary tables work with transactions | |
93 # | |
94 do_test temptable-2.1 { | |
95 execsql { | |
96 BEGIN TRANSACTION; | |
97 CREATE TEMPORARY TABLE t2(x,y); | |
98 INSERT INTO t2 VALUES(1,2); | |
99 SELECT * FROM t2; | |
100 } | |
101 } {1 2} | |
102 do_test temptable-2.2 { | |
103 execsql {ROLLBACK} | |
104 catchsql {SELECT * FROM t2} | |
105 } {1 {no such table: t2}} | |
106 do_test temptable-2.3 { | |
107 execsql { | |
108 BEGIN TRANSACTION; | |
109 CREATE TEMPORARY TABLE t2(x,y); | |
110 INSERT INTO t2 VALUES(1,2); | |
111 SELECT * FROM t2; | |
112 } | |
113 } {1 2} | |
114 do_test temptable-2.4 { | |
115 execsql {COMMIT} | |
116 catchsql {SELECT * FROM t2} | |
117 } {0 {1 2}} | |
118 do_test temptable-2.5 { | |
119 set r [catch {db2 eval {SELECT * FROM t2}} msg] | |
120 lappend r $msg | |
121 } {1 {no such table: t2}} | |
122 | |
123 # Make sure indices on temporary tables are also temporary. | |
124 # | |
125 do_test temptable-3.1 { | |
126 execsql { | |
127 CREATE INDEX i2 ON t2(x); | |
128 SELECT name FROM sqlite_master WHERE type='index'; | |
129 } | |
130 } {} | |
131 do_test temptable-3.2 { | |
132 execsql { | |
133 SELECT y FROM t2 WHERE x=1; | |
134 } | |
135 } {2} | |
136 do_test temptable-3.3 { | |
137 execsql { | |
138 DROP INDEX i2; | |
139 SELECT y FROM t2 WHERE x=1; | |
140 } | |
141 } {2} | |
142 do_test temptable-3.4 { | |
143 execsql { | |
144 CREATE INDEX i2 ON t2(x); | |
145 DROP TABLE t2; | |
146 } | |
147 catchsql {DROP INDEX i2} | |
148 } {1 {no such index: i2}} | |
149 | |
150 # Check for correct name collision processing. A name collision can | |
151 # occur when process A creates a temporary table T then process B | |
152 # creates a permanent table also named T. The temp table in process A | |
153 # hides the existence of the permanent table. | |
154 # | |
155 do_test temptable-4.1 { | |
156 execsql { | |
157 CREATE TEMP TABLE t2(x,y); | |
158 INSERT INTO t2 VALUES(10,20); | |
159 SELECT * FROM t2; | |
160 } db2 | |
161 } {10 20} | |
162 do_test temptable-4.2 { | |
163 execsql { | |
164 CREATE TABLE t2(x,y,z); | |
165 INSERT INTO t2 VALUES(9,8,7); | |
166 SELECT * FROM t2; | |
167 } | |
168 } {9 8 7} | |
169 do_test temptable-4.3 { | |
170 catchsql { | |
171 SELECT * FROM t2; | |
172 } db2 | |
173 } {0 {10 20}} | |
174 do_test temptable-4.4.1 { | |
175 catchsql { | |
176 SELECT * FROM temp.t2; | |
177 } db2 | |
178 } {0 {10 20}} | |
179 do_test temptable-4.4.2 { | |
180 catchsql { | |
181 SELECT * FROM main.t2; | |
182 } db2 | |
183 } {0 {9 8 7}} | |
184 #do_test temptable-4.4.3 { | |
185 # catchsql { | |
186 # SELECT name FROM main.sqlite_master WHERE type='table'; | |
187 # } db2 | |
188 #} {1 {database schema has changed}} | |
189 do_test temptable-4.4.4 { | |
190 catchsql { | |
191 SELECT name FROM main.sqlite_master WHERE type='table'; | |
192 } db2 | |
193 } {0 {t1 t2}} | |
194 do_test temptable-4.4.5 { | |
195 catchsql { | |
196 SELECT * FROM main.t2; | |
197 } db2 | |
198 } {0 {9 8 7}} | |
199 do_test temptable-4.4.6 { | |
200 # TEMP takes precedence over MAIN | |
201 catchsql { | |
202 SELECT * FROM t2; | |
203 } db2 | |
204 } {0 {10 20}} | |
205 do_test temptable-4.5 { | |
206 catchsql { | |
207 DROP TABLE t2; -- should drop TEMP | |
208 SELECT * FROM t2; -- data should be from MAIN | |
209 } db2 | |
210 } {0 {9 8 7}} | |
211 do_test temptable-4.6 { | |
212 db2 close | |
213 sqlite3 db2 ./test.db | |
214 catchsql { | |
215 SELECT * FROM t2; | |
216 } db2 | |
217 } {0 {9 8 7}} | |
218 do_test temptable-4.7 { | |
219 catchsql { | |
220 DROP TABLE t2; | |
221 SELECT * FROM t2; | |
222 } | |
223 } {1 {no such table: t2}} | |
224 do_test temptable-4.8 { | |
225 db2 close | |
226 sqlite3 db2 ./test.db | |
227 execsql { | |
228 CREATE TEMP TABLE t2(x unique,y); | |
229 INSERT INTO t2 VALUES(1,2); | |
230 SELECT * FROM t2; | |
231 } db2 | |
232 } {1 2} | |
233 do_test temptable-4.9 { | |
234 execsql { | |
235 CREATE TABLE t2(x unique, y); | |
236 INSERT INTO t2 VALUES(3,4); | |
237 SELECT * FROM t2; | |
238 } | |
239 } {3 4} | |
240 do_test temptable-4.10.1 { | |
241 catchsql { | |
242 SELECT * FROM t2; | |
243 } db2 | |
244 } {0 {1 2}} | |
245 # Update: The schema is reloaded in test temptable-4.10.1. And tclsqlite.c | |
246 # handles it and retries the query anyway. | |
247 # do_test temptable-4.10.2 { | |
248 # catchsql { | |
249 # SELECT name FROM sqlite_master WHERE type='table' | |
250 # } db2 | |
251 # } {1 {database schema has changed}} | |
252 do_test temptable-4.10.3 { | |
253 catchsql { | |
254 SELECT name FROM sqlite_master WHERE type='table' | |
255 } db2 | |
256 } {0 {t1 t2}} | |
257 do_test temptable-4.11 { | |
258 execsql { | |
259 SELECT * FROM t2; | |
260 } db2 | |
261 } {1 2} | |
262 do_test temptable-4.12 { | |
263 execsql { | |
264 SELECT * FROM t2; | |
265 } | |
266 } {3 4} | |
267 do_test temptable-4.13 { | |
268 catchsql { | |
269 DROP TABLE t2; -- drops TEMP.T2 | |
270 SELECT * FROM t2; -- uses MAIN.T2 | |
271 } db2 | |
272 } {0 {3 4}} | |
273 do_test temptable-4.14 { | |
274 execsql { | |
275 SELECT * FROM t2; | |
276 } | |
277 } {3 4} | |
278 do_test temptable-4.15 { | |
279 db2 close | |
280 sqlite3 db2 ./test.db | |
281 execsql { | |
282 SELECT * FROM t2; | |
283 } db2 | |
284 } {3 4} | |
285 | |
286 # Now create a temporary table in db2 and a permanent index in db. The | |
287 # temporary table in db2 should mask the name of the permanent index, | |
288 # but the permanent index should still be accessible and should still | |
289 # be updated when its corresponding table changes. | |
290 # | |
291 do_test temptable-5.1 { | |
292 execsql { | |
293 CREATE TEMP TABLE mask(a,b,c) | |
294 } db2 | |
295 if {[permutation]=="prepare"} { db2 cache flush } | |
296 execsql { | |
297 CREATE INDEX mask ON t2(x); | |
298 SELECT * FROM t2; | |
299 } | |
300 } {3 4} | |
301 #do_test temptable-5.2 { | |
302 # catchsql { | |
303 # SELECT * FROM t2; | |
304 # } db2 | |
305 #} {1 {database schema has changed}} | |
306 do_test temptable-5.3 { | |
307 catchsql { | |
308 SELECT * FROM t2; | |
309 } db2 | |
310 } {0 {3 4}} | |
311 do_test temptable-5.4 { | |
312 execsql { | |
313 SELECT y FROM t2 WHERE x=3 | |
314 } | |
315 } {4} | |
316 do_test temptable-5.5 { | |
317 execsql { | |
318 SELECT y FROM t2 WHERE x=3 | |
319 } db2 | |
320 } {4} | |
321 do_test temptable-5.6 { | |
322 execsql { | |
323 INSERT INTO t2 VALUES(1,2); | |
324 SELECT y FROM t2 WHERE x=1; | |
325 } db2 | |
326 } {2} | |
327 do_test temptable-5.7 { | |
328 execsql { | |
329 SELECT y FROM t2 WHERE x=3 | |
330 } db2 | |
331 } {4} | |
332 do_test temptable-5.8 { | |
333 execsql { | |
334 SELECT y FROM t2 WHERE x=1; | |
335 } | |
336 } {2} | |
337 do_test temptable-5.9 { | |
338 execsql { | |
339 SELECT y FROM t2 WHERE x=3 | |
340 } | |
341 } {4} | |
342 | |
343 db2 close | |
344 | |
345 # Test for correct operation of read-only databases | |
346 # | |
347 do_test temptable-6.1 { | |
348 execsql { | |
349 CREATE TABLE t8(x); | |
350 INSERT INTO t8 VALUES('xyzzy'); | |
351 SELECT * FROM t8; | |
352 } | |
353 } {xyzzy} | |
354 do_test temptable-6.2 { | |
355 db close | |
356 catch {file attributes test.db -permissions 0444} | |
357 catch {file attributes test.db -readonly 1} | |
358 sqlite3 db test.db | |
359 if {[file writable test.db]} { | |
360 error "Unable to make the database file test.db readonly - rerun this test a
s an unprivileged user" | |
361 } | |
362 execsql { | |
363 SELECT * FROM t8; | |
364 } | |
365 } {xyzzy} | |
366 do_test temptable-6.3 { | |
367 if {[file writable test.db]} { | |
368 error "Unable to make the database file test.db readonly - rerun this test a
s an unprivileged user" | |
369 } | |
370 catchsql { | |
371 CREATE TABLE t9(x,y); | |
372 } | |
373 } {1 {attempt to write a readonly database}} | |
374 do_test temptable-6.4 { | |
375 catchsql { | |
376 CREATE TEMP TABLE t9(x,y); | |
377 } | |
378 } {0 {}} | |
379 do_test temptable-6.5 { | |
380 catchsql { | |
381 INSERT INTO t9 VALUES(1,2); | |
382 SELECT * FROM t9; | |
383 } | |
384 } {0 {1 2}} | |
385 do_test temptable-6.6 { | |
386 if {[file writable test.db]} { | |
387 error "Unable to make the database file test.db readonly - rerun this test a
s an unprivileged user" | |
388 } | |
389 catchsql { | |
390 INSERT INTO t8 VALUES('hello'); | |
391 SELECT * FROM t8; | |
392 } | |
393 } {1 {attempt to write a readonly database}} | |
394 do_test temptable-6.7 { | |
395 catchsql { | |
396 SELECT * FROM t8,t9; | |
397 } | |
398 } {0 {xyzzy 1 2}} | |
399 do_test temptable-6.8 { | |
400 db close | |
401 sqlite3 db test.db | |
402 catchsql { | |
403 SELECT * FROM t8,t9; | |
404 } | |
405 } {1 {no such table: t9}} | |
406 | |
407 forcedelete test2.db test2.db-journal | |
408 ifcapable attach { | |
409 do_test temptable-7.1 { | |
410 catchsql { | |
411 ATTACH 'test2.db' AS two; | |
412 CREATE TEMP TABLE two.abc(x,y); | |
413 } | |
414 } {1 {temporary table name must be unqualified}} | |
415 } | |
416 | |
417 # Need to do the following for tcl 8.5 on mac. On that configuration, the | |
418 # -readonly flag is taken so seriously that a subsequent [forcedelete] | |
419 # (required before the next test file can be executed) will fail. | |
420 # | |
421 catch {file attributes test.db -readonly 0} | |
422 | |
423 do_test temptable-8.0 { | |
424 db close | |
425 catch {forcedelete test.db} | |
426 sqlite3 db test.db | |
427 } {} | |
428 do_test temptable-8.1 { | |
429 execsql { CREATE TEMP TABLE tbl2(a, b); } | |
430 execsql { | |
431 CREATE TABLE tbl(a, b); | |
432 INSERT INTO tbl VALUES(1, 2); | |
433 } | |
434 execsql {SELECT * FROM tbl} | |
435 } {1 2} | |
436 do_test temptable-8.2 { | |
437 execsql { CREATE TEMP TABLE tbl(a, b); } | |
438 execsql {SELECT * FROM tbl} | |
439 } {} | |
440 | |
441 finish_test | |
OLD | NEW |