From e807bdba86b39f5996683c14842c705e3f6e25d6 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 21 Jan 2016 17:06:33 +0000 Subject: [PATCH 1/7] Add a new hint bit on the flags parameter of sqlite3BtreeDelete(). The new BTREE_IDXDELETE bit indicates that the call is to delete an index entry corresponding to a table row that has already been deleted. FossilOrigin-Name: ac2cbadd8000947c097da5b00c00090fe58fdcff --- manifest | 23 +++++++++++++---------- manifest.uuid | 2 +- src/btree.c | 41 +++++++++++++++++++++++++++++------------ src/btree.h | 7 ++++++- src/delete.c | 5 ++++- src/sqliteInt.h | 5 ++++- src/vdbe.c | 23 ++++++++++++++++------- 7 files changed, 73 insertions(+), 33 deletions(-) diff --git a/manifest b/manifest index d459ef1f26..084be630fe 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\scomments\son\sthe\sFORDELETE\shint.\s\sNo\slogic\schanges. -D 2016-01-21T15:55:37.704 +C Add\sa\snew\shint\sbit\son\sthe\sflags\sparameter\sof\ssqlite3BtreeDelete().\s\sThe\snew\nBTREE_IDXDELETE\sbit\sindicates\sthat\sthe\scall\sis\sto\sdelete\san\sindex\sentry\s\ncorresponding\sto\sa\stable\srow\sthat\shas\salready\sbeen\sdeleted. +D 2016-01-21T17:06:33.267 F Makefile.in 7be88f5b473891e3a8c07245ed60535fcda4f9ee F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc c5ead4aa22ff6f528c755b07ed1e31184ac5b3d2 @@ -288,8 +288,8 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c 2869a76c03eb393ee795416e2387005553df72bc F src/bitvec.c 1a78d450a17c5016710eec900bedfc5729bf9bdf F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 -F src/btree.c f224ae877fde69d1a9d430f502edaf8502752dbe -F src/btree.h 526137361963e746949ab966a910c7f455ac6b04 +F src/btree.c 97cf881292e085ee71faf44f7167b6312965b562 +F src/btree.h c5dfbbc59226fa5fcc2b03befa85fe10ef23c1b5 F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 F src/build.c 31af80bba31ac159967951ef58f3144cc7db9d70 F src/callback.c 29ae4faba226c7ebb9aee93016b5ce8a8f071261 @@ -297,7 +297,7 @@ F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 F src/date.c 997651e3ee6c2818fbf7fcdb7156cef9eb3ece20 F src/dbstat.c ffd63fc8ba7541476ced189b95e95d7f2bc63f78 -F src/delete.c 00af9f08a15ddc5cba5962d3d3e5bf2d67b2e7da +F src/delete.c f02e46234c5fc86f6c03ae34dc0ba48e93cd5029 F src/expr.c df0d7c3230d59abd679da22ff5ce4cfd0e3a0e63 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c e18b3dff7d47c7bcac5ac4fc178a89b9fd322b44 @@ -350,7 +350,7 @@ F src/shell.c dcd7a83645ef2a58ee9c6d0ea4714d877d7835c4 F src/sqlite.h.in 214476a62012e578f42133a9a3b4f97a9aa421a3 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h 0403328581127bc8ad2f9cc7af2c3bb23d5316da +F src/sqliteInt.h 46e0bac7a3cdab96e8b5afd1436accc25d2c3d6a F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e @@ -410,7 +410,7 @@ F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3 F src/utf.c 32d7f82aa921322f3e1c956f4b58f019ebd2c6b3 F src/util.c e802e8e311a0d6c48cd1b3e89db164f6f0248d70 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 -F src/vdbe.c b90d9d38e5e0260c2eafa3cb4c2274d8ea94da27 +F src/vdbe.c e21a506d17a7397cba16c162d8c9c96e9769c68e F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 F src/vdbeInt.h 42eefa4f9e7432b9968d321b44e48821ec13b189 F src/vdbeapi.c ffae8f5af4570fbd548504e815e9fb7227f0822e @@ -1419,7 +1419,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P f60f025027ab3acdbc97701f81ff9c11c8463022 -R 58c662ebb54c7087fe70ba0b9b653627 +P a3cec529f0238e4ca1196fec420f2de80d28db78 +R 76198b2176fddd32b1fb9b7a5f18b4c8 +T *branch * btree-fordelete-flag +T *sym-btree-fordelete-flag * +T -sym-trunk * U drh -Z 656e64b9ebb4ed29ac85ca9fad2e65b0 +Z c987d8ca8053309611f1f75e6c6acde5 diff --git a/manifest.uuid b/manifest.uuid index 80d0db3e83..57018fb84b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a3cec529f0238e4ca1196fec420f2de80d28db78 \ No newline at end of file +ac2cbadd8000947c097da5b00c00090fe58fdcff \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 4e6f6478af..89144e7a84 100644 --- a/src/btree.c +++ b/src/btree.c @@ -4049,13 +4049,13 @@ int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){ ** on the database already. If a write-cursor is requested, then ** the caller is assumed to have an open write transaction. ** -** If wrFlag==0, then the cursor can only be used for reading. -** If wrFlag==1, then the cursor can be used for reading or for -** writing if other conditions for writing are also met. These -** are the conditions that must be met in order for writing to -** be allowed: +** If the BTREE_WRCSR bit of wrFlag is clear, then the cursor can only +** be used for reading. If the BTREE_WRCSR bit is set, then the cursor +** can be used for reading or for writing if other conditions for writing +** are also met. These are the conditions that must be met in order +** for writing to be allowed: ** -** 1: The cursor must have been opened with wrFlag==1 +** 1: The cursor must have been opened with wrFlag containing BTREE_WRCSR ** ** 2: Other database connections that share the same pager cache ** but which are not in the READ_UNCOMMITTED state may not have @@ -4067,6 +4067,16 @@ int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){ ** ** 4: There must be an active transaction. ** +** The BTREE_FORDELETE bit of wrFlag may optionally be set if BTREE_WRCSR +** is set. If FORDELETE is set, that is a hint to the implementation that +** this cursor will only be used to seek to and delete entries of an index +** as part of a larger DELETE statement. The FORDELETE hint is not used by +** this implementation. But in a hypothetical alternative storage engine +** in which index entries are automatically deleted when corresponding table +** rows are deleted, the FORDELETE flag is a hint that all SEEK and DELETE +** operations on this cursor can be no-ops and all READ operations can +** return a null row (2-bytes: 0x01 0x00). +** ** No checking is done to make sure that page iTable really is the ** root page of a b-tree. If it is not, then the cursor acquired ** will not work correctly. @@ -8082,13 +8092,18 @@ end_insert: /* ** Delete the entry that the cursor is pointing to. ** -** If the second parameter is zero, then the cursor is left pointing at an -** arbitrary location after the delete. If it is non-zero, then the cursor -** is left in a state such that the next call to BtreeNext() or BtreePrev() -** moves it to the same row as it would if the call to BtreeDelete() had -** been omitted. +** If the BTREE_SAVEPOSITION bit of the flags parameter is zero, then +** the cursor is left pointing at an arbitrary location after the delete. +** But if that bit is set, then the cursor is left in a state such that +** the next call to BtreeNext() or BtreePrev() moves it to the same row +** as it would have been on if the call to BtreeDelete() had been omitted. +** +** The BTREE_IDXDELETE bit of flags indicates that this is a delete of +** an index entry where the corresponding table row has already been deleted. +** The BTREE_IDXDELETE bit is a hint that is not used by this implementation, +** but which might be used by alternative storage engines. */ -int sqlite3BtreeDelete(BtCursor *pCur, int bPreserve){ +int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ Btree *p = pCur->pBtree; BtShared *pBt = p->pBt; int rc; /* Return code */ @@ -8098,6 +8113,7 @@ int sqlite3BtreeDelete(BtCursor *pCur, int bPreserve){ int iCellDepth; /* Depth of node containing pCell */ u16 szCell; /* Size of the cell being deleted */ int bSkipnext = 0; /* Leaf cursor in SKIPNEXT state */ + u8 bPreserve = flags & BTREE_SAVEPOSITION; /* Keep cursor valid */ assert( cursorOwnsBtShared(pCur) ); assert( pBt->inTransaction==TRANS_WRITE ); @@ -8107,6 +8123,7 @@ int sqlite3BtreeDelete(BtCursor *pCur, int bPreserve){ assert( !hasReadConflicts(p, pCur->pgnoRoot) ); assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell ); assert( pCur->eState==CURSOR_VALID ); + assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_IDXDELETE))==0 ); iCellDepth = pCur->iPage; iCellIdx = pCur->aiIdx[iCellDepth]; diff --git a/src/btree.h b/src/btree.h index 37a9915eda..416faca651 100644 --- a/src/btree.h +++ b/src/btree.h @@ -245,7 +245,12 @@ int sqlite3BtreeMovetoUnpacked( ); int sqlite3BtreeCursorHasMoved(BtCursor*); int sqlite3BtreeCursorRestore(BtCursor*, int*); -int sqlite3BtreeDelete(BtCursor*, int); +int sqlite3BtreeDelete(BtCursor*, u8 flags); + +/* Allowed flags for the 2nd argument to sqlite3BtreeDelete() */ +#define BTREE_SAVEPOSITION 0x02 /* Leave cursor pointing at NEXT or PREV */ +#define BTREE_IDXDELETE 0x04 /* this is index, table row already deleted */ + int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey, const void *pData, int nData, int nZero, int bias, int seekResult); diff --git a/src/delete.c b/src/delete.c index ed273bde81..98c49c9930 100644 --- a/src/delete.c +++ b/src/delete.c @@ -718,6 +718,7 @@ void sqlite3GenerateRowDelete( ** a view (in which case the only effect of the DELETE statement is to ** fire the INSTEAD OF triggers). */ if( pTab->pSelect==0 ){ + u8 p5 = 0; sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek); sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0)); if( count ){ @@ -725,8 +726,10 @@ void sqlite3GenerateRowDelete( } if( iIdxNoSeek>=0 ){ sqlite3VdbeAddOp1(v, OP_Delete, iIdxNoSeek); + if( eMode!=ONEPASS_OFF ) p5 = OPFLAG_IDXDELETE; } - sqlite3VdbeChangeP5(v, eMode==ONEPASS_MULTI); + if( eMode==ONEPASS_MULTI ) p5 |= OPFLAG_SAVEPOSITION; + sqlite3VdbeChangeP5(v, p5); } /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to diff --git a/src/sqliteInt.h b/src/sqliteInt.h index b536b8ab28..25aff00151 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2847,7 +2847,8 @@ struct AuthContext { /* ** Bitfield flags for P5 value in various opcodes. */ -#define OPFLAG_NCHANGE 0x01 /* Set to update db->nChange */ +#define OPFLAG_NCHANGE 0x01 /* OP_Insert: Set to update db->nChange */ + /* Also used in P2 (not P5) of OP_Delete */ #define OPFLAG_EPHEM 0x01 /* OP_Column: Ephemeral output is ok */ #define OPFLAG_LASTROWID 0x02 /* Set to update db->lastRowid */ #define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */ @@ -2860,6 +2861,8 @@ struct AuthContext { #define OPFLAG_FORDELETE 0x08 /* OP_Open should use BTREE_FORDELETE */ #define OPFLAG_P2ISREG 0x10 /* P2 to OP_Open** is a register number */ #define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */ +#define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete: keep cursor position */ +#define OPFLAG_IDXDELETE 0x04 /* OP_Delete: index in a DELETE op */ /* * Each trigger present in the database schema is stored as an instance of diff --git a/src/vdbe.c b/src/vdbe.c index c6d5f7b0cc..c290097da2 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -4341,14 +4341,20 @@ case OP_InsertInt: { ** ** Delete the record at which the P1 cursor is currently pointing. ** -** If the P5 parameter is non-zero, the cursor will be left pointing at -** either the next or the previous record in the table. If it is left -** pointing at the next record, then the next Next instruction will be a -** no-op. As a result, in this case it is OK to delete a record from within a -** Next loop. If P5 is zero, then the cursor is left in an undefined state. +** If the OPFLAG_SAVEPOSITION bit of the P5 parameter is set, then +** the cursor will be left pointing at either the next or the previous +** record in the table. If it is left pointing at the next record, then +** the next Next instruction will be a no-op. As a result, in this case +** it is ok to delete a record from within a Next loop. If +** OPFLAG_SAVEPOSITION bit of P5 is clear, then the cursor will be +** left in an undefined state. ** -** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is -** incremented (otherwise not). +** If the OPFLAG_IDXDELETE bit is set on P5, that indicates that this +** delete is on an index cursor where the corresponding table row has +** already been deleted. +** +** If the OPFLAG_NCHANGE flag of P2 (NB: P2 not P5) is set, then the row +** change count is incremented (otherwise not). ** ** P1 must not be pseudo-table. It has to be a real table with ** multiple rows. @@ -4385,6 +4391,9 @@ case OP_Delete: { } #endif + assert( (pOp->p5 & ~(OPFLAG_SAVEPOSITION|OPFLAG_IDXDELETE))==0 ); + assert( OPFLAG_SAVEPOSITION==BTREE_SAVEPOSITION ); + assert( OPFLAG_IDXDELETE==BTREE_IDXDELETE ); rc = sqlite3BtreeDelete(pC->uc.pCursor, pOp->p5); pC->cacheStatus = CACHE_STALE; From b89aeb6aa2cacdb57ef4bd73f980eb4f16ec52e4 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 27 Jan 2016 15:49:32 +0000 Subject: [PATCH 2/7] Add assert() statements on the nExtraDelete variable in vdbe.c to try to verify that the FORDELETE and IDXDELETE flags are being generated correctly. Those flags are not currently generated correctly, and so the assert()s trip on this check-in. FossilOrigin-Name: dde1db0dd2e2cf04706117629756c352b178ebb8 --- manifest | 25 ++++++++++++++----------- manifest.uuid | 2 +- src/delete.c | 11 +++++++---- src/insert.c | 11 ++++++----- src/vdbe.c | 34 ++++++++++++++++++++++++++++++++-- src/vdbeInt.h | 1 + test/e_changes.test | 1 + 7 files changed, 62 insertions(+), 23 deletions(-) diff --git a/manifest b/manifest index 101db20db8..bf4b14906c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sall\srecent\strunk\senhancements. -D 2016-01-26T23:32:55.750 +C Add\sassert()\sstatements\son\sthe\snExtraDelete\svariable\sin\svdbe.c\sto\stry\sto\sverify\nthat\sthe\sFORDELETE\sand\sIDXDELETE\sflags\sare\sbeing\sgenerated\scorrectly.\s\sThose\nflags\sare\snot\scurrently\sgenerated\scorrectly,\sand\sso\sthe\sassert()s\strip\son\sthis\ncheck-in. +D 2016-01-27T15:49:32.327 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6fca5455aaecbd14479f33f091aa19df2d3d2969 @@ -13,7 +13,7 @@ F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 F autoconf/Makefile.am 1c1657650775960804945dc392e14d9e43c5ed84 F autoconf/Makefile.msc 68ed752a809b611d97b95d8572a34fe6fd1196f1 F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 -F autoconf/README.txt e9757a381e5ce2553dbaa6247bb8ad00eb8d87aa w autoconf/README +F autoconf/README.txt e9757a381e5ce2553dbaa6247bb8ad00eb8d87aa F autoconf/configure.ac 7b1ea0dcaf49fafba262ce4b0ee8cb3281b555d1 F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873 @@ -299,7 +299,7 @@ F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 F src/date.c 997651e3ee6c2818fbf7fcdb7156cef9eb3ece20 F src/dbstat.c b2ec6793eef97aebb4d171d490a4ffdfa9f2475c -F src/delete.c f02e46234c5fc86f6c03ae34dc0ba48e93cd5029 +F src/delete.c db231a9895681efed007c0887e38b49f4d1291a5 F src/expr.c d10c1cdef5810cdbf73adc9f9b383684230b360a F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c c66d3e5b35d4d95b5c1e2ee6c12f5df13a7f9ad6 @@ -308,7 +308,7 @@ F src/global.c bd5a0af3f30b0c01be6db756c626cd3c33a3d260 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c a00e6d8a843dc22e2c136df04e6300c4528d9b9f +F src/insert.c 410f52b9ef4603dc0aebb169b7cb6b3c60eda07e F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e F src/loadext.c 84996d7d70a605597d79c1f1d7b2012a5fd34f2b @@ -412,9 +412,9 @@ F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3 F src/utf.c 32d7f82aa921322f3e1c956f4b58f019ebd2c6b3 F src/util.c 72d40df0a52d3f30b462a15f0e094fcbade6dc82 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 -F src/vdbe.c 6039096edea4ed25f7b1e28aa5d46b0ee3ba73ef +F src/vdbe.c a27a3fdc65f5728c6e9bff49b6753fbf9d73c8c0 F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 -F src/vdbeInt.h 42eefa4f9e7432b9968d321b44e48821ec13b189 +F src/vdbeInt.h 40c728712a2975855a2ac6aac44bf02dfd4a4c30 F src/vdbeapi.c ffae8f5af4570fbd548504e815e9fb7227f0822e F src/vdbeaux.c 757f86e6fef8efb3dd4226cb31e2e82b9c44c883 F src/vdbeblob.c 37c3d11a753e403698c69e17383d282e1ae73e75 @@ -595,7 +595,7 @@ F test/e_blobbytes.test 9bea1d3e2b20f3010b04abba58f6ba172301f49f F test/e_blobclose.test df756753f571bc30e42e3a6cba2807576e49e716 F test/e_blobopen.test 234f960d90235a9b51ec3ca1e062e8541dd558d8 F test/e_blobwrite.test 615b405f29feb2cfb5a1f03dab7933258294fa26 -F test/e_changes.test fd66105385153dbf21fdb35eb8ef6c3e1eade579 +F test/e_changes.test d66e8c1e33f5ec61af32eda729c8a2475404e49b F test/e_createtable.test d4c6059d44dcd4b636de9aae322766062b471844 F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412 @@ -1422,7 +1422,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P ac2cbadd8000947c097da5b00c00090fe58fdcff a3d7b8ac53f94d29a11362f193fd1967f30583df -R 7855243eb7d1aae3e5a98345ca05c333 +P 9a71d56dcea953cb965f1fdda9a8b8f158cdeff6 +R 3af2d64e2a860c6e0d1b5193b911b983 +T *branch * fordelete-assert +T *sym-fordelete-assert * +T -sym-btree-fordelete-flag * U drh -Z 6eda54656ca87ef44dc31ff7472a92ee +Z f5e1f3160ce620e13f32c1dda67a1107 diff --git a/manifest.uuid b/manifest.uuid index 7255a707a7..beafd3f9d6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9a71d56dcea953cb965f1fdda9a8b8f158cdeff6 \ No newline at end of file +dde1db0dd2e2cf04706117629756c352b178ebb8 \ No newline at end of file diff --git a/src/delete.c b/src/delete.c index 98c49c9930..b3143c5f72 100644 --- a/src/delete.c +++ b/src/delete.c @@ -479,13 +479,12 @@ void sqlite3DeleteFrom( */ if( !isView ){ int iAddrOnce = 0; - u8 p5 = (eOnePass==ONEPASS_OFF ? 0 : OPFLAG_FORDELETE); if( eOnePass==ONEPASS_MULTI ){ iAddrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v); } testcase( IsVirtual(pTab) ); - sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, p5, iTabCur, - aToOpen, &iDataCur, &iIdxCur); + sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, OPFLAG_FORDELETE, + iTabCur, aToOpen, &iDataCur, &iIdxCur); assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur ); assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 ); if( eOnePass==ONEPASS_MULTI ) sqlite3VdbeJumpHere(v, iAddrOnce); @@ -724,9 +723,13 @@ void sqlite3GenerateRowDelete( if( count ){ sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT); } + if( eMode!=ONEPASS_OFF ){ + sqlite3VdbeChangeP5(v, OPFLAG_IDXDELETE); + p5 = OPFLAG_IDXDELETE; + } if( iIdxNoSeek>=0 ){ sqlite3VdbeAddOp1(v, OP_Delete, iIdxNoSeek); - if( eMode!=ONEPASS_OFF ) p5 = OPFLAG_IDXDELETE; + p5 = 0; } if( eMode==ONEPASS_MULTI ) p5 |= OPFLAG_SAVEPOSITION; sqlite3VdbeChangeP5(v, p5); diff --git a/src/insert.c b/src/insert.c index 8082bcb459..cbe933c221 100644 --- a/src/insert.c +++ b/src/insert.c @@ -1647,7 +1647,7 @@ int sqlite3OpenTableAndIndices( Parse *pParse, /* Parsing context */ Table *pTab, /* Table to be opened */ int op, /* OP_OpenRead or OP_OpenWrite */ - u8 p5, /* P5 value for OP_Open* instructions */ + u8 p5, /* P5 value for OP_Open* opcodes (except on WITHOUT ROWID) */ int iBase, /* Use this for the table cursor, if there is one */ u8 *aToOpen, /* If not NULL: boolean for each table and index */ int *piDataCur, /* Write the database source cursor number here */ @@ -1682,15 +1682,16 @@ int sqlite3OpenTableAndIndices( for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ int iIdxCur = iBase++; assert( pIdx->pSchema==pTab->pSchema ); - if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) && piDataCur ){ - *piDataCur = iIdxCur; - } if( aToOpen==0 || aToOpen[i+1] ){ sqlite3VdbeAddOp3(v, op, iIdxCur, pIdx->tnum, iDb); sqlite3VdbeSetP4KeyInfo(pParse, pIdx); - sqlite3VdbeChangeP5(v, p5); VdbeComment((v, "%s", pIdx->zName)); } + if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){ + if( piDataCur ) *piDataCur = iIdxCur; + }else{ + sqlite3VdbeChangeP5(v, p5); + } } if( iBase>pParse->nTab ) pParse->nTab = iBase; return i; diff --git a/src/vdbe.c b/src/vdbe.c index adbdab0652..8583bcd4ba 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -551,6 +551,9 @@ int sqlite3VdbeExec( Op *pOp = aOp; /* Current operation */ #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) Op *pOrigOp; /* Value of pOp at the top of the loop */ +#endif +#ifdef SQLITE_DEBUG + int nExtraDelete = 0; /* Verifies FORDELETE and IDXDELETE flags */ #endif int rc = SQLITE_OK; /* Value to return */ sqlite3 *db = p->db; /* The database */ @@ -3392,6 +3395,9 @@ case OP_OpenWrite: pCur->nullRow = 1; pCur->isOrdered = 1; pCur->pgnoRoot = p2; +#ifdef SQLITE_DEBUG + pCur->wrFlag = wrFlag; +#endif rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->uc.pCursor); pCur->pKeyInfo = pKeyInfo; /* Set the VdbeCursor.isTable variable. Previous versions of @@ -4390,10 +4396,24 @@ case OP_Delete: { assert( pC->movetoTarget==iKey ); } #endif - + + /* Only flags that can be set are SAVEPOISTION and IDXDELETE */ assert( (pOp->p5 & ~(OPFLAG_SAVEPOSITION|OPFLAG_IDXDELETE))==0 ); assert( OPFLAG_SAVEPOSITION==BTREE_SAVEPOSITION ); assert( OPFLAG_IDXDELETE==BTREE_IDXDELETE ); + +#ifdef SQLITE_DEBUG + if( pC->isEphemeral==0 + && (pOp->p5 & OPFLAG_IDXDELETE)==0 + && (pC->wrFlag & OPFLAG_FORDELETE)==0 + ){ + nExtraDelete++; + } + if( pOp->p2 & OPFLAG_NCHANGE ){ + nExtraDelete--; + } +#endif + rc = sqlite3BtreeDelete(pC->uc.pCursor, pOp->p5); pC->cacheStatus = CACHE_STALE; @@ -4939,7 +4959,16 @@ case OP_IdxDelete: { r.default_rc = 0; r.aMem = &aMem[pOp->p2]; #ifdef SQLITE_DEBUG - { int i; for(i=0; iisEphemeral==0 + && (pOp->p5 & OPFLAG_IDXDELETE)==0 + && (pC->wrFlag & OPFLAG_FORDELETE)==0 + ){ + nExtraDelete++; + } + } #endif rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res); if( rc==SQLITE_OK && res==0 ){ @@ -6762,6 +6791,7 @@ vdbe_return: testcase( nVmStep>0 ); p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep; sqlite3VdbeLeave(p); + assert( nExtraDelete==0 || sqlite3_strlike("DELETE%",p->zSql,0)!=0 ); return rc; /* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH diff --git a/src/vdbeInt.h b/src/vdbeInt.h index b231cf908e..646cf31fed 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -82,6 +82,7 @@ struct VdbeCursor { u8 isTable; /* True for rowid tables. False for indexes */ #ifdef SQLITE_DEBUG u8 seekOp; /* Most recent seek operation on this cursor */ + u8 wrFlag; /* The wrFlag argument to sqlite3BtreeCursor() */ #endif Bool isEphemeral:1; /* True for an ephemeral table */ Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */ diff --git a/test/e_changes.test b/test/e_changes.test index a77e22a2ee..c4b4406f7b 100644 --- a/test/e_changes.test +++ b/test/e_changes.test @@ -65,6 +65,7 @@ foreach {tn schema} { UPDATE t1 SET b=b+1 WHERE a<5; } 5 +exit # Delete 4 rows do_changes_test 1.$tn.4 { DELETE FROM t1 WHERE a>6 From 127f720240d07433276e0ce98cb8426a23266467 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 27 Jan 2016 16:17:41 +0000 Subject: [PATCH 3/7] Fix tests in fordelete.test to test for the BTREE_AUXDELETE flag. FossilOrigin-Name: bbd25cf179df5bda1fe729928d6746248f06e46f --- manifest | 17 ++++++------- manifest.uuid | 2 +- test/fordelete.test | 58 +++++++++++++++++++++++++++++++++++---------- 3 files changed, 53 insertions(+), 24 deletions(-) diff --git a/manifest b/manifest index bf4b14906c..dfebd3f6ae 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sassert()\sstatements\son\sthe\snExtraDelete\svariable\sin\svdbe.c\sto\stry\sto\sverify\nthat\sthe\sFORDELETE\sand\sIDXDELETE\sflags\sare\sbeing\sgenerated\scorrectly.\s\sThose\nflags\sare\snot\scurrently\sgenerated\scorrectly,\sand\sso\sthe\sassert()s\strip\son\sthis\ncheck-in. -D 2016-01-27T15:49:32.327 +C Fix\stests\sin\sfordelete.test\sto\stest\sfor\sthe\sBTREE_AUXDELETE\sflag. +D 2016-01-27T16:17:41.726 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6fca5455aaecbd14479f33f091aa19df2d3d2969 @@ -642,7 +642,7 @@ F test/fkey6.test abb59f866c1b44926fd02d1fdd217d831fe04f48 F test/fkey7.test 72e915890ee4a005daaf3002cb208e8fe973ac13 F test/fkey8.test 8f08203458321e6c19a263829de4cfc936274ab0 F test/fkey_malloc.test 594a7ea1fbab553c036c70813cd8bd9407d63749 -F test/fordelete.test ba12ec1d27cc34a4c23db4446029126d773f3849 +F test/fordelete.test f794392f1768584609fa439f7528484dc04d3a03 F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb F test/fts-9fd058691.test 78b887e30ae6816df0e1fed6259de4b5a64ad33c F test/fts1a.test 46090311f85da51bb33bd5ce84f7948359c6d8d7 @@ -1422,10 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 9a71d56dcea953cb965f1fdda9a8b8f158cdeff6 -R 3af2d64e2a860c6e0d1b5193b911b983 -T *branch * fordelete-assert -T *sym-fordelete-assert * -T -sym-btree-fordelete-flag * -U drh -Z f5e1f3160ce620e13f32c1dda67a1107 +P dde1db0dd2e2cf04706117629756c352b178ebb8 +R 112344660260002964aa8c335bb07305 +U dan +Z e0043c886092534757bb67db359c02f9 diff --git a/manifest.uuid b/manifest.uuid index beafd3f9d6..2b4460a277 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -dde1db0dd2e2cf04706117629756c352b178ebb8 \ No newline at end of file +bbd25cf179df5bda1fe729928d6746248f06e46f \ No newline at end of file diff --git a/test/fordelete.test b/test/fordelete.test index 1e860e8867..7a49b5cbfd 100644 --- a/test/fordelete.test +++ b/test/fordelete.test @@ -30,17 +30,49 @@ proc analyze_delete_program {sql} { } { set T($rootpage) $name } - - # Calculate the results. - set res [list] + + # For each OpenWrite instruction generated for the proposed DELETE + # statement, add the following array entries: + # + # $M() -> + # $O() -> "*" | "" + # + # The O() entry is set to "*" if the BTREE_FORDELETE flag is specified, + # or "" otherwise. + # db eval "EXPLAIN $sql" R { - if {$R(opcode) == "OpenWrite"} { - set obj $T($R(p2)) - if {"0x$R(p5)" & 0x08} { append obj *} - lappend res $obj + if {$R(opcode)=="OpenWrite"} { + set root $R(p2) + set csr $R(p1) + if {[info exists T($root)]} { set M($csr) $T($root) } + + set obj $T($root) + set O($obj) "" + if {"0x$R(p5)" & 0x08} { + set O($obj) * + } else { + set O($obj) "" + } } } + db eval "EXPLAIN $sql" R { + if {$R(opcode) == "Delete"} { + set csr $R(p1) + if {[info exists M($csr)]} { + set idxdelete [expr {("0x$R(p5)" & 0x04) ? 1 : 0}] + if {$idxdelete} { + append O($M($csr)) "+" + } + } + } + } + + set res [list] + foreach {k v} [array get O] { + lappend res "${k}${v}" + } + lsort $res } @@ -53,10 +85,10 @@ do_execsql_test 1.0 { } foreach {tn sql res} { - 1 { DELETE FROM t1 WHERE a=?} { sqlite_autoindex_t1_1 t1* } - 2 { DELETE FROM t1 WHERE a=? AND b=? } { sqlite_autoindex_t1_1 t1 } - 3 { DELETE FROM t1 WHERE a>? } { sqlite_autoindex_t1_1 t1* } - 4 { DELETE FROM t1 WHERE rowid=? } { sqlite_autoindex_t1_1* t1 } + 1 { DELETE FROM t1 WHERE a=?} { sqlite_autoindex_t1_1 t1*+ } + 2 { DELETE FROM t1 WHERE a=? AND b=? } { sqlite_autoindex_t1_1 t1+ } + 3 { DELETE FROM t1 WHERE a>? } { sqlite_autoindex_t1_1 t1*+ } + 4 { DELETE FROM t1 WHERE rowid=? } { sqlite_autoindex_t1_1* t1 } } { do_adp_test 1.$tn $sql $res } @@ -68,8 +100,8 @@ do_execsql_test 2.0 { CREATE INDEX t2c ON t2(c); } foreach {tn sql res} { - 1 { DELETE FROM t2 WHERE a=?} { t2* t2a t2b* t2c* } - 2 { DELETE FROM t2 WHERE a=? AND +b=?} { t2 t2a t2b* t2c* } + 1 { DELETE FROM t2 WHERE a=?} { t2*+ t2a t2b* t2c* } + 2 { DELETE FROM t2 WHERE a=? AND +b=?} { t2+ t2a t2b* t2c* } 3 { DELETE FROM t2 WHERE a=? OR b=?} { t2 t2a* t2b* t2c* } 4 { DELETE FROM t2 WHERE +a=? } { t2 t2a* t2b* t2c* } 5 { DELETE FROM t2 WHERE rowid=? } { t2 t2a* t2b* t2c* } From def19e3b48c4064f38e6c701469f5365962f1481 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 27 Jan 2016 16:26:25 +0000 Subject: [PATCH 4/7] Change the name of the BTREE_IDXDELETE flag to BTREE_AUXDELETE, to better reflect its purpose. FossilOrigin-Name: 1d3bf6bebdda9f96734bc139601e9b05344ea0b4 --- manifest | 22 +++++++++++----------- manifest.uuid | 2 +- src/btree.c | 11 +++++++---- src/btree.h | 2 +- src/delete.c | 4 +--- src/sqliteInt.h | 2 +- src/vdbe.c | 20 +++++++++++--------- 7 files changed, 33 insertions(+), 30 deletions(-) diff --git a/manifest b/manifest index dfebd3f6ae..9790c25453 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\stests\sin\sfordelete.test\sto\stest\sfor\sthe\sBTREE_AUXDELETE\sflag. -D 2016-01-27T16:17:41.726 +C Change\sthe\sname\sof\sthe\sBTREE_IDXDELETE\sflag\sto\sBTREE_AUXDELETE,\sto\sbetter\nreflect\sits\spurpose. +D 2016-01-27T16:26:25.226 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6fca5455aaecbd14479f33f091aa19df2d3d2969 @@ -290,8 +290,8 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c 2869a76c03eb393ee795416e2387005553df72bc F src/bitvec.c 1a78d450a17c5016710eec900bedfc5729bf9bdf F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 -F src/btree.c 97cf881292e085ee71faf44f7167b6312965b562 -F src/btree.h c5dfbbc59226fa5fcc2b03befa85fe10ef23c1b5 +F src/btree.c 16edaf415a54a2fc9058e3bc47d0c894cd59635e +F src/btree.h 368ceeb4bd9312dc8df2ffd64b4b7dbcf4db5f8e F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 F src/build.c b4eba1e84752ec9cae7ff3dacd5a8b6d1ab8deb9 F src/callback.c 29ae4faba226c7ebb9aee93016b5ce8a8f071261 @@ -299,7 +299,7 @@ F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 F src/date.c 997651e3ee6c2818fbf7fcdb7156cef9eb3ece20 F src/dbstat.c b2ec6793eef97aebb4d171d490a4ffdfa9f2475c -F src/delete.c db231a9895681efed007c0887e38b49f4d1291a5 +F src/delete.c 33ed87dc0746b1f8ce186f62b608bf40801af9c0 F src/expr.c d10c1cdef5810cdbf73adc9f9b383684230b360a F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c c66d3e5b35d4d95b5c1e2ee6c12f5df13a7f9ad6 @@ -352,7 +352,7 @@ F src/shell.c dcd7a83645ef2a58ee9c6d0ea4714d877d7835c4 F src/sqlite.h.in 214476a62012e578f42133a9a3b4f97a9aa421a3 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h 0faffdeed20201bedb202cf6ec07f14b29158c66 +F src/sqliteInt.h 12ec54454fc0f1c25f5c7057423ada1a363b6db0 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e @@ -412,7 +412,7 @@ F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3 F src/utf.c 32d7f82aa921322f3e1c956f4b58f019ebd2c6b3 F src/util.c 72d40df0a52d3f30b462a15f0e094fcbade6dc82 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 -F src/vdbe.c a27a3fdc65f5728c6e9bff49b6753fbf9d73c8c0 +F src/vdbe.c c367615fecb5fae8a39113ee2b6ecbab94e4bcd3 F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 F src/vdbeInt.h 40c728712a2975855a2ac6aac44bf02dfd4a4c30 F src/vdbeapi.c ffae8f5af4570fbd548504e815e9fb7227f0822e @@ -1422,7 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P dde1db0dd2e2cf04706117629756c352b178ebb8 -R 112344660260002964aa8c335bb07305 -U dan -Z e0043c886092534757bb67db359c02f9 +P bbd25cf179df5bda1fe729928d6746248f06e46f +R 21474325914b9893f106ce3a1694990c +U drh +Z 6ce2f1bf15f4f84bace517d6cc10a5ac diff --git a/manifest.uuid b/manifest.uuid index 2b4460a277..d16254398c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bbd25cf179df5bda1fe729928d6746248f06e46f \ No newline at end of file +1d3bf6bebdda9f96734bc139601e9b05344ea0b4 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 89144e7a84..04748e1b37 100644 --- a/src/btree.c +++ b/src/btree.c @@ -8098,9 +8098,12 @@ end_insert: ** the next call to BtreeNext() or BtreePrev() moves it to the same row ** as it would have been on if the call to BtreeDelete() had been omitted. ** -** The BTREE_IDXDELETE bit of flags indicates that this is a delete of -** an index entry where the corresponding table row has already been deleted. -** The BTREE_IDXDELETE bit is a hint that is not used by this implementation, +** The BTREE_AUXDELETE bit of flags indicates that is one of several deletes +** associated with a single table entry and its indexes. Only one of those +** deletes is considered the "primary" delete. The primary delete occurs +** on a cursor that is not a BTREE_FORDELETE cursor. All but one delete +** operation on non-FORDELETE cursors is tagged with the AUXDELETE flag. +** The BTREE_AUXDELETE bit is a hint that is not used by this implementation, ** but which might be used by alternative storage engines. */ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ @@ -8123,7 +8126,7 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ assert( !hasReadConflicts(p, pCur->pgnoRoot) ); assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell ); assert( pCur->eState==CURSOR_VALID ); - assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_IDXDELETE))==0 ); + assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 ); iCellDepth = pCur->iPage; iCellIdx = pCur->aiIdx[iCellDepth]; diff --git a/src/btree.h b/src/btree.h index 416faca651..30522e99e1 100644 --- a/src/btree.h +++ b/src/btree.h @@ -249,7 +249,7 @@ int sqlite3BtreeDelete(BtCursor*, u8 flags); /* Allowed flags for the 2nd argument to sqlite3BtreeDelete() */ #define BTREE_SAVEPOSITION 0x02 /* Leave cursor pointing at NEXT or PREV */ -#define BTREE_IDXDELETE 0x04 /* this is index, table row already deleted */ +#define BTREE_AUXDELETE 0x04 /* not the primary delete operation */ int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey, const void *pData, int nData, diff --git a/src/delete.c b/src/delete.c index b3143c5f72..5b5a5e3cb1 100644 --- a/src/delete.c +++ b/src/delete.c @@ -724,12 +724,10 @@ void sqlite3GenerateRowDelete( sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT); } if( eMode!=ONEPASS_OFF ){ - sqlite3VdbeChangeP5(v, OPFLAG_IDXDELETE); - p5 = OPFLAG_IDXDELETE; + sqlite3VdbeChangeP5(v, OPFLAG_AUXDELETE); } if( iIdxNoSeek>=0 ){ sqlite3VdbeAddOp1(v, OP_Delete, iIdxNoSeek); - p5 = 0; } if( eMode==ONEPASS_MULTI ) p5 |= OPFLAG_SAVEPOSITION; sqlite3VdbeChangeP5(v, p5); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 9aeffe216c..364b7a352e 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2862,7 +2862,7 @@ struct AuthContext { #define OPFLAG_P2ISREG 0x10 /* P2 to OP_Open** is a register number */ #define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */ #define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete: keep cursor position */ -#define OPFLAG_IDXDELETE 0x04 /* OP_Delete: index in a DELETE op */ +#define OPFLAG_AUXDELETE 0x04 /* OP_Delete: index in a DELETE op */ /* * Each trigger present in the database schema is stored as an instance of diff --git a/src/vdbe.c b/src/vdbe.c index 8583bcd4ba..f6a7946e6f 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -553,7 +553,7 @@ int sqlite3VdbeExec( Op *pOrigOp; /* Value of pOp at the top of the loop */ #endif #ifdef SQLITE_DEBUG - int nExtraDelete = 0; /* Verifies FORDELETE and IDXDELETE flags */ + int nExtraDelete = 0; /* Verifies FORDELETE and AUXDELETE flags */ #endif int rc = SQLITE_OK; /* Value to return */ sqlite3 *db = p->db; /* The database */ @@ -4355,9 +4355,11 @@ case OP_InsertInt: { ** OPFLAG_SAVEPOSITION bit of P5 is clear, then the cursor will be ** left in an undefined state. ** -** If the OPFLAG_IDXDELETE bit is set on P5, that indicates that this -** delete is on an index cursor where the corresponding table row has -** already been deleted. +** If the OPFLAG_AUXDELETE bit is set on P5, that indicates that this +** delete one of several associated with deleting a table row and all its +** associated index entries. Exactly one of those deletes is the "primary" +** delete. The others are all on OPFLAG_FORDELETE cursors or else are +** marked with the AUXDELETE flag. ** ** If the OPFLAG_NCHANGE flag of P2 (NB: P2 not P5) is set, then the row ** change count is incremented (otherwise not). @@ -4397,14 +4399,14 @@ case OP_Delete: { } #endif - /* Only flags that can be set are SAVEPOISTION and IDXDELETE */ - assert( (pOp->p5 & ~(OPFLAG_SAVEPOSITION|OPFLAG_IDXDELETE))==0 ); + /* Only flags that can be set are SAVEPOISTION and AUXDELETE */ + assert( (pOp->p5 & ~(OPFLAG_SAVEPOSITION|OPFLAG_AUXDELETE))==0 ); assert( OPFLAG_SAVEPOSITION==BTREE_SAVEPOSITION ); - assert( OPFLAG_IDXDELETE==BTREE_IDXDELETE ); + assert( OPFLAG_AUXDELETE==BTREE_AUXDELETE ); #ifdef SQLITE_DEBUG if( pC->isEphemeral==0 - && (pOp->p5 & OPFLAG_IDXDELETE)==0 + && (pOp->p5 & OPFLAG_AUXDELETE)==0 && (pC->wrFlag & OPFLAG_FORDELETE)==0 ){ nExtraDelete++; @@ -4963,7 +4965,7 @@ case OP_IdxDelete: { int i; for(i=0; iisEphemeral==0 - && (pOp->p5 & OPFLAG_IDXDELETE)==0 + && (pOp->p5 & OPFLAG_AUXDELETE)==0 && (pC->wrFlag & OPFLAG_FORDELETE)==0 ){ nExtraDelete++; From e61bbf441746d6129c9bfb09ab70ccdd6bfc421f Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 28 Jan 2016 17:06:17 +0000 Subject: [PATCH 5/7] Modifications to ensure the nExtraDelete-related assert() statement does not fail. FossilOrigin-Name: f43ff8f82d6c1239e6f9a32e7716421c1180ac74 --- manifest | 16 +++++++-------- manifest.uuid | 2 +- src/vdbe.c | 32 +++++++++++------------------- test/fordelete.test | 48 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 30 deletions(-) diff --git a/manifest b/manifest index 9790c25453..dc719b86ce 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\sname\sof\sthe\sBTREE_IDXDELETE\sflag\sto\sBTREE_AUXDELETE,\sto\sbetter\nreflect\sits\spurpose. -D 2016-01-27T16:26:25.226 +C Modifications\sto\sensure\sthe\snExtraDelete-related\sassert()\sstatement\sdoes\snot\sfail. +D 2016-01-28T17:06:17.501 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6fca5455aaecbd14479f33f091aa19df2d3d2969 @@ -412,7 +412,7 @@ F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3 F src/utf.c 32d7f82aa921322f3e1c956f4b58f019ebd2c6b3 F src/util.c 72d40df0a52d3f30b462a15f0e094fcbade6dc82 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 -F src/vdbe.c c367615fecb5fae8a39113ee2b6ecbab94e4bcd3 +F src/vdbe.c 66c429896ce44ebcbe199f1c7a592c12095158f0 F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 F src/vdbeInt.h 40c728712a2975855a2ac6aac44bf02dfd4a4c30 F src/vdbeapi.c ffae8f5af4570fbd548504e815e9fb7227f0822e @@ -642,7 +642,7 @@ F test/fkey6.test abb59f866c1b44926fd02d1fdd217d831fe04f48 F test/fkey7.test 72e915890ee4a005daaf3002cb208e8fe973ac13 F test/fkey8.test 8f08203458321e6c19a263829de4cfc936274ab0 F test/fkey_malloc.test 594a7ea1fbab553c036c70813cd8bd9407d63749 -F test/fordelete.test f794392f1768584609fa439f7528484dc04d3a03 +F test/fordelete.test 57ed9b953eeace09dd2eac3251b40bf9d6990aec F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb F test/fts-9fd058691.test 78b887e30ae6816df0e1fed6259de4b5a64ad33c F test/fts1a.test 46090311f85da51bb33bd5ce84f7948359c6d8d7 @@ -1422,7 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P bbd25cf179df5bda1fe729928d6746248f06e46f -R 21474325914b9893f106ce3a1694990c -U drh -Z 6ce2f1bf15f4f84bace517d6cc10a5ac +P 1d3bf6bebdda9f96734bc139601e9b05344ea0b4 +R 8c4c31e27c8a082a17d0a49af9f3ce1b +U dan +Z 9dc5d2517a8a4fb456754e0a3cfe77cf diff --git a/manifest.uuid b/manifest.uuid index d16254398c..b83d35e772 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1d3bf6bebdda9f96734bc139601e9b05344ea0b4 \ No newline at end of file +f43ff8f82d6c1239e6f9a32e7716421c1180ac74 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index f6a7946e6f..c2e70ea8b2 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -4405,14 +4405,16 @@ case OP_Delete: { assert( OPFLAG_AUXDELETE==BTREE_AUXDELETE ); #ifdef SQLITE_DEBUG - if( pC->isEphemeral==0 - && (pOp->p5 & OPFLAG_AUXDELETE)==0 - && (pC->wrFlag & OPFLAG_FORDELETE)==0 - ){ - nExtraDelete++; - } - if( pOp->p2 & OPFLAG_NCHANGE ){ - nExtraDelete--; + if( p->pFrame==0 ){ + if( pC->isEphemeral==0 + && (pOp->p5 & OPFLAG_AUXDELETE)==0 + && (pC->wrFlag & OPFLAG_FORDELETE)==0 + ){ + nExtraDelete++; + } + if( pOp->p2 & OPFLAG_NCHANGE ){ + nExtraDelete--; + } } #endif @@ -4960,21 +4962,9 @@ case OP_IdxDelete: { r.nField = (u16)pOp->p3; r.default_rc = 0; r.aMem = &aMem[pOp->p2]; -#ifdef SQLITE_DEBUG - { - int i; - for(i=0; iisEphemeral==0 - && (pOp->p5 & OPFLAG_AUXDELETE)==0 - && (pC->wrFlag & OPFLAG_FORDELETE)==0 - ){ - nExtraDelete++; - } - } -#endif rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res); if( rc==SQLITE_OK && res==0 ){ - rc = sqlite3BtreeDelete(pCrsr, 0); + rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE); } assert( pC->deferredMoveto==0 ); pC->cacheStatus = CACHE_STALE; diff --git a/test/fordelete.test b/test/fordelete.test index 7a49b5cbfd..bc38a4c5e3 100644 --- a/test/fordelete.test +++ b/test/fordelete.test @@ -158,5 +158,53 @@ do_test 3.2 { } } {6 {} {} {}} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 4.0 { + CREATE TABLE log(x); + CREATE TABLE p1(one PRIMARY KEY, two); + + CREATE TRIGGER tr_bd BEFORE DELETE ON p1 BEGIN + INSERT INTO log VALUES('delete'); + END; + INSERT INTO p1 VALUES('a', 'A'), ('b', 'B'), ('c', 'C'); + DELETE FROM p1 WHERE one = 'a'; +} + +reset_db +do_execsql_test 4.1 { + BEGIN TRANSACTION; + CREATE TABLE tbl(a PRIMARY KEY, b, c); + CREATE TABLE log(a, b, c); + INSERT INTO "tbl" VALUES(1,2,3); + CREATE TRIGGER the_trigger BEFORE DELETE ON tbl BEGIN + INSERT INTO log VALUES(1, 2,3); + END; + COMMIT; + DELETE FROM tbl WHERE a=1; +} + +reset_db +do_execsql_test 5.1 { + PRAGMA foreign_keys = 1; + CREATE TABLE t1(a INTEGER PRIMARY KEY, b); + CREATE TABLE t2( + c INTEGER PRIMARY KEY, + d INTEGER DEFAULT 1 REFERENCES t1 ON DELETE SET DEFAULT + ); +} {} +do_execsql_test 5.2 { + INSERT INTO t1 VALUES(1, 'one'); + INSERT INTO t1 VALUES(2, 'two'); + INSERT INTO t2 VALUES(1, 2); + SELECT * FROM t2; +} {1 2} +do_execsql_test 5.3 { + DELETE FROM t1 WHERE a = 2; +} {} + + finish_test From 83f0ab8087a16eadb29b74a7849a52230ac731b4 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 29 Jan 2016 18:04:31 +0000 Subject: [PATCH 6/7] Prepend "rc!=SQLITE_OK || " to the nExtraDelete assert() condition. FossilOrigin-Name: 2a055ed0afd56e8c6b17cfc31e7808debe9ec765 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbe.c | 4 +++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index dc719b86ce..8ccd1f3c1a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Modifications\sto\sensure\sthe\snExtraDelete-related\sassert()\sstatement\sdoes\snot\sfail. -D 2016-01-28T17:06:17.501 +C Prepend\s"rc!=SQLITE_OK\s||\s"\sto\sthe\snExtraDelete\sassert()\scondition. +D 2016-01-29T18:04:31.311 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6fca5455aaecbd14479f33f091aa19df2d3d2969 @@ -412,7 +412,7 @@ F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3 F src/utf.c 32d7f82aa921322f3e1c956f4b58f019ebd2c6b3 F src/util.c 72d40df0a52d3f30b462a15f0e094fcbade6dc82 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 -F src/vdbe.c 66c429896ce44ebcbe199f1c7a592c12095158f0 +F src/vdbe.c e86e100a3f90a861f28a5bda9c9abf1bca119a54 F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 F src/vdbeInt.h 40c728712a2975855a2ac6aac44bf02dfd4a4c30 F src/vdbeapi.c ffae8f5af4570fbd548504e815e9fb7227f0822e @@ -1422,7 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 1d3bf6bebdda9f96734bc139601e9b05344ea0b4 -R 8c4c31e27c8a082a17d0a49af9f3ce1b +P f43ff8f82d6c1239e6f9a32e7716421c1180ac74 +R 089a2135f4238760de692cbeaf9edaeb U dan -Z 9dc5d2517a8a4fb456754e0a3cfe77cf +Z f28c932cf1fbf9988a116d4b713a0ec7 diff --git a/manifest.uuid b/manifest.uuid index b83d35e772..3bf3d8a23c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f43ff8f82d6c1239e6f9a32e7716421c1180ac74 \ No newline at end of file +2a055ed0afd56e8c6b17cfc31e7808debe9ec765 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index c2e70ea8b2..c36802c300 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -6783,7 +6783,9 @@ vdbe_return: testcase( nVmStep>0 ); p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep; sqlite3VdbeLeave(p); - assert( nExtraDelete==0 || sqlite3_strlike("DELETE%",p->zSql,0)!=0 ); + assert( rc!=SQLITE_OK || nExtraDelete==0 + || sqlite3_strlike("DELETE%",p->zSql,0)!=0 + ); return rc; /* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH From 47ab455c2bb5e8256181e46fadc53979943075c7 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 29 Jan 2016 18:48:08 +0000 Subject: [PATCH 7/7] Remove a stray "exit" in a test script. FossilOrigin-Name: 10c88bf9f2c238abbbb54797ee2327ab72713e6f --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/e_changes.test | 1 - 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 8ccd1f3c1a..26f3353966 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Prepend\s"rc!=SQLITE_OK\s||\s"\sto\sthe\snExtraDelete\sassert()\scondition. -D 2016-01-29T18:04:31.311 +C Remove\sa\sstray\s"exit"\sin\sa\stest\sscript. +D 2016-01-29T18:48:08.448 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6fca5455aaecbd14479f33f091aa19df2d3d2969 @@ -595,7 +595,7 @@ F test/e_blobbytes.test 9bea1d3e2b20f3010b04abba58f6ba172301f49f F test/e_blobclose.test df756753f571bc30e42e3a6cba2807576e49e716 F test/e_blobopen.test 234f960d90235a9b51ec3ca1e062e8541dd558d8 F test/e_blobwrite.test 615b405f29feb2cfb5a1f03dab7933258294fa26 -F test/e_changes.test d66e8c1e33f5ec61af32eda729c8a2475404e49b +F test/e_changes.test fd66105385153dbf21fdb35eb8ef6c3e1eade579 F test/e_createtable.test d4c6059d44dcd4b636de9aae322766062b471844 F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412 @@ -1422,7 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P f43ff8f82d6c1239e6f9a32e7716421c1180ac74 -R 089a2135f4238760de692cbeaf9edaeb -U dan -Z f28c932cf1fbf9988a116d4b713a0ec7 +P 2a055ed0afd56e8c6b17cfc31e7808debe9ec765 +R 4fbaa01893d53f4580e8296002d14aff +U drh +Z dbc978af0b86d437c82a817aee2df876 diff --git a/manifest.uuid b/manifest.uuid index 3bf3d8a23c..79ac026d59 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2a055ed0afd56e8c6b17cfc31e7808debe9ec765 \ No newline at end of file +10c88bf9f2c238abbbb54797ee2327ab72713e6f \ No newline at end of file diff --git a/test/e_changes.test b/test/e_changes.test index c4b4406f7b..a77e22a2ee 100644 --- a/test/e_changes.test +++ b/test/e_changes.test @@ -65,7 +65,6 @@ foreach {tn schema} { UPDATE t1 SET b=b+1 WHERE a<5; } 5 -exit # Delete 4 rows do_changes_test 1.$tn.4 { DELETE FROM t1 WHERE a>6