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