Home | History | Annotate | Download | only in test
      1 # The author disclaims copyright to this source code.  In place of
      2 # a legal notice, here is a blessing:
      3 #
      4 #    May you do good and not evil.
      5 #    May you find forgiveness for yourself and forgive others.
      6 #    May you share freely, never taking more than you give.
      7 #
      8 #***********************************************************************
      9 #
     10 # Tests to make sure that value returned by last_insert_rowid() (LIRID)
     11 # is updated properly, especially inside triggers
     12 #
     13 # Note 1: insert into table is now the only statement which changes LIRID
     14 # Note 2: upon entry into before or instead of triggers,
     15 #           LIRID is unchanged (rather than -1)
     16 # Note 3: LIRID is changed within the context of a trigger,
     17 #           but is restored once the trigger exits
     18 # Note 4: LIRID is not changed by an insert into a view (since everything
     19 #           is done within instead of trigger context)
     20 #
     21 
     22 set testdir [file dirname $argv0]
     23 source $testdir/tester.tcl
     24 
     25 # ----------------------------------------------------------------------------
     26 # 1.x - basic tests (no triggers)
     27 
     28 # LIRID changed properly after an insert into a table
     29 do_test lastinsert-1.1 {
     30     catchsql {
     31         create table t1 (k integer primary key);
     32         insert into t1 values (1);
     33         insert into t1 values (NULL);
     34         insert into t1 values (NULL);
     35         select last_insert_rowid();
     36     }
     37 } {0 3}
     38 
     39 # LIRID unchanged after an update on a table
     40 do_test lastinsert-1.2 {
     41     catchsql {
     42         update t1 set k=4 where k=2;
     43         select last_insert_rowid();
     44     }
     45 } {0 3}
     46 
     47 # LIRID unchanged after a delete from a table
     48 do_test lastinsert-1.3 {
     49     catchsql {
     50         delete from t1 where k=4;
     51         select last_insert_rowid();
     52     }
     53 } {0 3}
     54 
     55 # LIRID unchanged after create table/view statements
     56 do_test lastinsert-1.4.1 {
     57     catchsql {
     58         create table t2 (k integer primary key, val1, val2, val3);
     59         select last_insert_rowid();
     60     }
     61 } {0 3}
     62 ifcapable view {
     63 do_test lastinsert-1.4.2 {
     64     catchsql {
     65         create view v as select * from t1;
     66         select last_insert_rowid();
     67     }
     68 } {0 3}
     69 } ;# ifcapable view
     70 
     71 # All remaining tests involve triggers.  Skip them if triggers are not
     72 # supported in this build.
     73 #
     74 ifcapable {!trigger} {
     75   finish_test
     76   return
     77 }
     78 
     79 # ----------------------------------------------------------------------------
     80 # 2.x - tests with after insert trigger
     81 
     82 # LIRID changed properly after an insert into table containing an after trigger
     83 do_test lastinsert-2.1 {
     84     catchsql {
     85         delete from t2;
     86         create trigger r1 after insert on t1 for each row begin
     87             insert into t2 values (NEW.k*2, last_insert_rowid(), NULL, NULL);
     88             update t2 set k=k+10, val2=100+last_insert_rowid();
     89             update t2 set val3=1000+last_insert_rowid();
     90         end;
     91         insert into t1 values (13);
     92         select last_insert_rowid();
     93     }
     94 } {0 13}
     95 
     96 # LIRID equals NEW.k upon entry into after insert trigger
     97 do_test lastinsert-2.2 {
     98     catchsql {
     99         select val1 from t2;
    100     }
    101 } {0 13}
    102 
    103 # LIRID changed properly by insert within context of after insert trigger
    104 do_test lastinsert-2.3 {
    105     catchsql {
    106         select val2 from t2;
    107     }
    108 } {0 126}
    109 
    110 # LIRID unchanged by update within context of after insert trigger
    111 do_test lastinsert-2.4 {
    112     catchsql {
    113         select val3 from t2;
    114     }
    115 } {0 1026}
    116 
    117 # ----------------------------------------------------------------------------
    118 # 3.x - tests with after update trigger
    119 
    120 # LIRID not changed after an update onto a table containing an after trigger
    121 do_test lastinsert-3.1 {
    122     catchsql {
    123         delete from t2;
    124         drop trigger r1;
    125         create trigger r1 after update on t1 for each row begin
    126             insert into t2 values (NEW.k*2, last_insert_rowid(), NULL, NULL);
    127             update t2 set k=k+10, val2=100+last_insert_rowid();
    128             update t2 set val3=1000+last_insert_rowid();
    129         end;
    130         update t1 set k=14 where k=3;
    131         select last_insert_rowid();
    132     }
    133 } {0 13}
    134 
    135 # LIRID unchanged upon entry into after update trigger
    136 do_test lastinsert-3.2 {
    137     catchsql {
    138         select val1 from t2;
    139     }
    140 } {0 13}
    141 
    142 # LIRID changed properly by insert within context of after update trigger
    143 do_test lastinsert-3.3 {
    144     catchsql {
    145         select val2 from t2;
    146     }
    147 } {0 128}
    148 
    149 # LIRID unchanged by update within context of after update trigger
    150 do_test lastinsert-3.4 {
    151     catchsql {
    152         select val3 from t2;
    153     }
    154 } {0 1028}
    155 
    156 # ----------------------------------------------------------------------------
    157 # 4.x - tests with instead of insert trigger
    158 # These may not be run if either views or triggers were disabled at 
    159 # compile-time
    160 
    161 ifcapable {view && trigger} {
    162 # LIRID not changed after an insert into view containing an instead of trigger
    163 do_test lastinsert-4.1 {
    164     catchsql {
    165         delete from t2;
    166         drop trigger r1;
    167         create trigger r1 instead of insert on v for each row begin
    168             insert into t2 values (NEW.k*2, last_insert_rowid(), NULL, NULL);
    169             update t2 set k=k+10, val2=100+last_insert_rowid();
    170             update t2 set val3=1000+last_insert_rowid();
    171         end;
    172         insert into v values (15);
    173         select last_insert_rowid();
    174     }
    175 } {0 13}
    176 
    177 # LIRID unchanged upon entry into instead of trigger
    178 do_test lastinsert-4.2 {
    179     catchsql {
    180         select val1 from t2;
    181     }
    182 } {0 13}
    183 
    184 # LIRID changed properly by insert within context of instead of trigger
    185 do_test lastinsert-4.3 {
    186     catchsql {
    187         select val2 from t2;
    188     }
    189 } {0 130}
    190 
    191 # LIRID unchanged by update within context of instead of trigger
    192 do_test lastinsert-4.4 {
    193     catchsql {
    194         select val3 from t2;
    195     }
    196 } {0 1030}
    197 } ;# ifcapable (view && trigger)
    198 
    199 # ----------------------------------------------------------------------------
    200 # 5.x - tests with before delete trigger
    201 
    202 # LIRID not changed after a delete on a table containing a before trigger
    203 do_test lastinsert-5.1 {
    204     catchsql {
    205       drop trigger r1;  -- This was not created if views are disabled.
    206     }
    207     catchsql {
    208         delete from t2;
    209         create trigger r1 before delete on t1 for each row begin
    210             insert into t2 values (77, last_insert_rowid(), NULL, NULL);
    211             update t2 set k=k+10, val2=100+last_insert_rowid();
    212             update t2 set val3=1000+last_insert_rowid();
    213         end;
    214         delete from t1 where k=1;
    215         select last_insert_rowid();
    216     }
    217 } {0 13}
    218 
    219 # LIRID unchanged upon entry into delete trigger
    220 do_test lastinsert-5.2 {
    221     catchsql {
    222         select val1 from t2;
    223     }
    224 } {0 13}
    225 
    226 # LIRID changed properly by insert within context of delete trigger
    227 do_test lastinsert-5.3 {
    228     catchsql {
    229         select val2 from t2;
    230     }
    231 } {0 177}
    232 
    233 # LIRID unchanged by update within context of delete trigger
    234 do_test lastinsert-5.4 {
    235     catchsql {
    236         select val3 from t2;
    237     }
    238 } {0 1077}
    239 
    240 # ----------------------------------------------------------------------------
    241 # 6.x - tests with instead of update trigger
    242 # These tests may not run if either views or triggers are disabled.
    243 
    244 ifcapable {view && trigger} {
    245 # LIRID not changed after an update on a view containing an instead of trigger
    246 do_test lastinsert-6.1 {
    247     catchsql {
    248         delete from t2;
    249         drop trigger r1;
    250         create trigger r1 instead of update on v for each row begin
    251             insert into t2 values (NEW.k*2, last_insert_rowid(), NULL, NULL);
    252             update t2 set k=k+10, val2=100+last_insert_rowid();
    253             update t2 set val3=1000+last_insert_rowid();
    254         end;
    255         update v set k=16 where k=14;
    256         select last_insert_rowid();
    257     }
    258 } {0 13}
    259 
    260 # LIRID unchanged upon entry into instead of trigger
    261 do_test lastinsert-6.2 {
    262     catchsql {
    263         select val1 from t2;
    264     }
    265 } {0 13}
    266 
    267 # LIRID changed properly by insert within context of instead of trigger
    268 do_test lastinsert-6.3 {
    269     catchsql {
    270         select val2 from t2;
    271     }
    272 } {0 132}
    273 
    274 # LIRID unchanged by update within context of instead of trigger
    275 do_test lastinsert-6.4 {
    276     catchsql {
    277         select val3 from t2;
    278     }
    279 } {0 1032}
    280 } ;# ifcapable (view && trigger)
    281 
    282 # ----------------------------------------------------------------------------
    283 # 7.x - complex tests with temporary tables and nested instead of triggers
    284 # These do not run if views or triggers are disabled.
    285 
    286 ifcapable {trigger && view && tempdb} {
    287 do_test lastinsert-7.1 {
    288     catchsql {
    289         drop table t1; drop table t2; drop trigger r1;
    290         create temp table t1 (k integer primary key);
    291         create temp table t2 (k integer primary key);
    292         create temp view v1 as select * from t1;
    293         create temp view v2 as select * from t2;
    294         create temp table rid (k integer primary key, rin, rout);
    295         insert into rid values (1, NULL, NULL);
    296         insert into rid values (2, NULL, NULL);
    297         create temp trigger r1 instead of insert on v1 for each row begin
    298             update rid set rin=last_insert_rowid() where k=1;
    299             insert into t1 values (100+NEW.k);
    300             insert into v2 values (100+last_insert_rowid());
    301             update rid set rout=last_insert_rowid() where k=1;
    302         end;
    303         create temp trigger r2 instead of insert on v2 for each row begin
    304             update rid set rin=last_insert_rowid() where k=2;
    305             insert into t2 values (1000+NEW.k);
    306             update rid set rout=last_insert_rowid() where k=2;
    307         end;
    308         insert into t1 values (77);
    309         select last_insert_rowid();
    310     }
    311 } {0 77}
    312 
    313 do_test lastinsert-7.2 {
    314     catchsql {
    315         insert into v1 values (5);
    316         select last_insert_rowid();
    317     }
    318 } {0 77}
    319 
    320 do_test lastinsert-7.3 {
    321     catchsql {
    322         select rin from rid where k=1;
    323     }
    324 } {0 77}
    325 
    326 do_test lastinsert-7.4 {
    327     catchsql {
    328         select rout from rid where k=1;
    329     }
    330 } {0 105}
    331 
    332 do_test lastinsert-7.5 {
    333     catchsql {
    334         select rin from rid where k=2;
    335     }
    336 } {0 105}
    337 
    338 do_test lastinsert-7.6 {
    339     catchsql {
    340         select rout from rid where k=2;
    341     }
    342 } {0 1205}
    343 
    344 do_test lastinsert-8.1 {
    345   db close
    346   sqlite3 db test.db
    347   execsql {
    348     CREATE TABLE t2(x INTEGER PRIMARY KEY, y);
    349     CREATE TABLE t3(a, b);
    350     CREATE TRIGGER after_t2 AFTER INSERT ON t2 BEGIN
    351       INSERT INTO t3 VALUES(new.x, new.y);
    352     END;
    353     INSERT INTO t2 VALUES(5000000000, 1);
    354     SELECT last_insert_rowid();
    355   }
    356 } 5000000000
    357 
    358 do_test lastinsert-9.1 {
    359   db eval {INSERT INTO t2 VALUES(123456789012345,0)}
    360   db last_insert_rowid
    361 } {123456789012345}
    362 
    363 
    364 } ;# ifcapable (view && trigger)
    365 
    366 finish_test
    367