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