- C Merge\sall\srecent\strunk\schanges.
- D 2014-10-10T12:56:35.492
-C Optimize\sa\sdatabase\scorruption\stest\sinside\sof\sthe\sOP_Column\sopcode.
-D 2014-10-13T23:39:02.463
++C Merge\srecent\strunk\smicro-optimizations\sand\sthe\sDESC\sindex\sGROUP\sBY\sORDER\sBY\nbug\sfix\sinto\sthe\ssessions\sbranch.
++D 2014-10-14T13:41:32.002
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
-F Makefile.in cf57f673d77606ab0f2d9627ca52a9ba1464146a
+F Makefile.in dd5f245aa8c741bc65845747203c8ce2f3fb6c83
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
-F Makefile.msc e31dee24038965fb6269d6d61073fd6b7e331dec
+F Makefile.msc 35808af7f8d999176ed5b38fb482a87a129ee3e1
F Makefile.vxworks 034289efa9d591b04b1a73598623119c306cbba0
F README.md 64f270c43c38c46de749e419c22f0ae2f4499fe8
F VERSION 53a0b870e7f16d3b06623c31d233a304c163a6af
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
F src/resolve.c a3466128b52a86c466e47ac1a19e2174f7b5cf89
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
- F src/select.c f11533162b57ed5ed37f549add34cbcdf51f6712
- F src/shell.c 801af09adf9bc64dea59b62880bfb72b42c5f5f2
+ F src/select.c 428165951748151e87a15295b7357221433e311b
-F src/shell.c 18ee8bbe9502d8848072dc2eddd1ea09254ba494
-F src/sqlite.h.in 4a5e5158c189d2bcd45c7c4607c2c0eb6d25c153
++F src/shell.c f2b146c89967d83cca8735126ee9ff4ce7345dd1
+F src/sqlite.h.in 514eeb7b0845840c132736e714ddd98ab9216e6c
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d
- F src/sqliteInt.h eaacd377fa2eb4761dbad3b762b0483886f76565
-F src/sqliteInt.h f7812f74f2d0c6041ef6b91a99c5a45f775dd408
++F src/sqliteInt.h f712b324bafdc646c7fcfe813f81e8b8eebb57b9
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 961d5926e5a8fda611d385ec22c226b8635cd1cb
F src/table.c 2e99ef7ef16187e17033d9398dc962ce22dab5cb
F src/test_vfs.c f84075a388527892ff184988f43b69ce69b8083c
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
- F src/threads.c 22dded4283dc4b25422f6444cdcb8d6b1ea0b5ff
+ F src/threads.c 60c9d400abf17ccdc8767cdc6af90b9c5acf58bd
F src/tokenize.c cc9016e5007fc5e76789079616d2f26741bcc689
F src/trigger.c 25571661fdeae8c7f975ff40ffec205520a3f92f
-F src/update.c 729f6f18fc27740591d085e1172cebe311144bf0
+F src/update.c b9e5295d3a78e96b7c2978c4f9d224d06880f031
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
F src/util.c 4006c01772bd8d8ac4306d523bbcee41d3e392d8
F src/vacuum.c 59f03f92bcff57faa6a8ca256eb29ccddfb0614a
- F src/vdbe.c 10880af9bbd7e19eda4db1ed7a3f2dd1b645f858
-F src/vdbe.c 5ee15a66ce07e0482b92aa29e4dd0c5827a22d79
-F src/vdbe.h 09f5b4e3719fa454f252322b1cdab5cf1f361327
-F src/vdbeInt.h e2a060a55ee18a6ab973353a5e2ec7ee569bf787
-F src/vdbeapi.c 37a6c6ae284a97bcace365f2f0a225680c0499d9
-F src/vdbeaux.c edbb7a9c8b2a8f7a68ac75c2475edd4040266b76
-F src/vdbeblob.c 848238dc73e93e48432991bb5651bf87d865eca4
-F src/vdbemem.c 481327f50d9da330053aa7456702ce46d0a4e70f
++F src/vdbe.c a1465183697f2a187520d13cebf6a41f3832e0c0
+F src/vdbe.h d61daeffed696e21630759de9e135ee298ad9573
- F src/vdbeInt.h 6d4bf3fd28699b5c81a68398e9d23720da58fcd8
++F src/vdbeInt.h 7254c20b45033e1194601a02f3a386e39263c0ab
+F src/vdbeapi.c 30a1c991147fdf4334900b5fed8a312ae7678707
- F src/vdbeaux.c ea20bde8cad7b15198879255af849f105daa2fa0
++F src/vdbeaux.c 191ea23e5adbe5b6adcb9d31860b9fb890834e24
+F src/vdbeblob.c d65b01f439df63911ac3d7a9a85c15503965f2c3
+F src/vdbemem.c 1731e1db2b71e62243cf825b920d14adefaba3c7
F src/vdbesort.c 5c1bacf90578d22b630fbf6ed98ccf60d83435ef
F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010
F src/vtab.c 019dbfd0406a7447c990e1f7bd1dfcdb8895697f
F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
F test/hexlit.test f9ecde8145bfc2341573473256c74ae37a200497
- F test/hook.test 76201cfcba801d02d13600700f26ab64313d1826
-F test/hook.test 162d7cef7a2d2b04839fe14402934e6a1b79442f
++F test/hook.test aa41c095d26822b8a51aa4c82904a14347961be6
F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4
F test/in.test 047c4671328e9032ab95666a67021adbbd36e98e
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
- P 2695772c984c215649a16e1e3e18a8048a6a60dd 49dfee7cd1c9ab2901b8a871a6cd00b2ead76801
- R 0a03cea1a4d1a941b11aa663569e1d01
-P 4b3b65ee5ea61e9b9671ca027940bf02689cb890
-R 42e26b1c48be06a100ad5530a5448c12
++P abfef254721ca29b653f24bfe80e88adaa92dc6c 005e5b388a8a97bca6d1f0e06c40d68d92aa1212
++R 97eb4d72b7b8377fe0610a9bf4a72e27
U drh
- Z 20a722d001f64c3e0f0d27d851d3747e
-Z 6b074ae9a762ef61cbe684b68fc815ba
++Z 615445a8ed5827e2422bf5308f655db8
- abfef254721ca29b653f24bfe80e88adaa92dc6c
-005e5b388a8a97bca6d1f0e06c40d68d92aa1212
++83d4114f2aa404e670ced33511183baacd813a01
#define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */
#define OPFLAG_APPEND 0x08 /* This is likely to be an append */
#define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */
- #define OPFLAG_CLEARCACHE 0x20 /* Clear pseudo-table cache in OP_Column */
+#define OPFLAG_ISNOOP 0x40 /* OP_Delete does pre-update-hook only */
#define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */
#define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */
#define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */
iKey = pOp->p3;
}
- && (!(pOp->p5 & OPFLAG_ISUPDATE) || pC->rowidIsValid==0)
+ if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){
+ assert( pC->isTable );
+ assert( pC->iDb>=0 );
+ zDb = db->aDb[pC->iDb].zName;
+ pTab = pOp->p4.pTab;
+ op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
+ }
+
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
+ /* Invoke the pre-update hook, if any */
+ if( db->xPreUpdateCallback
+ && pOp->p4type==P4_TABLE
++ && !(pOp->p5 & OPFLAG_ISUPDATE)
+ && HasRowid(pTab)
+ ){
+ sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, pTab, iKey, pOp->p2);
+ }
+#endif
+
if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = iKey;
if( pData->flags & MEM_Null ){
** P1 must not be pseudo-table. It has to be a real table with
** multiple rows.
**
-** If P4 is not NULL, then it is the name of the table that P1 is
-** pointing to. The update hook will be invoked, if it exists.
-** If P4 is not NULL then the P1 cursor must have been positioned
-** using OP_NotFound prior to invoking this opcode.
+** If P4 is not NULL then it points to a Table struture. In this case either
+** the update or pre-update hook, or both, may be invoked. The P1 cursor must
+** have been positioned using OP_NotFound prior to invoking this opcode in
+** this case. Specifically, if one is configured, the pre-update hook is
+** invoked if P4 is not NULL. The update-hook is invoked if one is configured,
+** P4 is not NULL, and the OPFLAG_NCHANGE flag is set in P2.
+**
+** If the OPFLAG_ISUPDATE flag is set in P2, then P3 contains the address
+** of the memory cell that contains the value that the rowid of the row will
+** be set to by the update.
*/
case OP_Delete: {
- i64 iKey;
VdbeCursor *pC;
+ const char *zDb;
+ Table *pTab;
+ int opflags;
+ opflags = pOp->p2;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pC->pCursor!=0 ); /* Only valid for real tables, no pseudotables */
- iKey = pC->lastRowid; /* Only used for the update hook */
-
- /* The OP_Delete opcode always follows an OP_NotExists or OP_Last or
- ** OP_Column on the same table without any intervening operations that
- ** might move or invalidate the cursor. Hence cursor pC is always pointing
- ** to the row to be deleted and the sqlite3VdbeCursorMoveto() operation
- ** below is always a no-op and cannot fail. We will run it anyhow, though,
- ** to guard against future changes to the code generator.
- **/
assert( pC->deferredMoveto==0 );
- rc = sqlite3VdbeCursorMoveto(pC);
- if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
+
+ #ifdef SQLITE_DEBUG
- /* The seek operation that positioned the cursor prior to OP_Delete will
- ** have also set the pC->movetoTarget field to the rowid of the row that
- ** is being deleted */
- if( pOp->p4.z && pC->isTable ){
++ if( pOp->p4type==P4_TABLE && HasRowid(pOp->p4.pTab) ){
++ /* The seek operation that positioned the cursor prior to OP_Delete will
++ ** have also set the pC->movetoTarget field to the rowid of the row that
++ ** is being deleted */
+ i64 iKey = 0;
+ sqlite3BtreeKeySize(pC->pCursor, &iKey);
- assert( pC->movetoTarget==iKey );
++ assert( pC->movetoTarget==iKey );
+ }
+ #endif
+
+ /* If the update-hook or pre-update-hook will be invoked, set iKey to
+ ** the rowid of the row being deleted. Set zDb and zTab as well.
+ */
+ if( pOp->p4.z && HAS_UPDATE_HOOK(db) ){
+ assert( pC->iDb>=0 );
- assert( pC->rowidIsValid || !HasRowid(pOp->p4.pTab) );
- iKey = pC->lastRowid;
+ zDb = db->aDb[pC->iDb].zName;
+ pTab = pOp->p4.pTab;
- }
++ }
+
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
+ /* Invoke the pre-update-hook if required. */
+ if( db->xPreUpdateCallback && pOp->p4.z && HasRowid(pTab) ){
+ assert( !(opflags & OPFLAG_ISUPDATE) || (aMem[pOp->p3].flags & MEM_Int) );
+ sqlite3VdbePreUpdateHook(p, pC,
+ (opflags & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_DELETE,
- zDb, pTab, iKey,
++ zDb, pTab, pC->movetoTarget,
+ pOp->p3
+ );
+ }
+#endif
+
+ if( opflags & OPFLAG_ISNOOP ) break;
-
+
rc = sqlite3BtreeDelete(pC->pCursor);
pC->cacheStatus = CACHE_STALE;
- /* Invoke the update-hook if required. */
- if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z && pC->isTable ){
- db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE,
- db->aDb[pC->iDb].zName, pOp->p4.z, pC->movetoTarget);
- assert( pC->iDb>=0 );
+ /* Update the change-counter and invoke the update-hook if required. */
+ if( opflags & OPFLAG_NCHANGE ){
+ p->nChange++;
+ assert( pOp->p4.z );
+ if( rc==SQLITE_OK && db->xUpdateCallback && HasRowid(pTab) ){
- db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, pTab->zName,iKey);
++ db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, pTab->zName,
++ pC->movetoTarget);
+ }
}
- if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
break;
}
/* Opcode: ResetCount * * * * *
set ::update_hook {}
execsql {
INSERT INTO t1w VALUES(4, 'four');
++PRAGMA vdbe_debug=on;
++PRAGMA vdbe_addoptrace=on;
DELETE FROM t1w WHERE b = 'two';
UPDATE t1w SET b = '' WHERE a = 1 OR a = 3;
DELETE FROM t1w WHERE 1; -- Avoid the truncate optimization (for now)