Annotation of embedaddon/sqlite3/test/alter2.test, revision 1.1.1.1

1.1       misho       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.14 2009/04/07 14:14:22 danielk1977 Exp $
                     17: #
                     18: 
                     19: set testdir [file dirname $argv0]
                     20: source $testdir/tester.tcl
                     21: 
                     22: # We have to have pragmas in order to do this test
                     23: ifcapable {!pragma} return
                     24: 
                     25: # Do not use a codec for tests in this file, as the database file is
                     26: # manipulated directly using tcl scripts. See proc [set_file_format].
                     27: #
                     28: do_not_use_codec
                     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: # 
                     44: proc set_file_format {newval} {
                     45:   hexio_write test.db 44 [hexio_render_int32 $newval]
                     46:   set schemacookie [hexio_get_int [hexio_read test.db 40 4]]
                     47:   incr schemacookie
                     48:   hexio_write test.db 40 [hexio_render_int32 $schemacookie]
                     49:   return {}
                     50: }
                     51: 
                     52: # This procedure returns the value of the file-format in file 'test.db'.
                     53: # 
                     54: proc get_file_format {{fname test.db}} {
                     55:   return [hexio_get_int [hexio_read $fname 44 4]]
                     56: }
                     57: 
                     58: # This procedure sets the SQL statement stored for table $tbl in the
                     59: # sqlite_master table of file 'test.db' to $sql. Also set the file format
                     60: # to the supplied value. This is 2 if the added column has a default that is
                     61: # NULL, or 3 otherwise. 
                     62: #
                     63: proc alter_table {tbl sql {file_format 2}} {
                     64:   sqlite3 dbat test.db
                     65:   set s [string map {' ''} $sql]
                     66:   set t [string map {' ''} $tbl]
                     67:   dbat eval [subst {
                     68:     PRAGMA writable_schema = 1;
                     69:     UPDATE sqlite_master SET sql = '$s' WHERE name = '$t' AND type = 'table';
                     70:     PRAGMA writable_schema = 0;
                     71:   }]
                     72:   dbat close
                     73:   set_file_format 2
                     74: }
                     75: 
                     76: # Create bogus application-defined functions for functions used 
                     77: # internally by ALTER TABLE, to ensure that ALTER TABLE falls back
                     78: # to the built-in functions.
                     79: #
                     80: proc failing_app_func {args} {error "bad function"}
                     81: do_test alter2-1.0 {
                     82:   db func substr failing_app_func
                     83:   db func like failing_app_func
                     84:   db func sqlite_rename_table failing_app_func
                     85:   db func sqlite_rename_trigger failing_app_func
                     86:   db func sqlite_rename_parent failing_app_func
                     87:   catchsql {SELECT substr('abcdefg',1,3)}
                     88: } {1 {bad function}}
                     89: 
                     90: 
                     91: #-----------------------------------------------------------------------
                     92: # Some basic tests to make sure short rows are handled.
                     93: #
                     94: do_test alter2-1.1 {
                     95:   execsql {
                     96:     CREATE TABLE abc(a, b);
                     97:     INSERT INTO abc VALUES(1, 2);
                     98:     INSERT INTO abc VALUES(3, 4);
                     99:     INSERT INTO abc VALUES(5, 6);
                    100:   }
                    101: } {}
                    102: do_test alter2-1.2 {
                    103:   # ALTER TABLE abc ADD COLUMN c;
                    104:   alter_table abc {CREATE TABLE abc(a, b, c);}
                    105: } {}
                    106: do_test alter2-1.3 {
                    107:   execsql {
                    108:     SELECT * FROM abc;
                    109:   }
                    110: } {1 2 {} 3 4 {} 5 6 {}}
                    111: do_test alter2-1.4 {
                    112:   execsql {
                    113:     UPDATE abc SET c = 10 WHERE a = 1;
                    114:     SELECT * FROM abc;
                    115:   }
                    116: } {1 2 10 3 4 {} 5 6 {}}
                    117: do_test alter2-1.5 {
                    118:   execsql {
                    119:     CREATE INDEX abc_i ON abc(c);
                    120:   }
                    121: } {}
                    122: do_test alter2-1.6 {
                    123:   execsql {
                    124:     SELECT c FROM abc ORDER BY c;
                    125:   }
                    126: } {{} {} 10}
                    127: do_test alter2-1.7 {
                    128:   execsql {
                    129:     SELECT * FROM abc WHERE c = 10;
                    130:   }
                    131: } {1 2 10}
                    132: do_test alter2-1.8 {
                    133:   execsql {
                    134:     SELECT sum(a), c FROM abc GROUP BY c;
                    135:   }
                    136: } {8 {} 1 10}
                    137: do_test alter2-1.9 {
                    138:   # ALTER TABLE abc ADD COLUMN d;
                    139:   alter_table abc {CREATE TABLE abc(a, b, c, d);}
                    140:   if {[permutation] == "prepare"} { db cache flush }
                    141:   execsql { SELECT * FROM abc; }
                    142:   execsql {
                    143:     UPDATE abc SET d = 11 WHERE c IS NULL AND a<4;
                    144:     SELECT * FROM abc;
                    145:   }
                    146: } {1 2 10 {} 3 4 {} 11 5 6 {} {}}
                    147: do_test alter2-1.10 {
                    148:   execsql {
                    149:     SELECT typeof(d) FROM abc;
                    150:   }
                    151: } {null integer null}
                    152: do_test alter2-1.99 {
                    153:   execsql {
                    154:     DROP TABLE abc;
                    155:   }
                    156: } {}
                    157: 
                    158: #-----------------------------------------------------------------------
                    159: # Test that views work when the underlying table structure is changed.
                    160: #
                    161: ifcapable view {
                    162:   do_test alter2-2.1 {
                    163:     execsql {
                    164:       CREATE TABLE abc2(a, b, c);
                    165:       INSERT INTO abc2 VALUES(1, 2, 10);
                    166:       INSERT INTO abc2 VALUES(3, 4, NULL);
                    167:       INSERT INTO abc2 VALUES(5, 6, NULL);
                    168:       CREATE VIEW abc2_v AS SELECT * FROM abc2;
                    169:       SELECT * FROM abc2_v;
                    170:     }
                    171:   } {1 2 10 3 4 {} 5 6 {}}
                    172:   do_test alter2-2.2 {
                    173:     # ALTER TABLE abc ADD COLUMN d;
                    174:     alter_table abc2 {CREATE TABLE abc2(a, b, c, d);}
                    175:     execsql {
                    176:       SELECT * FROM abc2_v;
                    177:     }
                    178:   } {1 2 10 {} 3 4 {} {} 5 6 {} {}}
                    179:   do_test alter2-2.3 {
                    180:     execsql {
                    181:       DROP TABLE abc2;
                    182:       DROP VIEW abc2_v;
                    183:     }
                    184:   } {}
                    185: }
                    186: 
                    187: #-----------------------------------------------------------------------
                    188: # Test that triggers work when a short row is copied to the old.*
                    189: # trigger pseudo-table.
                    190: #
                    191: ifcapable trigger {
                    192:   do_test alter2-3.1 {
                    193:     execsql {
                    194:       CREATE TABLE abc3(a, b);
                    195:       CREATE TABLE blog(o, n);
                    196:       CREATE TRIGGER abc3_t AFTER UPDATE OF b ON abc3 BEGIN
                    197:         INSERT INTO blog VALUES(old.b, new.b);
                    198:       END;
                    199:     }
                    200:   } {}
                    201:   do_test alter2-3.2 {
                    202:     execsql {
                    203:       INSERT INTO abc3 VALUES(1, 4);
                    204:       UPDATE abc3 SET b = 2 WHERE b = 4;
                    205:       SELECT * FROM blog;
                    206:     }
                    207:   } {4 2}
                    208:   do_test alter2-3.3 {
                    209:     execsql {
                    210:       INSERT INTO abc3 VALUES(3, 4);
                    211:       INSERT INTO abc3 VALUES(5, 6);
                    212:     }
                    213:     alter_table abc3 {CREATE TABLE abc3(a, b, c);}
                    214:     execsql {
                    215:       SELECT * FROM abc3;
                    216:     }
                    217:   } {1 2 {} 3 4 {} 5 6 {}}
                    218:   do_test alter2-3.4 {
                    219:     execsql {
                    220:       UPDATE abc3 SET b = b*2 WHERE a<4;
                    221:       SELECT * FROM abc3;
                    222:     }
                    223:   } {1 4 {} 3 8 {} 5 6 {}}
                    224:   do_test alter2-3.5 {
                    225:     execsql {
                    226:       SELECT * FROM blog;
                    227:     }
                    228:   } {4 2 2 4 4 8}
                    229: 
                    230:   do_test alter2-3.6 {
                    231:     execsql {
                    232:       CREATE TABLE clog(o, n);
                    233:       CREATE TRIGGER abc3_t2 AFTER UPDATE OF c ON abc3 BEGIN
                    234:         INSERT INTO clog VALUES(old.c, new.c);
                    235:       END;
                    236:       UPDATE abc3 SET c = a*2;
                    237:       SELECT * FROM clog;
                    238:     }
                    239:   } {{} 2 {} 6 {} 10}
                    240: } else {
                    241:   execsql { CREATE TABLE abc3(a, b); }
                    242: }
                    243: 
                    244: #---------------------------------------------------------------------
                    245: # Check that an error occurs if the database is upgraded to a file
                    246: # format that SQLite does not support (in this case 5). Note: The 
                    247: # file format is checked each time the schema is read, so changing the
                    248: # file format requires incrementing the schema cookie.
                    249: #
                    250: do_test alter2-4.1 {
                    251:   db close
                    252:   set_file_format 5
                    253:   catch { sqlite3 db test.db }
                    254:   set {} {}
                    255: } {}
                    256: do_test alter2-4.2 {
                    257:   # We have to run two queries here because the Tcl interface uses
                    258:   # sqlite3_prepare_v2(). In this case, the first query encounters an 
                    259:   # SQLITE_SCHEMA error. Then, when trying to recompile the statement, the
                    260:   # "unsupported file format" error is encountered. So the error code
                    261:   # returned is SQLITE_SCHEMA, not SQLITE_ERROR as required by the following
                    262:   # test case.
                    263:   #
                    264:   # When the query is attempted a second time, the same error message is
                    265:   # returned but the error code is SQLITE_ERROR, because the unsupported
                    266:   # file format was detected during a call to sqlite3_prepare(), not
                    267:   # sqlite3_step().
                    268:   #
                    269:   catchsql { SELECT * FROM sqlite_master; }
                    270:   catchsql { SELECT * FROM sqlite_master; }
                    271: } {1 {unsupported file format}}
                    272: do_test alter2-4.3 {
                    273:   sqlite3_errcode db
                    274: } {SQLITE_ERROR}
                    275: do_test alter2-4.4 {
                    276:   set ::DB [sqlite3_connection_pointer db]
                    277:   catchsql {
                    278:     SELECT * FROM sqlite_master;
                    279:   }
                    280: } {1 {unsupported file format}}
                    281: do_test alter2-4.5 {
                    282:   sqlite3_errcode db
                    283: } {SQLITE_ERROR}
                    284: 
                    285: #---------------------------------------------------------------------
                    286: # Check that executing VACUUM on a file with file-format version 2
                    287: # resets the file format to 1.
                    288: #
                    289: set default_file_format [expr $SQLITE_DEFAULT_FILE_FORMAT==4 ? 4 : 1]
                    290: ifcapable vacuum {
                    291:   do_test alter2-5.1 {
                    292:     set_file_format 2
                    293:     db close
                    294:     sqlite3 db test.db
                    295:     execsql {SELECT 1 FROM sqlite_master LIMIT 1;}
                    296:     get_file_format
                    297:   } {2}
                    298:   do_test alter2-5.2 {
                    299:     execsql { VACUUM }
                    300:   } {}
                    301:   do_test alter2-5.3 {
                    302:     get_file_format
                    303:   } $default_file_format
                    304: }
                    305:  
                    306: #---------------------------------------------------------------------
                    307: # Test that when a database with file-format 2 is opened, new 
                    308: # databases are still created with file-format 1.
                    309: #
                    310: do_test alter2-6.1 {
                    311:   db close
                    312:   set_file_format 2
                    313:   sqlite3 db test.db
                    314:   get_file_format
                    315: } {2}
                    316: ifcapable attach {
                    317:   do_test alter2-6.2 {
                    318:     forcedelete test2.db-journal
                    319:     forcedelete test2.db
                    320:     execsql {
                    321:       ATTACH 'test2.db' AS aux;
                    322:       CREATE TABLE aux.t1(a, b);
                    323:     }
                    324:     get_file_format test2.db
                    325:   } $default_file_format
                    326: }
                    327: do_test alter2-6.3 {
                    328:   execsql {
                    329:     CREATE TABLE t1(a, b);
                    330:   }
                    331:   get_file_format 
                    332: } {2}
                    333: 
                    334: #---------------------------------------------------------------------
                    335: # Test that types and values for columns added with default values 
                    336: # other than NULL work with SELECT statements.
                    337: #
                    338: do_test alter2-7.1 {
                    339:   execsql {
                    340:     DROP TABLE t1;
                    341:     CREATE TABLE t1(a);
                    342:     INSERT INTO t1 VALUES(1);
                    343:     INSERT INTO t1 VALUES(2);
                    344:     INSERT INTO t1 VALUES(3);
                    345:     INSERT INTO t1 VALUES(4);
                    346:     SELECT * FROM t1;
                    347:   }
                    348: } {1 2 3 4}
                    349: do_test alter2-7.2 {
                    350:   set sql {CREATE TABLE t1(a, b DEFAULT '123', c INTEGER DEFAULT '123')}
                    351:   alter_table t1 $sql 3
                    352:   execsql {
                    353:     SELECT * FROM t1 LIMIT 1;
                    354:   }
                    355: } {1 123 123}
                    356: do_test alter2-7.3 {
                    357:   execsql {
                    358:     SELECT a, typeof(a), b, typeof(b), c, typeof(c) FROM t1 LIMIT 1;
                    359:   }
                    360: } {1 integer 123 text 123 integer}
                    361: do_test alter2-7.4 {
                    362:   execsql {
                    363:     SELECT a, typeof(a), b, typeof(b), c, typeof(c) FROM t1 LIMIT 1;
                    364:   }
                    365: } {1 integer 123 text 123 integer}
                    366: do_test alter2-7.5 {
                    367:   set sql {CREATE TABLE t1(a, b DEFAULT -123.0, c VARCHAR(10) default 5)}
                    368:   alter_table t1 $sql 3
                    369:   execsql {
                    370:     SELECT a, typeof(a), b, typeof(b), c, typeof(c) FROM t1 LIMIT 1;
                    371:   }
                    372: } {1 integer -123 integer 5 text}
                    373: 
                    374: #-----------------------------------------------------------------------
                    375: # Test that UPDATE trigger tables work with default values, and that when
                    376: # a row is updated the default values are correctly transfered to the 
                    377: # new row.
                    378: # 
                    379: ifcapable trigger {
                    380: db function set_val {set ::val}
                    381:   do_test alter2-8.1 {
                    382:     execsql {
                    383:       CREATE TRIGGER trig1 BEFORE UPDATE ON t1 BEGIN
                    384:       SELECT set_val(
                    385:           old.b||' '||typeof(old.b)||' '||old.c||' '||typeof(old.c)||' '||
                    386:           new.b||' '||typeof(new.b)||' '||new.c||' '||typeof(new.c) 
                    387:       );
                    388:       END;
                    389:     }
                    390:     list
                    391:   } {}
                    392: }
                    393: do_test alter2-8.2 {
                    394:   execsql {
                    395:     UPDATE t1 SET c = 10 WHERE a = 1;
                    396:     SELECT a, typeof(a), b, typeof(b), c, typeof(c) FROM t1 LIMIT 1;
                    397:   }
                    398: } {1 integer -123 integer 10 text}
                    399: ifcapable trigger {
                    400:   do_test alter2-8.3 {
                    401:     set ::val
                    402:   } {-123 integer 5 text -123 integer 10 text}
                    403: }
                    404: 
                    405: #-----------------------------------------------------------------------
                    406: # Test that DELETE trigger tables work with default values, and that when
                    407: # a row is updated the default values are correctly transfered to the 
                    408: # new row.
                    409: # 
                    410: ifcapable trigger {
                    411:   do_test alter2-9.1 {
                    412:     execsql {
                    413:       CREATE TRIGGER trig2 BEFORE DELETE ON t1 BEGIN
                    414:       SELECT set_val(
                    415:           old.b||' '||typeof(old.b)||' '||old.c||' '||typeof(old.c)
                    416:       );
                    417:       END;
                    418:     }
                    419:     list
                    420:   } {}
                    421:   do_test alter2-9.2 {
                    422:     execsql {
                    423:       DELETE FROM t1 WHERE a = 2;
                    424:     }
                    425:     set ::val
                    426:   } {-123 integer 5 text}
                    427: }
                    428: 
                    429: #-----------------------------------------------------------------------
                    430: # Test creating an index on a column added with a default value. 
                    431: #
                    432: ifcapable bloblit {
                    433:   do_test alter2-10.1 {
                    434:     execsql {
                    435:       CREATE TABLE t2(a);
                    436:       INSERT INTO t2 VALUES('a');
                    437:       INSERT INTO t2 VALUES('b');
                    438:       INSERT INTO t2 VALUES('c');
                    439:       INSERT INTO t2 VALUES('d');
                    440:     }
                    441:     alter_table t2 {CREATE TABLE t2(a, b DEFAULT X'ABCD', c DEFAULT NULL);} 3
                    442:     catchsql {
                    443:       SELECT * FROM sqlite_master;
                    444:     }
                    445:     execsql {
                    446:       SELECT quote(a), quote(b), quote(c) FROM t2 LIMIT 1;
                    447:     }
                    448:   } {'a' X'ABCD' NULL}
                    449:   do_test alter2-10.2 {
                    450:     execsql {
                    451:       CREATE INDEX i1 ON t2(b);
                    452:       SELECT a FROM t2 WHERE b = X'ABCD';
                    453:     }
                    454:   } {a b c d}
                    455:   do_test alter2-10.3 {
                    456:     execsql {
                    457:       DELETE FROM t2 WHERE a = 'c';
                    458:       SELECT a FROM t2 WHERE b = X'ABCD';
                    459:     }
                    460:   } {a b d}
                    461:   do_test alter2-10.4 {
                    462:     execsql {
                    463:       SELECT count(b) FROM t2 WHERE b = X'ABCD';
                    464:     }
                    465:   } {3}
                    466: }
                    467: 
                    468: finish_test

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>