1# 2005 February 18 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. The 12# focus of this script is testing that SQLite can handle a subtle 13# file format change that may be used in the future to implement 14# "ALTER TABLE ... ADD COLUMN". 15# 16# $Id: alter2.test,v 1.6 2007/01/04 14:36:02 drh Exp $ 17# 18 19set testdir [file dirname $argv0] 20source $testdir/tester.tcl 21 22# We have to have pragmas in order to do this test 23ifcapable {!pragma} return 24 25# These tests do not work if there is a codec. The 26# btree_open command does not know how to handle codecs. 27# 28#if {[catch {sqlite3 -has_codec} r] || $r} return 29 30# The file format change affects the way row-records stored in tables (but 31# not indices) are interpreted. Before version 3.1.3, a row-record for a 32# table with N columns was guaranteed to contain exactly N fields. As 33# of version 3.1.3, the record may contain up to N fields. In this case 34# the M fields that are present are the values for the left-most M 35# columns. The (N-M) rightmost columns contain NULL. 36# 37# If any records in the database contain less fields than their table 38# has columns, then the file-format meta value should be set to (at least) 2. 39# 40 41# This procedure sets the value of the file-format in file 'test.db' 42# to $newval. Also, the schema cookie is incremented. 43# 44proc set_file_format {newval} { 45 set bt [btree_open test.db 10 0] 46 btree_begin_transaction $bt 47 set meta [btree_get_meta $bt] 48 lset meta 2 $newval ;# File format 49 lset meta 1 [expr [lindex $meta 1]+1] ;# Schema cookie 50 eval "btree_update_meta $bt $meta" 51 btree_commit $bt 52 btree_close $bt 53} 54 55# This procedure returns the value of the file-format in file 'test.db'. 56# 57proc get_file_format {{fname test.db}} { 58 set bt [btree_open $fname 10 0] 59 set meta [btree_get_meta $bt] 60 btree_close $bt 61 lindex $meta 2 62} 63 64# This procedure sets the SQL statement stored for table $tbl in the 65# sqlite_master table of file 'test.db' to $sql. Also set the file format 66# to the supplied value. This is 2 if the added column has a default that is 67# NULL, or 3 otherwise. 68# 69proc alter_table {tbl sql {file_format 2}} { 70 sqlite3 dbat test.db 71 dbat eval { 72 PRAGMA writable_schema = 1; 73 UPDATE sqlite_master SET sql = $sql WHERE name = $tbl AND type = 'table'; 74 PRAGMA writable_schema = 0; 75 } 76 dbat close 77 set_file_format 2 78} 79 80#----------------------------------------------------------------------- 81# Some basic tests to make sure short rows are handled. 82# 83do_test alter2-1.1 { 84 execsql { 85 CREATE TABLE abc(a, b); 86 INSERT INTO abc VALUES(1, 2); 87 INSERT INTO abc VALUES(3, 4); 88 INSERT INTO abc VALUES(5, 6); 89 } 90} {} 91do_test alter2-1.2 { 92 # ALTER TABLE abc ADD COLUMN c; 93 alter_table abc {CREATE TABLE abc(a, b, c);} 94} {} 95do_test alter2-1.3 { 96 execsql { 97 SELECT * FROM abc; 98 } 99} {1 2 {} 3 4 {} 5 6 {}} 100do_test alter2-1.4 { 101 execsql { 102 UPDATE abc SET c = 10 WHERE a = 1; 103 SELECT * FROM abc; 104 } 105} {1 2 10 3 4 {} 5 6 {}} 106do_test alter2-1.5 { 107 execsql { 108 CREATE INDEX abc_i ON abc(c); 109 } 110} {} 111do_test alter2-1.6 { 112 execsql { 113 SELECT c FROM abc ORDER BY c; 114 } 115} {{} {} 10} 116do_test alter2-1.7 { 117 execsql { 118 SELECT * FROM abc WHERE c = 10; 119 } 120} {1 2 10} 121do_test alter2-1.8 { 122 execsql { 123 SELECT sum(a), c FROM abc GROUP BY c; 124 } 125} {8 {} 1 10} 126do_test alter2-1.9 { 127 # ALTER TABLE abc ADD COLUMN d; 128 alter_table abc {CREATE TABLE abc(a, b, c, d);} 129 execsql { SELECT * FROM abc; } 130 execsql { 131 UPDATE abc SET d = 11 WHERE c IS NULL AND a<4; 132 SELECT * FROM abc; 133 } 134} {1 2 10 {} 3 4 {} 11 5 6 {} {}} 135do_test alter2-1.10 { 136 execsql { 137 SELECT typeof(d) FROM abc; 138 } 139} {null integer null} 140do_test alter2-1.99 { 141 execsql { 142 DROP TABLE abc; 143 } 144} {} 145 146#----------------------------------------------------------------------- 147# Test that views work when the underlying table structure is changed. 148# 149ifcapable view { 150 do_test alter2-2.1 { 151 execsql { 152 CREATE TABLE abc2(a, b, c); 153 INSERT INTO abc2 VALUES(1, 2, 10); 154 INSERT INTO abc2 VALUES(3, 4, NULL); 155 INSERT INTO abc2 VALUES(5, 6, NULL); 156 CREATE VIEW abc2_v AS SELECT * FROM abc2; 157 SELECT * FROM abc2_v; 158 } 159 } {1 2 10 3 4 {} 5 6 {}} 160 do_test alter2-2.2 { 161 # ALTER TABLE abc ADD COLUMN d; 162 alter_table abc2 {CREATE TABLE abc2(a, b, c, d);} 163 execsql { 164 SELECT * FROM abc2_v; 165 } 166 } {1 2 10 {} 3 4 {} {} 5 6 {} {}} 167 do_test alter2-2.3 { 168 execsql { 169 DROP TABLE abc2; 170 DROP VIEW abc2_v; 171 } 172 } {} 173} 174 175#----------------------------------------------------------------------- 176# Test that triggers work when a short row is copied to the old.* 177# trigger pseudo-table. 178# 179ifcapable trigger { 180 do_test alter2-3.1 { 181 execsql { 182 CREATE TABLE abc3(a, b); 183 CREATE TABLE blog(o, n); 184 CREATE TRIGGER abc3_t AFTER UPDATE OF b ON abc3 BEGIN 185 INSERT INTO blog VALUES(old.b, new.b); 186 END; 187 } 188 } {} 189 do_test alter2-3.2 { 190 execsql { 191 INSERT INTO abc3 VALUES(1, 4); 192 UPDATE abc3 SET b = 2 WHERE b = 4; 193 SELECT * FROM blog; 194 } 195 } {4 2} 196 do_test alter2-3.3 { 197 execsql { 198 INSERT INTO abc3 VALUES(3, 4); 199 INSERT INTO abc3 VALUES(5, 6); 200 } 201 alter_table abc3 {CREATE TABLE abc3(a, b, c);} 202 execsql { 203 SELECT * FROM abc3; 204 } 205 } {1 2 {} 3 4 {} 5 6 {}} 206 do_test alter2-3.4 { 207 execsql { 208 UPDATE abc3 SET b = b*2 WHERE a<4; 209 SELECT * FROM abc3; 210 } 211 } {1 4 {} 3 8 {} 5 6 {}} 212 do_test alter2-3.5 { 213 execsql { 214 SELECT * FROM blog; 215 } 216 } {4 2 2 4 4 8} 217 218 do_test alter2-3.6 { 219 execsql { 220 CREATE TABLE clog(o, n); 221 CREATE TRIGGER abc3_t2 AFTER UPDATE OF c ON abc3 BEGIN 222 INSERT INTO clog VALUES(old.c, new.c); 223 END; 224 UPDATE abc3 SET c = a*2; 225 SELECT * FROM clog; 226 } 227 } {{} 2 {} 6 {} 10} 228} 229 230#--------------------------------------------------------------------- 231# Check that an error occurs if the database is upgraded to a file 232# format that SQLite does not support (in this case 5). Note: The 233# file format is checked each time the schema is read, so changing the 234# file format requires incrementing the schema cookie. 235# 236do_test alter2-4.1 { 237 set_file_format 5 238} {} 239do_test alter2-4.2 { 240 catchsql { 241 SELECT * FROM sqlite_master; 242 } 243} {1 {unsupported file format}} 244do_test alter2-4.3 { 245 sqlite3_errcode $::DB 246} {SQLITE_ERROR} 247do_test alter2-4.4 { 248 set ::DB [sqlite3_connection_pointer db] 249 catchsql { 250 SELECT * FROM sqlite_master; 251 } 252} {1 {unsupported file format}} 253do_test alter2-4.5 { 254 sqlite3_errcode $::DB 255} {SQLITE_ERROR} 256 257#--------------------------------------------------------------------- 258# Check that executing VACUUM on a file with file-format version 2 259# resets the file format to 1. 260# 261do_test alter2-5.1 { 262 set_file_format 2 263 get_file_format 264} {2} 265do_test alter2-5.2 { 266 execsql { 267 VACUUM; 268 } 269} {} 270do_test alter2-5.3 { 271 get_file_format 272} {1} 273 274#--------------------------------------------------------------------- 275# Test that when a database with file-format 2 is opened, new 276# databases are still created with file-format 1. 277# 278do_test alter2-6.1 { 279 db close 280 set_file_format 2 281 sqlite3 db test.db 282 set ::DB [sqlite3_connection_pointer db] 283 get_file_format 284} {2} 285do_test alter2-6.2 { 286 file delete -force test2.db-journal 287 file delete -force test2.db 288 execsql { 289 ATTACH 'test2.db' AS aux; 290 CREATE TABLE aux.t1(a, b); 291 } 292 get_file_format test2.db 293} {1} 294do_test alter2-6.3 { 295 execsql { 296 CREATE TABLE t1(a, b); 297 } 298 get_file_format 299} {2} 300 301#--------------------------------------------------------------------- 302# Test that types and values for columns added with default values 303# other than NULL work with SELECT statements. 304# 305do_test alter2-7.1 { 306 execsql { 307 DROP TABLE t1; 308 CREATE TABLE t1(a); 309 INSERT INTO t1 VALUES(1); 310 INSERT INTO t1 VALUES(2); 311 INSERT INTO t1 VALUES(3); 312 INSERT INTO t1 VALUES(4); 313 SELECT * FROM t1; 314 } 315} {1 2 3 4} 316do_test alter2-7.2 { 317 set sql {CREATE TABLE t1(a, b DEFAULT '123', c INTEGER DEFAULT '123')} 318 alter_table t1 $sql 3 319 execsql { 320 SELECT * FROM t1 LIMIT 1; 321 } 322} {1 123 123} 323do_test alter2-7.3 { 324 execsql { 325 SELECT a, typeof(a), b, typeof(b), c, typeof(c) FROM t1 LIMIT 1; 326 } 327} {1 integer 123 text 123 integer} 328do_test alter2-7.4 { 329 execsql { 330 SELECT a, typeof(a), b, typeof(b), c, typeof(c) FROM t1 LIMIT 1; 331 } 332} {1 integer 123 text 123 integer} 333do_test alter2-7.5 { 334 set sql {CREATE TABLE t1(a, b DEFAULT -123.0, c VARCHAR(10) default 5)} 335 alter_table t1 $sql 3 336 execsql { 337 SELECT a, typeof(a), b, typeof(b), c, typeof(c) FROM t1 LIMIT 1; 338 } 339} {1 integer -123 integer 5 text} 340 341#----------------------------------------------------------------------- 342# Test that UPDATE trigger tables work with default values, and that when 343# a row is updated the default values are correctly transfered to the 344# new row. 345# 346ifcapable trigger { 347db function set_val {set ::val} 348 do_test alter2-8.1 { 349 execsql { 350 CREATE TRIGGER trig1 BEFORE UPDATE ON t1 BEGIN 351 SELECT set_val( 352 old.b||' '||typeof(old.b)||' '||old.c||' '||typeof(old.c)||' '|| 353 new.b||' '||typeof(new.b)||' '||new.c||' '||typeof(new.c) 354 ); 355 END; 356 } 357 list 358 } {} 359} 360do_test alter2-8.2 { 361 execsql { 362 UPDATE t1 SET c = 10 WHERE a = 1; 363 SELECT a, typeof(a), b, typeof(b), c, typeof(c) FROM t1 LIMIT 1; 364 } 365} {1 integer -123 integer 10 text} 366ifcapable trigger { 367 do_test alter2-8.3 { 368 set ::val 369 } {-123 integer 5 text -123 integer 10 text} 370} 371 372#----------------------------------------------------------------------- 373# Test that DELETE trigger tables work with default values, and that when 374# a row is updated the default values are correctly transfered to the 375# new row. 376# 377ifcapable trigger { 378 do_test alter2-9.1 { 379 execsql { 380 CREATE TRIGGER trig2 BEFORE DELETE ON t1 BEGIN 381 SELECT set_val( 382 old.b||' '||typeof(old.b)||' '||old.c||' '||typeof(old.c) 383 ); 384 END; 385 } 386 list 387 } {} 388 do_test alter2-9.2 { 389 execsql { 390 DELETE FROM t1 WHERE a = 2; 391 } 392 set ::val 393 } {-123 integer 5 text} 394} 395 396#----------------------------------------------------------------------- 397# Test creating an index on a column added with a default value. 398# 399do_test alter2-10.1 { 400 execsql { 401 CREATE TABLE t2(a); 402 INSERT INTO t2 VALUES('a'); 403 INSERT INTO t2 VALUES('b'); 404 INSERT INTO t2 VALUES('c'); 405 INSERT INTO t2 VALUES('d'); 406 } 407 alter_table t2 {CREATE TABLE t2(a, b DEFAULT X'ABCD', c DEFAULT NULL);} 3 408 catchsql { 409 SELECT * FROM sqlite_master; 410 } 411 execsql { 412 SELECT quote(a), quote(b), quote(c) FROM t2 LIMIT 1; 413 } 414} {'a' X'ABCD' NULL} 415do_test alter2-10.2 { 416 execsql { 417 CREATE INDEX i1 ON t2(b); 418 SELECT a FROM t2 WHERE b = X'ABCD'; 419 } 420} {a b c d} 421do_test alter2-10.3 { 422 execsql { 423 DELETE FROM t2 WHERE a = 'c'; 424 SELECT a FROM t2 WHERE b = X'ABCD'; 425 } 426} {a b d} 427do_test alter2-10.4 { 428 execsql { 429 SELECT count(b) FROM t2 WHERE b = X'ABCD'; 430 } 431} {3} 432 433finish_test 434