]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add API function sqlite3_preupdate_depth(), for determining the depth of the trigger...
authordan <dan@noemail.net>
Tue, 22 Mar 2011 18:45:29 +0000 (18:45 +0000)
committerdan <dan@noemail.net>
Tue, 22 Mar 2011 18:45:29 +0000 (18:45 +0000)
FossilOrigin-Name: bdea70895c2c686a4dd3f4bf0a475fd1501d9551

manifest
manifest.uuid
src/sqlite.h.in
src/tclsqlite.c
src/vdbeapi.c
test/hook.test

index 8c992e020b7dc3ec89b290c5ce619e71a2dc49ad..20662eaa2fb61adcdabebcf3298e687eb21d91e4 100644 (file)
--- a/manifest
+++ b/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
index 406e8e890259c0f82c34c14b1647dcb753056824..cf0cd54d723e6e3e765df09d78993768ac611c8d 100644 (file)
@@ -1 +1 @@
-183c236e991faaabdc768e52e926c52cf4a7abc9
\ No newline at end of file
+bdea70895c2c686a4dd3f4bf0a475fd1501d9551
\ No newline at end of file
index 80a19002fa5f65890fde26beedd1e0bcc5c0a841..2ee63f24f1d11dba084592146f4539493ea15724 100644 (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_count(sqlite3 *);
+SQLITE_EXPERIMENTAL int sqlite3_preupdate_depth(sqlite3 *);
 SQLITE_EXPERIMENTAL int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
 
 /*
index 092295a2d19898b87e5458de9d756739ddcbc8d5..2d945be532c4da8e5cb235ebbbed961dfc5bce8a 100644 (file)
@@ -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;
index 829d4678b64dd8661d2374d67db0c28419ee9f4c..b485aa74833e8eb05aee4a347b9c63a18cc09e1c 100644 (file)
@@ -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.
index 9ceedbb75d1fc0ba60618a49b08859aa38d9b510..016569f0aec6b9842fd8e3a3bf49422f61430868 100644 (file)
@@ -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