Home | History | Annotate | Download | only in tool
      1 
      2 package require sqlite3
      3 
      4 proc do_test {name cmd expected} {
      5   puts -nonewline "$name ..."
      6   set res [uplevel $cmd]
      7   if {$res eq $expected} {
      8     puts Ok
      9   } else {
     10     puts Error
     11     puts "  Got: $res"
     12     puts "  Expected: $expected"
     13     exit
     14   }
     15 }
     16 
     17 proc execsql {sql} {
     18   uplevel [list db eval $sql]
     19 }
     20 
     21 proc catchsql {sql} {
     22   set rc [catch {uplevel [list db eval $sql]} msg]
     23   list $rc $msg
     24 }
     25 
     26 file delete -force test.db test.db.journal
     27 sqlite3 db test.db
     28 
     29 # The following tests - genfkey-1.* - test RESTRICT foreign keys.
     30 #
     31 do_test genfkey-1.1 {
     32   execsql {
     33     CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, UNIQUE(b, c));
     34     CREATE TABLE t2(e REFERENCES t1, f);
     35     CREATE TABLE t3(g, h, i, FOREIGN KEY (h, i) REFERENCES t1(b, c));
     36   }
     37 } {}
     38 do_test genfkey-1.2 {
     39   execsql [exec ./sqlite3 test.db .genfkey]
     40 } {}
     41 do_test genfkey-1.3 {
     42   catchsql { INSERT INTO t2 VALUES(1, 2) }
     43 } {1 {constraint failed}}
     44 do_test genfkey-1.4 {
     45   execsql {
     46     INSERT INTO t1 VALUES(1, 2, 3);
     47     INSERT INTO t2 VALUES(1, 2);
     48   }
     49 } {}
     50 do_test genfkey-1.5 {
     51   execsql { INSERT INTO t2 VALUES(NULL, 3) }
     52 } {}
     53 do_test genfkey-1.6 {
     54   catchsql { UPDATE t2 SET e = 5 WHERE e IS NULL }
     55 } {1 {constraint failed}}
     56 do_test genfkey-1.7 {
     57   execsql { UPDATE t2 SET e = 1 WHERE e IS NULL }
     58 } {}
     59 do_test genfkey-1.8 {
     60   execsql { UPDATE t2 SET e = NULL WHERE f = 3 }
     61 } {}
     62 do_test genfkey-1.9 {
     63   catchsql { UPDATE t1 SET a = 10 }
     64 } {1 {constraint failed}}
     65 do_test genfkey-1.9a {
     66   catchsql { UPDATE t1 SET a = NULL }
     67 } {1 {datatype mismatch}}
     68 do_test genfkey-1.10 {
     69   catchsql { DELETE FROM t1 }
     70 } {1 {constraint failed}}
     71 do_test genfkey-1.11 {
     72   execsql { UPDATE t2 SET e = NULL }
     73 } {}
     74 do_test genfkey-1.12 {
     75   execsql { 
     76     UPDATE t1 SET a = 10 ;
     77     DELETE FROM t1;
     78     DELETE FROM t2;
     79   }
     80 } {}
     81 
     82 do_test genfkey-1.13 {
     83   execsql {
     84     INSERT INTO t3 VALUES(1, NULL, NULL);
     85     INSERT INTO t3 VALUES(1, 2, NULL);
     86     INSERT INTO t3 VALUES(1, NULL, 3);
     87   }
     88 } {}
     89 do_test genfkey-1.14 {
     90   catchsql { INSERT INTO t3 VALUES(3, 1, 4) }
     91 } {1 {constraint failed}}
     92 do_test genfkey-1.15 {
     93   execsql { 
     94     INSERT INTO t1 VALUES(1, 1, 4);
     95     INSERT INTO t3 VALUES(3, 1, 4);
     96   }
     97 } {}
     98 do_test genfkey-1.16 {
     99   catchsql { DELETE FROM t1 }
    100 } {1 {constraint failed}}
    101 do_test genfkey-1.17 {
    102   catchsql { UPDATE t1 SET b = 10}
    103 } {1 {constraint failed}}
    104 do_test genfkey-1.18 {
    105   execsql { UPDATE t1 SET a = 10}
    106 } {}
    107 do_test genfkey-1.19 {
    108   catchsql { UPDATE t3 SET h = 'hello' WHERE i = 3}
    109 } {1 {constraint failed}}
    110 
    111 do_test genfkey-1.X {
    112   execsql {
    113     DROP TABLE t1;
    114     DROP TABLE t2;
    115     DROP TABLE t3;
    116   }
    117 } {}
    118 
    119 # The following tests - genfkey-2.* - test CASCADE foreign keys.
    120 #
    121 do_test genfkey-2.1 {
    122   execsql {
    123     CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, UNIQUE(b, c));
    124     CREATE TABLE t2(e REFERENCES t1 ON UPDATE CASCADE ON DELETE CASCADE, f);
    125     CREATE TABLE t3(g, h, i, 
    126         FOREIGN KEY (h, i) 
    127         REFERENCES t1(b, c) ON UPDATE CASCADE ON DELETE CASCADE
    128     );
    129   }
    130 } {}
    131 do_test genfkey-2.2 {
    132   execsql [exec ./sqlite3 test.db .genfkey]
    133 } {}
    134 do_test genfkey-2.3 {
    135   execsql {
    136     INSERT INTO t1 VALUES(1, 2, 3);
    137     INSERT INTO t1 VALUES(4, 5, 6);
    138     INSERT INTO t2 VALUES(1, 'one');
    139     INSERT INTO t2 VALUES(4, 'four');
    140   }
    141 } {}
    142 do_test genfkey-2.4 {
    143   execsql {
    144     UPDATE t1 SET a = 2 WHERE a = 1;
    145     SELECT * FROM t2;
    146   }
    147 } {2 one 4 four}
    148 do_test genfkey-2.5 {
    149   execsql {
    150     DELETE FROM t1 WHERE a = 4;
    151     SELECT * FROM t2;
    152   }
    153 } {2 one}
    154 do_test genfkey-2.6 {
    155   execsql {
    156     INSERT INTO t3 VALUES('hello', 2, 3);
    157     UPDATE t1 SET c = 2;
    158     SELECT * FROM t3;
    159   }
    160 } {hello 2 2}
    161 do_test genfkey-2.7 {
    162   execsql {
    163     DELETE FROM t1;
    164     SELECT * FROM t3;
    165   }
    166 } {}
    167 do_test genfkey-2.X {
    168   execsql {
    169     DROP TABLE t1;
    170     DROP TABLE t2;
    171     DROP TABLE t3;
    172   }
    173 } {}
    174 
    175 
    176 # The following tests - genfkey-3.* - test SET NULL foreign keys.
    177 #
    178 do_test genfkey-3.1 {
    179   execsql {
    180     CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, UNIQUE(c, b));
    181     CREATE TABLE t2(e REFERENCES t1 ON UPDATE SET NULL ON DELETE SET NULL, f);
    182     CREATE TABLE t3(g, h, i, 
    183         FOREIGN KEY (h, i) 
    184         REFERENCES t1(b, c) ON UPDATE SET NULL ON DELETE SET NULL
    185     );
    186   }
    187 } {}
    188 do_test genfkey-3.2 {
    189   execsql [exec ./sqlite3 test.db .genfkey]
    190 } {}
    191 do_test genfkey-3.3 {
    192   execsql {
    193     INSERT INTO t1 VALUES(1, 2, 3);
    194     INSERT INTO t1 VALUES(4, 5, 6);
    195     INSERT INTO t2 VALUES(1, 'one');
    196     INSERT INTO t2 VALUES(4, 'four');
    197   }
    198 } {}
    199 do_test genfkey-3.4 {
    200   execsql {
    201     UPDATE t1 SET a = 2 WHERE a = 1;
    202     SELECT * FROM t2;
    203   }
    204 } {{} one 4 four}
    205 do_test genfkey-3.5 {
    206   execsql {
    207     DELETE FROM t1 WHERE a = 4;
    208     SELECT * FROM t2;
    209   }
    210 } {{} one {} four}
    211 do_test genfkey-3.6 {
    212   execsql {
    213     INSERT INTO t3 VALUES('hello', 2, 3);
    214     UPDATE t1 SET c = 2;
    215     SELECT * FROM t3;
    216   }
    217 } {hello {} {}}
    218 do_test genfkey-2.7 {
    219   execsql {
    220     UPDATE t3 SET h = 2, i = 2;
    221     DELETE FROM t1;
    222     SELECT * FROM t3;
    223   }
    224 } {hello {} {}}
    225 do_test genfkey-3.X {
    226   execsql {
    227     DROP TABLE t1;
    228     DROP TABLE t2;
    229     DROP TABLE t3;
    230   }
    231 } {}
    232 
    233 # The following tests - genfkey-4.* - test that errors in the schema
    234 # are detected correctly.
    235 #
    236 do_test genfkey-4.1 {
    237   execsql {
    238     CREATE TABLE t1(a REFERENCES nosuchtable, b);
    239     CREATE TABLE t2(a REFERENCES t1, b);
    240 
    241     CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b));
    242     CREATE TABLE t4(a, b, c, FOREIGN KEY(c, b) REFERENCES t3);
    243 
    244     CREATE TABLE t5(a REFERENCES t4(d), b, c);
    245     CREATE TABLE t6(a REFERENCES t4(a), b, c);
    246     CREATE TABLE t7(a REFERENCES t3(a), b, c);
    247     CREATE TABLE t8(a REFERENCES nosuchtable(a), b, c);
    248   }
    249 } {}
    250 
    251 do_test genfkey-4.X {
    252   set rc [catch {exec ./sqlite3 test.db .genfkey} msg]
    253   list $rc $msg
    254 } "1 {[string trim {
    255 Error in table t5: foreign key columns do not exist
    256 Error in table t8: foreign key columns do not exist
    257 Error in table t4: implicit mapping to composite primary key
    258 Error in table t1: implicit mapping to non-existant primary key
    259 Error in table t2: implicit mapping to non-existant primary key
    260 Error in table t6: foreign key is not unique
    261 Error in table t7: foreign key is not unique
    262 }]}"
    263 
    264 # Test that ticket #3800 has been resolved.
    265 #
    266 do_test genfkey-5.1 {
    267   execsql {
    268     DROP TABLE t1; DROP TABLE t2; DROP TABLE t3;
    269     DROP TABLE t4; DROP TABLE t5; DROP TABLE t6;
    270     DROP TABLE t7; DROP TABLE t8;
    271   }
    272 } {}
    273 do_test genfkey-5.2 {
    274   execsql {
    275     CREATE TABLE "t.3" (c1 PRIMARY KEY);
    276     CREATE TABLE t13 (c1, foreign key(c1) references "t.3"(c1));
    277   }
    278 } {}
    279 do_test genfkey-5.3 {
    280   set rc [catch {exec ./sqlite3 test.db .genfkey} msg]
    281 } {0}
    282 do_test genfkey-5.4 {
    283   db eval $msg
    284 } {}
    285 do_test genfkey-5.5 {
    286   catchsql { INSERT INTO t13 VALUES(1) }
    287 } {1 {constraint failed}}
    288 do_test genfkey-5.5 {
    289   catchsql { 
    290     INSERT INTO "t.3" VALUES(1);
    291     INSERT INTO t13 VALUES(1);
    292   }
    293 } {0 {}}
    294 
    295 # Test also column names that require quoting.
    296 do_test genfkey-6.1 {
    297   execsql {
    298     DROP TABLE "t.3";
    299     DROP TABLE t13;
    300     CREATE TABLE p(
    301       "a.1 first", "b.2 second", 
    302       UNIQUE("a.1 first", "b.2 second")
    303     );
    304     CREATE TABLE c(
    305       "c.1 I", "d.2 II", 
    306         FOREIGN KEY("c.1 I", "d.2 II") 
    307         REFERENCES p("a.1 first", "b.2 second")
    308         ON UPDATE CASCADE ON DELETE CASCADE
    309     );
    310   }
    311 } {}
    312 do_test genfkey-6.2 {
    313   set rc [catch {exec ./sqlite3 test.db .genfkey} msg]
    314 } {0}
    315 do_test genfkey-6.3 {
    316   execsql $msg
    317   execsql {
    318     INSERT INTO p VALUES('A', 'B');
    319     INSERT INTO p VALUES('C', 'D');
    320     INSERT INTO c VALUES('A', 'B');
    321     INSERT INTO c VALUES('C', 'D');
    322     UPDATE p SET "a.1 first" = 'X' WHERE rowid = 1;
    323     DELETE FROM p WHERE rowid = 2;
    324   }
    325   execsql { SELECT * FROM c }
    326 } {X B}
    327 
    328 do_test genfkey-6.4 {
    329   execsql {
    330     DROP TABLE p;
    331     DROP TABLE c;
    332     CREATE TABLE parent("a.1", PRIMARY KEY("a.1"));
    333     CREATE TABLE child("b.2", FOREIGN KEY("b.2") REFERENCES parent("a.1"));
    334   }
    335   set rc [catch {exec ./sqlite3 test.db .genfkey} msg]
    336 } {0}
    337 do_test genfkey-6.5 {
    338   execsql $msg
    339   execsql {
    340     INSERT INTO parent VALUES(1);
    341     INSERT INTO child VALUES(1);
    342   }
    343   catchsql { UPDATE parent SET "a.1"=0 }
    344 } {1 {constraint failed}}
    345 do_test genfkey-6.6 {
    346   catchsql { UPDATE child SET "b.2"=7 }
    347 } {1 {constraint failed}}
    348 do_test genfkey-6.7 {
    349   execsql {
    350     SELECT * FROM parent;
    351     SELECT * FROM child;
    352   }
    353 } {1 1}
    354 
    355