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.9 2003/03/30 00:19:50 drh 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} {1 {database schema has changed}} 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} {0 {9 8 7}} 179do_test temptable-4.4.3 { 180 # TEMP takes precedence over MAIN 181 catchsql { 182 SELECT * FROM t2; 183 } db2 184} {0 {10 20}} 185do_test temptable-4.5 { 186 catchsql { 187 DROP TABLE t2; -- should drop TEMP 188 SELECT * FROM t2; -- data should be from MAIN 189 } db2 190} {0 {9 8 7}} 191do_test temptable-4.6 { 192 db2 close 193 sqlite db2 ./test.db 194 catchsql { 195 SELECT * FROM t2; 196 } db2 197} {0 {9 8 7}} 198do_test temptable-4.7 { 199 catchsql { 200 DROP TABLE t2; 201 SELECT * FROM t2; 202 } 203} {1 {no such table: t2}} 204do_test temptable-4.8 { 205 db2 close 206 sqlite db2 ./test.db 207 execsql { 208 CREATE TEMP TABLE t2(x unique,y); 209 INSERT INTO t2 VALUES(1,2); 210 SELECT * FROM t2; 211 } db2 212} {1 2} 213do_test temptable-4.9 { 214 execsql { 215 CREATE TABLE t2(x unique, y); 216 INSERT INTO t2 VALUES(3,4); 217 SELECT * FROM t2; 218 } 219} {3 4} 220do_test temptable-4.10 { 221 catchsql { 222 SELECT * FROM t2; 223 } db2 224} {1 {database schema has changed}} 225do_test temptable-4.11 { 226 execsql { 227 SELECT * FROM t2; 228 } db2 229} {1 2} 230do_test temptable-4.12 { 231 execsql { 232 SELECT * FROM t2; 233 } 234} {3 4} 235do_test temptable-4.13 { 236 catchsql { 237 DROP TABLE t2; -- drops TEMP.T2 238 SELECT * FROM t2; -- uses MAIN.T2 239 } db2 240} {0 {3 4}} 241do_test temptable-4.14 { 242 execsql { 243 SELECT * FROM t2; 244 } 245} {3 4} 246do_test temptable-4.15 { 247 db2 close 248 sqlite db2 ./test.db 249 execsql { 250 SELECT * FROM t2; 251 } db2 252} {3 4} 253 254# Now create a temporary table in db2 and a permanent index in db. The 255# temporary table in db2 should mask the name of the permanent index, 256# but the permanent index should still be accessible and should still 257# be updated when its corresponding table changes. 258# 259do_test temptable-5.1 { 260 execsql { 261 CREATE TEMP TABLE mask(a,b,c) 262 } db2 263 execsql { 264 CREATE INDEX mask ON t2(x); 265 SELECT * FROM t2; 266 } 267} {3 4} 268do_test temptable-5.2 { 269 catchsql { 270 SELECT * FROM t2; 271 } db2 272} {1 {database schema has changed}} 273do_test temptable-5.3 { 274 catchsql { 275 SELECT * FROM t2; 276 } db2 277} {0 {3 4}} 278do_test temptable-5.4 { 279 execsql { 280 SELECT y FROM t2 WHERE x=3 281 } 282} {4} 283do_test temptable-5.5 { 284 execsql { 285 SELECT y FROM t2 WHERE x=3 286 } db2 287} {4} 288do_test temptable-5.6 { 289 execsql { 290 INSERT INTO t2 VALUES(1,2); 291 SELECT y FROM t2 WHERE x=1; 292 } db2 293} {2} 294do_test temptable-5.7 { 295 execsql { 296 SELECT y FROM t2 WHERE x=3 297 } db2 298} {4} 299do_test temptable-5.8 { 300 execsql { 301 SELECT y FROM t2 WHERE x=1; 302 } 303} {2} 304do_test temptable-5.9 { 305 execsql { 306 SELECT y FROM t2 WHERE x=3 307 } 308} {4} 309 310db2 close 311 312# Test for correct operation of read-only databases 313# 314do_test temptable-6.1 { 315 execsql { 316 CREATE TABLE t8(x); 317 INSERT INTO t8 VALUES('xyzzy'); 318 SELECT * FROM t8; 319 } 320} {xyzzy} 321do_test temptable-6.2 { 322 db close 323 catch {file attributes test.db -permissions 0444} 324 catch {file attributes test.db -readonly 1} 325 sqlite db test.db 326 if {[file writable test.db]} { 327 error "Unable to make the database file test.db readonly - rerun this test as an unprivileged user" 328 } 329 execsql { 330 SELECT * FROM t8; 331 } 332} {xyzzy} 333do_test temptable-6.3 { 334 if {[file writable test.db]} { 335 error "Unable to make the database file test.db readonly - rerun this test as an unprivileged user" 336 } 337 catchsql { 338 CREATE TABLE t9(x,y); 339 } 340} {1 {attempt to write a readonly database}} 341do_test temptable-6.4 { 342 catchsql { 343 CREATE TEMP TABLE t9(x,y); 344 } 345} {0 {}} 346do_test temptable-6.5 { 347 catchsql { 348 INSERT INTO t9 VALUES(1,2); 349 SELECT * FROM t9; 350 } 351} {0 {1 2}} 352do_test temptable-6.6 { 353 if {[file writable test.db]} { 354 error "Unable to make the database file test.db readonly - rerun this test as an unprivileged user" 355 } 356 catchsql { 357 INSERT INTO t8 VALUES('hello'); 358 SELECT * FROM t8; 359 } 360} {1 {attempt to write a readonly database}} 361do_test temptable-6.7 { 362 catchsql { 363 SELECT * FROM t8,t9; 364 } 365} {0 {xyzzy 1 2}} 366do_test temptable-6.8 { 367 db close 368 sqlite db test.db 369 catchsql { 370 SELECT * FROM t8,t9; 371 } 372} {1 {no such table: t9}} 373 374finish_test 375