Avoid unnecessary cursors and seeking when running a DELETE against a
WITHOUT ROWID table.

FossilOrigin-Name: 70ec88b29982f1a2437239ad4d3a9bf39bcc2a60
diff --git a/manifest b/manifest
index 6bcfc15..c4de5a2 100644
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Extra\sinformation\sprovided\sby\s.wheretrace\son\sinput\sflags\sto\sthe\squery\splanner\nand\son\sthe\sresult\sof\ssqlite3WhereOkOnePass().
-D 2015-09-28T17:05:22.174
+C Avoid\sunnecessary\scursors\sand\sseeking\swhen\srunning\sa\sDELETE\sagainst\sa\nWITHOUT\sROWID\stable.
+D 2015-09-28T23:45:19.527
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 2143eeef6d0cc26006ae5fc4bb242a4a8b973412
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -291,7 +291,7 @@
 F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b
 F src/date.c fb1c99172017dcc8e237339132c91a21a0788584
 F src/dbstat.c e637e7a7ff40ef32132a418c6fdf1cfb63aa27c7
-F src/delete.c 371df4fc86e96efeaed3d37565aef77f956be109
+F src/delete.c 514980fc1e6465e906ee7def3dfb70196e4c3aba
 F src/expr.c 3a76afcdac925294c39903b7002ddb9e5fd29863
 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
 F src/fkey.c 83e1baba999bed3144ea5a2143fc922edf51135f
@@ -300,7 +300,7 @@
 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
-F src/insert.c 9748a37e058256eb2ead69f028ab85ebf203ad15
+F src/insert.c d0f8d6d6baaec0492ba396aa4a455eb42cb01554
 F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
 F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
 F src/lempar.c d344a95d60c24e2f490ee59db9784b1b17439012
@@ -345,7 +345,7 @@
 F src/sqlite.h.in 02f6ed7de3a96d10bd1e6e5803e4e4b786dff014
 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
 F src/sqlite3ext.h 64350bf36833a56ad675e27392a913f417c5c308
-F src/sqliteInt.h 5afc6e50402be1e0a870f28e1cd8b32eb9db590f
+F src/sqliteInt.h 9773cdb949ec8c3ac71d04e25e63458389e8c3d1
 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
 F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
 F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
@@ -417,8 +417,8 @@
 F src/wal.c 18b0ed49830cf04fe2d68224b41838a73ac6cd24
 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
 F src/walker.c 2e14d17f592d176b6dc879c33fbdec4fbccaa2ba
-F src/where.c 25d7527226d63176b3cd4880a85119cda9f83844
-F src/whereInt.h 7892bb54cf9ca0ae5c7e6094491b94c9286dc647
+F src/where.c e779853aa40a6cdec7fadd026b17c0a98d3298a6
+F src/whereInt.h d7337103c9d40a66ca82ede8646a34fa2e544143
 F src/wherecode.c 7660e1ad16817a921b099af553f3e1349352d16f
 F src/whereexpr.c 2473e4350e30f9b55d1c6a8f66ca23c689f23f1d
 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
@@ -1388,7 +1388,10 @@
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 5c14d447055bb337428eb1fe0a2934abee381829
-R afaa284829583439d3c828667e0babfd
+P c5566bb39c8d9b58f77380b81a873429575c7d5c
+R 4e9ae99d481eaf33b22cedef90accac5
+T *branch * delete-without-rowid-opt
+T *sym-delete-without-rowid-opt *
+T -sym-trunk *
 U drh
