os/persistentdata/persistentstorage/sqlite3api/TEST/TclScript/trigger2.test
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
# The author disclaims copyright to this source code.  In place of
sl@0
     2
# a legal notice, here is a blessing:
sl@0
     3
#
sl@0
     4
#    May you do good and not evil.
sl@0
     5
#    May you find forgiveness for yourself and forgive others.
sl@0
     6
#    May you share freely, never taking more than you give.
sl@0
     7
#
sl@0
     8
#***********************************************************************
sl@0
     9
#
sl@0
    10
# Regression testing of FOR EACH ROW table triggers
sl@0
    11
#
sl@0
    12
# 1. Trigger execution order tests. 
sl@0
    13
# These tests ensure that BEFORE and AFTER triggers are fired at the correct
sl@0
    14
# times relative to each other and the triggering statement. 
sl@0
    15
#
sl@0
    16
# trigger2-1.1.*: ON UPDATE trigger execution model.
sl@0
    17
# trigger2-1.2.*: DELETE trigger execution model.
sl@0
    18
# trigger2-1.3.*: INSERT trigger execution model.
sl@0
    19
#
sl@0
    20
# 2. Trigger program execution tests.
sl@0
    21
# These tests ensure that trigger programs execute correctly (ie. that a
sl@0
    22
# trigger program can correctly execute INSERT, UPDATE, DELETE * SELECT
sl@0
    23
# statements, and combinations thereof).
sl@0
    24
#
sl@0
    25
# 3. Selective trigger execution 
sl@0
    26
# This tests that conditional triggers (ie. UPDATE OF triggers and triggers
sl@0
    27
# with WHEN clauses) are fired only fired when they are supposed to be.
sl@0
    28
#
sl@0
    29
# trigger2-3.1: UPDATE OF triggers
sl@0
    30
# trigger2-3.2: WHEN clause
sl@0
    31
#
sl@0
    32
# 4. Cascaded trigger execution 
sl@0
    33
# Tests that trigger-programs may cause other triggers to fire. Also that a 
sl@0
    34
# trigger-program is never executed recursively.
sl@0
    35
# 
sl@0
    36
# trigger2-4.1: Trivial cascading trigger
sl@0
    37
# trigger2-4.2: Trivial recursive trigger handling 
sl@0
    38
#
sl@0
    39
# 5. Count changes behaviour.
sl@0
    40
# Verify that rows altered by triggers are not included in the return value
sl@0
    41
# of the "count changes" interface.
sl@0
    42
#
sl@0
    43
# 6. ON CONFLICT clause handling
sl@0
    44
# trigger2-6.1[a-f]: INSERT statements
sl@0
    45
# trigger2-6.2[a-f]: UPDATE statements
sl@0
    46
#
sl@0
    47
# 7. & 8. Triggers on views fire correctly.
sl@0
    48
#
sl@0
    49
sl@0
    50
set testdir [file dirname $argv0]
sl@0
    51
source $testdir/tester.tcl
sl@0
    52
ifcapable {!trigger} {
sl@0
    53
  finish_test
sl@0
    54
  return
sl@0
    55
}
sl@0
    56
sl@0
    57
# 1.
sl@0
    58
