gitlab.com/CoiaPrant/sqlite3@v1.19.1/testdata/tcl/trigger1.test (about)

     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  # trigger1-1.1: Error if table does not exist
    15  # trigger1-1.2: Error if trigger already exists
    16  # trigger1-1.3: Created triggers are deleted if the transaction is rolled back
    17  # trigger1-1.4: DROP TRIGGER removes trigger
    18  # trigger1-1.5: Dropped triggers are restored if the transaction is rolled back
    19  # trigger1-1.6: Error if dropped trigger doesn't exist
    20  # trigger1-1.7: Dropping the table automatically drops all triggers
    21  # trigger1-1.8: A trigger created on a TEMP table is not inserted into sqlite_master
    22  # trigger1-1.9: Ensure that we cannot create a trigger on sqlite_master
    23  # trigger1-1.10:
    24  # trigger1-1.11:
    25  # trigger1-1.12: Ensure that INSTEAD OF triggers cannot be created on tables
    26  # trigger1-1.13: Ensure that AFTER triggers cannot be created on views
    27  # trigger1-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||!compound {
    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: 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: 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: 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 trigger1-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 trigger1-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 trigger1-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 trigger1-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 trigger1-3.6.1 {
   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), (NEW.b*100, NEW.a*100);
   298        END;
   299        INSERT INTO t1 VALUES(1,2);
   300        SELECT * FROM t2;
   301      }
   302    } {0 {1 2 200 100}}
   303    do_test trigger1-3.6.2 {
   304      catchsql {
   305        DROP TRIGGER r1;
   306        DELETE FROM t1;
   307        DELETE FROM t2;
   308        CREATE TEMP TRIGGER r1 AFTER INSERT ON t1 BEGIN
   309          INSERT INTO t2 VALUES(NEW.a,NEW.b);
   310        END;
   311        INSERT INTO t1 VALUES(1,2);
   312        SELECT * FROM t2;
   313      }
   314    } {0 {1 2}}
   315    do_test trigger1-3.7 {
   316      execsql {
   317        DROP TABLE t2;
   318        CREATE TABLE t2(x,y);
   319        SELECT * FROM t2;
   320      }
   321    } {}
   322  
   323    # There are two versions of trigger1-3.8 and trigger1-3.9. One that uses
   324    # compound SELECT statements, and another that does not.
   325    ifcapable compound {
   326    do_test trigger1-3.8 {
   327      execsql {
   328        INSERT INTO t1 VALUES(3,4);
   329        SELECT * FROM t1 UNION ALL SELECT * FROM t2;
   330      }
   331    } {1 2 3 4 3 4}
   332    do_test trigger1-3.9 {
   333      db close
   334      sqlite3 db test.db
   335      execsql {
   336        INSERT INTO t1 VALUES(5,6);
   337        SELECT * FROM t1 UNION ALL SELECT * FROM t2;
   338      }
   339    } {1 2 3 4 5 6 3 4}
   340    } ;# ifcapable compound
   341    ifcapable !compound {
   342    do_test trigger1-3.8 {
   343      execsql {
   344        INSERT INTO t1 VALUES(3,4);
   345        SELECT * FROM t1; 
   346        SELECT * FROM t2;
   347      }
   348    } {1 2 3 4 3 4}
   349    do_test trigger1-3.9 {
   350      db close
   351      sqlite3 db test.db
   352      execsql {
   353        INSERT INTO t1 VALUES(5,6);
   354        SELECT * FROM t1;
   355        SELECT * FROM t2;
   356      }
   357    } {1 2 3 4 5 6 3 4}
   358    } ;# ifcapable !compound
   359  
   360    do_test trigger1-4.1 {
   361      execsql {
   362        CREATE TEMP TRIGGER r1 BEFORE INSERT ON t1 BEGIN
   363          INSERT INTO t2 VALUES(NEW.a,NEW.b);
   364        END;
   365        INSERT INTO t1 VALUES(7,8);
   366        SELECT * FROM t2;
   367      }
   368    } {3 4 7 8}
   369    do_test trigger1-4.2 {
   370      sqlite3 db2 test.db
   371      execsql {
   372        INSERT INTO t1 VALUES(9,10);
   373      } db2;
   374      db2 close
   375      execsql {
   376        SELECT * FROM t2;
   377      }
   378    } {3 4 7 8}
   379    do_test trigger1-4.3 {
   380      execsql {
   381        DROP TABLE t1;
   382        SELECT * FROM t2;
   383      };
   384    } {3 4 7 8}
   385    do_test trigger1-4.4 {
   386      db close
   387      sqlite3 db test.db
   388      execsql {
   389        SELECT * FROM t2;
   390      };
   391    } {3 4 7 8}
   392  } else {
   393    execsql {
   394      CREATE TABLE t2(x,y);
   395      DROP TABLE t1;
   396      INSERT INTO t2 VALUES(3, 4);
   397      INSERT INTO t2 VALUES(7, 8);
   398    }
   399  }
   400  
   401  
   402  integrity_check trigger1-5.1
   403  
   404  # Create a trigger with the same name as a table.  Make sure the
   405  # trigger works.  Then drop the trigger.  Make sure the table is
   406  # still there.
   407  #
   408  set view_v1 {}
   409  ifcapable view {
   410    set view_v1 {view v1}
   411  }
   412  do_test trigger1-6.1 {
   413    execsql {SELECT type, name FROM sqlite_master}
   414  } [concat $view_v1 {table t2}]
   415  do_test trigger1-6.2 {
   416    execsql {
   417      CREATE TRIGGER t2 BEFORE DELETE ON t2 BEGIN
   418        SELECT RAISE(ABORT,'deletes are not permitted');
   419      END;
   420      SELECT type, name FROM sqlite_master;
   421    }
   422  } [concat $view_v1 {table t2 trigger t2}]
   423  do_test trigger1-6.3 {
   424    catchsql {DELETE FROM t2}
   425  } {1 {deletes are not permitted}}
   426  verify_ex_errcode trigger1-6.3b SQLITE_CONSTRAINT_TRIGGER
   427  do_test trigger1-6.4 {
   428    execsql {SELECT * FROM t2}
   429  } {3 4 7 8}
   430  do_test trigger1-6.5 {
   431    db close
   432    sqlite3 db test.db
   433    execsql {SELECT type, name FROM sqlite_master}
   434  } [concat $view_v1 {table t2 trigger t2}]
   435  do_test trigger1-6.6 {
   436    execsql {
   437      DROP TRIGGER t2;
   438      SELECT type, name FROM sqlite_master;
   439    }
   440  } [concat $view_v1 {table t2}]
   441  do_test trigger1-6.7 {
   442    execsql {SELECT * FROM t2}
   443  } {3 4 7 8}
   444  do_test trigger1-6.8 {
   445    db close
   446    sqlite3 db test.db
   447    execsql {SELECT * FROM t2}
   448  } {3 4 7 8}
   449  
   450  integrity_check trigger1-7.1
   451  
   452  # Check to make sure the name of a trigger can be quoted so that keywords
   453  # can be used as trigger names.  Ticket #468
   454  #
   455  do_test trigger1-8.1 {
   456    execsql {
   457      CREATE TRIGGER 'trigger' AFTER INSERT ON t2 BEGIN SELECT 1; END;
   458      SELECT name FROM sqlite_master WHERE type='trigger';
   459    }
   460  } {trigger}
   461  do_test trigger1-8.2 {
   462    execsql {
   463      DROP TRIGGER 'trigger';
   464      SELECT name FROM sqlite_master WHERE type='trigger';
   465    }
   466  } {}
   467  do_test trigger1-8.3 {
   468    execsql {
   469      CREATE TRIGGER "trigger" AFTER INSERT ON t2 BEGIN SELECT 1; END;
   470      SELECT name FROM sqlite_master WHERE type='trigger';
   471    }
   472  } {trigger}
   473  do_test trigger1-8.4 {
   474    execsql {
   475      DROP TRIGGER "trigger";
   476      SELECT name FROM sqlite_master WHERE type='trigger';
   477    }
   478  } {}
   479  do_test trigger1-8.5 {
   480    execsql {
   481      CREATE TRIGGER [trigger] AFTER INSERT ON t2 BEGIN SELECT 1; END;
   482      SELECT name FROM sqlite_master WHERE type='trigger';
   483    }
   484  } {trigger}
   485  do_test trigger1-8.6 {
   486    execsql {
   487      DROP TRIGGER [trigger];
   488      SELECT name FROM sqlite_master WHERE type='trigger';
   489    }
   490  } {}
   491  
   492  ifcapable conflict {
   493    # Make sure REPLACE works inside of triggers.
   494    #
   495    # There are two versions of trigger1-9.1 and trigger1-9.2. One that uses
   496    # compound SELECT statements, and another that does not.
   497    ifcapable compound {
   498      do_test trigger1-9.1 {
   499        execsql {
   500          CREATE TABLE t3(a,b);
   501          CREATE TABLE t4(x UNIQUE, b);
   502          CREATE TRIGGER r34 AFTER INSERT ON t3 BEGIN
   503            REPLACE INTO t4 VALUES(new.a,new.b);
   504          END;
   505          INSERT INTO t3 VALUES(1,2);
   506          SELECT * FROM t3 UNION ALL SELECT 99, 99 UNION ALL SELECT * FROM t4;
   507        }
   508      } {1 2 99 99 1 2}
   509      do_test trigger1-9.2 {
   510        execsql {
   511          INSERT INTO t3 VALUES(1,3);
   512          SELECT * FROM t3 UNION ALL SELECT 99, 99 UNION ALL SELECT * FROM t4;
   513        }
   514      } {1 2 1 3 99 99 1 3}
   515    } else {
   516      do_test trigger1-9.1 {
   517        execsql {
   518          CREATE TABLE t3(a,b);
   519          CREATE TABLE t4(x UNIQUE, b);
   520          CREATE TRIGGER r34 AFTER INSERT ON t3 BEGIN
   521            REPLACE INTO t4 VALUES(new.a,new.b);
   522          END;
   523          INSERT INTO t3 VALUES(1,2);
   524          SELECT * FROM t3; SELECT 99, 99; SELECT * FROM t4;
   525        }
   526      } {1 2 99 99 1 2}
   527      do_test trigger1-9.2 {
   528        execsql {
   529          INSERT INTO t3 VALUES(1,3);
   530          SELECT * FROM t3; SELECT 99, 99; SELECT * FROM t4;
   531        }
   532      } {1 2 1 3 99 99 1 3}
   533    }
   534    execsql {
   535      DROP TABLE t3;
   536      DROP TABLE t4;
   537    }
   538  }
   539  
   540  
   541  # Ticket #764. At one stage TEMP triggers would fail to re-install when the
   542  # schema was reloaded. The following tests ensure that TEMP triggers are
   543  # correctly re-installed.
   544  #
   545  # Also verify that references within trigger programs are resolved at
   546  # statement compile time, not trigger installation time. This means, for
   547  # example, that you can drop and re-create tables referenced by triggers. 
   548  ifcapable tempdb&&attach {
   549    do_test trigger1-10.0 {
   550      forcedelete test2.db
   551      forcedelete test2.db-journal
   552      execsql {
   553        ATTACH 'test2.db' AS aux;
   554      }
   555    } {}
   556    do_test trigger1-10.1 {
   557      execsql {
   558        CREATE TABLE main.t4(a, b, c);
   559        CREATE TABLE temp.t4(a, b, c);
   560        CREATE TABLE aux.t4(a, b, c);
   561        CREATE TABLE insert_log(db, a, b, c);
   562      }
   563    } {}
   564    do_test trigger1-10.2 {
   565      execsql {
   566        CREATE TEMP TRIGGER trig1 AFTER INSERT ON main.t4 BEGIN 
   567          INSERT INTO insert_log VALUES('main', new.a, new.b, new.c);
   568        END;
   569        CREATE TEMP TRIGGER trig2 AFTER INSERT ON temp.t4 BEGIN 
   570          INSERT INTO insert_log VALUES('temp', new.a, new.b, new.c);
   571        END;
   572        CREATE TEMP TRIGGER trig3 AFTER INSERT ON aux.t4 BEGIN 
   573          INSERT INTO insert_log VALUES('aux', new.a, new.b, new.c);
   574        END;
   575      }
   576    } {}
   577    do_test trigger1-10.3 {
   578      execsql {
   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      }
   583    } {}
   584    do_test trigger1-10.4 {
   585      execsql {
   586        SELECT * FROM insert_log;
   587      }
   588    } {main 1 2 3 temp 4 5 6 aux 7 8 9}
   589    do_test trigger1-10.5 {
   590      execsql {
   591        BEGIN;
   592        INSERT INTO main.t4 VALUES(1, 2, 3);
   593        INSERT INTO temp.t4 VALUES(4, 5, 6);
   594        INSERT INTO aux.t4  VALUES(7, 8, 9);
   595        ROLLBACK;
   596      }
   597    } {}
   598    do_test trigger1-10.6 {
   599      execsql {
   600        SELECT * FROM insert_log;
   601      }
   602    } {main 1 2 3 temp 4 5 6 aux 7 8 9}
   603    do_test trigger1-10.7 {
   604      execsql {
   605        DELETE FROM insert_log;
   606        INSERT INTO main.t4 VALUES(11, 12, 13);
   607        INSERT INTO temp.t4 VALUES(14, 15, 16);
   608        INSERT INTO aux.t4  VALUES(17, 18, 19);
   609      }
   610    } {}
   611    do_test trigger1-10.8 {
   612      execsql {
   613        SELECT * FROM insert_log;
   614      }
   615    } {main 11 12 13 temp 14 15 16 aux 17 18 19}
   616    do_test trigger1-10.9 {
   617    # Drop and re-create the insert_log table in a different database. Note
   618    # that we can change the column names because the trigger programs don't
   619    # use them explicitly.
   620      execsql {
   621        DROP TABLE insert_log;
   622        CREATE TABLE aux.insert_log(db, d, e, f);
   623      }
   624    } {}
   625    do_test trigger1-10.10 {
   626      execsql {
   627        INSERT INTO main.t4 VALUES(21, 22, 23);
   628        INSERT INTO temp.t4 VALUES(24, 25, 26);
   629        INSERT INTO aux.t4  VALUES(27, 28, 29);
   630      }
   631    } {}
   632    do_test trigger1-10.11 {
   633      execsql {
   634        SELECT * FROM insert_log;
   635      }
   636    } {main 21 22 23 temp 24 25 26 aux 27 28 29}
   637  }
   638  
   639  do_test trigger1-11.1 {
   640    catchsql {SELECT raise(abort,'message');}
   641  } {1 {RAISE() may only be used within a trigger-program}}
   642  
   643  do_test trigger1-15.1 {
   644    execsql {
   645      CREATE TABLE tA(a INTEGER PRIMARY KEY, b, c);
   646      CREATE TRIGGER tA_trigger BEFORE UPDATE ON "tA" BEGIN SELECT 1; END;
   647      INSERT INTO tA VALUES(1, 2, 3);
   648    }
   649    catchsql { UPDATE tA SET a = 'abc' }
   650  } {1 {datatype mismatch}}
   651  do_test trigger1-15.2 {
   652    catchsql { INSERT INTO tA VALUES('abc', 2, 3) }
   653  } {1 {datatype mismatch}}
   654  
   655  # Ticket #3947:  Do not allow qualified table names on INSERT, UPDATE, and
   656  # DELETE statements within triggers.  Actually, this has never been allowed
   657  # by the grammar.  But the error message is confusing: one simply gets a
   658  # "syntax error".  That has now been changed to give a full error message.
   659  #
   660  do_test trigger1-16.1 {
   661    db eval {
   662      CREATE TABLE t16(a,b,c);
   663      CREATE INDEX t16a ON t16(a);
   664      CREATE INDEX t16b ON t16(b);
   665    }
   666    catchsql {
   667      CREATE TRIGGER main.t16err1 AFTER INSERT ON tA BEGIN
   668        INSERT INTO main.t16 VALUES(1,2,3);
   669      END;
   670    }
   671  } {1 {qualified table names are not allowed on INSERT, UPDATE, and DELETE statements within triggers}}
   672  do_test trigger1-16.2 {
   673    catchsql {
   674      CREATE TRIGGER main.t16err2 AFTER INSERT ON tA BEGIN
   675        UPDATE main.t16 SET rowid=rowid+1;
   676      END;
   677    }
   678  } {1 {qualified table names are not allowed on INSERT, UPDATE, and DELETE statements within triggers}}
   679  do_test trigger1-16.3 {
   680    catchsql {
   681      CREATE TRIGGER main.t16err3 AFTER INSERT ON tA BEGIN
   682        DELETE FROM main.t16;
   683      END;
   684    }
   685  } {1 {qualified table names are not allowed on INSERT, UPDATE, and DELETE statements within triggers}}
   686  do_test trigger1-16.4 {
   687    catchsql {
   688      CREATE TRIGGER main.t16err4 AFTER INSERT ON tA BEGIN
   689        UPDATE t16 NOT INDEXED SET rowid=rowid+1;
   690      END;
   691    }
   692  } {1 {the NOT INDEXED clause is not allowed on UPDATE or DELETE statements within triggers}}
   693  do_test trigger1-16.5 {
   694    catchsql {
   695      CREATE TRIGGER main.t16err5 AFTER INSERT ON tA BEGIN
   696        UPDATE t16 INDEXED BY t16a SET rowid=rowid+1 WHERE a=1;
   697      END;
   698    }
   699  } {1 {the INDEXED BY clause is not allowed on UPDATE or DELETE statements within triggers}}
   700  do_test trigger1-16.6 {
   701    catchsql {
   702      CREATE TRIGGER main.t16err6 AFTER INSERT ON tA BEGIN
   703        DELETE FROM t16 NOT INDEXED WHERE a=123;
   704      END;
   705    }
   706  } {1 {the NOT INDEXED clause is not allowed on UPDATE or DELETE statements within triggers}}
   707  do_test trigger1-16.7 {
   708    catchsql {
   709      CREATE TRIGGER main.t16err7 AFTER INSERT ON tA BEGIN
   710        DELETE FROM t16 INDEXED BY t16a WHERE a=123;
   711      END;
   712    }
   713  } {1 {the INDEXED BY clause is not allowed on UPDATE or DELETE statements within triggers}}
   714  
   715  #-------------------------------------------------------------------------
   716  # Test that bug [34cd55d68e0e6e7c] has been fixed.
   717  #
   718  do_execsql_test trigger1-17.0 {
   719    CREATE TABLE t17a(ii INT);
   720    CREATE TABLE t17b(tt TEXT PRIMARY KEY, ss);
   721    CREATE TRIGGER t17a_ai AFTER INSERT ON t17a BEGIN
   722      INSERT INTO t17b(tt) VALUES(new.ii);
   723    END;
   724    CREATE TRIGGER t17b_ai AFTER INSERT ON t17b BEGIN
   725      UPDATE t17b SET ss = 4;
   726    END;
   727    INSERT INTO t17a(ii) VALUES('1');
   728    PRAGMA integrity_check;
   729  } {ok}
   730  
   731  # 2018-04-26
   732  # When a BEFORE UPDATE trigger changes a column value in a row being
   733  # updated, and that column value is used by the UPDATE to change other
   734  # column, the value used to compute the update is from before the trigger.
   735  # In the example that follows, the value of "b" in "c=b" is 2 (the value
   736  # prior to running the BEFORE UPDATE trigger) not 1000.
   737  #
   738  do_execsql_test trigger1-18.0 {
   739    CREATE TABLE t18(a PRIMARY KEY,b,c);
   740    INSERT INTO t18(a,b,c) VALUES(1,2,3);
   741    CREATE TRIGGER t18r1 BEFORE UPDATE ON t18 BEGIN
   742      UPDATE t18 SET b=1000 WHERE a=old.a;
   743    END;
   744    UPDATE t18 SET c=b WHERE a=1;
   745    SELECT * FROM t18;
   746  } {1 1000 2}  ;# Not: 1 1000 1000 
   747  do_execsql_test trigger1-18.1 {
   748    DELETE FROM t18;
   749    INSERT INTO t18(a,b,c) VALUES(1,2,3);
   750    UPDATE t18 SET c=b, b=b+1 WHERE a=1;
   751    SELECT * FROM t18;
   752  } {1 3 2}     ;# Not: 1 1001 1000
   753  
   754  # 2018-04-26 ticket [https://www.sqlite.org/src/tktview/d85fffd6ffe856092e]
   755  # VDBE Program uses an expired value.
   756  #
   757  do_execsql_test trigger1-19.0 {
   758    CREATE TABLE t19(a INT PRIMARY KEY, b, c)WITHOUT ROWID;
   759    INSERT INTO t19(a,b,c) VALUES(1,2,3);
   760    CREATE TRIGGER t19r3 BEFORE UPDATE ON t19 BEGIN SELECT new.b; END;
   761    UPDATE t19 SET c=b WHERE a=1;
   762    SELECT * FROM t19;
   763  } {1 2 2}
   764  do_execsql_test trigger1-19.1 {
   765    DELETE FROM t19;
   766    INSERT INTO t19(a,b,c) VALUES(1,2,3);
   767    UPDATE t19 SET c=CASE WHEN b=2 THEN b ELSE b+99 END WHERE a=1;
   768    SELECT * FROM t19;
   769  } {1 2 2}
   770  
   771  # 2019-08-26 Chromium sqlite3_fts3_lpm_fuzzer find.
   772  #
   773  db close
   774  sqlite3 db :memory:
   775  do_execsql_test trigger1-20.1 {
   776    CREATE TABLE t20_1(x);
   777    ATTACH ':memory:' AS aux;
   778    CREATE TABLE aux.t20_2(y);
   779    CREATE TABLE aux.t20_3(z);
   780    CREATE TEMP TRIGGER r20_3 AFTER INSERT ON t20_2 BEGIN UPDATE t20_3 SET z=z+1; END;
   781    DETACH aux;
   782    DROP TRIGGER r20_3;
   783  } {}
   784  
   785  # 2019-10-24 ticket 50c09fc2cf0d91ce
   786  #
   787  db close
   788  sqlite3 db :memory:
   789  do_execsql_test trigger1-21.1 {
   790    PRAGMA recursive_triggers = true;
   791    CREATE TABLE t0(a, b, c UNIQUE);
   792    CREATE UNIQUE INDEX i0 ON t0(b) WHERE a;
   793    CREATE TRIGGER tr0 AFTER DELETE ON t0 BEGIN
   794      DELETE FROM t0;
   795    END;
   796    INSERT INTO t0(a,b,c) VALUES(0,0,9),(1,1,1);
   797    REPLACE INTO t0(a,b,c) VALUES(2,0,9);
   798    SELECT * FROM t0;
   799  } {2 0 9}
   800  
   801  # 2020-01-04 From Yongheng
   802  # The test case below caused problems for the register validity
   803  # tracking logic.  There was no bug in the release build.  The
   804  # only problem was a false-positive in the register validity
   805  # tracking.
   806  #
   807  reset_db
   808  do_execsql_test trigger1-22.10 {
   809    CREATE TABLE t1(
   810      a INTEGER PRIMARY KEY,
   811      b DOUBLE
   812    );
   813    CREATE TRIGGER x AFTER UPDATE ON t1 BEGIN
   814     SELECT sum(b)OVER(ORDER BY (SELECT b FROM t1 AS x 
   815                                 WHERE b IN (t1.a,127,t1.b)
   816                                 GROUP BY b))
   817       FROM t1
   818       GROUP BY a;
   819    END;
   820    CREATE TEMP TRIGGER x BEFORE INSERT ON t1 BEGIN
   821      UPDATE t1
   822         SET b=randomblob(10)
   823       WHERE b >= 'E'
   824         AND a < (SELECT a FROM t1 WHERE a<22 GROUP BY b);
   825    END;
   826    INSERT INTO t1(b) VALUES('Y'),('X'),('Z');
   827    SELECT a, CASE WHEN typeof(b)='text' THEN quote(b) ELSE '<blob>' END, '|' FROM t1;
   828  } {1 <blob> | 2 'X' | 3 'Z' |}
   829  
   830  # 2022-03-06 https://sqlite.org/forum/forumpost/2024e94071
   831  # Harmless assertion fault following a syntax error.
   832  #
   833  reset_db
   834  do_catchsql_test trigger1-23.1 {
   835    CREATE TABLE t1(a INT);
   836    CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
   837      INSERT INTO t1 SELECT e_master LIMIT 1,#1;
   838    END;
   839  } {1 {near "#1": syntax error}}
   840  
   841  finish_test