Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Avoid recursive calls to sqlite3VdbeMemRelease() when deleting VM frames used by trigger programs. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
119ffe955eb1e8016cb8131a63bd1755 |
User & Date: | dan 2010-12-01 08:04:48.000 |
Context
2010-12-01
| ||
11:46 | Add test file e_resolve.test. (check-in: 6858df9c72 user: dan tags: trunk) | |
08:04 | Avoid recursive calls to sqlite3VdbeMemRelease() when deleting VM frames used by trigger programs. (check-in: 119ffe955e user: dan tags: trunk) | |
2010-11-30
| ||
12:12 | Add test file e_dropview.test. (check-in: 6197822cc8 user: dan tags: trunk) | |
Changes
Changes to src/vdbeInt.h.
︙ | ︙ | |||
93 94 95 96 97 98 99 | ** is allocated to store the current value of the program counter, as ** well as the current memory cell array and various other frame specific ** values stored in the Vdbe struct. When the sub-program is finished, ** these values are copied back to the Vdbe from the VdbeFrame structure, ** restoring the state of the VM to as it was before the sub-program ** began executing. ** | | | > > > > > > > > | | | | | | | 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | ** is allocated to store the current value of the program counter, as ** well as the current memory cell array and various other frame specific ** values stored in the Vdbe struct. When the sub-program is finished, ** these values are copied back to the Vdbe from the VdbeFrame structure, ** restoring the state of the VM to as it was before the sub-program ** began executing. ** ** 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 in parent (calling) frame */ Op *aOp; /* Program instructions for parent frame */ int nOp; /* Size of aOp array */ Mem *aMem; /* Array of memory cells for parent frame */ int nMem; /* Number of entries in aMem */ 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, or NULL if parent is main */ }; #define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))]) /* ** A value for VdbeCursor.cacheValid that means the cache is always invalid. */ |
︙ | ︙ | |||
329 330 331 332 333 334 335 336 337 338 339 340 341 342 | i64 nFkConstraint; /* Number of imm. FK constraints this VM */ i64 nStmtDefCons; /* Number of def. constraints when stmt started */ int iStatement; /* Statement number (or 0 if has not opened stmt) */ #ifdef SQLITE_DEBUG FILE *trace; /* Write an execution trace here, if not NULL */ #endif VdbeFrame *pFrame; /* Parent frame */ 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 */ }; /* ** The following are allowed values for Vdbe.magic | > | 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 | i64 nFkConstraint; /* Number of imm. FK constraints this VM */ i64 nStmtDefCons; /* Number of def. constraints when stmt started */ int iStatement; /* Statement number (or 0 if has not opened stmt) */ #ifdef SQLITE_DEBUG 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 */ }; /* ** The following are allowed values for Vdbe.magic |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 | p->apCsr[i] = 0; } } } if( p->aMem ){ releaseMemArray(&p->aMem[1], p->nMem); } } /* ** Clean up the VM after execution. ** ** This routine will automatically close any cursors, lists, and/or ** sorters that were left open. It also deletes the values of | > > > > > | 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 | p->apCsr[i] = 0; } } } if( p->aMem ){ releaseMemArray(&p->aMem[1], p->nMem); } while( p->pDelFrame ){ VdbeFrame *pDel = p->pDelFrame; p->pDelFrame = pDel->pParent; sqlite3VdbeFrameDelete(pDel); } } /* ** Clean up the VM after execution. ** ** This routine will automatically close any cursors, lists, and/or ** sorters that were left open. It also deletes the values of |
︙ | ︙ |
Changes to src/vdbemem.c.
︙ | ︙ | |||
483 484 485 486 487 488 489 | } /* ** Delete any previous value and set the value stored in *pMem to NULL. */ void sqlite3VdbeMemSetNull(Mem *pMem){ if( pMem->flags & MEM_Frame ){ | | > > | 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 | } /* ** Delete any previous value and set the value stored in *pMem to NULL. */ void sqlite3VdbeMemSetNull(Mem *pMem){ if( pMem->flags & MEM_Frame ){ VdbeFrame *pFrame = pMem->u.pFrame; pFrame->pParent = pFrame->v->pDelFrame; pFrame->v->pDelFrame = pFrame; } if( pMem->flags & MEM_RowSet ){ sqlite3RowSetClear(pMem->u.pRowSet); } MemSetTypeFlag(pMem, MEM_Null); pMem->type = SQLITE_NULL; } |
︙ | ︙ |
Changes to test/triggerC.test.
︙ | ︙ | |||
933 934 935 936 937 938 939 940 941 942 | do_test triggerC-12.2 { db eval { SELECT * FROM t1 } { if {$a == 3} { execsql { DROP TRIGGER tr1 } } } execsql { SELECT count(*) FROM sqlite_master } } {1} finish_test | > > > > > > > > > > > > | 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 | do_test triggerC-12.2 { db eval { SELECT * FROM t1 } { if {$a == 3} { execsql { DROP TRIGGER tr1 } } } 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 |