-Z 4d08d7f777c595957317ee86b8c88bc8
+Z f54d92c69fd86d18a737b52719ac709a
diff --git a/manifest.uuid b/manifest.uuid
index 544e794..67a1018 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-c5566bb39c8d9b58f77380b81a873429575c7d5c
\ No newline at end of file
+70ec88b29982f1a2437239ad4d3a9bf39bcc2a60
\ No newline at end of file
diff --git a/src/delete.c b/src/delete.c
index c387c20..6de2a75 100644
--- a/src/delete.c
+++ b/src/delete.c
@@ -434,9 +434,8 @@
     }
   
     if( eOnePass!=ONEPASS_OFF ){
-      /* 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.  */
+      /* For ONEPASS, no need to store the rowid/primary-key because rows
+      ** are deleted as they are discovered */
       nKey = nPk; /* OP_Found will use an unpacked key */
       aToOpen = sqlite3DbMallocRaw(db, nIdx+2);
       if( aToOpen==0 ){
@@ -449,6 +448,8 @@
       if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iTabCur] = 0;
       if( addrEphOpen ) sqlite3VdbeChangeToNoop(v, addrEphOpen);
     }else{
+      /* For non-ONEPASS, remember the rowid/primary-key of the row to
+      ** be deleted */
       if( pPk ){
         /* Add the PK key for this row to the temporary table */
         iKey = ++pParse->nMem;
@@ -522,6 +523,9 @@
     {
       int count = (pParse->nested==0);    /* True to count changes */
       int iIdxNoSeek = -1;
+      if( eOnePass!=ONEPASS_OFF ){
+        sqlite3WhereHenceforthUseTableCursor(pWInfo, sqlite3VdbeCurrentAddr(v));
+      }
       if( bComplex==0 && aiCurOnePass[1]!=iDataCur ){
         iIdxNoSeek = aiCurOnePass[1];
       }
diff --git a/src/insert.c b/src/insert.c
index 53b429c..a4268a8 100644
--- a/src/insert.c
+++ b/src/insert.c
@@ -1680,8 +1680,12 @@
   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( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
+      if( aToOpen && aToOpen[0]==0 ){
+        iIdxCur = iDataCur;
+        aToOpen[i+1] = 0;
+      }
+      if( piDataCur ) *piDataCur = iIdxCur;
     }
     if( aToOpen==0 || aToOpen[i+1] ){
       sqlite3VdbeAddOp3(v, op, iIdxCur, pIdx->tnum, iDb);
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 747f19b..6da7bbf 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -3374,6 +3374,7 @@
 void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
 WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int);
 void sqlite3WhereEnd(WhereInfo*);
+void sqlite3WhereHenceforthUseTableCursor(WhereInfo*,int addr);
 u64 sqlite3WhereOutputRowCount(WhereInfo*);
 int sqlite3WhereIsDistinct(WhereInfo*);
 int sqlite3WhereIsOrdered(WhereInfo*);
diff --git a/src/where.c b/src/where.c
index e224d40..54c4380 100644
--- a/src/where.c
+++ b/src/where.c
@@ -27,6 +27,18 @@
 /***/ int sqlite3WhereTrace = 0;
 #endif
 
+/*
+** When generating the end-of-WHERE-loop, do not transform references to
+** the main table into references to the index after this address.
+**
+** This interface is invoked by DELETE at a point after when the
+** table cursor is pointing to the correct address but before any
+** of the index cursors have been deleted.
+*/
+void sqlite3WhereHenceforthUseTableCursor(WhereInfo *pWInfo, int addr){
+  pWInfo->addrUseTabCur = addr;
+}
+
 
 /*
 ** Return the estimated number of output rows from a WHERE clause
@@ -4538,10 +4550,13 @@
       pIdx = pLevel->u.pCovidx;
     }
     if( pIdx
-     && (pWInfo->eOnePass==ONEPASS_OFF || !HasRowid(pIdx->pTable))
      && !db->mallocFailed
     ){
-      last = sqlite3VdbeCurrentAddr(v);
+      if( pWInfo->addrUseTabCur ){
+        last = pWInfo->addrUseTabCur;
+      }else{
+        last = sqlite3VdbeCurrentAddr(v);
+      }
       k = pLevel->addrBody;
       pOp = sqlite3VdbeGetOp(v, k);
       for(; k<last; k++, pOp++){
diff --git a/src/whereInt.h b/src/whereInt.h
index cae09ac..5372f4f 100644
--- a/src/whereInt.h
+++ b/src/whereInt.h
@@ -419,6 +419,7 @@
   int iTop;                 /* The very beginning of the WHERE loop */
   int iContinue;            /* Jump here to continue with next record */
   int iBreak;               /* Jump here to break out of the loop */
+  int addrUseTabCur;        /* Do not use index cursor after this address */
   int savedNQueryLoop;      /* pParse->nQueryLoop outside the WHERE loop */
   int aiCurOnePass[2];      /* OP_OpenWrite cursors for the ONEPASS opt */
   WhereMaskSet sMaskSet;    /* Map cursor numbers to bitmasks */