1
0
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:
dan
2011-03-22 18:45:29 +00:00
parent 245b49b203
commit 1e7a2d4315
6 changed files with 152 additions and 12 deletions

View File

@ -1,5 +1,5 @@
C Fix\sa\scrash\sthat\scan\sfollow\san\sOOM\swhen\s"all\stables"\sare\sregistered\swith\sa\ssession\smodule. C Add\sAPI\sfunction\ssqlite3_preupdate_depth(),\sfor\sdetermining\sthe\sdepth\sof\sthe\strigger\sstack\sfrom\swithin\sa\spre-update\scallback.
D 2011-03-22T16:54:12 D 2011-03-22T18:45:30
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@ -185,13 +185,13 @@ F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
F src/select.c d24406c45dd2442eb2eeaac413439066b149c944 F src/select.c d24406c45dd2442eb2eeaac413439066b149c944
F src/shell.c 4a5e0ad845475c84881f0b25b1abba2ddaab0a72 F src/shell.c 4a5e0ad845475c84881f0b25b1abba2ddaab0a72
F src/sqlite.h.in 62de507787b39cb58b52002a1ee974e09dd5c83a F src/sqlite.h.in 6b93765e048e0023e23c1d9827a561d7ead7100a
F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754 F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754
F src/sqliteInt.h 10707dc735a0077741e1b4b1550891abc26d7582 F src/sqliteInt.h 10707dc735a0077741e1b4b1550891abc26d7582
F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44 F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44
F src/status.c 4997380fbb915426fef9e500b4872e79c99267fc F src/status.c 4997380fbb915426fef9e500b4872e79c99267fc
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
F src/tclsqlite.c 520e124994e68fd8804ade95b5d3e2e791d0958d F src/tclsqlite.c 78713534e628ea92b032bfa20ea8a1afc6cdb124
F src/test1.c 9020310c7617234b33fd1c3064f89524db25f290 F src/test1.c 9020310c7617234b33fd1c3064f89524db25f290
F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31 F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31
F src/test3.c 056093cfef69ff4227a6bdb9108564dc7f45e4bc F src/test3.c 056093cfef69ff4227a6bdb9108564dc7f45e4bc
@ -241,7 +241,7 @@ F src/vacuum.c 924bd1bcee2dfb05376f79845bd3b4cec7b54b2f
F src/vdbe.c c90edafd941481506f001b17cd8523683fdac853 F src/vdbe.c c90edafd941481506f001b17cd8523683fdac853
F src/vdbe.h edef9c4f0be83e1f1dccd049da37b40e021b63d9 F src/vdbe.h edef9c4f0be83e1f1dccd049da37b40e021b63d9
F src/vdbeInt.h 2cf77c1d151a4a54facd596d52be6d60c1cb26e8 F src/vdbeInt.h 2cf77c1d151a4a54facd596d52be6d60c1cb26e8
F src/vdbeapi.c 3d620e00cb74b6034343009af42d5ff5eb7c19dc F src/vdbeapi.c e472b3e5985175e948e70025cb3bffa8a2e185c8
F src/vdbeaux.c 0216b2c37509a44c3833b297765bee7bdd04fa2f F src/vdbeaux.c 0216b2c37509a44c3833b297765bee7bdd04fa2f
F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562 F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562
F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b
@ -481,7 +481,7 @@ F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167
F test/fuzz3.test aec64345184d1662bd30e6a17851ff659d596dc5 F test/fuzz3.test aec64345184d1662bd30e6a17851ff659d596dc5
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
F test/fuzz_malloc.test dd7001ac86d09c154a7dff064f4739c60e2b312c F test/fuzz_malloc.test dd7001ac86d09c154a7dff064f4739c60e2b312c
F test/hook.test d054aad1a3772dd9045510382875468a9dcae15f F test/hook.test 14b2439b878c9aae03a3684cba717be4bfdcc1c1
F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4 F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4
F test/in.test 19b642bb134308980a92249750ea4ce3f6c75c2d F test/in.test 19b642bb134308980a92249750ea4ce3f6c75c2d
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75 F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
@ -923,7 +923,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
P e9037e4e4ccaa5c633759c4d041b60b631b92c6c P 183c236e991faaabdc768e52e926c52cf4a7abc9
R 93198cfc6613c93be1aa416f0de3d035 R 3714f49d9e3ab391fe868f9d204fa8d5
U dan U dan
Z ee6ba5845d31702e943c5fa7b7c9db34 Z 4e2f4fe62e6298f01b15895da5c35a23

View File

@ -1 +1 @@
183c236e991faaabdc768e52e926c52cf4a7abc9 bdea70895c2c686a4dd3f4bf0a475fd1501d9551

View File

@ -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_old(sqlite3 *, int, sqlite3_value **);
SQLITE_EXPERIMENTAL int sqlite3_preupdate_count(sqlite3 *); SQLITE_EXPERIMENTAL int sqlite3_preupdate_count(sqlite3 *);
SQLITE_EXPERIMENTAL int sqlite3_preupdate_depth(sqlite3 *);
SQLITE_EXPERIMENTAL int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **); SQLITE_EXPERIMENTAL int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
/* /*

View File

@ -2851,9 +2851,9 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
** $db preupdate_hook old INDEX ** $db preupdate_hook old INDEX
*/ */
case DB_PREUPDATE: { case DB_PREUPDATE: {
static const char *azSub[] = {"count", "hook", "new", "old", 0}; static const char *azSub[] = {"count", "depth", "hook", "new", "old", 0};
enum DbPreupdateSubCmd { enum DbPreupdateSubCmd {
PRE_COUNT, PRE_HOOK, PRE_NEW, PRE_OLD PRE_COUNT, PRE_DEPTH, PRE_HOOK, PRE_NEW, PRE_OLD
}; };
int iSub; int iSub;
@ -2880,6 +2880,17 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
break; 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_NEW:
case PRE_OLD: { case PRE_OLD: {
int iIdx; int iIdx;

View File

@ -1391,6 +1391,22 @@ int sqlite3_preupdate_count(sqlite3 *db){
return (p ? p->pCsr->nField : 0); 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 ** This function is called from within a pre-update callback to retrieve
** a field of the row currently being updated or inserted. ** a field of the row currently being updated or inserted.

View File

@ -651,6 +651,118 @@ do_preupdate_test 7.6.2 {
DELETE main t9 3 3 1 3 4 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 finish_test