Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Use a separate list of aux-data structures for each trigger program at the VDBE level. Fix for [dc9b1c91]. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
c4295725015d394f01b8563f47236e08 |
User & Date: | dan 2016-02-19 18:54:29.447 |
References
2016-02-22
| ||
09:45 | Add an extra test case for the change in commit [c4295725]. (check-in: a48ac4c347 user: dan tags: trunk) | |
2016-02-19
| ||
18:55 | • Ticket [dc9b1c91db] One trigger may use auxdata belonging to another. status still Open with 6 other changes (artifact: 0bea5f1c53 user: dan) | |
Context
2016-02-19
| ||
19:46 | Further enhancements to the MSVC batch build tool. (check-in: 06f1495f4b user: mistachkin tags: trunk) | |
18:54 | Use a separate list of aux-data structures for each trigger program at the VDBE level. Fix for [dc9b1c91]. (check-in: c429572501 user: dan tags: trunk) | |
16:19 | Enhance speedtest1 to display the particular version of SQLite under test. (check-in: 0cb728c15c user: drh tags: trunk) | |
Changes
Changes to src/vdbe.c.
︙ | ︙ | |||
5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 | } p->nFrame++; pFrame->pParent = p->pFrame; pFrame->lastRowid = lastRowid; pFrame->nChange = p->nChange; pFrame->nDbChange = p->db->nChange; p->nChange = 0; p->pFrame = pFrame; p->aMem = aMem = &VdbeFrameMem(pFrame)[-1]; p->nMem = pFrame->nChildMem; p->nCursor = (u16)pFrame->nChildCsr; p->apCsr = (VdbeCursor **)&aMem[p->nMem+1]; p->aOp = aOp = pProgram->aOp; | > > > | 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 | } p->nFrame++; pFrame->pParent = p->pFrame; pFrame->lastRowid = lastRowid; pFrame->nChange = p->nChange; pFrame->nDbChange = p->db->nChange; assert( pFrame->pAuxData==0 ); pFrame->pAuxData = p->pAuxData; p->pAuxData = 0; p->nChange = 0; p->pFrame = pFrame; p->aMem = aMem = &VdbeFrameMem(pFrame)[-1]; p->nMem = pFrame->nChildMem; p->nCursor = (u16)pFrame->nChildCsr; p->apCsr = (VdbeCursor **)&aMem[p->nMem+1]; p->aOp = aOp = pProgram->aOp; |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
157 158 159 160 161 162 163 164 165 166 167 168 169 170 | Op *aOp; /* Program instructions for parent frame */ i64 *anExec; /* Event counters from parent frame */ Mem *aMem; /* Array of memory cells for parent frame */ u8 *aOnceFlag; /* Array of OP_Once flags for parent frame */ VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */ void *token; /* Copy of SubProgram.token */ i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */ int nCursor; /* Number of entries in apCsr */ int pc; /* Program Counter in parent (calling) frame */ int nOp; /* Size of aOp array */ int nMem; /* Number of entries in aMem */ int nOnceFlag; /* Number of entries in aOnceFlag */ int nChildMem; /* Number of memory cells for child frame */ int nChildCsr; /* Number of cursors for child frame */ | > | 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | Op *aOp; /* Program instructions for parent frame */ i64 *anExec; /* Event counters from parent frame */ Mem *aMem; /* Array of memory cells for parent frame */ u8 *aOnceFlag; /* Array of OP_Once flags for parent frame */ VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */ void *token; /* Copy of SubProgram.token */ i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */ AuxData *pAuxData; /* Linked list of auxdata allocations */ int nCursor; /* Number of entries in apCsr */ int pc; /* Program Counter in parent (calling) frame */ int nOp; /* Size of aOp array */ int nMem; /* Number of entries in aMem */ int nOnceFlag; /* Number of entries in aOnceFlag */ int nChildMem; /* Number of memory cells for child frame */ int nChildCsr; /* Number of cursors for child frame */ |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 | p->szMalloc = 0; } p->flags = MEM_Undefined; }while( (++p)<pEnd ); } } /* ** Delete a VdbeFrame object and its contents. VdbeFrame objects are ** allocated by the OP_Program opcode in sqlite3VdbeExec(). */ void sqlite3VdbeFrameDelete(VdbeFrame *p){ int i; Mem *aMem = VdbeFrameMem(p); VdbeCursor **apCsr = (VdbeCursor **)&aMem[p->nChildMem]; for(i=0; i<p->nChildCsr; i++){ sqlite3VdbeFreeCursor(p->v, apCsr[i]); } releaseMemArray(aMem, p->nChildMem); sqlite3DbFree(p->v->db, p); } #ifndef SQLITE_OMIT_EXPLAIN /* ** Give a listing of the program in the virtual machine. ** | > > > > > > > > > > > > > > > > | 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 | p->szMalloc = 0; } p->flags = MEM_Undefined; }while( (++p)<pEnd ); } } /* ** Delete the linked list of AuxData structures attached to frame *p. */ static void deleteAuxdataInFrame(sqlite3 *db, VdbeFrame *p){ AuxData *pAux = p->pAuxData; while( pAux ){ AuxData *pNext = pAux->pNext; if( pAux->xDelete ){ pAux->xDelete(pAux->pAux); } sqlite3DbFree(db, pAux); pAux = pNext; } } /* ** Delete a VdbeFrame object and its contents. VdbeFrame objects are ** allocated by the OP_Program opcode in sqlite3VdbeExec(). */ void sqlite3VdbeFrameDelete(VdbeFrame *p){ int i; Mem *aMem = VdbeFrameMem(p); VdbeCursor **apCsr = (VdbeCursor **)&aMem[p->nChildMem]; for(i=0; i<p->nChildCsr; i++){ sqlite3VdbeFreeCursor(p->v, apCsr[i]); } releaseMemArray(aMem, p->nChildMem); deleteAuxdataInFrame(p->v->db, p); sqlite3DbFree(p->v->db, p); } #ifndef SQLITE_OMIT_EXPLAIN /* ** Give a listing of the program in the virtual machine. ** |
︙ | ︙ | |||
2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 | v->aMem = pFrame->aMem; v->nMem = pFrame->nMem; v->apCsr = pFrame->apCsr; v->nCursor = pFrame->nCursor; v->db->lastRowid = pFrame->lastRowid; v->nChange = pFrame->nChange; v->db->nChange = pFrame->nDbChange; return pFrame->pc; } /* ** Close all cursors. ** ** Also release any dynamic memory held by the VM in the Vdbe.aMem memory | > > > | 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 | v->aMem = pFrame->aMem; v->nMem = pFrame->nMem; v->apCsr = pFrame->apCsr; v->nCursor = pFrame->nCursor; v->db->lastRowid = pFrame->lastRowid; v->nChange = pFrame->nChange; v->db->nChange = pFrame->nDbChange; sqlite3VdbeDeleteAuxData(v, -1, 0); v->pAuxData = pFrame->pAuxData; pFrame->pAuxData = 0; return pFrame->pc; } /* ** Close all cursors. ** ** Also release any dynamic memory held by the VM in the Vdbe.aMem memory |
︙ | ︙ |
Added test/regexp2.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | # 2016 February 19 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # This file implements tests for the REGEXP operator in ext/misc/regexp.c. # It focuses on the use of the sqlite3_set_auxdata()/get_auxdata() APIs. # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix regexp2 load_static_extension db regexp #------------------------------------------------------------------------- # Test that triggers do not become confused and use aux-data created by # a different trigger for a different REGEXP invocation. # do_execsql_test 1.0 { CREATE TABLE t1(a, b, c); CREATE TABLE x1(x, y, z); CREATE TABLE x2(x, y, z); CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN INSERT INTO x1 VALUES( new.a REGEXP 'abc', new.b REGEXP 'abc', new.c REGEXP 'abc' ); END; CREATE TRIGGER tr2 AFTER INSERT ON t1 BEGIN INSERT INTO x2 VALUES( new.a REGEXP 'def', new.b REGEXP 'def', new.c REGEXP 'def' ); END; INSERT INTO t1 VALUES('abc', 'def', 'abc'); SELECT * FROM t1; } {abc def abc} do_execsql_test 1.1 { SELECT * FROM x1 } {1 0 1} do_execsql_test 1.2 { SELECT * FROM x2 } {0 1 0} #------------------------------------------------------------------------- # Test that if an exception is thrown several triggers deep, all aux-data # objects are cleaned up correctly. # proc sql_error {} { error "SQL error!" } db func error sql_error do_execsql_test 2.0 { CREATE TABLE t2(a, b); CREATE TABLE t3(c, d); CREATE TABLE t4(e, f); CREATE TRIGGER t2_tr1 AFTER UPDATE ON t2 BEGIN UPDATE t3 SET d = new.b WHERE c = old.a; END; CREATE TRIGGER t3_tr1 AFTER UPDATE ON t3 BEGIN UPDATE t4 SET f = new.d WHERE e = old.c AND new.d REGEXP 'a.*'; END; CREATE TRIGGER t4_tr1 AFTER UPDATE ON t4 BEGIN SELECT CASE WHEN new.f REGEXP '.*y.*' THEN error() ELSE 1 END; END; INSERT INTO t2 VALUES(1, 'a_x_1'); INSERT INTO t2 VALUES(2, 'a_y_1'); INSERT INTO t3 VALUES(1, 'b1'); INSERT INTO t3 VALUES(2, 'b2'); INSERT INTO t4 VALUES(1, 'b1'); INSERT INTO t4 VALUES(2, 'b2'); } {} do_catchsql_test 2.1 { UPDATE t2 SET a=a+1 WHERE b REGEXP 'a.*' AND b REGEXP '.*1'; } {1 {SQL error!}} # Test that the triggers used in the test above work as expected. # do_execsql_test 2.2 { UPDATE t2 SET b = 'a_abc_1'; } {} do_execsql_test 2.3 { SELECT * FROM t2; SELECT * FROM t3; SELECT * FROM t4; } {1 a_abc_1 2 a_abc_1 1 a_abc_1 2 a_abc_1 1 a_abc_1 2 a_abc_1} finish_test |