-C Fix\sthe\sspelling\sof\ssqliteRegisterBuiltinFunctions().\s(CVS\s613)
-D 2002-06-09T10:14:19
+C Add\sRAISE()\sfunction,\swhich\sallows\smore\sadvanced\sflow-control\sin\strigger\sprograms\s(ticket\s#55)\s(CVS\s614)
+D 2002-06-11T02:25:41
F Makefile.in 6291a33b87d2a395aafd7646ee1ed562c6f2c28c
F Makefile.template 4e11752e0b5c7a043ca50af4296ec562857ba495
F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0
F src/btree.c 8b86be8f234c1c5dab3186f69cee2544ec9d7257
F src/btree.h 8abeabfe6e0b1a990b64fa457592a6482f6674f3
F src/build.c 36e42718a7a94f554ea39508993378482f5335c7
-F src/delete.c a2b098cbbf518e6b641847e26de85827793bc523
+F src/delete.c 15789fc723a6776309945b13a79f9a0e78275fc0
F src/encode.c 346b12b46148506c32038524b95c4631ab46d760
-F src/expr.c cd2e3311c84533fad19336d3bbfdc3be3400d377
+F src/expr.c 2dcfcd0b032206954a307d7e2731bf070d58835b
F src/func.c b8d0fd3011f53ea0e46b6bab857612eb36b5d1ea
F src/hash.c 6a6236b89c8c060c65dabd300a1c8ce7c10edb72
F src/hash.h cd0433998bc1a3759d244e1637fe5a3c13b53bf8
-F src/insert.c 4b0bd94296fea46ef1b2ed8bfd05e12a38ce2c90
+F src/insert.c 3a90bb98cd246f88cc26c44f24d5b47760bc5cba
F src/main.c 3a4e53122c0b0d0a5719b73fa9ec642761291ba1
F src/md5.c 0ae1f3e2cac92d06fc6246d1b4b8f61a2fe66d3b
F src/os.c 9cc40c5384baba4a85e160e67807645ca98ba3cc
F src/os.h 4a361fccfbc4e7609b3e1557f604f94c1e96ad10
F src/pager.c 1e41053c949cea1f09d8dafada5fe8f90785e650
F src/pager.h 6fddfddd3b73aa8abc081b973886320e3c614f0e
-F src/parse.y 3b4989cb81ab2f441ef6c7cbb203829838eb299e
+F src/parse.y 42920305d49666419358b469e4ec522ac867a39f
F src/printf.c d8032ee18b860c812eeff596c9bebfdacb7930fd
F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe
F src/select.c 1d5cb1ae0bb3376bedfde7ae22e6e927e4d0b5e2
F src/shell.c 1d22fe870ee852cfb975fd000dbe3973713d0a15
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
F src/sqlite.h.in 0038faa6d642de06b91143ee65a131bd831d020b
-F src/sqliteInt.h 470056bd21902e15f5ac459f09f64a717657332b
+F src/sqliteInt.h 93e0ad1b37658391de6f211f65e7924a2064aa4d
F src/table.c eed2098c9b577aa17f8abe89313a9c4413f57d63
F src/tclsqlite.c 9300c9606a38bc0c75d6c0bc8a6197ab979353d1
F src/test1.c 09d95048b66ce6dcd2bae90f443589043d7d631e
F src/test2.c 669cc22781c6461a273416ec1a7414d25c081730
F src/test3.c 4e52fff8b01f08bd202f7633feda5639b7ba2b5e
F src/threadtest.c 81f0598e0f031c1bd506af337fdc1b7e8dff263f
-F src/tokenize.c 35c63867d03fcaf81fe520f8d8206981d0c7270e
-F src/trigger.c d02f8e3510c7c2ad948a0e8c3bb0cca8adaf80c5
-F src/update.c f68375173bf5338cae3e97012708e10f206aedd9
+F src/tokenize.c 890ca022d45f1798dadc300a798951597428853e
+F src/trigger.c 21342af6ac031fece39c8fc6eabd1739ca5327c1
+F src/update.c 05431e23a9c83502fd7911e771c8366fc2b90b4c
F src/util.c 7cf46b5612f5d12601c697374b9c6b38b2332ce8
-F src/vdbe.c b315d7ad5086164bb8d8aee8bc9edeafcb68b8ea
+F src/vdbe.c 836f2c4f823c94c3c3454125d9ba9283e8b22dda
F src/vdbe.h 1742d6f8b40f40879475b4c41cf4f9980ceb0e21
F src/where.c b7c653054d4941d17f3112776ebcaf00d9613cb7
F test/all.test e4d3821eeba751829b419cd47814bd20af4286d1
F test/trans.test ae0b9a82d5d34122c3a3108781eb8d078091ccee
F test/trigger1.test bb63749fa8a395a60541100607d86381604b7194
F test/trigger2.test c12759a0d7ba6488d9d24c96a1352ddee995c1ab
+F test/trigger3.test b4aca721ba92956c7fa16bb0158254f3c1b73efa
F test/unique.test 572aa791327c1e8d797932263e9d67f176cfdb44
F test/update.test a0aa0bf83e6fad8407d0e4ad25ebb09b513f5bf4
F test/vacuum.test 059871b312eb910bbe49dafde1d01490cc2c6bbe
F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279
F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
-P 2a710e18176c486525f0abb06644a511a2cd1d7a
-R e2c1bfb01c44cc3c89a1b280cee79956
-U drh
-Z bd401167cac426bd14d74027f33bb932
+P 74d297d97e66452acc5c21048ee8ddf2a90c846f
+R 5c5b230772c3601ecd48523835df13e1
+U danielk1977
+Z a3a6e123a401efc55c5086c35a87d954
-74d297d97e66452acc5c21048ee8ddf2a90c846f
\ No newline at end of file
+d4a2fb10067203a0d49317db747759872e62927e
\ No newline at end of file
** This file contains C code routines that are called by the parser
** to handle DELETE FROM statements.
**
-** $Id: delete.c,v 1.36 2002/05/24 02:04:33 drh Exp $
+** $Id: delete.c,v 1.37 2002/06/11 02:25:41 danielk1977 Exp $
*/
#include "sqliteInt.h"
sqliteVdbeAddOp(v, OP_Rewind, oldIdx, 0);
sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1,
- oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default);
+ oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
+ addr);
}
/* Open cursors for the table we are deleting from and all its
}
sqliteVdbeAddOp(v, OP_Close, base, 0);
sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1,
- oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default);
+ oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
+ addr);
}
/* End of the delete loop */
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
-** $Id: expr.c,v 1.70 2002/06/09 01:16:01 drh Exp $
+** $Id: expr.c,v 1.71 2002/06/11 02:25:41 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
if( pNew==0 ) return 0;
pNew->nSrc = p->nSrc;
pNew->a = sqliteMalloc( p->nSrc*sizeof(p->a[0]) );
- if( pNew->a==0 ) return 0;
+ if( pNew->a==0 && p->nSrc != 0 ) return 0;
for(i=0; i<p->nSrc; i++){
pNew->a[i].zName = sqliteStrDup(p->a[i].zName);
pNew->a[i].zAlias = sqliteStrDup(p->a[i].zAlias);
sqliteVdbeAddOp(v, OP_String, 0, 0);
}
sqliteVdbeResolveLabel(v, expr_end_label);
+ break;
+ }
+ case TK_RAISE: {
+ if( !pParse->trigStack ){
+ sqliteSetNString(&pParse->zErrMsg,
+ "RAISE() may only be used within a trigger-program", -1, 0);
+ pParse->nErr++;
+ return;
+ }
+ if( pExpr->iColumn == OE_Rollback ||
+ pExpr->iColumn == OE_Abort ||
+ pExpr->iColumn == OE_Fail ){
+ char * msg = sqliteStrNDup(pExpr->token.z, pExpr->token.n);
+ sqliteVdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn);
+ sqliteDequote(msg);
+ sqliteVdbeChangeP3(v, -1, msg, 0);
+ sqliteFree(msg);
+ } else {
+ assert( pExpr->iColumn == OE_Ignore );
+ sqliteVdbeAddOp(v, OP_Goto, 0, pParse->trigStack->ignoreJump);
+ sqliteVdbeChangeP3(v, -1, "(IGNORE jump)", -1);
+ }
}
break;
}
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
-** $Id: insert.c,v 1.60 2002/06/06 18:54:40 drh Exp $
+** $Id: insert.c,v 1.61 2002/06/11 02:25:42 danielk1977 Exp $
*/
#include "sqliteInt.h"
iCont = sqliteVdbeCurrentAddr(v);
}
+ endOfLoop = sqliteVdbeMakeLabel(v);
if( row_triggers_exist ){
/* build the new.* reference row */
/* Fire BEFORE triggers */
if( sqliteCodeRowTrigger(pParse, TK_INSERT, 0, TK_BEFORE, pTab, newIdx, -1,
- onError) ){
+ onError, endOfLoop) ){
goto insert_cleanup;
}
/* Generate code to check constraints and generate index keys and
** do the insertion.
*/
- endOfLoop = sqliteVdbeMakeLabel(v);
sqliteGenerateConstraintChecks(pParse, pTab, base, 0,0,0,onError,endOfLoop);
sqliteCompleteInsertion(pParse, pTab, base, 0,0,0);
/* Code AFTER triggers */
if( sqliteCodeRowTrigger(pParse, TK_INSERT, 0, TK_AFTER, pTab, newIdx, -1,
- onError) ){
+ onError, endOfLoop) ){
goto insert_cleanup;
}
}
** the parser. Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
-** @(#) $Id: parse.y,v 1.72 2002/06/06 19:04:16 drh Exp $
+** @(#) $Id: parse.y,v 1.73 2002/06/11 02:25:42 danielk1977 Exp $
*/
%token_prefix TK_
%token_type {Token}
ABORT AFTER ASC BEFORE BEGIN CASCADE CLUSTER CONFLICT
COPY DEFERRED DELIMITERS DESC EACH END EXPLAIN FAIL FOR
FULL IGNORE IMMEDIATE INITIALLY INSTEAD MATCH JOIN KEY
- OF OFFSET PARTIAL PRAGMA REPLACE RESTRICT ROW STATEMENT
+ OF OFFSET PARTIAL PRAGMA RAISE REPLACE RESTRICT ROW STATEMENT
TEMP TRIGGER VACUUM VIEW.
// And "ids" is an identifer-or-string.
// SELECT
trigger_cmd(A) ::= select(X). {A = sqliteTriggerSelectStep(X); }
+// The special RAISE expression that may occur in trigger programs
+expr(A) ::= RAISE(X) LP IGNORE RP(Y). { A = sqliteExpr(TK_RAISE, 0, 0, 0);
+ A->iColumn = OE_Ignore; sqliteExprSpan(A, &X, &Y);}
+expr(A) ::= RAISE(X) LP ROLLBACK COMMA ids(Z) RP(Y).
+{ A = sqliteExpr(TK_RAISE, 0, 0, &Z);
+ A->iColumn = OE_Rollback; sqliteExprSpan(A, &X, &Y);}
+expr(A) ::= RAISE(X) LP ABORT COMMA ids(Z) RP(Y).
+{ A = sqliteExpr(TK_RAISE, 0, 0, &Z);
+ A->iColumn = OE_Abort; sqliteExprSpan(A, &X, &Y);}
+expr(A) ::= RAISE(X) LP FAIL COMMA ids(Z) RP(Y).
+{ A = sqliteExpr(TK_RAISE, 0, 0, &Z);
+ A->iColumn = OE_Fail; sqliteExprSpan(A, &X, &Y);}
+
//////////////////////// DROP TRIGGER statement //////////////////////////////
cmd ::= DROP TRIGGER ids(X). {
sqliteDropTrigger(pParse,&X,0);
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.122 2002/06/09 10:14:19 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.123 2002/06/11 02:25:42 danielk1977 Exp $
*/
#include "sqlite.h"
#include "hash.h"
int newIdx; /* Index of vdbe cursor to "new" temp table */
int oldIdx; /* Index of vdbe cursor to "old" temp table */
int orconf; /* Current orconf policy */
+ int ignoreJump; /* where to jump to for a RAISE(IGNORE) */
Trigger *pTrigger;
TriggerStack *pNext;
int, Expr*, TriggerStep*, char const*,int);
void sqliteDropTrigger(Parse*, Token*, int);
int sqliteTriggersExist(Parse* , Trigger* , int , int , int, ExprList*);
-int sqliteCodeRowTrigger(Parse*, int, ExprList*, int, Table *, int, int, int);
+int sqliteCodeRowTrigger(Parse*, int, ExprList*, int, Table *, int, int,
+ int, int);
void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*);
TriggerStep *sqliteTriggerSelectStep(Select*);
TriggerStep *sqliteTriggerInsertStep(Token*, IdList*, ExprList*, Select*, int);
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
-** $Id: tokenize.c,v 1.44 2002/06/02 18:19:00 drh Exp $
+** $Id: tokenize.c,v 1.45 2002/06/11 02:25:42 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
{ "PARTIAL", 0, TK_PARTIAL, 0 },
{ "PRAGMA", 0, TK_PRAGMA, 0 },
{ "PRIMARY", 0, TK_PRIMARY, 0 },
+ { "RAISE", 0, TK_RAISE, 0 },
{ "REFERENCES", 0, TK_REFERENCES, 0 },
{ "REPLACE", 0, TK_REPLACE, 0 },
{ "RESTRICT", 0, TK_RESTRICT, 0 },
pParse->trigStack->orconf = orconf;
switch( pTriggerStep->op ){
case TK_SELECT: {
- sqliteSelect(pParse, pTriggerStep->pSelect, SRT_Discard, 0, 0, 0, 0);
+ Select * ss = sqliteSelectDup(pTriggerStep->pSelect);
+ assert(ss);
+ assert(ss->pSrc);
+ sqliteSelect(pParse, ss, SRT_Discard, 0, 0, 0, 0);
+ sqliteSelectDelete(ss);
break;
}
case TK_UPDATE: {
sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
sqliteUpdate(pParse, &pTriggerStep->target,
- sqliteExprListDup(pTriggerStep->pExprList),
- sqliteExprDup(pTriggerStep->pWhere), orconf);
+ sqliteExprListDup(pTriggerStep->pExprList),
+ sqliteExprDup(pTriggerStep->pWhere), orconf);
sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
break;
}
Table *pTab, /* The table to code triggers from */
int newIdx, /* The indice of the "new" row to access */
int oldIdx, /* The indice of the "old" row to access */
- int orconf /* ON CONFLICT policy */
+ int orconf, /* ON CONFLICT policy */
+ int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */
){
Trigger * pTrigger;
TriggerStack * pTriggerStack;
pTriggerStack->oldIdx = oldIdx;
pTriggerStack->pTab = pTab;
pTriggerStack->pNext = pParse->trigStack;
+ pTriggerStack->ignoreJump = ignoreJump;
pParse->trigStack = pTriggerStack;
/* code the WHEN clause */
sqliteVdbeAddOp(v, OP_Rewind, newIdx, 0);
sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE,
- pTab, newIdx, oldIdx, orconf);
+ pTab, newIdx, oldIdx, orconf, endOfLoop);
sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER,
- pTab, newIdx, oldIdx, orconf);
+ pTab, newIdx, oldIdx, orconf, endOfLoop);
}else{
sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, oldIdx,
- orconf);
+ orconf, endOfLoop);
sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, oldIdx,
- orconf);
+ orconf, endOfLoop);
}
sqliteVdbeAddOp(v, OP_Next, oldIdx, startOfLoop);
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
-** $Id: update.c,v 1.43 2002/05/24 02:04:34 drh Exp $
+** $Id: update.c,v 1.44 2002/06/11 02:25:42 danielk1977 Exp $
*/
#include "sqliteInt.h"
sqliteVdbeAddOp(v, OP_Rewind, newIdx, 0);
if( sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE, pTab,
- newIdx, oldIdx, onError) ){
+ newIdx, oldIdx, onError, addr) ){
goto update_cleanup;
}
}
pParse->nTab = base;
if( sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER, pTab,
- newIdx, oldIdx, onError) ){
+ newIdx, oldIdx, onError, addr) ){
goto update_cleanup;
}
}
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
-** $Id: vdbe.c,v 1.154 2002/06/08 23:25:09 drh Exp $
+** $Id: vdbe.c,v 1.155 2002/06/11 02:25:42 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
if( pOp->p1!=SQLITE_OK ){
rc = pOp->p1;
errorAction = pOp->p2;
+ if( pOp->p3 ){
+ sqliteSetString(pzErrMsg, pOp->p3, 0);
+ goto cleanup;
+ }
goto abort_due_to_error;
}else{
pc = p->nOp-1;
--- /dev/null
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+# This file tests the RAISE() function.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Test that we can cause ROLLBACK, FAIL and ABORT correctly
+# catchsql { DROP TABLE tbl; }
+catchsql { CREATE TABLE tbl (a, b, c) }
+
+execsql {
+ CREATE TRIGGER before_tbl_insert BEFORE INSERT ON tbl BEGIN SELECT CASE
+ WHEN (new.a = 4) THEN RAISE(IGNORE) END;
+ END;
+
+ CREATE TRIGGER after_tbl_insert AFTER INSERT ON tbl BEGIN SELECT CASE
+ WHEN (new.a = 1) THEN RAISE(ABORT, 'Trigger abort')
+ WHEN (new.a = 2) THEN RAISE(FAIL, 'Trigger fail')
+ WHEN (new.a = 3) THEN RAISE(ROLLBACK, 'Trigger rollback') END;
+ END;
+}
+# ABORT
+do_test trig-raise-1.1 {
+ catchsql {
+ BEGIN;
+ INSERT INTO tbl VALUES (5, 5, 6);
+ INSERT INTO tbl VALUES (1, 5, 6);
+ }
+} {1 {Trigger abort}}
+
+do_test trig-raise-1.2 {
+ execsql {
+ SELECT * FROM tbl;
+ ROLLBACK;
+ }
+} {5 5 6}
+
+# FAIL
+do_test trig-raise-2.1 {
+ catchsql {
+ BEGIN;
+ INSERT INTO tbl VALUES (5, 5, 6);
+ INSERT INTO tbl VALUES (2, 5, 6);
+ }
+} {1 {Trigger fail}}
+do_test trig-raise-2.2 {
+ execsql {
+ SELECT * FROM tbl;
+ ROLLBACK;
+ }
+} {5 5 6 2 5 6}
+# ROLLBACK
+do_test trig-raise-3.1 {
+ catchsql {
+ BEGIN;
+ INSERT INTO tbl VALUES (5, 5, 6);
+ INSERT INTO tbl VALUES (3, 5, 6);
+ }
+} {1 {Trigger rollback}}
+do_test trig-raise-3.2 {
+ execsql {
+ SELECT * FROM tbl;
+ ROLLBACK;
+ }
+} {}
+# IGNORE
+do_test trig-raise-4.1 {
+ catchsql {
+ BEGIN;
+ INSERT INTO tbl VALUES (5, 5, 6);
+ INSERT INTO tbl VALUES (4, 5, 6);
+ }
+} {0 {}}
+do_test trig-raise-4.2 {
+ execsql {
+ SELECT * FROM tbl;
+ ROLLBACK;
+ }
+} {5 5 6}
+
+# Check that we can also do RAISE(IGNORE) for UPDATE and DELETE
+execsql {DROP TABLE tbl;}
+execsql {CREATE TABLE tbl (a, b, c);}
+execsql {INSERT INTO tbl VALUES(1, 2, 3);}
+execsql {INSERT INTO tbl VALUES(4, 5, 6);}
+execsql {
+ CREATE TRIGGER before_tbl_update BEFORE UPDATE ON tbl BEGIN
+ SELECT CASE WHEN (old.a = 1) THEN RAISE(IGNORE) END;
+ END;
+
+ CREATE TRIGGER before_tbl_delete BEFORE DELETE ON tbl BEGIN
+ SELECT CASE WHEN (old.a = 1) THEN RAISE(IGNORE) END;
+ END;
+}
+do_test trig-raise-5.1 {
+ execsql {
+ UPDATE tbl SET c = 10;
+ SELECT * FROM tbl;
+ }
+} {1 2 3 4 5 10}
+do_test trig-raise-5.2 {
+ execsql {
+ DELETE FROM tbl;
+ SELECT * FROM tbl;
+ }
+} {1 2 3}
+
+# Check that RAISE(IGNORE) works correctly for nested triggers:
+execsql {CREATE TABLE tbl2(a, b, c)}
+execsql {
+ CREATE TRIGGER after_tbl2_insert AFTER INSERT ON tbl2 BEGIN
+ UPDATE tbl SET c = 10;
+ INSERT INTO tbl2 VALUES (new.a, new.b, new.c);
+ END;
+}
+do_test trig-raise-6 {
+ execsql {
+ INSERT INTO tbl2 VALUES (1, 2, 3);
+ SELECT * FROM tbl2;
+ SELECT * FROM tbl;
+ }
+} {1 2 3 1 2 3 1 2 3}
+
+# Check that things also work for view-triggers
+execsql {CREATE VIEW tbl_view AS SELECT * FROM tbl}
+execsql {
+ CREATE TRIGGER tbl_view_insert INSTEAD OF INSERT ON tbl_view BEGIN
+ SELECT CASE WHEN (new.a = 1) THEN RAISE(ROLLBACK, 'View rollback')
+ WHEN (new.a = 2) THEN RAISE(IGNORE)
+ WHEN (new.a = 3) THEN RAISE(ABORT, 'View abort') END;
+ END;
+}
+
+do_test trig-raise-7.1 {
+ catchsql {
+ INSERT INTO tbl_view VALUES(1, 2, 3);
+ }
+} {1 {View rollback}}
+do_test trig-raise-7.2 {
+ catchsql {
+ INSERT INTO tbl_view VALUES(2, 2, 3);
+ }
+} {0 {}}
+do_test trig-raise-7.3 {
+ catchsql {
+ INSERT INTO tbl_view VALUES(3, 2, 3);
+ }
+} {1 {View abort}}
+
+catchsql { DROP TABLE tbl; }
+catchsql { DROP TABLE tbl2; }
+catchsql { DROP VIEW tbl_view; }
+
+