mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
Add API function sqlite3_preupdate_depth(), for determining the depth of the trigger stack from within a pre-update callback.
FossilOrigin-Name: bdea70895c2c686a4dd3f4bf0a475fd1501d9551
This commit is contained in:
18
manifest
18
manifest
@ -1,5 +1,5 @@
|
||||
C Fix\sa\scrash\sthat\scan\sfollow\san\sOOM\swhen\s"all\stables"\sare\sregistered\swith\sa\ssession\smodule.
|
||||
D 2011-03-22T16:54:12
|
||||
C Add\sAPI\sfunction\ssqlite3_preupdate_depth(),\sfor\sdetermining\sthe\sdepth\sof\sthe\strigger\sstack\sfrom\swithin\sa\spre-update\scallback.
|
||||
D 2011-03-22T18:45:30
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -185,13 +185,13 @@ F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706
|
||||
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
|
||||
F src/select.c d24406c45dd2442eb2eeaac413439066b149c944
|
||||
F src/shell.c 4a5e0ad845475c84881f0b25b1abba2ddaab0a72
|
||||
F src/sqlite.h.in 62de507787b39cb58b52002a1ee974e09dd5c83a
|
||||
F src/sqlite.h.in 6b93765e048e0023e23c1d9827a561d7ead7100a
|
||||
F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754
|
||||
F src/sqliteInt.h 10707dc735a0077741e1b4b1550891abc26d7582
|
||||
F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44
|
||||
F src/status.c 4997380fbb915426fef9e500b4872e79c99267fc
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
F src/tclsqlite.c 520e124994e68fd8804ade95b5d3e2e791d0958d
|
||||
F src/tclsqlite.c 78713534e628ea92b032bfa20ea8a1afc6cdb124
|
||||
F src/test1.c 9020310c7617234b33fd1c3064f89524db25f290
|
||||
F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31
|
||||
F src/test3.c 056093cfef69ff4227a6bdb9108564dc7f45e4bc
|
||||
@ -241,7 +241,7 @@ F src/vacuum.c 924bd1bcee2dfb05376f79845bd3b4cec7b54b2f
|
||||
F src/vdbe.c c90edafd941481506f001b17cd8523683fdac853
|
||||
F src/vdbe.h edef9c4f0be83e1f1dccd049da37b40e021b63d9
|
||||
F src/vdbeInt.h 2cf77c1d151a4a54facd596d52be6d60c1cb26e8
|
||||
F src/vdbeapi.c 3d620e00cb74b6034343009af42d5ff5eb7c19dc
|
||||
F src/vdbeapi.c e472b3e5985175e948e70025cb3bffa8a2e185c8
|
||||
F src/vdbeaux.c 0216b2c37509a44c3833b297765bee7bdd04fa2f
|
||||
F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562
|
||||
F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b
|
||||
@ -481,7 +481,7 @@ F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167
|
||||
F test/fuzz3.test aec64345184d1662bd30e6a17851ff659d596dc5
|
||||
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
|
||||
F test/fuzz_malloc.test dd7001ac86d09c154a7dff064f4739c60e2b312c
|
||||
F test/hook.test d054aad1a3772dd9045510382875468a9dcae15f
|
||||
F test/hook.test 14b2439b878c9aae03a3684cba717be4bfdcc1c1
|
||||
F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4
|
||||
F test/in.test 19b642bb134308980a92249750ea4ce3f6c75c2d
|
||||
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
|
||||
@ -923,7 +923,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
P e9037e4e4ccaa5c633759c4d041b60b631b92c6c
|
||||
R 93198cfc6613c93be1aa416f0de3d035
|
||||
P 183c236e991faaabdc768e52e926c52cf4a7abc9
|
||||
R 3714f49d9e3ab391fe868f9d204fa8d5
|
||||
U dan
|
||||
Z ee6ba5845d31702e943c5fa7b7c9db34
|
||||
Z 4e2f4fe62e6298f01b15895da5c35a23
|
||||
|
@ -1 +1 @@
|
||||
183c236e991faaabdc768e52e926c52cf4a7abc9
|
||||
bdea70895c2c686a4dd3f4bf0a475fd1501d9551
|
@ -6405,6 +6405,7 @@ SQLITE_EXPERIMENTAL void *sqlite3_preupdate_hook(
|
||||
);
|
||||
SQLITE_EXPERIMENTAL int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **);
|
||||
SQLITE_EXPERIMENTAL int sqlite3_preupdate_count(sqlite3 *);
|
||||
SQLITE_EXPERIMENTAL int sqlite3_preupdate_depth(sqlite3 *);
|
||||
SQLITE_EXPERIMENTAL int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
|
||||
|
||||
/*
|
||||
|
@ -2851,9 +2851,9 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
||||
** $db preupdate_hook old INDEX
|
||||
*/
|
||||
case DB_PREUPDATE: {
|
||||
static const char *azSub[] = {"count", "hook", "new", "old", 0};
|
||||
static const char *azSub[] = {"count", "depth", "hook", "new", "old", 0};
|
||||
enum DbPreupdateSubCmd {
|
||||
PRE_COUNT, PRE_HOOK, PRE_NEW, PRE_OLD
|
||||
PRE_COUNT, PRE_DEPTH, PRE_HOOK, PRE_NEW, PRE_OLD
|
||||
};
|
||||
int iSub;
|
||||
|
||||
@ -2880,6 +2880,17 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
||||
break;
|
||||
}
|
||||
|
||||
case PRE_DEPTH: {
|
||||
Tcl_Obj *pRet;
|
||||
if( objc!=3 ){
|
||||
Tcl_WrongNumArgs(interp, 3, objv, "");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
pRet = Tcl_NewIntObj(sqlite3_preupdate_depth(pDb->db));
|
||||
Tcl_SetObjResult(interp, pRet);
|
||||
break;
|
||||
}
|
||||
|
||||
case PRE_NEW:
|
||||
case PRE_OLD: {
|
||||
int iIdx;
|
||||
|
@ -1391,6 +1391,22 @@ int sqlite3_preupdate_count(sqlite3 *db){
|
||||
return (p ? p->pCsr->nField : 0);
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is designed to be called from within a pre-update callback
|
||||
** only. It returns zero if the change that caused the callback was made
|
||||
** immediately by a user SQL statement. Or, if the change was made by a
|
||||
** trigger program, it returns the number of trigger programs currently
|
||||
** on the stack (1 for a top-level trigger, 2 for a trigger fired by a
|
||||
** top-level trigger etc.).
|
||||
**
|
||||
** For the purposes of the previous paragraph, a foreign key CASCADE, SET NULL
|
||||
** or SET DEFAULT action is considered a trigger.
|
||||
*/
|
||||
int sqlite3_preupdate_depth(sqlite3 *db){
|
||||
PreUpdate *p = db->pPreUpdate;
|
||||
return (p ? p->v->nFrame : 0);
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is called from within a pre-update callback to retrieve
|
||||
** a field of the row currently being updated or inserted.
|
||||
|
112
test/hook.test
112
test/hook.test
@ -651,6 +651,118 @@ do_preupdate_test 7.6.2 {
|
||||
DELETE main t9 3 3 1 3 4
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# Test that the sqlite3_preupdate_depth() API seems to work.
|
||||
#
|
||||
proc preupdate_hook {args} {
|
||||
set type [lindex $args 0]
|
||||
eval lappend ::preupdate $args
|
||||
eval lappend ::preupdate [db preupdate depth]
|
||||
|
||||
if {$type != "INSERT"} {
|
||||
for {set i 0} {$i < [db preupdate count]} {incr i} {
|
||||
lappend ::preupdate [db preupdate old $i]
|
||||
}
|
||||
}
|
||||
if {$type != "DELETE"} {
|
||||
for {set i 0} {$i < [db preupdate count]} {incr i} {
|
||||
set rc [catch { db preupdate new $i } v]
|
||||
lappend ::preupdate $v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
db preupdate hook preupdate_hook
|
||||
|
||||
do_execsql_test 7.6.1 {
|
||||
CREATE TABLE t1(x PRIMARY KEY);
|
||||
CREATE TABLE t2(x PRIMARY KEY);
|
||||
CREATE TABLE t3(x PRIMARY KEY);
|
||||
CREATE TABLE t4(x PRIMARY KEY);
|
||||
|
||||
CREATE TRIGGER a AFTER INSERT ON t1 BEGIN INSERT INTO t2 VALUES(new.x); END;
|
||||
CREATE TRIGGER b AFTER INSERT ON t2 BEGIN INSERT INTO t3 VALUES(new.x); END;
|
||||
CREATE TRIGGER c AFTER INSERT ON t3 BEGIN INSERT INTO t4 VALUES(new.x); END;
|
||||
|
||||
CREATE TRIGGER d AFTER UPDATE ON t1 BEGIN UPDATE t2 SET x = new.x; END;
|
||||
CREATE TRIGGER e AFTER UPDATE ON t2 BEGIN UPDATE t3 SET x = new.x; END;
|
||||
CREATE TRIGGER f AFTER UPDATE ON t3 BEGIN UPDATE t4 SET x = new.x; END;
|
||||
|
||||
CREATE TRIGGER g AFTER DELETE ON t1 BEGIN DELETE FROM t2 WHERE 1; END;
|
||||
CREATE TRIGGER h AFTER DELETE ON t2 BEGIN DELETE FROM t3 WHERE 1; END;
|
||||
CREATE TRIGGER i AFTER DELETE ON t3 BEGIN DELETE FROM t4 WHERE 1; END;
|
||||
}
|
||||
|
||||
do_preupdate_test 7.6.2 {
|
||||
INSERT INTO t1 VALUES('xyz');
|
||||
} {
|
||||
INSERT main t1 1 1 0 xyz
|
||||
INSERT main t2 1 1 1 xyz
|
||||
INSERT main t3 1 1 2 xyz
|
||||
INSERT main t4 1 1 3 xyz
|
||||
}
|
||||
do_preupdate_test 7.6.3 {
|
||||
UPDATE t1 SET x = 'abc';
|
||||
} {
|
||||
UPDATE main t1 1 1 0 xyz abc
|
||||
UPDATE main t2 1 1 1 xyz abc
|
||||
UPDATE main t3 1 1 2 xyz abc
|
||||
UPDATE main t4 1 1 3 xyz abc
|
||||
}
|
||||
do_preupdate_test 7.6.4 {
|
||||
DELETE FROM t1 WHERE 1;
|
||||
} {
|
||||
DELETE main t1 1 1 0 abc
|
||||
DELETE main t2 1 1 1 abc
|
||||
DELETE main t3 1 1 2 abc
|
||||
DELETE main t4 1 1 3 abc
|
||||
}
|
||||
|
||||
do_execsql_test 7.6.5 {
|
||||
DROP TRIGGER a; DROP TRIGGER b; DROP TRIGGER c;
|
||||
DROP TRIGGER d; DROP TRIGGER e; DROP TRIGGER f;
|
||||
DROP TRIGGER g; DROP TRIGGER h; DROP TRIGGER i;
|
||||
|
||||
CREATE TRIGGER a BEFORE INSERT ON t1 BEGIN INSERT INTO t2 VALUES(new.x); END;
|
||||
CREATE TRIGGER b BEFORE INSERT ON t2 BEGIN INSERT INTO t3 VALUES(new.x); END;
|
||||
CREATE TRIGGER c BEFORE INSERT ON t3 BEGIN INSERT INTO t4 VALUES(new.x); END;
|
||||
|
||||
CREATE TRIGGER d BEFORE UPDATE ON t1 BEGIN UPDATE t2 SET x = new.x; END;
|
||||
CREATE TRIGGER e BEFORE UPDATE ON t2 BEGIN UPDATE t3 SET x = new.x; END;
|
||||
CREATE TRIGGER f BEFORE UPDATE ON t3 BEGIN UPDATE t4 SET x = new.x; END;
|
||||
|
||||
CREATE TRIGGER g BEFORE DELETE ON t1 BEGIN DELETE FROM t2 WHERE 1; END;
|
||||
CREATE TRIGGER h BEFORE DELETE ON t2 BEGIN DELETE FROM t3 WHERE 1; END;
|
||||
CREATE TRIGGER i BEFORE DELETE ON t3 BEGIN DELETE FROM t4 WHERE 1; END;
|
||||
}
|
||||
|
||||
do_preupdate_test 7.6.6 {
|
||||
INSERT INTO t1 VALUES('xyz');
|
||||
} {
|
||||
INSERT main t4 1 1 3 xyz
|
||||
INSERT main t3 1 1 2 xyz
|
||||
INSERT main t2 1 1 1 xyz
|
||||
INSERT main t1 1 1 0 xyz
|
||||
}
|
||||
do_preupdate_test 7.6.3 {
|
||||
UPDATE t1 SET x = 'abc';
|
||||
} {
|
||||
UPDATE main t4 1 1 3 xyz abc
|
||||
UPDATE main t3 1 1 2 xyz abc
|
||||
UPDATE main t2 1 1 1 xyz abc
|
||||
UPDATE main t1 1 1 0 xyz abc
|
||||
}
|
||||
do_preupdate_test 7.6.4 {
|
||||
DELETE FROM t1 WHERE 1;
|
||||
} {
|
||||
DELETE main t4 1 1 3 abc
|
||||
DELETE main t3 1 1 2 abc
|
||||
DELETE main t2 1 1 1 abc
|
||||
DELETE main t1 1 1 0 abc
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
Reference in New Issue
Block a user