ifcapable subquery {
sl@0
    59
  set ii 0
sl@0
    60
  set tbl_definitions [list \
sl@0
    61
  	{CREATE TABLE tbl (a, b);}                                      \
sl@0
    62
  	{CREATE TABLE tbl (a INTEGER PRIMARY KEY, b);}                  \
sl@0
    63
        {CREATE TABLE tbl (a, b PRIMARY KEY);}                          \
sl@0
    64
  	{CREATE TABLE tbl (a, b); CREATE INDEX tbl_idx ON tbl(b);}      \
sl@0
    65
  ]
sl@0
    66
  ifcapable tempdb {
sl@0
    67
    lappend tbl_definitions \
sl@0
    68
        {CREATE TEMP TABLE tbl (a, b); CREATE INDEX tbl_idx ON tbl(b);} 
sl@0
    69
    lappend tbl_definitions {CREATE TEMP TABLE tbl (a, b);}
sl@0
    70
    lappend tbl_definitions \
sl@0
    71
        {CREATE TEMPORARY TABLE tbl (a INTEGER PRIMARY KEY, b);}
sl@0
    72
  }
sl@0
    73
  foreach tbl_defn $tbl_definitions {
sl@0
    74
    incr ii
sl@0
    75
    catchsql { DROP INDEX tbl_idx; }
sl@0
    76
    catchsql {
sl@0
    77
      DROP TABLE rlog;
sl@0
    78
      DROP TABLE clog;
sl@0
    79
      DROP TABLE tbl;
sl@0
    80
      DROP TABLE other_tbl;
sl@0
    81
    }
sl@0
    82
  
sl@0
    83
    execsql $tbl_defn
sl@0
    84
  
sl@0
    85
    execsql {
sl@0
    86
      INSERT INTO tbl VALUES(1, 2);
sl@0
    87
      INSERT INTO tbl VALUES(3, 4);
sl@0
    88
  
sl@0
    89
      CREATE TABLE rlog (idx, old_a, old_b, db_sum_a, db_sum_b, new_a, new_b);
sl@0
    90
      CREATE TABLE clog (idx, old_a, old_b, db_sum_a, db_sum_b, new_a, new_b);
sl@0
    91
  
sl@0
    92
      CREATE TRIGGER before_update_row BEFORE UPDATE ON tbl FOR EACH ROW 
sl@0
    93
        BEGIN
sl@0
    94
        INSERT INTO rlog VALUES ( (SELECT coalesce(max(idx),0) + 1 FROM rlog), 
sl@0
    95
  	  old.a, old.b, 
sl@0
    96
  	  (SELECT coalesce(sum(a),0) FROM tbl),
sl@0
    97
          (SELECT coalesce(sum(b),0) FROM tbl), 
sl@0
    98
  	  new.a, new.b);
sl@0
    99
      END;
sl@0
   100
  
sl@0
   101
      CREATE TRIGGER after_update_row AFTER UPDATE ON tbl FOR EACH ROW 
sl@0
   102
        BEGIN
sl@0
   103
        INSERT INTO rlog VALUES ( (SELECT coalesce(max(idx),0) + 1 FROM rlog), 
sl@0
   104
  	  old.a, old.b, 
sl@0
   105
  	  (SELECT coalesce(sum(a),0) FROM tbl),
sl@0
   106
          (SELECT coalesce(sum(b),0) FROM tbl), 
sl@0
   107
  	  new.a, new.b);
sl@0
   108
      END;
sl@0
   109
  
sl@0
   110
      CREATE TRIGGER conditional_update_row AFTER UPDATE ON tbl FOR EACH ROW
sl@0
   111
        WHEN old.a = 1
sl@0
   112
        BEGIN
sl@0
   113
        INSERT INTO clog VALUES ( (SELECT coalesce(max(idx),0) + 1 FROM clog), 
sl@0
   114
  	  old.a, old.b, 
sl@0
   115
  	  (SELECT coalesce(sum(a),0) FROM tbl),
sl@0
   116
          (SELECT coalesce(sum(b),0) FROM tbl), 
sl@0
   117
  	  new.a, new.b);
sl@0
   118
      END;
sl@0
   119
    }
sl@0
   120
  
sl@0
   121
    do_test trigger2-1.$ii.1 {
sl@0
   122
      set r {}
sl@0
   123
      foreach v [execsql { 
sl@0
   124
        UPDATE tbl SET a = a * 10, b = b * 10;
sl@0
   125
        SELECT * FROM rlog ORDER BY idx;
sl@0
   126
        SELECT * FROM clog ORDER BY idx;
sl@0
   127
      }] {
sl@0
   128
        lappend r [expr {int($v)}]
sl@0
   129
      }
sl@0
   130
      set r
sl@0
   131
    } [list 1 1 2  4  6 10 20 \
sl@0
   132
            2 1 2 13 24 10 20 \
sl@0
   133
  	    3 3 4 13 24 30 40 \
sl@0
   134
  	    4 3 4 40 60 30 40 \
sl@0
   135
            1 1 2 13 24 10 20 ]
sl@0
   136
  
sl@0
   137
    execsql {
sl@0
   138
      DELETE FROM rlog;
sl@0
   139
      DELETE FROM tbl;
sl@0
   140
      INSERT INTO tbl VALUES (100, 100);
sl@0
   141
      INSERT INTO tbl VALUES (300, 200);
sl@0
   142
      CREATE TRIGGER delete_before_row BEFORE DELETE ON tbl FOR EACH ROW
sl@0
   143
        BEGIN
sl@0
   144
        INSERT INTO rlog VALUES ( (SELECT coalesce(max(idx),0) + 1 FROM rlog), 
sl@0
   145
  	  old.a, old.b, 
sl@0
   146
  	  (SELECT coalesce(sum(a),0) FROM tbl),
sl@0
   147
          (SELECT coalesce(sum(b),0) FROM tbl), 
sl@0
   148
  	  0, 0);
sl@0
   149
      END;
sl@0
   150
  
sl@0
   151
      CREATE TRIGGER delete_after_row AFTER DELETE ON tbl FOR EACH ROW
sl@0
   152
        BEGIN
sl@0
   153
        INSERT INTO rlog VALUES ( (SELECT coalesce(max(idx),0) + 1 FROM rlog), 
sl@0
   154
  	  old.a, old.b, 
sl@0
   155
  	  (SELECT coalesce(sum(a),0) FROM tbl),
sl@0
   156
          (SELECT coalesce(sum(b),0) FROM tbl), 
sl@0
   157
  	  0, 0);
sl@0
   158
      END;
sl@0
   159
    }
sl@0
   160
    do_test trigger2-1.$ii.2 {
sl@0
   161
      set r {}
sl@0
   162
      foreach v [execsql {
sl@0
   163
        DELETE FROM tbl;
sl@0
   164
        SELECT * FROM rlog;
sl@0
   165
      }] {
sl@0
   166
        lappend r [expr {int($v)}]
sl@0
   167
      }
sl@0
   168
      set r
sl@0
   169
    } [list 1 100 100 400 300 0 0 \
sl@0
   170
            2 100 100 300 200 0 0 \
sl@0
   171
            3 300 200 300 200 0 0 \
sl@0
   172
            4 300 200 0 0 0 0 ]
sl@0
   173
  
sl@0
   174
    execsql {
sl@0
   175
      DELETE FROM rlog;
sl@0
   176
      CREATE TRIGGER insert_before_row BEFORE INSERT ON tbl FOR EACH ROW
sl@0
   177
        BEGIN
sl@0
   178
        INSERT INTO rlog VALUES ( (SELECT coalesce(max(idx),0) + 1 FROM rlog), 
sl@0
   179
  	  0, 0,
sl@0
   180
  	  (SELECT coalesce(sum(a),0) FROM tbl),
sl@0
   181
          (SELECT coalesce(sum(b),0) FROM tbl), 
sl@0
   182
  	  new.a, new.b);
sl@0
   183
      END;
sl@0
   184
  
sl@0
   185
      CREATE TRIGGER insert_after_row AFTER INSERT ON tbl FOR EACH ROW
sl@0
   186
        BEGIN
sl@0
   187
        INSERT INTO rlog VALUES ( (SELECT coalesce(max(idx),0) + 1 FROM rlog), 
sl@0
   188
  	  0, 0,
sl@0
   189
  	  (SELECT coalesce(sum(a),0) FROM tbl),
sl@0
   190
          (SELECT coalesce(sum(b),0) FROM tbl), 
sl@0
   191
  	  new.a, new.b);
sl@0
   192
      END;
sl@0
   193
    }
sl@0
   194
    do_test trigger2-1.$ii.3 {
sl@0
   195
      execsql {
sl@0
   196
  
sl@0
   197
        CREATE TABLE other_tbl(a, b);
sl@0
   198
        INSERT INTO other_tbl VALUES(1, 2);
sl@0
   199
        INSERT INTO other_tbl VALUES(3, 4);
sl@0
   200
        -- INSERT INTO tbl SELECT * FROM other_tbl;
sl@0
   201
        INSERT INTO tbl VALUES(5, 6);
sl@0
   202
        DROP TABLE other_tbl;
sl@0
   203
  
sl@0
   204
        SELECT * FROM rlog;
sl@0
   205
      }
sl@0
   206
    } [list 1 0 0 0 0 5 6 \
sl@0
   207
            2 0 0 5 6 5 6 ]
sl@0
   208
  
sl@0
   209
    integrity_check trigger2-1.$ii.4
sl@0
   210
  }
sl@0
   211
  catchsql {
sl@0
   212
    DROP TABLE rlog;
sl@0
   213
    DROP TABLE clog;
sl@0
   214
    DROP TABLE tbl;
sl@0
   215
    DROP TABLE other_tbl;
sl@0
   216
  }
sl@0
   217
}
sl@0
   218
