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.4 2005/03/10 12:52:47 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# 28if {[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 71puts one 72 dbat eval { 73 PRAGMA writable_schema = 1; 74 UPDATE sqlite_master SET sql = $sql WHERE name = $tbl AND type = 'table'; 75 PRAGMA writable_schema = 0; 76 } 77puts two 78 dbat close 79puts three 80 set_file_format 2 81puts four 82} 83 84#----------------------------------------------------------------------- 85# Some basic tests to make sure short rows are handled. 86# 87do_test alter2-1.1 { 88 execsql { 89 CREATE TABLE abc(a, b); 90 INSERT INTO abc VALUES(1, 2); 91 INSERT INTO abc VALUES(3, 4); 92 INSERT INTO abc VALUES(5, 6); 93 } 94} {} 95do_test alter2-1.2 { 96 # ALTER TABLE abc ADD COLUMN c; 97 alter_table abc {CREATE TABLE abc(a, b, c);} 98} {} 99exit 100do_test alter2-1.3 { 101 execsql { 102 SELECT * FROM abc; 103 } 104} {1 2 {} 3 4 {} 5 6 {}} 105do_test alter2-1.4 { 106 execsql { 107 UPDATE abc SET c = 10 WHERE a = 1; 108 SELECT * FROM abc; 109 } 110} {1 2 10 3 4 {} 5 6 {}} 111do_test alter2-1.5 { 112 execsql { 113 CREATE INDEX abc_i ON abc(c); 114 } 115} {} 116do_test alter2-1.6 { 117 execsql { 118 SELECT c FROM abc ORDER BY c; 119 } 120} {{} {} 10} 121do_test alter2-1.7 { 122 execsql { 123 SELECT * FROM abc WHERE c = 10; 124 } 125} {1 2 10} 126do_test alter2-1.8 { 127 execsql { 128 SELECT sum(a), c FROM abc GROUP BY c; 129 } 130} {8.0 {} 1.0 10} 131do_test alter2-1.9 { 132 # ALTER TABLE abc ADD COLUMN d; 133 alter_table abc {CREATE TABLE abc(a, b, c, d);} 134 execsql { SELECT * FROM abc; } 135 execsql { 136 UPDATE abc SET d = 11 WHERE c IS NULL AND a<4; 137 SELECT * FROM abc; 138 } 139} {1 2 10 {} 3 4 {} 11 5 6 {} {}} 140do_test alter2-1.10 { 141 execsql { 142 SELECT typeof(d) FROM abc; 143 } 144} {null integer null} 145do_test alter2-1.99 { 146 execsql { 147 DROP TABLE abc; 148 } 149} {} 150 151#----------------------------------------------------------------------- 152# Test that views work when the underlying table structure is changed. 153# 154ifcapable view { 155 do_test alter2-2.1 { 156 execsql { 157 CREATE TABLE abc2(a, b, c); 158 INSERT INTO abc2 VALUES(1, 2, 10); 159 INSERT INTO abc2 VALUES(3, 4, NULL); 160 INSERT INTO abc2 VALUES(5, 6, NULL); 161 CREATE VIEW abc2_v AS SELECT * FROM abc2; 162 SELECT * FROM abc2_v; 163 } 164 } {1 2 10 3 4 {} 5 6 {}} 165 do_test alter2-2.2 { 166 # ALTER TABLE abc ADD COLUMN d; 167 alter_table abc2 {CREATE TABLE abc2(a, b, c, d);} 168 execsql { 169 SELECT * FROM abc2_v; 170 } 171 } {1 2 10 {} 3 4 {} {} 5 6 {} {}} 172 do_test alter2-2.3 { 173 execsql { 174 DROP TABLE abc2; 175 DROP VIEW abc2_v; 176 } 177 } {} 178} 179 180#----------------------------------------------------------------------- 181# Test that triggers work when a short row is copied to the old.* 182# trigger pseudo-table. 183# 184ifcapable trigger { 185 do_test alter2-3.1 { 186 execsql { 187 CREATE TABLE abc3(a, b); 188 CREATE TABLE blog(o, n); 189 CREATE TRIGGER abc3_t AFTER UPDATE OF b ON abc3 BEGIN 190 INSERT INTO blog VALUES(old.b, new.b); 191 END; 192 } 193 } {} 194 do_test alter2-3.2 { 195 execsql { 196 INSERT INTO abc3 VALUES(1, 4); 197 UPDATE abc3 SET b = 2 WHERE b = 4; 198 SELECT * FROM blog; 199 } 200 } {4 2} 201 do_test alter2-3.3 { 202 execsql { 203 INSERT INTO abc3 VALUES(3, 4); 204 INSERT INTO abc3 VALUES(5, 6); 205 } 206 alter_table abc3 {CREATE TABLE abc3(a, b, c);} 207 execsql { 208 SELECT * FROM abc3; 209 } 210 } {1 2 {} 3 4 {} 5 6 {}} 211 do_test alter2-3.4 { 212 execsql { 213 UPDATE abc3 SET b = b*2 WHERE a<4; 214 SELECT * FROM abc3; 215 } 216 } {1 4 {} 3 8 {} 5 6 {}} 217 do_test alter2-3.5 { 218 execsql { 219 SELECT * FROM blog; 220 } 221 } {4 2 2 4 4 8} 222 223 do_test alter2-3.6 { 224 execsql { 225 CREATE TABLE clog(o, n); 226 CREATE TRIGGER abc3_t2 AFTER UPDATE OF c ON abc3 BEGIN 227 INSERT INTO clog VALUES(old.c, new.c); 228 END; 229 UPDATE abc3 SET c = a*2; 230 SELECT * FROM clog; 231 } 232 } {{} 2 {} 6 {} 10} 233} 234 235#--------------------------------------------------------------------- 236# Check that an error occurs if the database is upgraded to a file 237# format that SQLite does not support (in this case 4). Note: The 238# file format is checked each time the schema is read, so changing the 239# file format requires incrementing the schema cookie. 240# 241do_test alter2-4.1 { 242 set_file_format 4 243} {} 244do_test alter2-4.2 { 245 catchsql { 246 SELECT * FROM sqlite_master; 247 } 248} {1 {unsupported file format}} 249do_test alter2-4.3 { 250 sqlite3_errcode $::DB 251} {SQLITE_ERROR} 252do_test alter2-4.4 { 253 db close 254 set ::DB [sqlite3 db test.db] 255 catchsql { 256 SELECT * FROM sqlite_master; 257 } 258} {1 {unsupported file format}} 259do_test alter2-4.5 { 260 sqlite3_errcode $::DB 261} {SQLITE_ERROR} 262 263#--------------------------------------------------------------------- 264# Check that executing VACUUM on a file with file-format version 2 265# resets the file format to 1. 266# 267do_test alter2-5.1 { 268 set_file_format 2 269 get_file_format 270} {2} 271do_test alter2-5.2 { 272 execsql { 273 VACUUM; 274 } 275} {} 276do_test alter2-5.3 { 277 get_file_format 278} {1} 279 280#--------------------------------------------------------------------- 281# Test that when a database with file-format 2 is opened, new 282# databases are still created with file-format 1. 283# 284do_test alter2-6.1 { 285 db close 286 set_file_format 2 287 set ::DB [sqlite3 db test.db] 288 get_file_format 289} {2} 290do_test alter2-6.2 { 291 file delete -force test2.db-journal 292 file delete -force test2.db 293 execsql { 294 ATTACH 'test2.db' AS aux; 295 CREATE TABLE aux.t1(a, b); 296 } 297 get_file_format test2.db 298} {1} 299do_test alter2-6.3 { 300 execsql { 301 CREATE TABLE t1(a, b); 302 } 303 get_file_format 304} {2} 305 306#--------------------------------------------------------------------- 307# Test that types and values for columns added with default values 308# other than NULL work with SELECT statements. 309# 310do_test alter2-7.1 { 311 execsql { 312 DROP TABLE t1; 313 CREATE TABLE t1(a); 314 INSERT INTO t1 VALUES(1); 315 INSERT INTO t1 VALUES(2); 316 INSERT INTO t1 VALUES(3); 317 INSERT INTO t1 VALUES(4); 318 SELECT * FROM t1; 319 } 320} {1 2 3 4} 321do_test alter2-7.2 { 322 set sql {CREATE TABLE t1(a, b DEFAULT '123', c INTEGER DEFAULT '123')} 323 alter_table t1 $sql 3 324 execsql { 325 SELECT * FROM t1 LIMIT 1; 326 } 327} {1 123 123} 328do_test alter2-7.3 { 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.4 { 334 execsql { 335 SELECT a, typeof(a), b, typeof(b), c, typeof(c) FROM t1 LIMIT 1; 336 } 337} {1 integer 123 text 123 integer} 338do_test alter2-7.5 { 339 set sql {CREATE TABLE t1(a, b DEFAULT -123.0, c VARCHAR(10) default 5)} 340 alter_table t1 $sql 3 341 execsql { 342 SELECT a, typeof(a), b, typeof(b), c, typeof(c) FROM t1 LIMIT 1; 343 } 344} {1 integer -123.0 real 5 text} 345 346#----------------------------------------------------------------------- 347# Test that UPDATE trigger tables work with default values, and that when 348# a row is updated the default values are correctly transfered to the 349# new row. 350# 351ifcapable trigger { 352db function set_val {set ::val} 353 do_test alter2-8.1 { 354 execsql { 355 CREATE TRIGGER trig1 BEFORE UPDATE ON t1 BEGIN 356 SELECT set_val( 357 old.b||' '||typeof(old.b)||' '||old.c||' '||typeof(old.c)||' '|| 358 new.b||' '||typeof(new.b)||' '||new.c||' '||typeof(new.c) 359 ); 360 END; 361 } 362 list 363 } {} 364} 365do_test alter2-8.2 { 366 execsql { 367 UPDATE t1 SET c = 10 WHERE a = 1; 368 SELECT a, typeof(a), b, typeof(b), c, typeof(c) FROM t1 LIMIT 1; 369 } 370} {1 integer -123.0 real 10 text} 371ifcapable trigger { 372 do_test alter2-8.3 { 373 set ::val 374 } {-123 real 5 text -123 real 10 text} 375} 376 377#----------------------------------------------------------------------- 378# Test that DELETE trigger tables work with default values, and that when 379# a row is updated the default values are correctly transfered to the 380# new row. 381# 382ifcapable trigger { 383 do_test alter2-9.1 { 384 execsql { 385 CREATE TRIGGER trig2 BEFORE DELETE ON t1 BEGIN 386 SELECT set_val( 387 old.b||' '||typeof(old.b)||' '||old.c||' '||typeof(old.c) 388 ); 389 END; 390 } 391 list 392 } {} 393 do_test alter2-9.2 { 394 execsql { 395 DELETE FROM t1 WHERE a = 2; 396 } 397 set ::val 398 } {-123 real 5 text} 399} 400 401#----------------------------------------------------------------------- 402# Test creating an index on a column added with a default value. 403# 404do_test alter2-10.1 { 405 execsql { 406 CREATE TABLE t2(a); 407 INSERT INTO t2 VALUES('a'); 408 INSERT INTO t2 VALUES('b'); 409 INSERT INTO t2 VALUES('c'); 410 INSERT INTO t2 VALUES('d'); 411 } 412 alter_table t2 {CREATE TABLE t2(a, b DEFAULT X'ABCD', c DEFAULT NULL);} 3 413 catchsql { 414 SELECT * FROM sqlite_master; 415 } 416 execsql { 417 SELECT quote(a), quote(b), quote(c) FROM t2 LIMIT 1; 418 } 419} {'a' X'ABCD' NULL} 420do_test alter2-10.2 { 421 execsql { 422 CREATE INDEX i1 ON t2(b); 423 SELECT a FROM t2 WHERE b = X'ABCD'; 424 } 425} {a b c d} 426do_test alter2-10.3 { 427 execsql { 428 DELETE FROM t2 WHERE a = 'c'; 429 SELECT a FROM t2 WHERE b = X'ABCD'; 430 } 431} {a b d} 432do_test alter2-10.4 { 433 execsql { 434 SELECT count(b) FROM t2 WHERE b = X'ABCD'; 435 } 436} {3} 437 438finish_test 439