]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Avoid recursive calls to sqlite3VdbeMemRelease() when deleting VM frames used by...
authordan <dan@noemail.net>
Wed, 1 Dec 2010 08:04:47 +0000 (08:04 +0000)
committerdan <dan@noemail.net>
Wed, 1 Dec 2010 08:04:47 +0000 (08:04 +0000)
FossilOrigin-Name: 119ffe955eb1e8016cb8131a63bd17557f395f3f

manifest
manifest.uuid
src/vdbeInt.h
src/vdbeaux.c
src/vdbemem.c
test/triggerC.test

index 9e728b7c049fd2145454d9fecbcb528e38cb9360..e3c97266f25cfed151d18ae8821fc9c2021ad367 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\stest\sfile\se_dropview.test.
-D 2010-11-30T12:12:25
+C Avoid\srecursive\scalls\sto\ssqlite3VdbeMemRelease()\swhen\sdeleting\sVM\sframes\sused\sby\strigger\sprograms.
+D 2010-12-01T08:04:48
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 4547616ad2286053af6ccccefa242dc925e49bf0
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -230,11 +230,11 @@ F src/util.c ab1c92426494f499f42b9e307537b03e923d75c1
 F src/vacuum.c 924bd1bcee2dfb05376f79845bd3b4cec7b54b2f
 F src/vdbe.c 21a9285fedf2e310ffc4bad27b828645dc2b20bb
 F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2
-F src/vdbeInt.h 7f4cf1b2b69bef3a432b1f23dfebef57275436b4
+F src/vdbeInt.h 1f2137b905969f4de0648256aeb73abdf88f9213
 F src/vdbeapi.c fb0036185b3c56e15916a5ee96309cd4acf6818f
-F src/vdbeaux.c 762c2b146cf5fe7a7f743af1bbfed4a966aa937a
+F src/vdbeaux.c b810a66902ee40c71cdb9c64f43760da516c91df
 F src/vdbeblob.c e0ce3c54cc0c183af2ec67b63a289acf92251df4
-F src/vdbemem.c 23723a12cd3ba7ab3099193094cbb2eb78956aa9
+F src/vdbemem.c 411649a35686f54268ccabeda175322c4697f5a6
 F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2
 F src/vtab.c b297e8fa656ab5e66244ab15680d68db0adbec30
 F src/wal.c f26b8d297bd11cb792e609917f9d4c6718ac8e0e
@@ -796,7 +796,7 @@ F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4
 F test/trigger9.test 5b0789f1c5c4600961f8e68511b825b87be53e31
 F test/triggerA.test eaf11a29db2a11967d2d4b49d37f92bce598194e
 F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe
-F test/triggerC.test 2a23edcc00684d084902ba5ec93e721775c3a70a
+F test/triggerC.test 8a691ff6dd47df2e57395bbec4b62101fac0f363
 F test/triggerD.test c6add3817351451e419f6ff9e9a259b02b6e2de7
 F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff
 F test/types2.test 3555aacf8ed8dc883356e59efc314707e6247a84
@@ -891,7 +891,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P ee8dc8c87ed15b76ba437df23e1d7b1b7fa30296
-R 4a3bff37fc4c660278f60fbda77a6338
+P 6197822cc8310fd7e1d7151683833e8b39fe631a
+R 1616ff1293fc577a7a9463bdfe77090f
 U dan
-Z 27edb6190ff4f86a8a8a1f3444932c26
+Z 6b55fe83d9e16cee919cd05f710b1461
index 2f572f9cafea8bb1e428cf1b0d3d1f8a3fa0a0f0..6c1928255e85ff040da6856d6f5489709d99af69 100644 (file)
@@ -1 +1 @@
-6197822cc8310fd7e1d7151683833e8b39fe631a
\ No newline at end of file
+119ffe955eb1e8016cb8131a63bd17557f395f3f
\ No newline at end of file
index 816fc29a99609ce81de70c3e9b86af6edd224670..765852aaefec81725ac9ba6ce3601fae16db6005 100644 (file)
@@ -97,26 +97,34 @@ typedef struct VdbeCursor VdbeCursor;
 ** restoring the state of the VM to as it was before the sub-program
 ** began executing.
 **