sl@0
   219
# 2.
sl@0
   220
set ii 0
sl@0
   221
foreach tr_program {
sl@0
   222
  {UPDATE tbl SET b = old.b;}
sl@0
   223
  {INSERT INTO log VALUES(new.c, 2, 3);}
sl@0
   224
  {DELETE FROM log WHERE a = 1;}
sl@0
   225
  {INSERT INTO tbl VALUES(500, new.b * 10, 700); 
sl@0
   226
    UPDATE tbl SET c = old.c; 
sl@0
   227
    DELETE FROM log;}
sl@0
   228
  {INSERT INTO log select * from tbl;} 
sl@0
   229
} {
sl@0
   230
  foreach test_varset [ list \
sl@0
   231
    {
sl@0
   232
      set statement {UPDATE tbl SET c = 10 WHERE a = 1;} 
sl@0
   233
      set prep      {INSERT INTO tbl VALUES(1, 2, 3);}
sl@0
   234
      set newC 10
sl@0
   235
      set newB 2
sl@0
   236
      set newA 1
sl@0
   237
      set oldA 1
sl@0
   238
      set oldB 2
sl@0
   239
      set oldC 3
sl@0
   240
    } \
sl@0
   241
    {
sl@0
   242
      set statement {DELETE FROM tbl WHERE a = 1;}
sl@0
   243
      set prep      {INSERT INTO tbl VALUES(1, 2, 3);}
sl@0
   244
      set oldA 1
sl@0
   245
      set oldB 2
sl@0
   246
      set oldC 3
sl@0
   247
    } \
sl@0
   248
    {
sl@0
   249
      set statement {INSERT INTO tbl VALUES(1, 2, 3);}
sl@0
   250
      set newA 1
sl@0
   251
      set newB 2
sl@0
   252
      set newC 3
sl@0
   253
    }
sl@0
   254
  ] \
sl@0
   255
  {
sl@0
   256
    set statement {}
sl@0
   257
    set prep {}
sl@0
   258
    set newA {''}
sl@0
   259
    set newB {''}
sl@0
   260
    set newC {''}
sl@0
   261
    set oldA {''}
sl@0
   262
    set oldB {''}
sl@0
   263
    set oldC {''}
sl@0
   264
sl@0
   265
    incr ii
sl@0
   266
sl@0
   267
    eval $test_varset
sl@0
   268
sl@0
   269
    set statement_type [string range $statement 0 5]
sl@0
   270
    set tr_program_fixed $tr_program
sl@0
   271
    if {$statement_type == "DELETE"} {
sl@0
   272
      regsub -all new\.a $tr_program_fixed {''} tr_program_fixed 
sl@0
   273
      regsub -all new\.b $tr_program_fixed {''} tr_program_fixed 
sl@0
   274
      regsub -all new\.c $tr_program_fixed {''} tr_program_fixed 
sl@0
   275
    }
sl@0
   276
    if {$statement_type == "INSERT"} {
sl@0
   277
      regsub -all old\.a $tr_program_fixed {''} tr_program_fixed 
sl@0
   278
      regsub -all old\.b $tr_program_fixed {''} tr_program_fixed 
sl@0
   279
      regsub -all old\.c $tr_program_fixed {''} tr_program_fixed 
sl@0
   280
    }
sl@0
   281
sl@0
   282
sl@0
   283
    set tr_program_cooked $tr_program
sl@0
   284
    regsub -all new\.a $tr_program_cooked $newA tr_program_cooked 
sl@0
   285
    regsub -all new\.b $tr_program_cooked $newB tr_program_cooked 
sl@0
   286
    regsub -all new\.c $tr_program_cooked $newC tr_program_cooked 
sl@0
   287
    regsub -all old\.a $tr_program_cooked $oldA tr_program_cooked 
sl@0
   288
    regsub -all old\.b $tr_program_cooked $oldB tr_program_cooked 
sl@0
   289
    regsub -all old\.c $tr_program_cooked $oldC tr_program_cooked 
sl@0
   290
sl@0
   291
    catchsql {
sl@0
   292
      DROP TABLE tbl;
sl@0
   293
      DROP TABLE log;
sl@0
   294
    }
sl@0
   295
sl@0
   296
    execsql {
sl@0
   297
      CREATE TABLE tbl(a PRIMARY KEY, b, c);
sl@0
   298
      CREATE TABLE log(a, b, c);
sl@0
   299
    }
sl@0
   300
sl@0
   301
    set query {SELECT * FROM tbl; SELECT * FROM log;}
sl@0
   302
    set prep "$prep; INSERT INTO log VALUES(1, 2, 3);\
sl@0
   303
             INSERT INTO log VALUES(10, 20, 30);"
sl@0
   304
sl@0
   305
# Check execution of BEFORE programs:
sl@0
   306
sl@0
   307
    set before_data [ execsql "$prep $tr_program_cooked $statement $query" ]
sl@0
   308
sl@0
   309
    execsql "DELETE FROM tbl; DELETE FROM log; $prep";
sl@0
   310
    execsql "CREATE TRIGGER the_trigger BEFORE [string range $statement 0 6]\
sl@0
   311
             ON tbl BEGIN $tr_program_fixed END;"
sl@0
   312
sl@0
   313
    do_test trigger2-2.$ii-before "execsql {$statement $query}" $before_data
sl@0
   314
sl@0
   315
    execsql "DROP TRIGGER the_trigger;"
sl@0
   316
    execsql "DELETE FROM tbl; DELETE FROM log;"
sl@0
   317
sl@0
   318
# Check execution of AFTER programs
sl@0
   319
    set after_data [ execsql "$prep $statement $tr_program_cooked $query" ]
sl@0
   320
sl@0
   321
    execsql "DELETE FROM tbl; DELETE FROM log; $prep";
sl@0
   322
    execsql "CREATE TRIGGER the_trigger AFTER [string range $statement 0 6]\
sl@0
   323
             ON tbl BEGIN $tr_program_fixed END;"
sl@0
   324
sl@0
   325
    do_test trigger2-2.$ii-after "execsql {$statement $query}" $after_data
sl@0
   326
    execsql "DROP TRIGGER the_trigger;"
sl@0
   327
sl@0
   328
    integrity_check trigger2-2.$ii-integrity
sl@0
   329
  }
sl@0
   330
}
sl@0
   331
