Avoid recursive calls to sqlite3VdbeMemRelease() when deleting VM frames used by trigger programs.
FossilOrigin-Name: 119ffe955eb1e8016cb8131a63bd17557f395f3f
This commit is contained in:
parent
4a8198255d
commit
271065704c
18
manifest
18
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
|
||||
|
@ -1 +1 @@
|
||||
6197822cc8310fd7e1d7151683833e8b39fe631a
|
||||
119ffe955eb1e8016cb8131a63bd17557f395f3f
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user