]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Enable the ONEPASS optimization for DELETE, for both rowid and WITHOUT
authordrh <drh@noemail.net>
Mon, 18 Nov 2013 03:11:54 +0000 (03:11 +0000)
committerdrh <drh@noemail.net>
Mon, 18 Nov 2013 03:11:54 +0000 (03:11 +0000)
ROWID tables.

FossilOrigin-Name: 44a07afdd9b3ae2460bc963383295deb0915f899

1  2 
manifest
manifest.uuid
src/delete.c

diff --cc manifest
index 681c38774e7593201ebcbf8ed0775b3535ed7f06,9f1bb087f7f52d5e388716c3db31a60b088764ea..7c8e58d4aeb42486bf75b4deeded32da90c2cc26
+++ 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 6d386d4ae94c0ff6f51bb2d7d7cdbeeb3b5db4b7,01e77e462acc4732d9136891f0233ab6be172744..7959da7ea190b889b4136c97b89ab1a4fc52d7d5
@@@ -1,1 -1,1 +1,1 @@@
- 7edf39eb93a8f9059a788f5fccf41c2be40afd4d
 -6bd5750b7d5da221b0689f6df6be5ed0dce61bec
++44a07afdd9b3ae2460bc963383295deb0915f899
diff --cc src/delete.c
index 4fb394659581a6c5869fa9e26e36af5f1064dddb,c4bf8cc813701addf86af4b024956b56bccc22da..4b57cf2805ecfea11f709d649c1bc07f98165cc5
@@@ -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 */
      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