catchsql {
sl@0
   332
  DROP TABLE tbl;
sl@0
   333
  DROP TABLE log;
sl@0
   334
}
sl@0
   335
sl@0
   336
# 3.
sl@0
   337
sl@0
   338
# trigger2-3.1: UPDATE OF triggers
sl@0
   339
execsql {
sl@0
   340
  CREATE TABLE tbl (a, b, c, d);
sl@0
   341
  CREATE TABLE log (a);
sl@0
   342
  INSERT INTO log VALUES (0);
sl@0
   343
  INSERT INTO tbl VALUES (0, 0, 0, 0);
sl@0
   344
  INSERT INTO tbl VALUES (1, 0, 0, 0);
sl@0
   345
  CREATE TRIGGER tbl_after_update_cd BEFORE UPDATE OF c, d ON tbl
sl@0
   346
    BEGIN
sl@0
   347
      UPDATE log SET a = a + 1;
sl@0
   348
    END;
sl@0
   349
}
sl@0
   350
do_test trigger2-3.1 {
sl@0
   351
  execsql {
sl@0
   352
    UPDATE tbl SET b = 1, c = 10; -- 2
sl@0
   353
    UPDATE tbl SET b = 10; -- 0
sl@0
   354
    UPDATE tbl SET d = 4 WHERE a = 0; --1
sl@0
   355
    UPDATE tbl SET a = 4, b = 10; --0
sl@0
   356
    SELECT * FROM log;
sl@0
   357
  }
sl@0
   358
} {3}
sl@0
   359
execsql {
sl@0
   360
  DROP TABLE tbl;
sl@0
   361
  DROP TABLE log;
sl@0
   362
}
sl@0
   363