-** Frames are stored in a linked list headed at Vdbe.pParent. Vdbe.pParent
-** is the parent of the current frame, or zero if the current frame
-** is the main Vdbe program.
+** The memory for a VdbeFrame object is allocated and managed by a memory
+** cell in the parent (calling) frame. When the memory cell is deleted or
+** overwritten, the VdbeFrame object is not freed immediately. Instead, it
+** is linked into the Vdbe.pDelFrame list. The contents of the Vdbe.pDelFrame
+** list is deleted when the VM is reset in VdbeHalt(). The reason for doing
+** this instead of deleting the VdbeFrame immediately is to avoid recursive
+** calls to sqlite3VdbeMemRelease() when the memory cells belonging to the
+** child frame are released.
+**
+** The currently executing frame is stored in Vdbe.pFrame. Vdbe.pFrame is
+** set to NULL if the currently executing frame is the main program.
 */
 typedef struct VdbeFrame VdbeFrame;
 struct VdbeFrame {
   Vdbe *v;                /* VM this frame belongs to */
-  int pc;                 /* Program Counter */
-  Op *aOp;                /* Program instructions */
+  int pc;                 /* Program Counter in parent (calling) frame */
+  Op *aOp;                /* Program instructions for parent frame */
   int nOp;                /* Size of aOp array */
-  Mem *aMem;              /* Array of memory cells */
+  Mem *aMem;              /* Array of memory cells for parent frame */
   int nMem;               /* Number of entries in aMem */
-  VdbeCursor **apCsr;     /* Element of Vdbe cursors */
+  VdbeCursor **apCsr;     /* Array of Vdbe cursors for parent frame */
   u16 nCursor;            /* Number of entries in apCsr */
   void *token;            /* Copy of SubProgram.token */
   int nChildMem;          /* Number of memory cells for child frame */
   int nChildCsr;          /* Number of cursors for child frame */
   i64 lastRowid;          /* Last insert rowid (sqlite3.lastRowid) */
   int nChange;            /* Statement changes (Vdbe.nChanges)     */
-  VdbeFrame *pParent;     /* Parent of this frame */
+  VdbeFrame *pParent;     /* Parent of this frame, or NULL if parent is main */
 };
 
 #define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))])
@@ -333,6 +341,7 @@ struct Vdbe {
   FILE *trace;            /* Write an execution trace here, if not NULL */
 #endif
   VdbeFrame *pFrame;      /* Parent frame */
+  VdbeFrame *pDelFrame;   /* List of frame objects to free on VM reset */
   int nFrame;             /* Number of frames in pFrame list */
   u32 expmask;            /* Binding to these vars invalidates VM */
   SubProgram *pProgram;   /* Linked list of all sub-programs used by VM */
index e22387433bff3a3da118c6bacedf456fa03c358c..a9ac9b032dd037aac04951abef3fd26954fdfbb0 100644 (file)
@@ -1537,6 +1537,11 @@ static void closeAllCursors(Vdbe *p){
   if( p->aMem ){
     releaseMemArray(&p->aMem[1], p->nMem);
   }
+  while( p->pDelFrame ){
+    VdbeFrame *pDel = p->pDelFrame;
+    p->pDelFrame = pDel->pParent;
+    sqlite3VdbeFrameDelete(pDel);
+  }
 }
 
 /*
index 80160e60776879f3e074cf305d62da3efee0872e..4831d806585367e73a3f9feecfcc897930649b47 100644 (file)
@@ -487,7 +487,9 @@ int sqlite3VdbeMemNumerify(Mem *pMem){
 */
 void sqlite3VdbeMemSetNull(Mem *pMem){
   if( pMem->flags & MEM_Frame ){
-    sqlite3VdbeFrameDelete(pMem->u.pFrame);
+    VdbeFrame *pFrame = pMem->u.pFrame;
+    pFrame->pParent = pFrame->v->pDelFrame;
+    pFrame->v->pDelFrame = pFrame;
   }
   if( pMem->flags & MEM_RowSet ){
     sqlite3RowSetClear(pMem->u.pRowSet);
index d3300b42583fe1225bb2d91792634f05895aeb75..694d069d71181c721b846a4b690d412eeefdaa9f 100644 (file)
@@ -937,6 +937,18 @@ do_test triggerC-12.2 {
   execsql { SELECT count(*) FROM sqlite_master }
 } {1}
 
+do_execsql_test triggerC-13.1 {
+  PRAGMA recursive_triggers = ON;
+  CREATE TABLE t12(a, b);
+  INSERT INTO t12 VALUES(1, 2);
+  CREATE TRIGGER tr12 AFTER UPDATE ON t12 BEGIN
+    UPDATE t12 SET a=new.a+1, b=new.b+1;
+  END;
+} {}
+do_catchsql_test triggerC-13.2 {
+  UPDATE t12 SET a=a+1, b=b+1;
+} {1 {too many levels of trigger recursion}}
+
 
 
 finish_test