- 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
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
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
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 */
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; i<nPk; i++){
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur,
+ pPk->aiColumn[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