sl@0
   364
# trigger2-3.2: WHEN clause
sl@0
   365
set when_triggers [list {t1 BEFORE INSERT ON tbl WHEN new.a > 20}]
sl@0
   366
ifcapable subquery {
sl@0
   367
  lappend when_triggers \
sl@0
   368
      {t2 BEFORE INSERT ON tbl WHEN (SELECT count(*) FROM tbl) = 0}
sl@0
   369
}
sl@0
   370
sl@0
   371
execsql {
sl@0
   372
  CREATE TABLE tbl (a, b, c, d);
sl@0
   373
  CREATE TABLE log (a);
sl@0
   374
  INSERT INTO log VALUES (0);
sl@0
   375
}
sl@0
   376
sl@0
   377
foreach trig $when_triggers {
sl@0
   378
  execsql "CREATE TRIGGER $trig BEGIN UPDATE log set a = a + 1; END;"
sl@0
   379
}
sl@0
   380
sl@0
   381
ifcapable subquery {
sl@0
   382
  set t232 {1 0 1}
sl@0
   383
} else {
sl@0
   384
  set t232 {0 0 1}
sl@0
   385
}
sl@0
   386
do_test trigger2-3.2 {
sl@0
   387
  execsql { 
sl@0
   388
sl@0
   389
    INSERT INTO tbl VALUES(0, 0, 0, 0);     -- 1 (ifcapable subquery)
sl@0
   390
    SELECT * FROM log;
sl@0
   391
    UPDATE log SET a = 0;
sl@0
   392
sl@0
   393
    INSERT INTO tbl VALUES(0, 0, 0, 0);     -- 0
sl@0
   394
    SELECT * FROM log;
sl@0
   395
    UPDATE log SET a = 0;
sl@0
   396
sl@0
   397
    INSERT INTO tbl VALUES(200, 0, 0, 0);     -- 1
sl@0
   398
    SELECT * FROM log;
sl@0
   399
    UPDATE log SET a = 0;
sl@0
   400
  }
sl@0
   401
} $t232
sl@0
   402
execsql {
sl@0
   403
  DROP TABLE tbl;
sl@0
   404
  DROP TABLE log;
sl@0
   405
}
sl@0
   406
integrity_check trigger2-3.3
sl@0
   407
sl@0
   408
# Simple cascaded trigger
sl@0
   409
execsql {
sl@0
   410
  CREATE TABLE tblA(a, b);
sl@0
   411
  CREATE TABLE tblB(a, b);
sl@0
   412
  CREATE TABLE tblC(a, b);
sl@0
   413
sl@0
   414
  CREATE TRIGGER tr1 BEFORE INSERT ON tblA BEGIN
sl@0
   415
    INSERT INTO tblB values(new.a, new.b);
sl@0
   416
  END;
sl@0
   417
sl@0
   418
  CREATE TRIGGER tr2 BEFORE INSERT ON tblB BEGIN
sl@0
   419
    INSERT INTO tblC values(new.a, new.b);
sl@0
   420
  END;
sl@0
   421
}
sl@0
   422
do_test trigger2-4.1 {
sl@0
   423
  execsql {
sl@0
   424
    INSERT INTO tblA values(1, 2);
sl@0
   425
    SELECT * FROM tblA;
sl@0
   426
    SELECT * FROM tblB;
sl@0
   427
    SELECT * FROM tblC;
sl@0
   428
  }
sl@0
   429
} {1 2 1 2 1 2}
sl@0
   430
execsql {
sl@0
   431
  DROP TABLE tblA;
sl@0
   432
  DROP TABLE tblB;
sl@0
   433
  DROP TABLE tblC;
sl@0
   434
}
sl@0
   435
sl@0
   436
# Simple recursive trigger
sl@0
   437
execsql {
sl@0
   438
  CREATE TABLE tbl(a, b, c);
sl@0
   439
  CREATE TRIGGER tbl_trig BEFORE INSERT ON tbl 
sl@0
   440
    BEGIN
sl@0
   441
      INSERT INTO tbl VALUES (new.a, new.b, new.c);
sl@0
   442
    END;
sl@0
   443
}
sl@0
   444
do_test trigger2-4.2 {
sl@0
   445
  execsql {
sl@0
   446
    INSERT INTO tbl VALUES (1, 2, 3);
sl@0
   447
    select * from tbl;
sl@0
   448
  }
sl@0
   449
} {1 2 3 1 2 3}
sl@0
   450
execsql {
sl@0
   451
  DROP TABLE tbl;
sl@0
   452
}
sl@0
   453
sl@0
   454
# 5.
sl@0
   455
execsql {
sl@0
   456
  CREATE TABLE tbl(a, b, c);
sl@0
   457
  CREATE TRIGGER tbl_trig BEFORE INSERT ON tbl 
sl@0
   458
    BEGIN
sl@0
   459
      INSERT INTO tbl VALUES (1, 2, 3);
sl@0
   460
      INSERT INTO tbl VALUES (2, 2, 3);
sl@0
   461
      UPDATE tbl set b = 10 WHERE a = 1;
sl@0
   462
      DELETE FROM tbl WHERE a = 1;
sl@0
   463
      DELETE FROM tbl;
sl@0
   464
    END;
sl@0
   465
}
sl@0
   466
