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 # This file tests creating and dropping triggers, and interaction thereof
     11 # with the database COMMIT/ROLLBACK logic.
     12 #
     13 # 1. CREATE and DROP TRIGGER tests
     14 # trig-1.1: Error if table does not exist
     15 # trig-1.2: Error if trigger already exists
     16 # trig-1.3: Created triggers are deleted if the transaction is rolled back
     17 # trig-1.4: DROP TRIGGER removes trigger
     18 # trig-1.5: Dropped triggers are restored if the transaction is rolled back
     19 # trig-1.6: Error if dropped trigger doesn't exist
     20 # trig-1.7: Dropping the table automatically drops all triggers
     21 # trig-1.8: A trigger created on a TEMP table is not inserted into sqlite_master
     22 # trig-1.9: Ensure that we cannot create a trigger on sqlite_master
     23 # trig-1.10:
     24 # trig-1.11:
     25 # trig-1.12: Ensure that INSTEAD OF triggers cannot be created on tables
     26 # trig-1.13: Ensure that AFTER triggers cannot be created on views
     27 # trig-1.14: Ensure that BEFORE triggers cannot be created on views
     28 #
     29 
     30 set testdir [file dirname $argv0]
     31 source $testdir/tester.tcl
     32 ifcapable {!trigger} {
     33   finish_test
     34   return
     35 }
     36 
     37 do_test trigger1-1.1.1 {
     38    catchsql {
     39      CREATE TRIGGER trig UPDATE ON no_such_table BEGIN
     40        SELECT * from sqlite_master;
     41      END;
     42    } 
     43 } {1 {no such table: main.no_such_table}}
     44 
     45 ifcapable tempdb {
     46   do_test trigger1-1.1.2 {
     47      catchsql {
     48        CREATE TEMP TRIGGER trig UPDATE ON no_such_table BEGIN
     49          SELECT * from sqlite_master;
     50        END;
     51      } 
     52   } {1 {no such table: no_such_table}}
     53 }
     54 
     55 execsql {
     56     CREATE TABLE t1(a);
     57 }
     58 do_test trigger1-1.1.3 {
     59   catchsql {
     60      CREATE TRIGGER trig UPDATE ON t1 FOR EACH STATEMENT BEGIN
     61         SELECT * FROM sqlite_master;
     62      END;
     63   }
     64 } {1 {near "STATEMENT": syntax error}}
     65 execsql {
     66         CREATE TRIGGER tr1 INSERT ON t1 BEGIN
     67           INSERT INTO t1 values(1);
     68          END;
     69 }
     70 do_test trigger1-1.2.0 {
     71     catchsql {
     72         CREATE TRIGGER IF NOT EXISTS tr1 DELETE ON t1 BEGIN
     73             SELECT * FROM sqlite_master;
     74          END
     75      }
     76 } {0 {}}
     77 do_test trigger1-1.2.1 {
     78     catchsql {
     79         CREATE TRIGGER tr1 DELETE ON t1 BEGIN
     80             SELECT * FROM sqlite_master;
     81          END
     82      }
     83 } {1 {trigger tr1 already exists}}
     84 do_test trigger1-1.2.2 {
     85     catchsql {
     86         CREATE TRIGGER "tr1" DELETE ON t1 BEGIN
     87             SELECT * FROM sqlite_master;
     88          END
     89      }
     90 } {1 {trigger "tr1" already exists}}
     91 do_test trigger1-1.2.3 {
     92     catchsql {
     93         CREATE TRIGGER [tr1] DELETE ON t1 BEGIN
     94             SELECT * FROM sqlite_master;
     95          END
     96      }
     97 } {1 {trigger [tr1] already exists}}
     98 
     99 do_test trigger1-1.3 {
    100     catchsql {
    101         BEGIN;
    102         CREATE TRIGGER tr2 INSERT ON t1 BEGIN
    103             SELECT * from sqlite_master; END;
    104         ROLLBACK;
    105         CREATE TRIGGER tr2 INSERT ON t1 BEGIN
    106             SELECT * from sqlite_master; END;
    107     }
    108 } {0 {}}
    109 
    110 do_test trigger1-1.4 {
    111     catchsql {
    112         DROP TRIGGER IF EXISTS tr1;
    113         CREATE TRIGGER tr1 DELETE ON t1 BEGIN
    114             SELECT * FROM sqlite_master;
    115         END
    116     }
    117 } {0 {}}
    118 
    119 do_test trigger1-1.5 {
    120     execsql {
    121         BEGIN;
    122         DROP TRIGGER tr2;
    123         ROLLBACK;
    124         DROP TRIGGER tr2;
    125     }
    126 } {}
    127 
    128 do_test trigger1-1.6.1 {
    129     catchsql {
    130         DROP TRIGGER IF EXISTS biggles;
    131     }
    132 } {0 {}}
    133 
    134 do_test trigger1-1.6.2 {
    135     catchsql {
    136         DROP TRIGGER biggles;
    137     }
    138 } {1 {no such trigger: biggles}}
    139 
    140 do_test trigger1-1.7 {
    141     catchsql {
    142         DROP TABLE t1;
    143         DROP TRIGGER tr1;
    144     }
    145 } {1 {no such trigger: tr1}}
    146 
    147 ifcapable tempdb {
    148   execsql {
    149     CREATE TEMP TABLE temp_table(a);
    150   }
    151   do_test trigger1-1.8 {
    152     execsql {
    153           CREATE TRIGGER temp_trig UPDATE ON temp_table BEGIN
    154               SELECT * from sqlite_master;
    155           END;
    156           SELECT count(*) FROM sqlite_master WHERE name = 'temp_trig';
    157     } 
    158   } {0}
    159 }
    160 
    161 do_test trigger1-1.9 {
    162   catchsql {
    163     CREATE TRIGGER tr1 AFTER UPDATE ON sqlite_master BEGIN
    164        SELECT * FROM sqlite_master;
    165     END;
    166   }
    167 } {1 {cannot create trigger on system table}}
    168 
    169 # Check to make sure that a DELETE statement within the body of
    170 # a trigger does not mess up the DELETE that caused the trigger to
    171 # run in the first place.
    172 #
    173 do_test trigger1-1.10 {
    174   execsql {
    175     create table t1(a,b);
    176     insert into t1 values(1,'a');
    177     insert into t1 values(2,'b');
    178     insert into t1 values(3,'c');
    179     insert into t1 values(4,'d');
    180     create trigger r1 after delete on t1 for each row begin
    181       delete from t1 WHERE a=old.a+2;
    182     end;
    183     delete from t1 where a=1 OR a=3;
    184     select * from t1;
    185     drop table t1;
    186   }
    187 } {2 b 4 d}
    188 
    189 do_test trigger1-1.11 {
    190   execsql {
    191     create table t1(a,b);
    192     insert into t1 values(1,'a');
    193     insert into t1 values(2,'b');
    194     insert into t1 values(3,'c');
    195     insert into t1 values(4,'d');
    196     create trigger r1 after update on t1 for each row begin
    197       delete from t1 WHERE a=old.a+2;
    198     end;
    199     update t1 set b='x-' || b where a=1 OR a=3;
    200     select * from t1;
    201     drop table t1;
    202   }
    203 } {1 x-a 2 b 4 d}
    204 
    205 # Ensure that we cannot create INSTEAD OF triggers on tables
    206 do_test trigger1-1.12 {
    207   catchsql {
    208     create table t1(a,b);
    209     create trigger t1t instead of update on t1 for each row begin
    210       delete from t1 WHERE a=old.a+2;
    211     end;
    212   }
    213 } {1 {cannot create INSTEAD OF trigger on table: main.t1}}
    214 
    215 ifcapable view {
    216 # Ensure that we cannot create BEFORE triggers on views
    217 do_test trigger1-1.13 {
    218   catchsql {
    219     create view v1 as select * from t1;
    220     create trigger v1t before update on v1 for each row begin
    221       delete from t1 WHERE a=old.a+2;
    222     end;
    223   }
    224 } {1 {cannot create BEFORE trigger on view: main.v1}}
    225 # Ensure that we cannot create AFTER triggers on views
    226 do_test trigger1-1.14 {
    227   catchsql {
    228     drop view v1;
    229     create view v1 as select * from t1;
    230     create trigger v1t AFTER update on v1 for each row begin
    231       delete from t1 WHERE a=old.a+2;
    232     end;
    233   }
    234 } {1 {cannot create AFTER trigger on view: main.v1}}
    235 } ;# ifcapable view
    236 
    237 # Check for memory leaks in the trigger parser
    238 #
    239 do_test trigger1-2.1 {
    240   catchsql {
    241     CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
    242       SELECT * FROM;  -- Syntax error
    243     END;
    244   }
    245 } {1 {near ";": syntax error}}
    246 do_test trigger1-2.2 {
    247   catchsql {
    248     CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
    249       SELECT * FROM t1;
    250       SELECT * FROM;  -- Syntax error
    251     END;
    252   }
    253 } {1 {near ";": syntax error}}
    254 
    255 # Create a trigger that refers to a table that might not exist.
    256 #
    257 ifcapable tempdb {
    258   do_test trigger1-3.1 {
    259     execsql {
    260       CREATE TEMP TABLE t2(x,y);
    261     }
    262     catchsql {
    263       CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
    264         INSERT INTO t2 VALUES(NEW.a,NEW.b);
    265       END;
    266     }
    267   } {0 {}}
    268   do_test trigger-3.2 {
    269     catchsql {
    270       INSERT INTO t1 VALUES(1,2);
    271       SELECT * FROM t2;
    272     }
    273   } {1 {no such table: main.t2}}
    274   do_test trigger-3.3 {
    275     db close
    276     set rc [catch {sqlite3 db test.db} err]
    277     if {$rc} {lappend rc $err}
    278     set rc
    279   } {0}
    280   do_test trigger-3.4 {
    281     catchsql {
    282       INSERT INTO t1 VALUES(1,2);
    283       SELECT * FROM t2;
    284     }
    285   } {1 {no such table: main.t2}}
    286   do_test trigger-3.5 {
    287     catchsql {
    288       CREATE TEMP TABLE t2(x,y);
    289       INSERT INTO t1 VALUES(1,2);
    290       SELECT * FROM t2;
    291     }
    292   } {1 {no such table: main.t2}}
    293   do_test trigger-3.6 {
    294     catchsql {
    295       DROP TRIGGER r1;
    296       CREATE TEMP TRIGGER r1 AFTER INSERT ON t1 BEGIN
    297         INSERT INTO t2 VALUES(NEW.a,NEW.b);
    298       END;
    299       INSERT INTO t1 VALUES(1,2);
    300       SELECT * FROM t2;
    301     }
    302   } {0 {1 2}}
    303   do_test trigger-3.7 {
    304     execsql {
    305       DROP TABLE t2;
    306       CREATE TABLE t2(x,y);
    307       SELECT * FROM t2;
    308     }
    309   } {}
    310 
    311   # There are two versions of trigger-3.8 and trigger-3.9. One that uses
    312   # compound SELECT statements, and another that does not.
    313   ifcapable compound {
    314   do_test trigger1-3.8 {
    315     execsql {
    316       INSERT INTO t1 VALUES(3,4);
    317       SELECT * FROM t1 UNION ALL SELECT * FROM t2;
    318     }
    319   } {1 2 3 4 3 4}
    320   do_test trigger1-3.9 {
    321     db close
    322     sqlite3 db test.db
    323     execsql {
    324       INSERT INTO t1 VALUES(5,6);
    325       SELECT * FROM t1 UNION ALL SELECT * FROM t2;
    326     }
    327   } {1 2 3 4 5 6 3 4}
    328   } ;# ifcapable compound
    329   ifcapable !compound {
    330   do_test trigger1-3.8 {
    331     execsql {
    332       INSERT INTO t1 VALUES(3,4);
    333       SELECT * FROM t1; 
    334       SELECT * FROM t2;
    335     }
    336   } {1 2 3 4 3 4}
    337   do_test trigger1-3.9 {
    338     db close
    339     sqlite3 db test.db
    340     execsql {
    341       INSERT INTO t1 VALUES(5,6);
    342       SELECT * FROM t1;
    343       SELECT * FROM t2;
    344     }
    345   } {1 2 3 4 5 6 3 4}
    346   } ;# ifcapable !compound
    347 
    348   do_test trigger1-4.1 {
    349     execsql {
    350       CREATE TEMP TRIGGER r1 BEFORE INSERT ON t1 BEGIN
    351         INSERT INTO t2 VALUES(NEW.a,NEW.b);
    352       END;
    353       INSERT INTO t1 VALUES(7,8);
    354       SELECT * FROM t2;
    355     }
    356   } {3 4 7 8}
    357   do_test trigger1-4.2 {
    358     sqlite3 db2 test.db
    359     execsql {
    360       INSERT INTO t1 VALUES(9,10);
    361     } db2;
    362     db2 close
    363     execsql {
    364       SELECT * FROM t2;
    365     }
    366   } {3 4 7 8}
    367   do_test trigger1-4.3 {
    368     execsql {
    369       DROP TABLE t1;
    370       SELECT * FROM t2;
    371     };
    372   } {3 4 7 8}
    373   do_test trigger1-4.4 {
    374     db close
    375     sqlite3 db test.db
    376     execsql {
    377       SELECT * FROM t2;
    378     };
    379   } {3 4 7 8}
    380 } else {
    381   execsql {
    382     CREATE TABLE t2(x,y);
    383     DROP TABLE t1;
    384     INSERT INTO t2 VALUES(3, 4);
    385     INSERT INTO t2 VALUES(7, 8);
    386   }
    387 }
    388 
    389 
    390 integrity_check trigger1-5.1
    391 
    392 # Create a trigger with the same name as a table.  Make sure the
    393 # trigger works.  Then drop the trigger.  Make sure the table is
    394 # still there.
    395 #
    396 set view_v1 {}
    397 ifcapable view {
    398   set view_v1 {view v1}
    399 }
    400 do_test trigger1-6.1 {
    401   execsql {SELECT type, name FROM sqlite_master}
    402 } [concat $view_v1 {table t2}]
    403 do_test trigger1-6.2 {
    404   execsql {
    405     CREATE TRIGGER t2 BEFORE DELETE ON t2 BEGIN
    406       SELECT RAISE(ABORT,'deletes are not permitted');
    407     END;
    408     SELECT type, name FROM sqlite_master;
    409   }
    410 } [concat $view_v1 {table t2 trigger t2}]
    411 do_test trigger1-6.3 {
    412   catchsql {DELETE FROM t2}
    413 } {1 {deletes are not permitted}}
    414 do_test trigger1-6.4 {
    415   execsql {SELECT * FROM t2}
    416 } {3 4 7 8}
    417 do_test trigger1-6.5 {
    418   db close
    419   sqlite3 db test.db
    420   execsql {SELECT type, name FROM sqlite_master}
    421 } [concat $view_v1 {table t2 trigger t2}]
    422 do_test trigger1-6.6 {
    423   execsql {
    424     DROP TRIGGER t2;
    425     SELECT type, name FROM sqlite_master;
    426   }
    427 } [concat $view_v1 {table t2}]
    428 do_test trigger1-6.7 {
    429   execsql {SELECT * FROM t2}
    430 } {3 4 7 8}
    431 do_test trigger1-6.8 {
    432   db close
    433   sqlite3 db test.db
    434   execsql {SELECT * FROM t2}
    435 } {3 4 7 8}
    436 
    437 integrity_check trigger-7.1
    438 
    439 # Check to make sure the name of a trigger can be quoted so that keywords
    440 # can be used as trigger names.  Ticket #468
    441 #
    442 do_test trigger1-8.1 {
    443   execsql {
    444     CREATE TRIGGER 'trigger' AFTER INSERT ON t2 BEGIN SELECT 1; END;
    445     SELECT name FROM sqlite_master WHERE type='trigger';
    446   }
    447 } {trigger}
    448 do_test trigger1-8.2 {
    449   execsql {
    450     DROP TRIGGER 'trigger';
    451     SELECT name FROM sqlite_master WHERE type='trigger';
    452   }
    453 } {}
    454 do_test trigger1-8.3 {
    455   execsql {
    456     CREATE TRIGGER "trigger" AFTER INSERT ON t2 BEGIN SELECT 1; END;
    457     SELECT name FROM sqlite_master WHERE type='trigger';
    458   }
    459 } {trigger}
    460 do_test trigger1-8.4 {
    461   execsql {
    462     DROP TRIGGER "trigger";
    463     SELECT name FROM sqlite_master WHERE type='trigger';
    464   }
    465 } {}
    466 do_test trigger1-8.5 {
    467   execsql {
    468     CREATE TRIGGER [trigger] AFTER INSERT ON t2 BEGIN SELECT 1; END;
    469     SELECT name FROM sqlite_master WHERE type='trigger';
    470   }
    471 } {trigger}
    472 do_test trigger1-8.6 {
    473   execsql {
    474     DROP TRIGGER [trigger];
    475     SELECT name FROM sqlite_master WHERE type='trigger';
    476   }
    477 } {}
    478 
    479 ifcapable conflict {
    480   # Make sure REPLACE works inside of triggers.
    481   #
    482   # There are two versions of trigger-9.1 and trigger-9.2. One that uses
    483   # compound SELECT statements, and another that does not.
    484   ifcapable compound {
    485     do_test trigger1-9.1 {
    486       execsql {
    487         CREATE TABLE t3(a,b);
    488         CREATE TABLE t4(x UNIQUE, b);
    489         CREATE TRIGGER r34 AFTER INSERT ON t3 BEGIN
    490           REPLACE INTO t4 VALUES(new.a,new.b);
    491         END;
    492         INSERT INTO t3 VALUES(1,2);
    493         SELECT * FROM t3 UNION ALL SELECT 99, 99 UNION ALL SELECT * FROM t4;
    494       }
    495     } {1 2 99 99 1 2}
    496     do_test trigger1-9.2 {
    497       execsql {
    498         INSERT INTO t3 VALUES(1,3);
    499         SELECT * FROM t3 UNION ALL SELECT 99, 99 UNION ALL SELECT * FROM t4;
    500       }
    501     } {1 2 1 3 99 99 1 3}
    502   } else {
    503     do_test trigger1-9.1 {
    504       execsql {
    505         CREATE TABLE t3(a,b);
    506         CREATE TABLE t4(x UNIQUE, b);
    507         CREATE TRIGGER r34 AFTER INSERT ON t3 BEGIN
    508           REPLACE INTO t4 VALUES(new.a,new.b);
    509         END;
    510         INSERT INTO t3 VALUES(1,2);
    511         SELECT * FROM t3; SELECT 99, 99; SELECT * FROM t4;
    512       }
    513     } {1 2 99 99 1 2}
    514     do_test trigger1-9.2 {
    515       execsql {
    516         INSERT INTO t3 VALUES(1,3);
    517         SELECT * FROM t3; SELECT 99, 99; SELECT * FROM t4;
    518       }
    519     } {1 2 1 3 99 99 1 3}
    520   }
    521   execsql {
    522     DROP TABLE t3;
    523     DROP TABLE t4;
    524   }
    525 }
    526 
    527 
    528 # Ticket #764. At one stage TEMP triggers would fail to re-install when the
    529 # schema was reloaded. The following tests ensure that TEMP triggers are
    530 # correctly re-installed.
    531 #
    532 # Also verify that references within trigger programs are resolved at
    533 # statement compile time, not trigger installation time. This means, for
    534 # example, that you can drop and re-create tables referenced by triggers. 
    535 ifcapable tempdb&&attach {
    536   do_test trigger1-10.0 {
    537     file delete -force test2.db
    538     file delete -force test2.db-journal
    539     execsql {
    540       ATTACH 'test2.db' AS aux;
    541     }
    542   } {}
    543   do_test trigger1-10.1 {
    544     execsql {
    545       CREATE TABLE main.t4(a, b, c);
    546       CREATE TABLE temp.t4(a, b, c);
    547       CREATE TABLE aux.t4(a, b, c);
    548       CREATE TABLE insert_log(db, a, b, c);
    549     }
    550   } {}
    551   do_test trigger1-10.2 {
    552     execsql {
    553       CREATE TEMP TRIGGER trig1 AFTER INSERT ON main.t4 BEGIN 
    554         INSERT INTO insert_log VALUES('main', new.a, new.b, new.c);
    555       END;
    556       CREATE TEMP TRIGGER trig2 AFTER INSERT ON temp.t4 BEGIN 
    557         INSERT INTO insert_log VALUES('temp', new.a, new.b, new.c);
    558       END;
    559       CREATE TEMP TRIGGER trig3 AFTER INSERT ON aux.t4 BEGIN 
    560         INSERT INTO insert_log VALUES('aux', new.a, new.b, new.c);
    561       END;
    562     }
    563   } {}
    564   do_test trigger1-10.3 {
    565     execsql {
    566       INSERT INTO main.t4 VALUES(1, 2, 3);
    567       INSERT INTO temp.t4 VALUES(4, 5, 6);
    568       INSERT INTO aux.t4  VALUES(7, 8, 9);
    569     }
    570   } {}
    571   do_test trigger1-10.4 {
    572     execsql {
    573       SELECT * FROM insert_log;
    574     }
    575   } {main 1 2 3 temp 4 5 6 aux 7 8 9}
    576   do_test trigger1-10.5 {
    577     execsql {
    578       BEGIN;
    579       INSERT INTO main.t4 VALUES(1, 2, 3);
    580       INSERT INTO temp.t4 VALUES(4, 5, 6);
    581       INSERT INTO aux.t4  VALUES(7, 8, 9);
    582       ROLLBACK;
    583     }
    584   } {}
    585   do_test trigger1-10.6 {
    586     execsql {
    587       SELECT * FROM insert_log;
    588     }
    589   } {main 1 2 3 temp 4 5 6 aux 7 8 9}
    590   do_test trigger1-10.7 {
    591     execsql {
    592       DELETE FROM insert_log;
    593       INSERT INTO main.t4 VALUES(11, 12, 13);
    594       INSERT INTO temp.t4 VALUES(14, 15, 16);
    595       INSERT INTO aux.t4  VALUES(17, 18, 19);
    596     }
    597   } {}
    598   do_test trigger1-10.8 {
    599     execsql {
    600       SELECT * FROM insert_log;
    601     }
    602   } {main 11 12 13 temp 14 15 16 aux 17 18 19}
    603   do_test trigger1-10.8 {
    604   # Drop and re-create the insert_log table in a different database. Note
    605   # that we can change the column names because the trigger programs don't
    606   # use them explicitly.
    607     execsql {
    608       DROP TABLE insert_log;
    609       CREATE TABLE aux.insert_log(db, d, e, f);
    610     }
    611   } {}
    612   do_test trigger1-10.10 {
    613     execsql {
    614       INSERT INTO main.t4 VALUES(21, 22, 23);
    615       INSERT INTO temp.t4 VALUES(24, 25, 26);
    616       INSERT INTO aux.t4  VALUES(27, 28, 29);
    617     }
    618   } {}
    619   do_test trigger1-10.11 {
    620     execsql {
    621       SELECT * FROM insert_log;
    622     }
    623   } {main 21 22 23 temp 24 25 26 aux 27 28 29}
    624 }
    625 
    626 do_test trigger1-11.1 {
    627   catchsql {SELECT raise(abort,'message');}
    628 } {1 {RAISE() may only be used within a trigger-program}}
    629 
    630 do_test trigger1-15.1 {
    631   execsql {
    632     CREATE TABLE tA(a INTEGER PRIMARY KEY, b, c);
    633     CREATE TRIGGER tA_trigger BEFORE UPDATE ON "tA" BEGIN SELECT 1; END;
    634     INSERT INTO tA VALUES(1, 2, 3);
    635   }
    636   catchsql { UPDATE tA SET a = 'abc' }
    637 } {1 {datatype mismatch}}
    638 do_test trigger1-15.2 {
    639   catchsql { INSERT INTO tA VALUES('abc', 2, 3) }
    640 } {1 {datatype mismatch}}
    641 
    642 # Ticket #3947:  Do not allow qualified table names on INSERT, UPDATE, and
    643 # DELETE statements within triggers.  Actually, this has never been allowed
    644 # by the grammar.  But the error message is confusing: one simply gets a
    645 # "syntax error".  That has now been changed to give a full error message.
    646 #
    647 do_test trigger1-16.1 {
    648   db eval {
    649     CREATE TABLE t16(a,b,c);
    650     CREATE INDEX t16a ON t16(a);
    651     CREATE INDEX t16b ON t16(b);
    652   }
    653   catchsql {
    654     CREATE TRIGGER main.t16err1 AFTER INSERT ON tA BEGIN
    655       INSERT INTO main.t16 VALUES(1,2,3);
    656     END;
    657   }
    658 } {1 {qualified table names are not allowed on INSERT, UPDATE, and DELETE statements within triggers}}
    659 do_test trigger1-16.2 {
    660   catchsql {
    661     CREATE TRIGGER main.t16err2 AFTER INSERT ON tA BEGIN
    662       UPDATE main.t16 SET rowid=rowid+1;
    663     END;
    664   }
    665 } {1 {qualified table names are not allowed on INSERT, UPDATE, and DELETE statements within triggers}}
    666 do_test trigger1-16.3 {
    667   catchsql {
    668     CREATE TRIGGER main.t16err3 AFTER INSERT ON tA BEGIN
    669       DELETE FROM main.t16;
    670     END;
    671   }
    672 } {1 {qualified table names are not allowed on INSERT, UPDATE, and DELETE statements within triggers}}
    673 do_test trigger1-16.4 {
    674   catchsql {
    675     CREATE TRIGGER main.t16err4 AFTER INSERT ON tA BEGIN
    676       UPDATE t16 NOT INDEXED SET rowid=rowid+1;
    677     END;
    678   }
    679 } {1 {the NOT INDEXED clause is not allowed on UPDATE or DELETE statements within triggers}}
    680 do_test trigger1-16.5 {
    681   catchsql {
    682     CREATE TRIGGER main.t16err5 AFTER INSERT ON tA BEGIN
    683       UPDATE t16 INDEXED BY t16a SET rowid=rowid+1 WHERE a=1;
    684     END;
    685   }
    686 } {1 {the INDEXED BY clause is not allowed on UPDATE or DELETE statements within triggers}}
    687 do_test trigger1-16.6 {
    688   catchsql {
    689     CREATE TRIGGER main.t16err6 AFTER INSERT ON tA BEGIN
    690       DELETE FROM t16 NOT INDEXED WHERE a=123;
    691     END;
    692   }
    693 } {1 {the NOT INDEXED clause is not allowed on UPDATE or DELETE statements within triggers}}
    694 do_test trigger1-16.7 {
    695   catchsql {
    696     CREATE TRIGGER main.t16err7 AFTER INSERT ON tA BEGIN
    697       DELETE FROM t16 INDEXED BY t16a WHERE a=123;
    698     END;
    699   }
    700 } {1 {the INDEXED BY clause is not allowed on UPDATE or DELETE statements within triggers}}
    701 
    702 finish_test
    703