OLD | NEW |
(Empty) | |
| 1 # 2004 November 10 |
| 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 the ALTER TABLE statement. |
| 13 # |
| 14 # $Id: alter.test,v 1.32 2009/03/24 15:08:10 drh Exp $ |
| 15 # |
| 16 |
| 17 set testdir [file dirname $argv0] |
| 18 source $testdir/tester.tcl |
| 19 |
| 20 # If SQLITE_OMIT_ALTERTABLE is defined, omit this file. |
| 21 ifcapable !altertable { |
| 22 finish_test |
| 23 return |
| 24 } |
| 25 |
| 26 #---------------------------------------------------------------------- |
| 27 # Test organization: |
| 28 # |
| 29 # alter-1.1.* - alter-1.7.*: Basic tests of ALTER TABLE, including tables |
| 30 # with implicit and explicit indices. These tests came from an earlier |
| 31 # fork of SQLite that also supported ALTER TABLE. |
| 32 # alter-1.8.*: Tests for ALTER TABLE when the table resides in an |
| 33 # attached database. |
| 34 # alter-1.9.*: Tests for ALTER TABLE when their is whitespace between the |
| 35 # table name and left parenthesis token. i.e: |
| 36 # "CREATE TABLE abc (a, b, c);" |
| 37 # alter-2.*: Test error conditions and messages. |
| 38 # alter-3.*: Test ALTER TABLE on tables that have TRIGGERs attached to them. |
| 39 # alter-4.*: Test ALTER TABLE on tables that have AUTOINCREMENT fields. |
| 40 # ... |
| 41 # alter-12.*: Test ALTER TABLE on views. |
| 42 # |
| 43 |
| 44 # Create some tables to rename. Be sure to include some TEMP tables |
| 45 # and some tables with odd names. |
| 46 # |
| 47 do_test alter-1.1 { |
| 48 ifcapable tempdb { |
| 49 set ::temp TEMP |
| 50 } else { |
| 51 set ::temp {} |
| 52 } |
| 53 execsql [subst -nocommands { |
| 54 CREATE TABLE t1(a,b); |
| 55 INSERT INTO t1 VALUES(1,2); |
| 56 CREATE TABLE [t1'x1](c UNIQUE, b PRIMARY KEY); |
| 57 INSERT INTO [t1'x1] VALUES(3,4); |
| 58 CREATE INDEX t1i1 ON T1(B); |
| 59 CREATE INDEX t1i2 ON t1(a,b); |
| 60 CREATE INDEX i3 ON [t1'x1](b,c); |
| 61 CREATE $::temp TABLE "temp table"(e,f,g UNIQUE); |
| 62 CREATE INDEX i2 ON [temp table](f); |
| 63 INSERT INTO [temp table] VALUES(5,6,7); |
| 64 }] |
| 65 execsql { |
| 66 SELECT 't1', * FROM t1; |
| 67 SELECT 't1''x1', * FROM "t1'x1"; |
| 68 SELECT * FROM [temp table]; |
| 69 } |
| 70 } {t1 1 2 t1'x1 3 4 5 6 7} |
| 71 do_test alter-1.2 { |
| 72 execsql [subst { |
| 73 CREATE $::temp TABLE objlist(type, name, tbl_name); |
| 74 INSERT INTO objlist SELECT type, name, tbl_name |
| 75 FROM sqlite_master WHERE NAME!='objlist'; |
| 76 }] |
| 77 ifcapable tempdb { |
| 78 execsql { |
| 79 INSERT INTO objlist SELECT type, name, tbl_name |
| 80 FROM temp.sqlite_master WHERE NAME!='objlist'; |
| 81 } |
| 82 } |
| 83 |
| 84 execsql { |
| 85 SELECT type, name, tbl_name FROM objlist ORDER BY tbl_name, type desc, name; |
| 86 } |
| 87 } [list \ |
| 88 table t1 t1 \ |
| 89 index t1i1 t1 \ |
| 90 index t1i2 t1 \ |
| 91 table t1'x1 t1'x1 \ |
| 92 index i3 t1'x1 \ |
| 93 index {sqlite_autoindex_t1'x1_1} t1'x1 \ |
| 94 index {sqlite_autoindex_t1'x1_2} t1'x1 \ |
| 95 table {temp table} {temp table} \ |
| 96 index i2 {temp table} \ |
| 97 index {sqlite_autoindex_temp table_1} {temp table} \ |
| 98 ] |
| 99 |
| 100 # Make some changes |
| 101 # |
| 102 integrity_check alter-1.3.0 |
| 103 do_test alter-1.3 { |
| 104 execsql { |
| 105 ALTER TABLE [T1] RENAME to [-t1-]; |
| 106 ALTER TABLE "t1'x1" RENAME TO T2; |
| 107 ALTER TABLE [temp table] RENAME to TempTab; |
| 108 } |
| 109 } {} |
| 110 integrity_check alter-1.3.1 |
| 111 do_test alter-1.4 { |
| 112 execsql { |
| 113 SELECT 't1', * FROM [-t1-]; |
| 114 SELECT 't2', * FROM t2; |
| 115 SELECT * FROM temptab; |
| 116 } |
| 117 } {t1 1 2 t2 3 4 5 6 7} |
| 118 do_test alter-1.5 { |
| 119 execsql { |
| 120 DELETE FROM objlist; |
| 121 INSERT INTO objlist SELECT type, name, tbl_name |
| 122 FROM sqlite_master WHERE NAME!='objlist'; |
| 123 } |
| 124 catchsql { |
| 125 INSERT INTO objlist SELECT type, name, tbl_name |
| 126 FROM sqlite_temp_master WHERE NAME!='objlist'; |
| 127 } |
| 128 execsql { |
| 129 SELECT type, name, tbl_name FROM objlist ORDER BY tbl_name, type desc, name; |
| 130 } |
| 131 } [list \ |
| 132 table -t1- -t1- \ |
| 133 index t1i1 -t1- \ |
| 134 index t1i2 -t1- \ |
| 135 table T2 T2 \ |
| 136 index i3 T2 \ |
| 137 index {sqlite_autoindex_T2_1} T2 \ |
| 138 index {sqlite_autoindex_T2_2} T2 \ |
| 139 table {TempTab} {TempTab} \ |
| 140 index i2 {TempTab} \ |
| 141 index {sqlite_autoindex_TempTab_1} {TempTab} \ |
| 142 ] |
| 143 |
| 144 # Make sure the changes persist after restarting the database. |
| 145 # (The TEMP table will not persist, of course.) |
| 146 # |
| 147 ifcapable tempdb { |
| 148 do_test alter-1.6 { |
| 149 db close |
| 150 sqlite3 db test.db |
| 151 set DB [sqlite3_connection_pointer db] |
| 152 execsql { |
| 153 CREATE TEMP TABLE objlist(type, name, tbl_name); |
| 154 INSERT INTO objlist SELECT type, name, tbl_name FROM sqlite_master; |
| 155 INSERT INTO objlist |
| 156 SELECT type, name, tbl_name FROM temp.sqlite_master |
| 157 WHERE NAME!='objlist'; |
| 158 SELECT type, name, tbl_name FROM objlist |
| 159 ORDER BY tbl_name, type desc, name; |
| 160 } |
| 161 } [list \ |
| 162 table -t1- -t1- \ |
| 163 index t1i1 -t1- \ |
| 164 index t1i2 -t1- \ |
| 165 table T2 T2 \ |
| 166 index i3 T2 \ |
| 167 index {sqlite_autoindex_T2_1} T2 \ |
| 168 index {sqlite_autoindex_T2_2} T2 \ |
| 169 ] |
| 170 } else { |
| 171 execsql { |
| 172 DROP TABLE TempTab; |
| 173 } |
| 174 } |
| 175 |
| 176 # Create bogus application-defined functions for functions used |
| 177 # internally by ALTER TABLE, to ensure that ALTER TABLE falls back |
| 178 # to the built-in functions. |
| 179 # |
| 180 proc failing_app_func {args} {error "bad function"} |
| 181 do_test alter-1.7-prep { |
| 182 db func substr failing_app_func |
| 183 db func like failing_app_func |
| 184 db func sqlite_rename_table failing_app_func |
| 185 db func sqlite_rename_trigger failing_app_func |
| 186 db func sqlite_rename_parent failing_app_func |
| 187 catchsql {SELECT substr(name,1,3) FROM sqlite_master} |
| 188 } {1 {bad function}} |
| 189 |
| 190 # Make sure the ALTER TABLE statements work with the |
| 191 # non-callback API |
| 192 # |
| 193 do_test alter-1.7 { |
| 194 stepsql $DB { |
| 195 ALTER TABLE [-t1-] RENAME to [*t1*]; |
| 196 ALTER TABLE T2 RENAME TO [<t2>]; |
| 197 } |
| 198 execsql { |
| 199 DELETE FROM objlist; |
| 200 INSERT INTO objlist SELECT type, name, tbl_name |
| 201 FROM sqlite_master WHERE NAME!='objlist'; |
| 202 } |
| 203 catchsql { |
| 204 INSERT INTO objlist SELECT type, name, tbl_name |
| 205 FROM sqlite_temp_master WHERE NAME!='objlist'; |
| 206 } |
| 207 execsql { |
| 208 SELECT type, name, tbl_name FROM objlist ORDER BY tbl_name, type desc, name; |
| 209 } |
| 210 } [list \ |
| 211 table *t1* *t1* \ |
| 212 index t1i1 *t1* \ |
| 213 index t1i2 *t1* \ |
| 214 table <t2> <t2> \ |
| 215 index i3 <t2> \ |
| 216 index {sqlite_autoindex_<t2>_1} <t2> \ |
| 217 index {sqlite_autoindex_<t2>_2} <t2> \ |
| 218 ] |
| 219 |
| 220 # Check that ALTER TABLE works on attached databases. |
| 221 # |
| 222 ifcapable attach { |
| 223 do_test alter-1.8.1 { |
| 224 forcedelete test2.db |
| 225 forcedelete test2.db-journal |
| 226 execsql { |
| 227 ATTACH 'test2.db' AS aux; |
| 228 } |
| 229 } {} |
| 230 do_test alter-1.8.2 { |
| 231 execsql { |
| 232 CREATE TABLE t4(a PRIMARY KEY, b, c); |
| 233 CREATE TABLE aux.t4(a PRIMARY KEY, b, c); |
| 234 CREATE INDEX i4 ON t4(b); |
| 235 CREATE INDEX aux.i4 ON t4(b); |
| 236 } |
| 237 } {} |
| 238 do_test alter-1.8.3 { |
| 239 execsql { |
| 240 INSERT INTO t4 VALUES('main', 'main', 'main'); |
| 241 INSERT INTO aux.t4 VALUES('aux', 'aux', 'aux'); |
| 242 SELECT * FROM t4 WHERE a = 'main'; |
| 243 } |
| 244 } {main main main} |
| 245 do_test alter-1.8.4 { |
| 246 execsql { |
| 247 ALTER TABLE t4 RENAME TO t5; |
| 248 SELECT * FROM t4 WHERE a = 'aux'; |
| 249 } |
| 250 } {aux aux aux} |
| 251 do_test alter-1.8.5 { |
| 252 execsql { |
| 253 SELECT * FROM t5; |
| 254 } |
| 255 } {main main main} |
| 256 do_test alter-1.8.6 { |
| 257 execsql { |
| 258 SELECT * FROM t5 WHERE b = 'main'; |
| 259 } |
| 260 } {main main main} |
| 261 do_test alter-1.8.7 { |
| 262 execsql { |
| 263 ALTER TABLE aux.t4 RENAME TO t5; |
| 264 SELECT * FROM aux.t5 WHERE b = 'aux'; |
| 265 } |
| 266 } {aux aux aux} |
| 267 } |
| 268 |
| 269 do_test alter-1.9.1 { |
| 270 execsql { |
| 271 CREATE TABLE tbl1 (a, b, c); |
| 272 INSERT INTO tbl1 VALUES(1, 2, 3); |
| 273 } |
| 274 } {} |
| 275 do_test alter-1.9.2 { |
| 276 execsql { |
| 277 SELECT * FROM tbl1; |
| 278 } |
| 279 } {1 2 3} |
| 280 do_test alter-1.9.3 { |
| 281 execsql { |
| 282 ALTER TABLE tbl1 RENAME TO tbl2; |
| 283 SELECT * FROM tbl2; |
| 284 } |
| 285 } {1 2 3} |
| 286 do_test alter-1.9.4 { |
| 287 execsql { |
| 288 DROP TABLE tbl2; |
| 289 } |
| 290 } {} |
| 291 |
| 292 # Test error messages |
| 293 # |
| 294 do_test alter-2.1 { |
| 295 catchsql { |
| 296 ALTER TABLE none RENAME TO hi; |
| 297 } |
| 298 } {1 {no such table: none}} |
| 299 do_test alter-2.2 { |
| 300 execsql { |
| 301 CREATE TABLE t3(p,q,r); |
| 302 } |
| 303 catchsql { |
| 304 ALTER TABLE [<t2>] RENAME TO t3; |
| 305 } |
| 306 } {1 {there is already another table or index with this name: t3}} |
| 307 do_test alter-2.3 { |
| 308 catchsql { |
| 309 ALTER TABLE [<t2>] RENAME TO i3; |
| 310 } |
| 311 } {1 {there is already another table or index with this name: i3}} |
| 312 do_test alter-2.4 { |
| 313 catchsql { |
| 314 ALTER TABLE SqLiTe_master RENAME TO master; |
| 315 } |
| 316 } {1 {table sqlite_master may not be altered}} |
| 317 do_test alter-2.5 { |
| 318 catchsql { |
| 319 ALTER TABLE t3 RENAME TO sqlite_t3; |
| 320 } |
| 321 } {1 {object name reserved for internal use: sqlite_t3}} |
| 322 do_test alter-2.6 { |
| 323 catchsql { |
| 324 ALTER TABLE t3 ADD COLUMN (ALTER TABLE t3 ADD COLUMN); |
| 325 } |
| 326 } {1 {near "(": syntax error}} |
| 327 |
| 328 # If this compilation does not include triggers, omit the alter-3.* tests. |
| 329 ifcapable trigger { |
| 330 |
| 331 #----------------------------------------------------------------------- |
| 332 # Tests alter-3.* test ALTER TABLE on tables that have triggers. |
| 333 # |
| 334 # alter-3.1.*: ALTER TABLE with triggers. |
| 335 # alter-3.2.*: Test that the ON keyword cannot be used as a database, |
| 336 # table or column name unquoted. This is done because part of the |
| 337 # ALTER TABLE code (specifically the implementation of SQL function |
| 338 # "sqlite_alter_trigger") will break in this case. |
| 339 # alter-3.3.*: ALTER TABLE with TEMP triggers (todo). |
| 340 # |
| 341 |
| 342 # An SQL user-function for triggers to fire, so that we know they |
| 343 # are working. |
| 344 proc trigfunc {args} { |
| 345 set ::TRIGGER $args |
| 346 } |
| 347 db func trigfunc trigfunc |
| 348 |
| 349 do_test alter-3.1.0 { |
| 350 execsql { |
| 351 CREATE TABLE t6(a, b, c); |
| 352 -- Different case for the table name in the trigger. |
| 353 CREATE TRIGGER trig1 AFTER INSERT ON T6 BEGIN |
| 354 SELECT trigfunc('trig1', new.a, new.b, new.c); |
| 355 END; |
| 356 } |
| 357 } {} |
| 358 do_test alter-3.1.1 { |
| 359 execsql { |
| 360 INSERT INTO t6 VALUES(1, 2, 3); |
| 361 } |
| 362 set ::TRIGGER |
| 363 } {trig1 1 2 3} |
| 364 do_test alter-3.1.2 { |
| 365 execsql { |
| 366 ALTER TABLE t6 RENAME TO t7; |
| 367 INSERT INTO t7 VALUES(4, 5, 6); |
| 368 } |
| 369 set ::TRIGGER |
| 370 } {trig1 4 5 6} |
| 371 do_test alter-3.1.3 { |
| 372 execsql { |
| 373 DROP TRIGGER trig1; |
| 374 } |
| 375 } {} |
| 376 do_test alter-3.1.4 { |
| 377 execsql { |
| 378 CREATE TRIGGER trig2 AFTER INSERT ON main.t7 BEGIN |
| 379 SELECT trigfunc('trig2', new.a, new.b, new.c); |
| 380 END; |
| 381 INSERT INTO t7 VALUES(1, 2, 3); |
| 382 } |
| 383 set ::TRIGGER |
| 384 } {trig2 1 2 3} |
| 385 do_test alter-3.1.5 { |
| 386 execsql { |
| 387 ALTER TABLE t7 RENAME TO t8; |
| 388 INSERT INTO t8 VALUES(4, 5, 6); |
| 389 } |
| 390 set ::TRIGGER |
| 391 } {trig2 4 5 6} |
| 392 do_test alter-3.1.6 { |
| 393 execsql { |
| 394 DROP TRIGGER trig2; |
| 395 } |
| 396 } {} |
| 397 do_test alter-3.1.7 { |
| 398 execsql { |
| 399 CREATE TRIGGER trig3 AFTER INSERT ON main.'t8'BEGIN |
| 400 SELECT trigfunc('trig3', new.a, new.b, new.c); |
| 401 END; |
| 402 INSERT INTO t8 VALUES(1, 2, 3); |
| 403 } |
| 404 set ::TRIGGER |
| 405 } {trig3 1 2 3} |
| 406 do_test alter-3.1.8 { |
| 407 execsql { |
| 408 ALTER TABLE t8 RENAME TO t9; |
| 409 INSERT INTO t9 VALUES(4, 5, 6); |
| 410 } |
| 411 set ::TRIGGER |
| 412 } {trig3 4 5 6} |
| 413 |
| 414 # Make sure "ON" cannot be used as a database, table or column name without |
| 415 # quoting. Otherwise the sqlite_alter_trigger() function might not work. |
| 416 forcedelete test3.db |
| 417 forcedelete test3.db-journal |
| 418 ifcapable attach { |
| 419 do_test alter-3.2.1 { |
| 420 catchsql { |
| 421 ATTACH 'test3.db' AS ON; |
| 422 } |
| 423 } {1 {near "ON": syntax error}} |
| 424 do_test alter-3.2.2 { |
| 425 catchsql { |
| 426 ATTACH 'test3.db' AS 'ON'; |
| 427 } |
| 428 } {0 {}} |
| 429 do_test alter-3.2.3 { |
| 430 catchsql { |
| 431 CREATE TABLE ON.t1(a, b, c); |
| 432 } |
| 433 } {1 {near "ON": syntax error}} |
| 434 do_test alter-3.2.4 { |
| 435 catchsql { |
| 436 CREATE TABLE 'ON'.t1(a, b, c); |
| 437 } |
| 438 } {0 {}} |
| 439 do_test alter-3.2.4 { |
| 440 catchsql { |
| 441 CREATE TABLE 'ON'.ON(a, b, c); |
| 442 } |
| 443 } {1 {near "ON": syntax error}} |
| 444 do_test alter-3.2.5 { |
| 445 catchsql { |
| 446 CREATE TABLE 'ON'.'ON'(a, b, c); |
| 447 } |
| 448 } {0 {}} |
| 449 } |
| 450 do_test alter-3.2.6 { |
| 451 catchsql { |
| 452 CREATE TABLE t10(a, ON, c); |
| 453 } |
| 454 } {1 {near "ON": syntax error}} |
| 455 do_test alter-3.2.7 { |
| 456 catchsql { |
| 457 CREATE TABLE t10(a, 'ON', c); |
| 458 } |
| 459 } {0 {}} |
| 460 do_test alter-3.2.8 { |
| 461 catchsql { |
| 462 CREATE TRIGGER trig4 AFTER INSERT ON ON BEGIN SELECT 1; END; |
| 463 } |
| 464 } {1 {near "ON": syntax error}} |
| 465 ifcapable attach { |
| 466 do_test alter-3.2.9 { |
| 467 catchsql { |
| 468 CREATE TRIGGER 'on'.trig4 AFTER INSERT ON 'ON' BEGIN SELECT 1; END; |
| 469 } |
| 470 } {0 {}} |
| 471 } |
| 472 do_test alter-3.2.10 { |
| 473 execsql { |
| 474 DROP TABLE t10; |
| 475 } |
| 476 } {} |
| 477 |
| 478 do_test alter-3.3.1 { |
| 479 execsql [subst { |
| 480 CREATE TABLE tbl1(a, b, c); |
| 481 CREATE $::temp TRIGGER trig1 AFTER INSERT ON tbl1 BEGIN |
| 482 SELECT trigfunc('trig1', new.a, new.b, new.c); |
| 483 END; |
| 484 }] |
| 485 } {} |
| 486 do_test alter-3.3.2 { |
| 487 execsql { |
| 488 INSERT INTO tbl1 VALUES('a', 'b', 'c'); |
| 489 } |
| 490 set ::TRIGGER |
| 491 } {trig1 a b c} |
| 492 do_test alter-3.3.3 { |
| 493 execsql { |
| 494 ALTER TABLE tbl1 RENAME TO tbl2; |
| 495 INSERT INTO tbl2 VALUES('d', 'e', 'f'); |
| 496 } |
| 497 set ::TRIGGER |
| 498 } {trig1 d e f} |
| 499 do_test alter-3.3.4 { |
| 500 execsql [subst { |
| 501 CREATE $::temp TRIGGER trig2 AFTER UPDATE ON tbl2 BEGIN |
| 502 SELECT trigfunc('trig2', new.a, new.b, new.c); |
| 503 END; |
| 504 }] |
| 505 } {} |
| 506 do_test alter-3.3.5 { |
| 507 execsql { |
| 508 ALTER TABLE tbl2 RENAME TO tbl3; |
| 509 INSERT INTO tbl3 VALUES('g', 'h', 'i'); |
| 510 } |
| 511 set ::TRIGGER |
| 512 } {trig1 g h i} |
| 513 do_test alter-3.3.6 { |
| 514 execsql { |
| 515 UPDATE tbl3 SET a = 'G' where a = 'g'; |
| 516 } |
| 517 set ::TRIGGER |
| 518 } {trig2 G h i} |
| 519 do_test alter-3.3.7 { |
| 520 execsql { |
| 521 DROP TABLE tbl3; |
| 522 } |
| 523 } {} |
| 524 ifcapable tempdb { |
| 525 do_test alter-3.3.8 { |
| 526 execsql { |
| 527 SELECT * FROM temp.sqlite_master WHERE type = 'trigger'; |
| 528 } |
| 529 } {} |
| 530 } |
| 531 |
| 532 } ;# ifcapable trigger |
| 533 |
| 534 # If the build does not include AUTOINCREMENT fields, omit alter-4.*. |
| 535 ifcapable autoinc { |
| 536 |
| 537 do_test alter-4.1 { |
| 538 execsql { |
| 539 CREATE TABLE tbl1(a INTEGER PRIMARY KEY AUTOINCREMENT); |
| 540 INSERT INTO tbl1 VALUES(10); |
| 541 } |
| 542 } {} |
| 543 do_test alter-4.2 { |
| 544 execsql { |
| 545 INSERT INTO tbl1 VALUES(NULL); |
| 546 SELECT a FROM tbl1; |
| 547 } |
| 548 } {10 11} |
| 549 do_test alter-4.3 { |
| 550 execsql { |
| 551 ALTER TABLE tbl1 RENAME TO tbl2; |
| 552 DELETE FROM tbl2; |
| 553 INSERT INTO tbl2 VALUES(NULL); |
| 554 SELECT a FROM tbl2; |
| 555 } |
| 556 } {12} |
| 557 do_test alter-4.4 { |
| 558 execsql { |
| 559 DROP TABLE tbl2; |
| 560 } |
| 561 } {} |
| 562 |
| 563 } ;# ifcapable autoinc |
| 564 |
| 565 # Test that it is Ok to execute an ALTER TABLE immediately after |
| 566 # opening a database. |
| 567 do_test alter-5.1 { |
| 568 execsql { |
| 569 CREATE TABLE tbl1(a, b, c); |
| 570 INSERT INTO tbl1 VALUES('x', 'y', 'z'); |
| 571 } |
| 572 } {} |
| 573 do_test alter-5.2 { |
| 574 sqlite3 db2 test.db |
| 575 execsql { |
| 576 ALTER TABLE tbl1 RENAME TO tbl2; |
| 577 SELECT * FROM tbl2; |
| 578 } db2 |
| 579 } {x y z} |
| 580 do_test alter-5.3 { |
| 581 db2 close |
| 582 } {} |
| 583 |
| 584 foreach tblname [execsql { |
| 585 SELECT name FROM sqlite_master |
| 586 WHERE type='table' AND name NOT GLOB 'sqlite*' |
| 587 }] { |
| 588 execsql "DROP TABLE \"$tblname\"" |
| 589 } |
| 590 |
| 591 set ::tbl_name "abc\uABCDdef" |
| 592 do_test alter-6.1 { |
| 593 string length $::tbl_name |
| 594 } {7} |
| 595 do_test alter-6.2 { |
| 596 execsql " |
| 597 CREATE TABLE ${tbl_name}(a, b, c); |
| 598 " |
| 599 set ::oid [execsql {SELECT max(oid) FROM sqlite_master}] |
| 600 execsql " |
| 601 SELECT sql FROM sqlite_master WHERE oid = $::oid; |
| 602 " |
| 603 } "{CREATE TABLE ${::tbl_name}(a, b, c)}" |
| 604 execsql " |
| 605 SELECT * FROM ${::tbl_name} |
| 606 " |
| 607 set ::tbl_name2 "abcXdef" |
| 608 do_test alter-6.3 { |
| 609 execsql " |
| 610 ALTER TABLE $::tbl_name RENAME TO $::tbl_name2 |
| 611 " |
| 612 execsql " |
| 613 SELECT sql FROM sqlite_master WHERE oid = $::oid |
| 614 " |
| 615 } "{CREATE TABLE \"${::tbl_name2}\"(a, b, c)}" |
| 616 do_test alter-6.4 { |
| 617 execsql " |
| 618 ALTER TABLE $::tbl_name2 RENAME TO $::tbl_name |
| 619 " |
| 620 execsql " |
| 621 SELECT sql FROM sqlite_master WHERE oid = $::oid |
| 622 " |
| 623 } "{CREATE TABLE \"${::tbl_name}\"(a, b, c)}" |
| 624 set ::col_name ghi\1234\jkl |
| 625 do_test alter-6.5 { |
| 626 execsql " |
| 627 ALTER TABLE $::tbl_name ADD COLUMN $::col_name VARCHAR |
| 628 " |
| 629 execsql " |
| 630 SELECT sql FROM sqlite_master WHERE oid = $::oid |
| 631 " |
| 632 } "{CREATE TABLE \"${::tbl_name}\"(a, b, c, $::col_name VARCHAR)}" |
| 633 set ::col_name2 B\3421\A |
| 634 do_test alter-6.6 { |
| 635 db close |
| 636 sqlite3 db test.db |
| 637 execsql " |
| 638 ALTER TABLE $::tbl_name ADD COLUMN $::col_name2 |
| 639 " |
| 640 execsql " |
| 641 SELECT sql FROM sqlite_master WHERE oid = $::oid |
| 642 " |
| 643 } "{CREATE TABLE \"${::tbl_name}\"(a, b, c, $::col_name VARCHAR, $::col_name2)}" |
| 644 do_test alter-6.7 { |
| 645 execsql " |
| 646 INSERT INTO ${::tbl_name} VALUES(1, 2, 3, 4, 5); |
| 647 SELECT $::col_name, $::col_name2 FROM $::tbl_name; |
| 648 " |
| 649 } {4 5} |
| 650 |
| 651 # Ticket #1665: Make sure ALTER TABLE ADD COLUMN works on a table |
| 652 # that includes a COLLATE clause. |
| 653 # |
| 654 do_realnum_test alter-7.1 { |
| 655 execsql { |
| 656 CREATE TABLE t1(a TEXT COLLATE BINARY); |
| 657 ALTER TABLE t1 ADD COLUMN b INTEGER COLLATE NOCASE; |
| 658 INSERT INTO t1 VALUES(1,'-2'); |
| 659 INSERT INTO t1 VALUES(5.4e-08,'5.4e-08'); |
| 660 SELECT typeof(a), a, typeof(b), b FROM t1; |
| 661 } |
| 662 } {text 1 integer -2 text 5.4e-08 real 5.4e-08} |
| 663 |
| 664 # Make sure that when a column is added by ALTER TABLE ADD COLUMN and has |
| 665 # a default value that the default value is used by aggregate functions. |
| 666 # |
| 667 do_test alter-8.1 { |
| 668 execsql { |
| 669 CREATE TABLE t2(a INTEGER); |
| 670 INSERT INTO t2 VALUES(1); |
| 671 INSERT INTO t2 VALUES(1); |
| 672 INSERT INTO t2 VALUES(2); |
| 673 ALTER TABLE t2 ADD COLUMN b INTEGER DEFAULT 9; |
| 674 SELECT sum(b) FROM t2; |
| 675 } |
| 676 } {27} |
| 677 do_test alter-8.2 { |
| 678 execsql { |
| 679 SELECT a, sum(b) FROM t2 GROUP BY a; |
| 680 } |
| 681 } {1 18 2 9} |
| 682 |
| 683 #-------------------------------------------------------------------------- |
| 684 # alter-9.X - Special test: Make sure the sqlite_rename_trigger() and |
| 685 # rename_table() functions do not crash when handed bad input. |
| 686 # |
| 687 ifcapable trigger { |
| 688 do_test alter-9.1 { |
| 689 execsql {SELECT SQLITE_RENAME_TRIGGER(0,0)} |
| 690 } {{}} |
| 691 } |
| 692 do_test alter-9.2 { |
| 693 execsql { |
| 694 SELECT SQLITE_RENAME_TABLE(0,0); |
| 695 SELECT SQLITE_RENAME_TABLE(10,20); |
| 696 SELECT SQLITE_RENAME_TABLE('foo', 'foo'); |
| 697 } |
| 698 } {{} {} {}} |
| 699 |
| 700 #------------------------------------------------------------------------ |
| 701 # alter-10.X - Make sure ALTER TABLE works with multi-byte UTF-8 characters |
| 702 # in the names. |
| 703 # |
| 704 do_test alter-10.1 { |
| 705 execsql "CREATE TABLE xyz(x UNIQUE)" |
| 706 execsql "ALTER TABLE xyz RENAME TO xyz\u1234abc" |
| 707 execsql {SELECT name FROM sqlite_master WHERE name GLOB 'xyz*'} |
| 708 } [list xyz\u1234abc] |
| 709 do_test alter-10.2 { |
| 710 execsql {SELECT name FROM sqlite_master WHERE name GLOB 'sqlite_autoindex*'} |
| 711 } [list sqlite_autoindex_xyz\u1234abc_1] |
| 712 do_test alter-10.3 { |
| 713 execsql "ALTER TABLE xyz\u1234abc RENAME TO xyzabc" |
| 714 execsql {SELECT name FROM sqlite_master WHERE name GLOB 'xyz*'} |
| 715 } [list xyzabc] |
| 716 do_test alter-10.4 { |
| 717 execsql {SELECT name FROM sqlite_master WHERE name GLOB 'sqlite_autoindex*'} |
| 718 } [list sqlite_autoindex_xyzabc_1] |
| 719 |
| 720 do_test alter-11.1 { |
| 721 sqlite3_exec db {CREATE TABLE t11(%c6%c6)} |
| 722 execsql { |
| 723 ALTER TABLE t11 ADD COLUMN abc; |
| 724 } |
| 725 catchsql { |
| 726 ALTER TABLE t11 ADD COLUMN abc; |
| 727 } |
| 728 } {1 {duplicate column name: abc}} |
| 729 set isutf16 [regexp 16 [db one {PRAGMA encoding}]] |
| 730 if {!$isutf16} { |
| 731 do_test alter-11.2 { |
| 732 execsql {INSERT INTO t11 VALUES(1,2)} |
| 733 sqlite3_exec db {SELECT %c6%c6 AS xyz, abc FROM t11} |
| 734 } {0 {xyz abc 1 2}} |
| 735 } |
| 736 do_test alter-11.3 { |
| 737 sqlite3_exec db {CREATE TABLE t11b("%81%82%83" text)} |
| 738 execsql { |
| 739 ALTER TABLE t11b ADD COLUMN abc; |
| 740 } |
| 741 catchsql { |
| 742 ALTER TABLE t11b ADD COLUMN abc; |
| 743 } |
| 744 } {1 {duplicate column name: abc}} |
| 745 if {!$isutf16} { |
| 746 do_test alter-11.4 { |
| 747 execsql {INSERT INTO t11b VALUES(3,4)} |
| 748 sqlite3_exec db {SELECT %81%82%83 AS xyz, abc FROM t11b} |
| 749 } {0 {xyz abc 3 4}} |
| 750 do_test alter-11.5 { |
| 751 sqlite3_exec db {SELECT [%81%82%83] AS xyz, abc FROM t11b} |
| 752 } {0 {xyz abc 3 4}} |
| 753 do_test alter-11.6 { |
| 754 sqlite3_exec db {SELECT "%81%82%83" AS xyz, abc FROM t11b} |
| 755 } {0 {xyz abc 3 4}} |
| 756 } |
| 757 do_test alter-11.7 { |
| 758 sqlite3_exec db {CREATE TABLE t11c(%81%82%83 text)} |
| 759 execsql { |
| 760 ALTER TABLE t11c ADD COLUMN abc; |
| 761 } |
| 762 catchsql { |
| 763 ALTER TABLE t11c ADD COLUMN abc; |
| 764 } |
| 765 } {1 {duplicate column name: abc}} |
| 766 if {!$isutf16} { |
| 767 do_test alter-11.8 { |
| 768 execsql {INSERT INTO t11c VALUES(5,6)} |
| 769 sqlite3_exec db {SELECT %81%82%83 AS xyz, abc FROM t11c} |
| 770 } {0 {xyz abc 5 6}} |
| 771 do_test alter-11.9 { |
| 772 sqlite3_exec db {SELECT [%81%82%83] AS xyz, abc FROM t11c} |
| 773 } {0 {xyz abc 5 6}} |
| 774 do_test alter-11.10 { |
| 775 sqlite3_exec db {SELECT "%81%82%83" AS xyz, abc FROM t11c} |
| 776 } {0 {xyz abc 5 6}} |
| 777 } |
| 778 |
| 779 do_test alter-12.1 { |
| 780 execsql { |
| 781 CREATE TABLE t12(a, b, c); |
| 782 CREATE VIEW v1 AS SELECT * FROM t12; |
| 783 } |
| 784 } {} |
| 785 do_test alter-12.2 { |
| 786 catchsql { |
| 787 ALTER TABLE v1 RENAME TO v2; |
| 788 } |
| 789 } {1 {view v1 may not be altered}} |
| 790 do_test alter-12.3 { |
| 791 execsql { SELECT * FROM v1; } |
| 792 } {} |
| 793 do_test alter-12.4 { |
| 794 db close |
| 795 sqlite3 db test.db |
| 796 execsql { SELECT * FROM v1; } |
| 797 } {} |
| 798 do_test alter-12.5 { |
| 799 catchsql { |
| 800 ALTER TABLE v1 ADD COLUMN new_column; |
| 801 } |
| 802 } {1 {Cannot add a column to a view}} |
| 803 |
| 804 # Ticket #3102: |
| 805 # Verify that comments do not interfere with the table rename |
| 806 # algorithm. |
| 807 # |
| 808 do_test alter-13.1 { |
| 809 execsql { |
| 810 CREATE TABLE /* hi */ t3102a(x); |
| 811 CREATE TABLE t3102b -- comment |
| 812 (y); |
| 813 CREATE INDEX t3102c ON t3102a(x); |
| 814 SELECT name FROM sqlite_master WHERE name GLOB 't3102*' ORDER BY 1; |
| 815 } |
| 816 } {t3102a t3102b t3102c} |
| 817 do_test alter-13.2 { |
| 818 execsql { |
| 819 ALTER TABLE t3102a RENAME TO t3102a_rename; |
| 820 SELECT name FROM sqlite_master WHERE name GLOB 't3102*' ORDER BY 1; |
| 821 } |
| 822 } {t3102a_rename t3102b t3102c} |
| 823 do_test alter-13.3 { |
| 824 execsql { |
| 825 ALTER TABLE t3102b RENAME TO t3102b_rename; |
| 826 SELECT name FROM sqlite_master WHERE name GLOB 't3102*' ORDER BY 1; |
| 827 } |
| 828 } {t3102a_rename t3102b_rename t3102c} |
| 829 |
| 830 # Ticket #3651 |
| 831 do_test alter-14.1 { |
| 832 catchsql { |
| 833 CREATE TABLE t3651(a UNIQUE); |
| 834 ALTER TABLE t3651 ADD COLUMN b UNIQUE; |
| 835 } |
| 836 } {1 {Cannot add a UNIQUE column}} |
| 837 do_test alter-14.2 { |
| 838 catchsql { |
| 839 ALTER TABLE t3651 ADD COLUMN b PRIMARY KEY; |
| 840 } |
| 841 } {1 {Cannot add a PRIMARY KEY column}} |
| 842 |
| 843 |
| 844 #------------------------------------------------------------------------- |
| 845 # Test that it is not possible to use ALTER TABLE on any system table. |
| 846 # |
| 847 set system_table_list {1 sqlite_master} |
| 848 catchsql ANALYZE |
| 849 ifcapable analyze { lappend system_table_list 2 sqlite_stat1 } |
| 850 ifcapable stat3 { lappend system_table_list 3 sqlite_stat3 } |
| 851 ifcapable stat4 { lappend system_table_list 4 sqlite_stat4 } |
| 852 |
| 853 foreach {tn tbl} $system_table_list { |
| 854 do_test alter-15.$tn.1 { |
| 855 catchsql "ALTER TABLE $tbl RENAME TO xyz" |
| 856 } [list 1 "table $tbl may not be altered"] |
| 857 |
| 858 do_test alter-15.$tn.2 { |
| 859 catchsql "ALTER TABLE $tbl ADD COLUMN xyz" |
| 860 } [list 1 "table $tbl may not be altered"] |
| 861 } |
| 862 |
| 863 #------------------------------------------------------------------------ |
| 864 # Verify that ALTER TABLE works on tables with the WITHOUT rowid option. |
| 865 # |
| 866 do_execsql_test alter-16.1 { |
| 867 CREATE TABLE t16a(a TEXT, b REAL, c INT, PRIMARY KEY(a,b)) WITHOUT rowid; |
| 868 INSERT INTO t16a VALUES('abc',1.25,99); |
| 869 ALTER TABLE t16a ADD COLUMN d TEXT DEFAULT 'xyzzy'; |
| 870 INSERT INTO t16a VALUES('cba',5.5,98,'fizzle'); |
| 871 SELECT * FROM t16a ORDER BY a; |
| 872 } {abc 1.25 99 xyzzy cba 5.5 98 fizzle} |
| 873 do_execsql_test alter-16.2 { |
| 874 ALTER TABLE t16a RENAME TO t16a_rn; |
| 875 SELECT * FROM t16a_rn ORDER BY a; |
| 876 } {abc 1.25 99 xyzzy cba 5.5 98 fizzle} |
| 877 |
| 878 #------------------------------------------------------------------------- |
| 879 # Verify that NULL values into the internal-use-only sqlite_rename_*() |
| 880 # functions do not cause problems. |
| 881 # |
| 882 do_execsql_test alter-17.1 { |
| 883 SELECT sqlite_rename_table('CREATE TABLE xyz(a,b,c)','abc'); |
| 884 } {{CREATE TABLE "abc"(a,b,c)}} |
| 885 do_execsql_test alter-17.2 { |
| 886 SELECT sqlite_rename_table('CREATE TABLE xyz(a,b,c)',NULL); |
| 887 } {{CREATE TABLE "(NULL)"(a,b,c)}} |
| 888 do_execsql_test alter-17.3 { |
| 889 SELECT sqlite_rename_table(NULL,'abc'); |
| 890 } {{}} |
| 891 do_execsql_test alter-17.4 { |
| 892 SELECT sqlite_rename_trigger('CREATE TRIGGER r1 ON xyz WHEN','abc'); |
| 893 } {{CREATE TRIGGER r1 ON "abc" WHEN}} |
| 894 do_execsql_test alter-17.5 { |
| 895 SELECT sqlite_rename_trigger('CREATE TRIGGER r1 ON xyz WHEN',NULL); |
| 896 } {{CREATE TRIGGER r1 ON "(NULL)" WHEN}} |
| 897 do_execsql_test alter-17.6 { |
| 898 SELECT sqlite_rename_trigger(NULL,'abc'); |
| 899 } {{}} |
| 900 do_execsql_test alter-17.7 { |
| 901 SELECT sqlite_rename_parent('CREATE TABLE t1(a REFERENCES "xyzzy")', |
| 902 'xyzzy','lmnop'); |
| 903 } {{CREATE TABLE t1(a REFERENCES "lmnop")}} |
| 904 do_execsql_test alter-17.8 { |
| 905 SELECT sqlite_rename_parent('CREATE TABLE t1(a REFERENCES "xyzzy")', |
| 906 'xyzzy',NULL); |
| 907 } {{CREATE TABLE t1(a REFERENCES "(NULL)")}} |
| 908 do_execsql_test alter-17.9 { |
| 909 SELECT sqlite_rename_parent('CREATE TABLE t1(a REFERENCES "xyzzy")', |
| 910 NULL, 'lmnop'); |
| 911 } {{}} |
| 912 do_execsql_test alter-17.10 { |
| 913 SELECT sqlite_rename_parent(NULL,'abc','xyz'); |
| 914 } {{}} |
| 915 do_execsql_test alter-17.11 { |
| 916 SELECT sqlite_rename_parent('create references ''','abc','xyz'); |
| 917 } {{create references '}} |
| 918 do_execsql_test alter-17.12 { |
| 919 SELECT sqlite_rename_parent('create references "abc"123" ','abc','xyz'); |
| 920 } {{create references "xyz"123" }} |
| 921 do_execsql_test alter-17.13 { |
| 922 SELECT sqlite_rename_parent("references '''",'abc','xyz'); |
| 923 } {{references '''}} |
| 924 |
| 925 finish_test |
OLD | NEW |