do_test trigger2-5 {
sl@0
   467
  execsql {
sl@0
   468
    INSERT INTO tbl VALUES(100, 200, 300);
sl@0
   469
  }
sl@0
   470
  db changes
sl@0
   471
} {1}
sl@0
   472
execsql {
sl@0
   473
  DROP TABLE tbl;
sl@0
   474
}
sl@0
   475
sl@0
   476
ifcapable conflict {
sl@0
   477
  # Handling of ON CONFLICT by INSERT statements inside triggers
sl@0
   478
  execsql {
sl@0
   479
    CREATE TABLE tbl (a primary key, b, c);
sl@0
   480
    CREATE TRIGGER ai_tbl AFTER INSERT ON tbl BEGIN
sl@0
   481
      INSERT OR IGNORE INTO tbl values (new.a, 0, 0);
sl@0
   482
    END;
sl@0
   483
  }
sl@0
   484
  do_test trigger2-6.1a {
sl@0
   485
    execsql {
sl@0
   486
      BEGIN;
sl@0
   487
      INSERT INTO tbl values (1, 2, 3);
sl@0
   488
      SELECT * from tbl;
sl@0
   489
    }
sl@0
   490
  } {1 2 3}
sl@0
   491
  do_test trigger2-6.1b {
sl@0
   492
    catchsql {
sl@0
   493
      INSERT OR ABORT INTO tbl values (2, 2, 3);
sl@0
   494
    }
sl@0
   495
  } {1 {column a is not unique}}
sl@0
   496
  do_test trigger2-6.1c {
sl@0
   497
    execsql {
sl@0
   498
      SELECT * from tbl;
sl@0
   499
    }
sl@0
   500
  } {1 2 3}
sl@0
   501
  do_test trigger2-6.1d {
sl@0
   502
    catchsql {
sl@0
   503
      INSERT OR FAIL INTO tbl values (2, 2, 3);
sl@0
   504
    }
sl@0
   505
  } {1 {column a is not unique}}
sl@0
   506
  do_test trigger2-6.1e {
sl@0
   507
    execsql {
sl@0
   508
      SELECT * from tbl;
sl@0
   509
    }
sl@0
   510
  } {1 2 3 2 2 3}
sl@0
   511
  do_test trigger2-6.1f {
sl@0
   512
    execsql {
sl@0
   513
      INSERT OR REPLACE INTO tbl values (2, 2, 3);
sl@0
   514
      SELECT * from tbl;
sl@0
   515
    }
sl@0
   516
  } {1 2 3 2 0 0}
sl@0
   517
  do_test trigger2-6.1g {
sl@0
   518
    catchsql {
sl@0
   519
      INSERT OR ROLLBACK INTO tbl values (3, 2, 3);
sl@0
   520
    }
sl@0
   521
  } {1 {column a is not unique}}
sl@0
   522
  do_test trigger2-6.1h {
sl@0
   523
    execsql {
sl@0
   524
      SELECT * from tbl;
sl@0
   525
    }
sl@0
   526
  } {}
sl@0
   527
  execsql {DELETE FROM tbl}
sl@0
   528
  
sl@0
   529
  
sl@0
   530
  # Handling of ON CONFLICT by UPDATE statements inside triggers
sl@0
   531
  execsql {
sl@0
   532
    INSERT INTO tbl values (4, 2, 3);
sl@0
   533
    INSERT INTO tbl values (6, 3, 4);
sl@0
   534
    CREATE TRIGGER au_tbl AFTER UPDATE ON tbl BEGIN
sl@0
   535
      UPDATE OR IGNORE tbl SET a = new.a, c = 10;
sl@0
   536
    END;
sl@0
   537
  }
sl@0
   538
  do_test trigger2-6.2a {
sl@0
   539
    execsql {
sl@0
   540
      BEGIN;
sl@0
   541
      UPDATE tbl SET a = 1 WHERE a = 4;
sl@0
   542
      SELECT * from tbl;
sl@0
   543
    }
sl@0
   544
  } {1 2 10 6 3 4}
sl@0
   545
  do_test trigger2-6.2b {
sl@0
   546
    catchsql {
sl@0
   547
      UPDATE OR ABORT tbl SET a = 4 WHERE a = 1;
sl@0
   548
    }
sl@0
   549
  } {1 {column a is not unique}}
sl@0
   550
  do_test trigger2-6.2c {
sl@0
   551
    execsql {
sl@0
   552
      SELECT * from tbl;
sl@0
   553
    }
sl@0
   554
  } {1 2 10 6 3 4}
sl@0
   555
  do_test trigger2-6.2d {
sl@0
   556
    catchsql {
sl@0
   557
      UPDATE OR FAIL tbl SET a = 4 WHERE a = 1;
sl@0
   558
    }
sl@0
   559
  } {1 {column a is not unique}}
sl@0
   560
  do_test trigger2-6.2e {
sl@0
   561
    execsql {
sl@0
   562
      SELECT * from tbl;
sl@0
   563
    }
sl@0
   564
  } {4 2 10 6 3 4}
sl@0
   565
  do_test trigger2-6.2f.1 {
sl@0
   566
    execsql {
sl@0
   567
      UPDATE OR REPLACE tbl SET a = 1 WHERE a = 4;
sl@0
   568
      SELECT * from tbl;
sl@0
   569
    }
sl@0
   570
  } {1 3 10}
sl@0
   571
  do_test trigger2-6.2f.2 {
sl@0
   572
    execsql {
sl@0
   573
      INSERT INTO tbl VALUES (2, 3, 4);
sl@0
   574
      SELECT * FROM tbl;
sl@0
   575
    }
sl@0
   576
  } {1 3 10 2 3 4}
sl@0
   577
  do_test trigger2-6.2g {
sl@0
   578
    catchsql {
sl@0
   579
      UPDATE OR ROLLBACK tbl SET a = 4 WHERE a = 1;
sl@0
   580
    }
sl@0
   581
  } {1 {column a is not unique}}
sl@0
   582
  do_test trigger2-6.2h {
sl@0
   583
    execsql {
sl@0
   584
      SELECT * from tbl;
sl@0
   585
    }
sl@0
   586
  } {4 2 3 6 3 4}
sl@0
   587
  execsql {
sl@0
   588
    DROP TABLE tbl;
sl@0
   589
  }
sl@0
   590
} ; # ifcapable conflict
sl@0
   591
