From: drh Date: Mon, 18 Nov 2013 03:11:54 +0000 (+0000) Subject: Enable the ONEPASS optimization for DELETE, for both rowid and WITHOUT X-Git-Tag: version-3.8.2~81 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e73e067187470c0e336057dc692caa8840821832;p=thirdparty%2Fsqlite.git Enable the ONEPASS optimization for DELETE, for both rowid and WITHOUT ROWID tables. FossilOrigin-Name: 44a07afdd9b3ae2460bc963383295deb0915f899 --- e73e067187470c0e336057dc692caa8840821832 diff --cc manifest index 681c38774e,9f1bb087f7..7c8e58d4ae --- a/manifest +++ b/manifest @@@ -1,5 -1,5 +1,5 @@@ - C Fully\sconstraint\sthe\sORDER\sBY\son\sthe\stop-10\sline\sof\sthe\s--summary\soutput\nfrom\sthe\swordcount\stest\sprogram.\s\sAdd\sthe\srun-wordcount.bash\sscript\sfor\nrunning\swordcount\sin\svarious\sconfigurations. - D 2013-11-16T15:35:18.956 -C Make\ssure\sone-pass\sDELETE\sfor\sWITHOUT\sROWID\stables\scorrectly\spositions\sthe\nPRIMARY\sKEY\scursor.\s\sMake\sthe\ssame\sfix\sfor\sUPDATE. -D 2013-11-17T02:42:02.540 ++C Enable\sthe\sONEPASS\soptimization\sfor\sDELETE,\sfor\sboth\srowid\sand\sWITHOUT\nROWID\stables. ++D 2013-11-18T03:11:54.195 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 8a07bebafbfda0eb67728f4bd15a36201662d1a1 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@@ -174,7 -174,7 +174,7 @@@ F src/callback.c f99a8957ba2adf369645fa F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c F src/date.c 593c744b2623971e45affd0bde347631bdfa4625 - F src/delete.c ddb92f44595366c4817e576b5f11cad5a915c3ef -F src/delete.c d88e4fbfeca5a8cf48b7d358b9a68d5e81f314b7 ++F src/delete.c 909936019ccb8d0f4a10d0d10ad607c38ee62cbe F src/expr.c 1a295d8b0a2ba08919ad9300ebf7b67988ff4030 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 78364daed38e26269c53ddb94c515bceac1063c6 @@@ -1140,7 -1140,7 +1140,8 @@@ F tool/vdbe-compress.tcl f12c884766bd14 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff - P de08a7e7abbad9b94d0268d096ef4555d31c8b0c - R 172f7957a55e2959255a9b6c3406c731 -P a11243f840d35aaed8ee3b9901c3950bc584a417 -R f429117cda51c1a8c08160d9a3f515e6 ++P 7edf39eb93a8f9059a788f5fccf41c2be40afd4d 6bd5750b7d5da221b0689f6df6be5ed0dce61bec ++R de0ce1af524d0d7134e767478b5898b6 ++T +closed 6bd5750b7d5da221b0689f6df6be5ed0dce61bec U drh - Z e8555787a9b5df5e1de6c7d36654ffb3 -Z 2718e457b564d6fbe8d10873d690a300 ++Z b3bca10fc785a82e3f00cdade511d055 diff --cc manifest.uuid index 6d386d4ae9,01e77e462a..7959da7ea1 --- a/manifest.uuid +++ b/manifest.uuid @@@ -1,1 -1,1 +1,1 @@@ - 7edf39eb93a8f9059a788f5fccf41c2be40afd4d -6bd5750b7d5da221b0689f6df6be5ed0dce61bec ++44a07afdd9b3ae2460bc963383295deb0915f899 diff --cc src/delete.c index 4fb3946595,c4bf8cc813..4b57cf2805 --- a/src/delete.c +++ b/src/delete.c @@@ -240,7 -240,21 +240,21 @@@ void sqlite3DeleteFrom int iDb; /* Database number */ int memCnt = -1; /* Memory cell used for change counting */ int rcauth; /* Value returned by authorization callback */ - + int okOnePass; /* True for one-pass algorithm without the FIFO */ + int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */ + u8 *aToOpen = 0; /* Open cursor iTabCur+j if aToOpen[j] is true */ + Index *pPk; /* The PRIMARY KEY index on the table */ - int iPk; /* First of nPk registerss holding PRIMARY KEY value */ - i16 nPk = 1; /* Number of components of the PRIMARY KEY */ - int iKey; /* Memory cell holding row key of to be deleted */ - i16 nKey; /* Number of memory cells of row key */ ++ int iPk; /* First of nPk registers holding PRIMARY KEY value */ ++ i16 nPk = 1; /* Number of columns in the PRIMARY KEY */ ++ int iKey; /* Memory cell holding key of row to be deleted */ ++ i16 nKey; /* Number of memory cells in the row key */ + int iEphCur = 0; /* Ephemeral table holding all primary key values */ + int iRowSet = 0; /* Register for rowset of rows to delete */ + int addrBypass = 0; /* Address of jump over the delete logic */ + int addrLoop = 0; /* Top of the delete loop */ + int addrDelete = 0; /* Jump directly to the delete logic */ + int addrEphOpen = 0; /* Instruction to open the Ephermeral table */ + #ifndef SQLITE_OMIT_TRIGGER int isView; /* True if attempting to delete from a view */ Trigger *pTrigger; /* List of table triggers, if required */ @@@ -395,57 -412,60 +412,59 @@@ if( db->flags & SQLITE_CountRows ){ sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1); } - sqlite3WhereEnd(pWInfo); - - /* Open cursors for all indices of the table. - */ - sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, - iTabCur, &iDataCur, &iIdxCur); - - /* Loop over the primary keys to be deleted. */ - addr = sqlite3VdbeAddOp1(v, OP_Rewind, iEph); - sqlite3VdbeAddOp2(v, OP_RowKey, iEph, iPk); - - /* Delete the row */ - sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, - iPk, 0, 1, OE_Default, 0); - - /* End of the delete loop */ - sqlite3VdbeAddOp2(v, OP_Next, iEph, addr+1); - sqlite3VdbeJumpHere(v, addr); - - /* Close the cursors open on the table and its indexes. */ - assert( iDataCur>=iIdxCur ); - for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ - sqlite3VdbeAddOp1(v, OP_Close, iIdxCur+i); + + /* Extract the rowid or primary key for the current row */ + if( pPk ){ + for(i=0; iaiColumn[i], iPk+i); + } + iKey = iPk; - nKey = nPk; + }else{ + iKey = pParse->nMem + 1; + iKey = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iTabCur, iKey, 0); + if( iKey>pParse->nMem ) pParse->nMem = iKey; } - }else{ - /* There is a WHERE clause on a rowid table. Run a loop that extracts - ** all rowids to be deleted into a RowSet. - */ - int iRowSet = ++pParse->nMem; /* Register for rowset of rows to delete */ - int iRowid = ++pParse->nMem; /* Used for storing rowid values. */ - int regRowid; /* Actual register containing rowids */ - - /* Collect rowids of every row to be deleted. - */ - sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet); - pWInfo = sqlite3WhereBegin( - pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK, 0 - ); - if( pWInfo==0 ) goto delete_from_cleanup; - regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iTabCur, iRowid, 0); - sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid); - if( db->flags & SQLITE_CountRows ){ - sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1); + + if( okOnePass ){ + /* For ONEPASS, no need to store the rowid/primary-key. There is only + ** one, so just keep it in its register(s) and fall through to the + ** delete code. + */ + nKey = nPk; /* OP_Found will use an unpacked key */ + aToOpen = sqlite3DbMallocRaw(db, nIdx+2); + if( aToOpen==0 ){ + sqlite3WhereEnd(pWInfo); + goto delete_from_cleanup; + } + memset(aToOpen, 1, nIdx+1); + aToOpen[nIdx+1] = 0; + if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iTabCur] = 0; + if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iTabCur] = 0; + if( addrEphOpen ) sqlite3VdbeChangeToNoop(v, addrEphOpen); + addrDelete = sqlite3VdbeAddOp0(v, OP_Goto); /* Jump to DELETE logic */ + }else if( pPk ){ + /* Construct a composite key for the row to be deleted and remember it */ + iKey = ++pParse->nMem; + nKey = 0; /* Zero tells OP_Found to use a composite key */ + sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey, + sqlite3IndexAffinityStr(v, pPk), P4_TRANSIENT); + sqlite3VdbeAddOp2(v, OP_IdxInsert, iEphCur, iKey); + }else{ + /* Get the rowid of the row to be deleted and remember it in the RowSet */ + nKey = 1; /* OP_Seek always uses a single rowid */ + sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iKey); } + + /* End of the WHERE loop */ sqlite3WhereEnd(pWInfo); - - /* Delete every item whose key was written to the list during the - ** database scan. We have to delete items after the scan is complete - ** because deleting an item can change the scan order. */ - end = sqlite3VdbeMakeLabel(v); - + if( okOnePass ){ + /* Bypass the delete logic below if the WHERE loop found zero rows */ + addrBypass = sqlite3VdbeMakeLabel(v); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrBypass); + sqlite3VdbeJumpHere(v, addrDelete); + } + /* Unless this is a view, open cursors for the table we are ** deleting from and all its indices. If this is a view, then the ** only effect this statement has is to fire the INSTEAD OF