- C Merge\sthe\slatest\strunk\senhancements.
- D 2015-09-14T10:47:29.524
-C Add\stest\scases\sto\scover\sfts5\sintegrity-check\scode.
-D 2015-09-15T14:39:17.597
++C Merge\sthe\slatest\strunk\senhancements\swith\sthis\sbranch.
++D 2015-09-15T15:55:15.671
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
-F Makefile.in f85066ce844a28b671aaeeff320921cd0ce36239
+F Makefile.in 00b690660681c22e7ce3a9cbebd69894766ebbd8
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
-F Makefile.msc b268d8be2e800b9d35f074b1ed6b2f698deebdd6
+F Makefile.msc a71cfab97780281290f01b212f907d6d438b7e2d
F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858
F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7
F VERSION ccfc4d1576dbfdeece0a4372a2e6a2e37d3e7975
F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b
F src/date.c fb1c99172017dcc8e237339132c91a21a0788584
F src/dbstat.c e637e7a7ff40ef32132a418c6fdf1cfb63aa27c7
- F src/delete.c 7949fe60607686f3e359ae513d999d7be9ef8451
-F src/delete.c 5ab483f15aaf202290227d5dd1f10a7ecce3d6b1
++F src/delete.c fb64e308242aa09a47a874f5fd45aa00249208be
F src/expr.c 3a76afcdac925294c39903b7002ddb9e5fd29863
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 83e1baba999bed3144ea5a2143fc922edf51135f
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
- F src/insert.c 19b8749cbf1160918ed3e54c0e0e130c8ee2d0f3
-F src/insert.c 9748a37e058256eb2ead69f028ab85ebf203ad15
++F src/insert.c 7708c63195ba6397325fe64b8442085e73da6851
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
F src/lempar.c d344a95d60c24e2f490ee59db9784b1b17439012
F src/resolve.c 3126f7694b8ce0f97282d7dd3a5198b8fa18dce9
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
F src/select.c c17613385bc6b095c421b1f30548814f5fd8a9b2
-F src/shell.c 6332ef06db1390ef812cfdff1fc97b4fd76cdd42
-F src/sqlite.h.in 50f83145c6543000b7d27525ecaec59a23d8280b
+F src/shell.c 2b29a6f5c1b431eb0d25196e249d7e69b68d5ef0
+F src/sqlite.h.in 6ee38de04d4836a0a5171482aa1655eb70aa4ff9
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
F src/sqlite3ext.h 64350bf36833a56ad675e27392a913f417c5c308
- F src/sqliteInt.h 6376e8f55360a1495f2141add001d07875a98f32
-F src/sqliteInt.h 5afc6e50402be1e0a870f28e1cd8b32eb9db590f
++F src/sqliteInt.h 211b8080f46e7cda9f6df9ab590a7aec1b51d999
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
F src/tokenize.c 83c6ed569423a3af83a83973b444cf7123be33a6
F src/treeview.c 154f0acc622fa3514de8777dcedf4c8a8802b4ce
F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f
- F src/update.c ce5157218efb9b6412ca9a7536ce0eff1c9b8a72
-F src/update.c eb7ab3ff2928628692a4f14be397c95f4a681d97
++F src/update.c 04a06489008ad1d6007e6de3fbe4caed7c6c620b
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
F src/util.c fc612367108b74573c5fd13a85d0a23027f438bd
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
- F src/vdbe.c 76304f37d020d217ee6cfd3ac632fb4e6fcddb26
-F src/vdbe.c 5048103aa6bc9c01bf1a4620729256d1e873bb6c
-F src/vdbe.h 4bc88bd0e06f8046ee6ab7487c0015e85ad949ad
-F src/vdbeInt.h 8b867eac234e28627ffcace3cd4b4b79bbec664b
-F src/vdbeapi.c 0d890f57caf143b114a95ce699e59af51359c508
-F src/vdbeaux.c fd00b489ab3f44f2dca1e4344faf289b7bfcf649
-F src/vdbeblob.c 1d7b97115e7bbac4c318db416d2ca83fc779544a
-F src/vdbemem.c 19b3036aa4d676e7103b0fb5efd6327da455f915
++F src/vdbe.c b61897b3e827e600f2a773031326471e49205fa5
+F src/vdbe.h 67151895e779b35475c6c11b16be2ceb839066c8
+F src/vdbeInt.h 42fa34502937071aabd3c0596575ba9776547353
+F src/vdbeapi.c 82973abfc02aaba46ec1020423ffcee66665ee45
+F src/vdbeaux.c 4cbd4cc79dad0e2c2b9996ae018d79a7330110f4
+F src/vdbeblob.c 53ed7f38ab93922038bcfa17aae514dc47752f1e
+F src/vdbemem.c 28ab8455ac490373798cf2c21def2c1287942551
F src/vdbesort.c f5009e7a35e3065635d8918b9a31f498a499976b
F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0
F src/vtab.c 2ecfe020c10e0a0c7b078203fdba2fae844744bc
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
- P 6a513c05850949900f396c7a61accb97cc6d2af5 9a867d9fbe74fe2b33d55e32737a66e9a77b7466
- R 13a4fce04942a61d26f4e958ede5b588
- U drh
- Z 990fce3de452a73c29793e828eabdda7
-P eade355fafec558fc13dc4b08ca0b07713a2cd84
-R 1694ed50f41ea37a05fbcbd009cf49d5
++P 22ce9218fb2bb56cc5dd4e32077a16f669250d5f 1d018c35b9e81982df036f5e62a4a42219b54e02
++R ba7adfa610b6d372707d43b6ef7bdad4
+ U dan
-Z ab887f4a44598b0175c78de8cb058da9
++Z 579d0e0aee90abe69ff327b544da1baf
- 22ce9218fb2bb56cc5dd4e32077a16f669250d5f
-1d018c35b9e81982df036f5e62a4a42219b54e02
++b7469c44be77358e02892a3abc696f7caa0dcd3b
/* Special case: A DELETE without a WHERE clause deletes everything.
** It is easier just to erase the whole table. Prior to version 3.6.5,
** this optimization caused the row change count (the value returned by
- ** API function sqlite3_count_changes) to be set incorrectly.
- */
+ ** API function sqlite3_count_changes) to be set incorrectly. */
if( rcauth==SQLITE_OK
&& pWhere==0
- && !pTrigger
- && !IsVirtual(pTab)
+ && !bComplex
+ && !IsVirtual(pTab)
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
+ && db->xPreUpdateCallback==0
+#endif
- && 0==sqlite3FkRequired(pParse, pTab, 0, 0)
){
assert( !isView );
sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName);
/* Delete the index and table entries. Skip this step if pTab is really
** a view (in which case the only effect of the DELETE statement is to
- ** fire the INSTEAD OF triggers). */
+ ** fire the INSTEAD OF triggers).
+ **
+ ** If variable 'count' is non-zero, then this OP_Delete instruction should
+ ** invoke the update-hook. The pre-update-hook, on the other hand should
+ ** be invoked unless table pTab is a system table. The difference is that
+ ** the update-hook is not invoked for rows removed by REPLACE, but the
+ ** pre-update-hook is.
+ */
if( pTab->pSelect==0 ){
- sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, 0);
+ sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek);
sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0));
- if( count ){
- sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT);
- }
+ sqlite3VdbeChangeP4(v, -1, (char*)pTab, P4_TABLE);
+ if( iIdxNoSeek>=0 ){
+ sqlite3VdbeAddOp1(v, OP_Delete, iIdxNoSeek);
+ }
+ sqlite3VdbeChangeP5(v, eMode==ONEPASS_MULTI);
}
/* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
sqlite3MultiWrite(pParse);
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
- regNewData, 1, 0, OE_Replace, 1);
- regNewData, 1, 0, OE_Replace,
- ONEPASS_SINGLE, -1);
++ regNewData, 1, 0, OE_Replace, 1, -1);
}else{
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
+ if( HasRowid(pTab) ){
+ /* This OP_Delete opcode fires the pre-update-hook only. It does
+ ** not modify the b-tree. It is more efficient to let the coming
+ ** OP_Insert replace the existing entry than it is to delete the
+ ** existing entry and then insert a new one. */
+ sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, OPFLAG_ISNOOP);
+ sqlite3VdbeChangeP4(v, -1, (char *)pTab, P4_TABLE);
+ }
+#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
if( pTab->pIndex ){
sqlite3MultiWrite(pParse);
- sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, 0);
+ sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,-1);
}
}
seenReplace = 1;
}
VdbeCoverageNeverTaken(v);
}
- sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx);
+ sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx, -1);
-
- /* If changing the record number, delete the old record. */
- if( hasFK || chngKey || pPk!=0 ){
- sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0);
+
+ /* If changing the rowid value, or if there are foreign key constraints
+ ** to process, delete the old record. Otherwise, add a noop OP_Delete
+ ** to invoke the pre-update hook.
+ **
+ ** That (regNew==regnewRowid+1) is true is also important for the
+ ** pre-update hook. If the caller invokes preupdate_new(), the returned
+ ** value is copied from memory cell (regNewRowid+1+iCol), where iCol
+ ** is the column index supplied by the user.
+ */
+ assert( regNew==regNewRowid+1 );
+ sqlite3VdbeAddOp3(v, OP_Delete, iDataCur,
+ OPFLAG_ISUPDATE | ((hasFK || chngKey || pPk!=0) ? 0 : OPFLAG_ISNOOP),
+ regNewRowid
+ );
+ if( !pParse->nested ){
+ sqlite3VdbeChangeP4(v, -1, (char*)pTab, P4_TABLE);
}
if( bReplace || chngKey ){
sqlite3VdbeJumpHere(v, j1);
break;
}
- /* Opcode: Delete P1 P2 P3 P4 *
-/* Opcode: Delete P1 P2 * P4 P5
++/* Opcode: Delete P1 P2 P3 P4 P5
**
** Delete the record at which the P1 cursor is currently pointing.
**
assert( pC->pCursor!=0 ); /* Only valid for real tables, no pseudotables */
assert( pC->deferredMoveto==0 );
- hasUpdateCallback = db->xUpdateCallback && pOp->p4.z && pC->isTable;
- if( pOp->p5 && hasUpdateCallback ){
- sqlite3BtreeKeySize(pC->pCursor, &pC->movetoTarget);
- }
+
#ifdef SQLITE_DEBUG
- 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 */
- /* 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 && pOp->p5==0 ){
++ if( pOp->p4type==P4_TABLE && HasRowid(pOp->p4.pTab) && pOp->p5==0 ){
++ /* If p5 is zero, 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) ){
++ /* If the update-hook or pre-update-hook will be invoked, set zDb to
++ ** the name of the db to pass as to it. Also set local pTab to a copy
++ ** of p4.pTab. Finally, if p5 is true, indicating that this cursor was
++ ** last moved with OP_Next or OP_Prev, not Seek or NotFound, set
++ ** VdbeCursor.movetoTarget to the current rowid. */
++ if( pOp->p4.pTab && HAS_UPDATE_HOOK(db) ){
+ assert( pC->iDb>=0 );
+ zDb = db->aDb[pC->iDb].zName;
+ pTab = pOp->p4.pTab;
++ if( pOp->p5 && pC->isTable ){
++ sqlite3BtreeKeySize(pC->pCursor, &pC->movetoTarget);
++ }
+ }
+
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
+ /* Invoke the pre-update-hook if required. */
- if( db->xPreUpdateCallback && pOp->p4.z && HasRowid(pTab) ){
++ if( db->xPreUpdateCallback && pOp->p4.pTab && HasRowid(pTab) ){
+ assert( !(opflags & OPFLAG_ISUPDATE) || (aMem[pOp->p3].flags & MEM_Int) );
+ sqlite3VdbePreUpdateHook(p, pC,
+ (opflags & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_DELETE,
+ zDb, pTab, pC->movetoTarget,
+ pOp->p3
+ );
}
#endif
+
+ if( opflags & OPFLAG_ISNOOP ) break;
- rc = sqlite3BtreeDelete(pC->pCursor);
+ rc = sqlite3BtreeDelete(pC->pCursor, pOp->p5);
pC->cacheStatus = CACHE_STALE;
- /* Update the change-counter and invoke the update-hook if required. */
+ /* Invoke the update-hook if required. */
- if( rc==SQLITE_OK && hasUpdateCallback ){
- db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE,
- db->aDb[pC->iDb].zName, pOp->p4.z, pC->movetoTarget);
- assert( pC->iDb>=0 );
+ 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,
- pC->movetoTarget);
++ pC->movetoTarget);
++ assert( pC->iDb>=0 );
+ }
}
- if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
++
break;
}
/* Opcode: ResetCount * * * * *