Home | History | Annotate | Download | only in test
      1 # 2008 January 1
      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. Specifically,
     12 # it tests some compiler optimizations for SQL statements featuring
     13 # triggers:
     14 #
     15 #
     16 #
     17 
     18 # trigger9-1.* -   Test that if there are no references to OLD.* cols, or a
     19 #                  reference to only OLD.rowid, the data is not loaded.
     20 #
     21 # trigger9-2.* -   Test that for NEW.* records populated by UPDATE 
     22 #                  statements, unused fields are populated with NULL values. 
     23 #
     24 # trigger9-3.* -   Test that the temporary tables used for OLD.* references
     25 #                  in "INSTEAD OF" triggers have NULL values in unused 
     26 #                  fields.
     27 #
     28 
     29 set testdir [file dirname $argv0]
     30 source $testdir/tester.tcl
     31 ifcapable {!trigger} {
     32   finish_test
     33   return
     34 }
     35 
     36 proc has_rowdata {sql} {
     37   expr {[lsearch [execsql "explain $sql"] RowData]>=0}
     38 }
     39 
     40 do_test trigger9-1.1 {
     41   execsql {
     42     PRAGMA page_size = 1024;
     43     CREATE TABLE t1(x, y, z);
     44     INSERT INTO t1 VALUES('1', randstr(10000,10000), '2');
     45     INSERT INTO t1 VALUES('2', randstr(10000,10000), '4');
     46     INSERT INTO t1 VALUES('3', randstr(10000,10000), '6');
     47     CREATE TABLE t2(x);
     48   }
     49 } {}
     50 
     51 do_test trigger9-1.2.1 {
     52   execsql {
     53     BEGIN;
     54       CREATE TRIGGER trig1 BEFORE DELETE ON t1 BEGIN
     55         INSERT INTO t2 VALUES(old.rowid);
     56       END;
     57       DELETE FROM t1;
     58       SELECT * FROM t2;
     59   }
     60 } {1 2 3}
     61 do_test trigger9-1.2.3 {
     62   has_rowdata {DELETE FROM t1}
     63 } 0
     64 do_test trigger9-1.2.4 { execsql { ROLLBACK } } {}
     65 
     66 do_test trigger9-1.3.1 {
     67   execsql {
     68     BEGIN;
     69       CREATE TRIGGER trig1 BEFORE DELETE ON t1 BEGIN
     70         INSERT INTO t2 VALUES(old.x);
     71       END;
     72       DELETE FROM t1;
     73       SELECT * FROM t2;
     74   }
     75 } {1 2 3}
     76 do_test trigger9-1.3.2 {
     77   has_rowdata {DELETE FROM t1}
     78 } 0
     79 do_test trigger9-1.3.3 { execsql { ROLLBACK } } {}
     80 
     81 do_test trigger9-1.4.1 {
     82   execsql {
     83     BEGIN;
     84       CREATE TRIGGER trig1 BEFORE DELETE ON t1 WHEN old.x='1' BEGIN
     85         INSERT INTO t2 VALUES(old.rowid);
     86       END;
     87       DELETE FROM t1;
     88       SELECT * FROM t2;
     89   }
     90 } {1}
     91 do_test trigger9-1.4.2 {
     92   has_rowdata {DELETE FROM t1}
     93 } 0
     94 do_test trigger9-1.4.3 { execsql { ROLLBACK } } {}
     95 
     96 do_test trigger9-1.5.1 {
     97   execsql {
     98     BEGIN;
     99       CREATE TRIGGER trig1 BEFORE UPDATE ON t1 BEGIN
    100         INSERT INTO t2 VALUES(old.rowid);
    101       END;
    102       UPDATE t1 SET y = '';
    103       SELECT * FROM t2;
    104   }
    105 } {1 2 3}
    106 do_test trigger9-1.5.2 {
    107   has_rowdata {UPDATE t1 SET y = ''}
    108 } 0
    109 do_test trigger9-1.5.3 { execsql { ROLLBACK } } {}
    110 
    111 do_test trigger9-1.6.1 {
    112   execsql {
    113     BEGIN;
    114       CREATE TRIGGER trig1 BEFORE UPDATE ON t1 BEGIN
    115         INSERT INTO t2 VALUES(old.x);
    116       END;
    117       UPDATE t1 SET y = '';
    118       SELECT * FROM t2;
    119   }
    120 } {1 2 3}
    121 do_test trigger9-1.6.2 {
    122   has_rowdata {UPDATE t1 SET y = ''}
    123 } 0
    124 do_test trigger9-1.6.3 { execsql { ROLLBACK } } {}
    125 
    126 do_test trigger9-1.7.1 {
    127   execsql {
    128     BEGIN;
    129       CREATE TRIGGER trig1 BEFORE UPDATE ON t1 WHEN old.x>='2' BEGIN
    130         INSERT INTO t2 VALUES(old.x);
    131       END;
    132       UPDATE t1 SET y = '';
    133       SELECT * FROM t2;
    134   }
    135 } {2 3}
    136 do_test trigger9-1.7.2 {
    137   has_rowdata {UPDATE t1 SET y = ''}
    138 } 0
    139 do_test trigger9-1.7.3 { execsql { ROLLBACK } } {}
    140 
    141 do_test trigger9-3.1 {
    142   execsql {
    143     CREATE TABLE t3(a, b);
    144     INSERT INTO t3 VALUES(1, 'one');
    145     INSERT INTO t3 VALUES(2, 'two');
    146     INSERT INTO t3 VALUES(3, 'three');
    147   }
    148 } {}
    149 do_test trigger9-3.2 {
    150   execsql {
    151     BEGIN;
    152       CREATE VIEW v1 AS SELECT * FROM t3;
    153       CREATE TRIGGER trig1 INSTEAD OF UPDATE ON v1 BEGIN
    154         INSERT INTO t2 VALUES(old.a);
    155       END;
    156       UPDATE v1 SET b = 'hello';
    157       SELECT * FROM t2;
    158     ROLLBACK;
    159   }
    160 } {1 2 3}
    161 do_test trigger9-3.3 {
    162   # In this test the 'c' column of the view is not required by
    163   # the INSTEAD OF trigger, but the expression is reused internally as
    164   # part of the view's WHERE clause. Check that this does not cause
    165   # a problem.
    166   #
    167   execsql {
    168     BEGIN;
    169       CREATE VIEW v1 AS SELECT a, b AS c FROM t3 WHERE c > 'one';
    170       CREATE TRIGGER trig1 INSTEAD OF UPDATE ON v1 BEGIN
    171         INSERT INTO t2 VALUES(old.a);
    172       END;
    173       UPDATE v1 SET c = 'hello';
    174       SELECT * FROM t2;
    175     ROLLBACK;
    176   }
    177 } {2 3}
    178 do_test trigger9-3.4 {
    179   execsql {
    180     BEGIN;
    181       INSERT INTO t3 VALUES(3, 'three');
    182       INSERT INTO t3 VALUES(3, 'four');
    183       CREATE VIEW v1 AS SELECT DISTINCT a, b FROM t3;
    184       CREATE TRIGGER trig1 INSTEAD OF UPDATE ON v1 BEGIN
    185         INSERT INTO t2 VALUES(old.a);
    186       END;
    187       UPDATE v1 SET b = 'hello';
    188       SELECT * FROM t2;
    189     ROLLBACK;
    190   }
    191 } {1 2 3 3}
    192 
    193 ifcapable compound {
    194   do_test trigger9-3.5 {
    195     execsql {
    196       BEGIN;
    197         INSERT INTO t3 VALUES(1, 'uno');
    198         CREATE VIEW v1 AS SELECT a, b FROM t3 EXCEPT SELECT 1, 'one';
    199         CREATE TRIGGER trig1 INSTEAD OF UPDATE ON v1 BEGIN
    200           INSERT INTO t2 VALUES(old.a);
    201         END;
    202         UPDATE v1 SET b = 'hello';
    203         SELECT * FROM t2;
    204       ROLLBACK;
    205     }
    206   } {1 2 3}
    207   do_test trigger9-3.6 {
    208     execsql {
    209       BEGIN;
    210         INSERT INTO t3 VALUES(1, 'zero');
    211         CREATE VIEW v1 AS 
    212           SELECT sum(a) AS a, max(b) AS b FROM t3 GROUP BY t3.a HAVING b>'two';
    213         CREATE TRIGGER trig1 INSTEAD OF UPDATE ON v1 BEGIN
    214           INSERT INTO t2 VALUES(old.a);
    215         END;
    216         UPDATE v1 SET b = 'hello';
    217         SELECT * FROM t2;
    218       ROLLBACK;
    219     }
    220   } {2}
    221 }
    222 
    223 finish_test
    224