sl@0
   592
# 7. Triggers on views
sl@0
   593
ifcapable view {
sl@0
   594
sl@0
   595
do_test trigger2-7.1 {
sl@0
   596
  execsql {
sl@0
   597
  CREATE TABLE ab(a, b);
sl@0
   598
  CREATE TABLE cd(c, d);
sl@0
   599
  INSERT INTO ab VALUES (1, 2);
sl@0
   600
  INSERT INTO ab VALUES (0, 0);
sl@0
   601
  INSERT INTO cd VALUES (3, 4);
sl@0
   602
sl@0
   603
  CREATE TABLE tlog(ii INTEGER PRIMARY KEY, 
sl@0
   604
      olda, oldb, oldc, oldd, newa, newb, newc, newd);
sl@0
   605
sl@0
   606
  CREATE VIEW abcd AS SELECT a, b, c, d FROM ab, cd;
sl@0
   607
sl@0
   608
  CREATE TRIGGER before_update INSTEAD OF UPDATE ON abcd BEGIN
sl@0
   609
    INSERT INTO tlog VALUES(NULL, 
sl@0
   610
	old.a, old.b, old.c, old.d, new.a, new.b, new.c, new.d);
sl@0
   611
  END;
sl@0
   612
  CREATE TRIGGER after_update INSTEAD OF UPDATE ON abcd BEGIN
sl@0
   613
    INSERT INTO tlog VALUES(NULL, 
sl@0
   614
	old.a, old.b, old.c, old.d, new.a, new.b, new.c, new.d);
sl@0
   615
  END;
sl@0
   616
sl@0
   617
  CREATE TRIGGER before_delete INSTEAD OF DELETE ON abcd BEGIN
sl@0
   618
    INSERT INTO tlog VALUES(NULL, 
sl@0
   619
	old.a, old.b, old.c, old.d, 0, 0, 0, 0);
sl@0
   620
  END;
sl@0
   621
  CREATE TRIGGER after_delete INSTEAD OF DELETE ON abcd BEGIN
sl@0
   622
    INSERT INTO tlog VALUES(NULL, 
sl@0
   623
	old.a, old.b, old.c, old.d, 0, 0, 0, 0);
sl@0
   624
  END;
sl@0
   625
sl@0
   626
  CREATE TRIGGER before_insert INSTEAD OF INSERT ON abcd BEGIN
sl@0
   627
    INSERT INTO tlog VALUES(NULL, 
sl@0
   628
	0, 0, 0, 0, new.a, new.b, new.c, new.d);
sl@0
   629
  END;
sl@0
   630
   CREATE TRIGGER after_insert INSTEAD OF INSERT ON abcd BEGIN
sl@0
   631
    INSERT INTO tlog VALUES(NULL, 
sl@0
   632
	0, 0, 0, 0, new.a, new.b, new.c, new.d);
sl@0
   633
   END;
sl@0
   634
  }
sl@0
   635
} {};
sl@0
   636
sl@0
   637
do_test trigger2-7.2 {
sl@0
   638
  execsql {
sl@0
   639
    UPDATE abcd SET a = 100, b = 5*5 WHERE a = 1;
sl@0
   640
    DELETE FROM abcd WHERE a = 1;
sl@0
   641
    INSERT INTO abcd VALUES(10, 20, 30, 40);
sl@0
   642
    SELECT * FROM tlog;
sl@0
   643
  }
sl@0
   644
} [ list 1 1 2 3 4 100 25 3 4 \
sl@0
   645
         2 1 2 3 4 100 25 3 4 \
sl@0
   646
	 3 1 2 3 4 0 0 0 0 \
sl@0
   647
	 4 1 2 3 4 0 0 0 0 \
sl@0
   648
	 5 0 0 0 0 10 20 30 40 \
sl@0
   649
	 6 0 0 0 0 10 20 30 40 ]
sl@0
   650
sl@0
   651
do_test trigger2-7.3 {
sl@0
   652
  execsql {
sl@0
   653
    DELETE FROM tlog;
sl@0
   654
    INSERT INTO abcd VALUES(10, 20, 30, 40);
sl@0
   655
    UPDATE abcd SET a = 100, b = 5*5 WHERE a = 1;
sl@0
   656
    DELETE FROM abcd WHERE a = 1;
sl@0
   657
    SELECT * FROM tlog;
sl@0
   658
  }
sl@0
   659
} [ list \
sl@0
   660
   1 0 0 0 0 10 20 30 40 \
sl@0
   661
   2 0 0 0 0 10 20 30 40 \
sl@0
   662
   3 1 2 3 4 100 25 3 4 \
sl@0
   663
   4 1 2 3 4 100 25 3 4 \
sl@0
   664
   5 1 2 3 4 0 0 0 0 \
sl@0
   665
   6 1 2 3 4 0 0 0 0 \
sl@0
   666
]
sl@0
   667
do_test trigger2-7.4 {
sl@0
   668
  execsql {
sl@0
   669
    DELETE FROM tlog;
sl@0
   670
    DELETE FROM abcd WHERE a = 1;
sl@0
   671
    INSERT INTO abcd VALUES(10, 20, 30, 40);
sl@0
   672
    UPDATE abcd SET a = 100, b = 5*5 WHERE a = 1;
sl@0
   673
    SELECT * FROM tlog;
sl@0
   674
  }
sl@0
   675
} [ list \
sl@0
   676
   1 1 2 3 4 0 0 0 0 \
sl@0
   677
   2 1 2 3 4 0 0 0 0 \
sl@0
   678
   3 0 0 0 0 10 20 30 40 \
sl@0
   679
   4 0 0 0 0 10 20 30 40 \
sl@0
   680
   5 1 2 3 4 100 25 3 4 \
sl@0
   681
   6 1 2 3 4 100 25 3 4 \
sl@0
   682
]
sl@0
   683
sl@0
   684
do_test trigger2-8.1 {
sl@0
   685
  execsql {
sl@0
   686
    CREATE TABLE t1(a,b,c);
sl@0
   687
    INSERT INTO t1 VALUES(1,2,3);
sl@0
   688
    CREATE VIEW v1 AS
sl@0
   689
      SELECT a+b AS x, b+c AS y, a+c AS z FROM t1;
sl@0
   690
    SELECT * FROM v1;
sl@0
   691
  }
sl@0
   692
} {3 5 4}
sl@0
   693
do_test trigger2-8.2 {
sl@0
   694
  execsql {
sl@0
   695
    CREATE TABLE v1log(a,b,c,d,e,f);
sl@0
   696
    CREATE TRIGGER r1 INSTEAD OF DELETE ON v1 BEGIN
sl@0
   697
      INSERT INTO v1log VALUES(OLD.x,NULL,OLD.y,NULL,OLD.z,NULL);
sl@0
   698
    END;
sl@0
   699
    DELETE FROM v1 WHERE x=1;
sl@0
   700
    SELECT * FROM v1log;
sl@0
   701
  }
sl@0
   702
} {}
sl@0
   703
do_test trigger2-8.3 {
sl@0
   704
  execsql {
sl@0
   705
    DELETE FROM v1 WHERE x=3;
sl@0
   706
    SELECT * FROM v1log;
sl@0
   707
  }
sl@0
   708
} {3 {} 5 {} 4 {}}
sl@0
   709
do_test trigger2-8.4 {
sl@0
   710
  execsql {
sl@0
   711
    INSERT INTO t1 VALUES(4,5,6);
sl@0
   712
    DELETE FROM v1log;
sl@0
   713
    DELETE FROM v1 WHERE y=11;
sl@0
   714
    SELECT * FROM v1log;
sl@0
   715
  }
sl@0
   716
} {9 {} 11 {} 10 {}}
sl@0
   717
do_test trigger2-8.5 {
sl@0
   718
  execsql {
sl@0
   719
    CREATE TRIGGER r2 INSTEAD OF INSERT ON v1 BEGIN
sl@0
   720
      INSERT INTO v1log VALUES(NULL,NEW.x,NULL,NEW.y,NULL,NEW.z);
sl@0
   721
    END;
sl@0
   722
    DELETE FROM v1log;
sl@0
   723
    INSERT INTO v1 VALUES(1,2,3);
sl@0
   724
    SELECT * FROM v1log;
sl@0
   725
  }
sl@0
   726
} {{} 1 {} 2 {} 3}
sl@0
   727
do_test trigger2-8.6 {
sl@0
   728
  execsql {
sl@0
   729
    CREATE TRIGGER r3 INSTEAD OF UPDATE ON v1 BEGIN
sl@0
   730
      INSERT INTO v1log VALUES(OLD.x,NEW.x,OLD.y,NEW.y,OLD.z,NEW.z);
sl@0
   731
    END;
sl@0
   732
    DELETE FROM v1log;
sl@0
   733
    UPDATE v1 SET x=x+100, y=y+200, z=z+300;
sl@0
   734
    SELECT * FROM v1log;
sl@0
   735
  }
sl@0
   736
} {3 103 5 205 4 304 9 109 11 211 10 310}
sl@0
   737
sl@0
   738
} ;# ifcapable view
sl@0
   739
sl@0
   740
integrity_check trigger2-9.9
sl@0
   741
sl@0
   742
finish_test