1# 2005 February 19 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: alter3.test,v 1.7 2005/12/30 16:28:02 danielk1977 Exp $ 17# 18 19set testdir [file dirname $argv0] 20 21source $testdir/tester.tcl 22 23# If SQLITE_OMIT_ALTERTABLE is defined, omit this file. 24ifcapable !altertable { 25 finish_test 26 return 27} 28 29# Determine if there is a codec available on this test. 30# 31if {[catch {sqlite3 -has_codec} r] || $r} { 32 set has_codec 1 33} else { 34 set has_codec 0 35} 36 37 38# Test Organisation: 39# ------------------ 40# 41# alter3-1.*: Test that ALTER TABLE correctly modifies the CREATE TABLE sql. 42# alter3-2.*: Test error messages. 43# alter3-3.*: Test adding columns with default value NULL. 44# alter3-4.*: Test adding columns with default values other than NULL. 45# alter3-5.*: Test adding columns to tables in ATTACHed databases. 46# alter3-6.*: Test that temp triggers are not accidentally dropped. 47# alter3-7.*: Test that VACUUM resets the file-format. 48# 49 50# This procedure returns the value of the file-format in file 'test.db'. 51# 52proc get_file_format {{fname test.db}} { 53 set bt [btree_open $fname 10 0] 54 set meta [btree_get_meta $bt] 55 btree_close $bt 56 lindex $meta 2 57} 58 59do_test alter3-1.1 { 60 execsql { 61 CREATE TABLE abc(a, b, c); 62 SELECT sql FROM sqlite_master; 63 } 64} {{CREATE TABLE abc(a, b, c)}} 65do_test alter3-1.2 { 66 execsql {ALTER TABLE abc ADD d INTEGER;} 67 execsql { 68 SELECT sql FROM sqlite_master; 69 } 70} {{CREATE TABLE abc(a, b, c, d INTEGER)}} 71do_test alter3-1.3 { 72 execsql {ALTER TABLE abc ADD e} 73 execsql { 74 SELECT sql FROM sqlite_master; 75 } 76} {{CREATE TABLE abc(a, b, c, d INTEGER, e)}} 77do_test alter3-1.4 { 78 execsql { 79 CREATE TABLE main.t1(a, b); 80 ALTER TABLE t1 ADD c; 81 SELECT sql FROM sqlite_master WHERE tbl_name = 't1'; 82 } 83} {{CREATE TABLE t1(a, b, c)}} 84do_test alter3-1.5 { 85 execsql { 86 ALTER TABLE t1 ADD d CHECK (a>d); 87 SELECT sql FROM sqlite_master WHERE tbl_name = 't1'; 88 } 89} {{CREATE TABLE t1(a, b, c, d CHECK (a>d))}} 90do_test alter3-1.6 { 91 execsql { 92 CREATE TABLE t2(a, b, UNIQUE(a, b)); 93 ALTER TABLE t2 ADD c REFERENCES t1(c) ; 94 SELECT sql FROM sqlite_master WHERE tbl_name = 't2' AND type = 'table'; 95 } 96} {{CREATE TABLE t2(a, b, c REFERENCES t1(c), UNIQUE(a, b))}} 97do_test alter3-1.7 { 98 execsql { 99 CREATE TABLE t3(a, b, UNIQUE(a, b)); 100 ALTER TABLE t3 ADD COLUMN c VARCHAR(10, 20); 101 SELECT sql FROM sqlite_master WHERE tbl_name = 't3' AND type = 'table'; 102 } 103} {{CREATE TABLE t3(a, b, c VARCHAR(10, 20), UNIQUE(a, b))}} 104do_test alter3-1.99 { 105 execsql { 106 DROP TABLE abc; 107 DROP TABLE t1; 108 DROP TABLE t2; 109 DROP TABLE t3; 110 } 111} {} 112 113do_test alter3-2.1 { 114 execsql { 115 CREATE TABLE t1(a, b); 116 } 117 catchsql { 118 ALTER TABLE t1 ADD c PRIMARY KEY; 119 } 120} {1 {Cannot add a PRIMARY KEY column}} 121do_test alter3-2.2 { 122 catchsql { 123 ALTER TABLE t1 ADD c UNIQUE 124 } 125} {1 {Cannot add a UNIQUE column}} 126do_test alter3-2.3 { 127 catchsql { 128 ALTER TABLE t1 ADD b VARCHAR(10) 129 } 130} {1 {duplicate column name: b}} 131do_test alter3-2.3 { 132 catchsql { 133 ALTER TABLE t1 ADD c NOT NULL; 134 } 135} {1 {Cannot add a NOT NULL column with default value NULL}} 136do_test alter3-2.4 { 137 catchsql { 138 ALTER TABLE t1 ADD c NOT NULL DEFAULT 10; 139 } 140} {0 {}} 141do_test alter3-2.5 { 142 execsql { 143 CREATE VIEW v1 AS SELECT * FROM t1; 144 } 145 catchsql { 146 alter table v1 add column d; 147 } 148} {1 {Cannot add a column to a view}} 149do_test alter3-2.6 { 150 catchsql { 151 alter table t1 add column d DEFAULT CURRENT_TIME; 152 } 153} {1 {Cannot add a column with non-constant default}} 154do_test alter3-2.99 { 155 execsql { 156 DROP TABLE t1; 157 } 158} {} 159 160do_test alter3-3.1 { 161 execsql { 162 CREATE TABLE t1(a, b); 163 INSERT INTO t1 VALUES(1, 100); 164 INSERT INTO t1 VALUES(2, 300); 165 SELECT * FROM t1; 166 } 167} {1 100 2 300} 168do_test alter3-3.1 { 169 execsql { 170 PRAGMA schema_version = 10; 171 } 172} {} 173do_test alter3-3.2 { 174 execsql { 175 ALTER TABLE t1 ADD c; 176 SELECT * FROM t1; 177 } 178} {1 100 {} 2 300 {}} 179if {!$has_codec} { 180 do_test alter3-3.3 { 181 get_file_format 182 } {3} 183} 184do_test alter3-3.4 { 185 execsql { 186 PRAGMA schema_version; 187 } 188} {11} 189 190do_test alter3-4.1 { 191 db close 192 file delete -force test.db 193 set ::DB [sqlite3 db test.db] 194 execsql { 195 CREATE TABLE t1(a, b); 196 INSERT INTO t1 VALUES(1, 100); 197 INSERT INTO t1 VALUES(2, 300); 198 SELECT * FROM t1; 199 } 200} {1 100 2 300} 201do_test alter3-4.1 { 202 execsql { 203 PRAGMA schema_version = 20; 204 } 205} {} 206do_test alter3-4.2 { 207 execsql { 208 ALTER TABLE t1 ADD c DEFAULT 'hello world'; 209 SELECT * FROM t1; 210 } 211} {1 100 {hello world} 2 300 {hello world}} 212if {!$has_codec} { 213 do_test alter3-4.3 { 214 get_file_format 215 } {3} 216} 217do_test alter3-4.4 { 218 execsql { 219 PRAGMA schema_version; 220 } 221} {21} 222do_test alter3-4.99 { 223 execsql { 224 DROP TABLE t1; 225 } 226} {} 227 228do_test alter3-5.1 { 229 file delete -force test2.db 230 file delete -force test2.db-journal 231 execsql { 232 CREATE TABLE t1(a, b); 233 INSERT INTO t1 VALUES(1, 'one'); 234 INSERT INTO t1 VALUES(2, 'two'); 235 ATTACH 'test2.db' AS aux; 236 CREATE TABLE aux.t1 AS SELECT * FROM t1; 237 PRAGMA aux.schema_version = 30; 238 SELECT sql FROM aux.sqlite_master; 239 } 240} {{CREATE TABLE t1(a,b)}} 241do_test alter3-5.2 { 242 execsql { 243 ALTER TABLE aux.t1 ADD COLUMN c VARCHAR(128); 244 SELECT sql FROM aux.sqlite_master; 245 } 246} {{CREATE TABLE t1(a,b, c VARCHAR(128))}} 247do_test alter3-5.3 { 248 execsql { 249 SELECT * FROM aux.t1; 250 } 251} {1 one {} 2 two {}} 252do_test alter3-5.4 { 253 execsql { 254 PRAGMA aux.schema_version; 255 } 256} {31} 257if {!$has_codec} { 258 do_test alter3-5.5 { 259 list [get_file_format test2.db] [get_file_format] 260 } {2 3} 261} 262do_test alter3-5.6 { 263 execsql { 264 ALTER TABLE aux.t1 ADD COLUMN d DEFAULT 1000; 265 SELECT sql FROM aux.sqlite_master; 266 } 267} {{CREATE TABLE t1(a,b, c VARCHAR(128), d DEFAULT 1000)}} 268do_test alter3-5.7 { 269 execsql { 270 SELECT * FROM aux.t1; 271 } 272} {1 one {} 1000 2 two {} 1000} 273do_test alter3-5.8 { 274 execsql { 275 PRAGMA aux.schema_version; 276 } 277} {32} 278do_test alter3-5.9 { 279 execsql { 280 SELECT * FROM t1; 281 } 282} {1 one 2 two} 283do_test alter3-5.99 { 284 execsql { 285 DROP TABLE aux.t1; 286 DROP TABLE t1; 287 } 288} {} 289 290#---------------------------------------------------------------- 291# Test that the table schema is correctly reloaded when a column 292# is added to a table. 293# 294ifcapable trigger&&tempdb { 295 do_test alter3-6.1 { 296 execsql { 297 CREATE TABLE t1(a, b); 298 CREATE TABLE log(trig, a, b); 299 300 CREATE TRIGGER t1_a AFTER INSERT ON t1 BEGIN 301 INSERT INTO log VALUES('a', new.a, new.b); 302 END; 303 CREATE TEMP TRIGGER t1_b AFTER INSERT ON t1 BEGIN 304 INSERT INTO log VALUES('b', new.a, new.b); 305 END; 306 307 INSERT INTO t1 VALUES(1, 2); 308 SELECT * FROM log; 309 } 310 } {b 1 2 a 1 2} 311 do_test alter3-6.2 { 312 execsql { 313 ALTER TABLE t1 ADD COLUMN c DEFAULT 'c'; 314 INSERT INTO t1(a, b) VALUES(3, 4); 315 SELECT * FROM log; 316 } 317 } {b 1 2 a 1 2 b 3 4 a 3 4} 318} 319 320if {!$has_codec} { 321 ifcapable vacuum { 322 do_test alter3-7.1 { 323 execsql { 324 VACUUM; 325 } 326 get_file_format 327 } {1} 328 do_test alter3-7.2 { 329 execsql { 330 CREATE TABLE abc(a, b, c); 331 ALTER TABLE abc ADD d DEFAULT NULL; 332 } 333 get_file_format 334 } {2} 335 do_test alter3-7.3 { 336 execsql { 337 ALTER TABLE abc ADD e DEFAULT 10; 338 } 339 get_file_format 340 } {3} 341 do_test alter3-7.4 { 342 execsql { 343 ALTER TABLE abc ADD f DEFAULT NULL; 344 } 345 get_file_format 346 } {3} 347 do_test alter3-7.5 { 348 execsql { 349 VACUUM; 350 } 351 get_file_format 352 } {1} 353 } 354} 355 356# Ticket #1183 - Make sure adding columns to large tables does not cause 357# memory corruption (as was the case before this bug was fixed). 358do_test alter3-8.1 { 359 execsql { 360 CREATE TABLE t4(c1); 361 } 362} {} 363set ::sql "" 364do_test alter3-8.2 { 365 set cols c1 366 for {set i 2} {$i < 100} {incr i} { 367 execsql " 368 ALTER TABLE t4 ADD c$i 369 " 370 lappend cols c$i 371 } 372 set ::sql "CREATE TABLE t4([join $cols {, }])" 373 list 374} {} 375do_test alter3-8.2 { 376 execsql { 377 SELECT sql FROM sqlite_master WHERE name = 't4'; 378 } 379} [list $::sql] 380 381finish_test 382