/ Check-in [439c8162]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Remove the NextIfOpen and PrevIfOpen opcodes which are no longer needed when the IN-early-out optimization is working.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | multikey-opt-idea
Files: files | file ages | folders
SHA3-256:439c8162272795b422a0e01b01b832fbc12b39914c9632a674162af8bdecff98
User & Date: drh 2018-06-07 17:32:59
Context
2018-06-07
18:01
Fix the assert()s in the byte-code engine that prove that cursors are unidirectional. Closed-Leaf check-in: 4b0b4e14 user: drh tags: multikey-opt-idea
17:32
Remove the NextIfOpen and PrevIfOpen opcodes which are no longer needed when the IN-early-out optimization is working. check-in: 439c8162 user: drh tags: multikey-opt-idea
16:07
Test cases. check-in: 085e8637 user: drh tags: multikey-opt-idea
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/shell.c.in.

  2563   2563   static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
  2564   2564     const char *zSql;               /* The text of the SQL statement */
  2565   2565     const char *z;                  /* Used to check if this is an EXPLAIN */
  2566   2566     int *abYield = 0;               /* True if op is an OP_Yield */
  2567   2567     int nAlloc = 0;                 /* Allocated size of p->aiIndent[], abYield */
  2568   2568     int iOp;                        /* Index of operation in p->aiIndent[] */
  2569   2569   
  2570         -  const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext",
  2571         -                           "NextIfOpen", "PrevIfOpen", 0 };
         2570  +  const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", 0 };
  2572   2571     const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead",
  2573   2572                               "Rewind", 0 };
  2574   2573     const char *azGoto[] = { "Goto", 0 };
  2575   2574   
  2576   2575     /* Try to figure out if this is really an EXPLAIN statement. If this
  2577   2576     ** cannot be verified, return early.  */
  2578   2577     if( sqlite3_column_count(pSql)!=8 ){

Changes to src/vdbe.c.

  5128   5128   **
  5129   5129   ** P4 is always of type P4_ADVANCE. The function pointer points to
  5130   5130   ** sqlite3BtreeNext().
  5131   5131   **
  5132   5132   ** If P5 is positive and the jump is taken, then event counter
  5133   5133   ** number P5-1 in the prepared statement is incremented.
  5134   5134   **
  5135         -** See also: Prev, NextIfOpen
  5136         -*/
  5137         -/* Opcode: NextIfOpen P1 P2 P3 P4 P5
  5138         -**
  5139         -** This opcode works just like Next except that if cursor P1 is not
  5140         -** open it behaves a no-op.
         5135  +** See also: Prev
  5141   5136   */
  5142   5137   /* Opcode: Prev P1 P2 P3 P4 P5
  5143   5138   **
  5144   5139   ** Back up cursor P1 so that it points to the previous key/data pair in its
  5145   5140   ** table or index.  If there is no previous key/value pairs then fall through
  5146   5141   ** to the following instruction.  But if the cursor backup was successful,
  5147   5142   ** jump immediately to P2.
................................................................................
  5161   5156   **
  5162   5157   ** P4 is always of type P4_ADVANCE. The function pointer points to
  5163   5158   ** sqlite3BtreePrevious().
  5164   5159   **
  5165   5160   ** If P5 is positive and the jump is taken, then event counter
  5166   5161   ** number P5-1 in the prepared statement is incremented.
  5167   5162   */
  5168         -/* Opcode: PrevIfOpen P1 P2 P3 P4 P5
  5169         -**
  5170         -** This opcode works just like Prev except that if cursor P1 is not
  5171         -** open it behaves a no-op.
  5172         -*/
  5173   5163   /* Opcode: SorterNext P1 P2 * * P5
  5174   5164   **
  5175   5165   ** This opcode works just like OP_Next except that P1 must be a
  5176   5166   ** sorter object for which the OP_SorterSort opcode has been
  5177   5167   ** invoked.  This opcode advances the cursor to the next sorted
  5178   5168   ** record, or jumps to P2 if there are no more sorted records.
  5179   5169   */
................................................................................
  5180   5170   case OP_SorterNext: {  /* jump */
  5181   5171     VdbeCursor *pC;
  5182   5172   
  5183   5173     pC = p->apCsr[pOp->p1];
  5184   5174     assert( isSorter(pC) );
  5185   5175     rc = sqlite3VdbeSorterNext(db, pC);
  5186   5176     goto next_tail;
  5187         -case OP_PrevIfOpen:    /* jump */
  5188         -case OP_NextIfOpen:    /* jump */
  5189         -  if( p->apCsr[pOp->p1]==0 ) break;
  5190         -  /* Fall through */
  5191   5177   case OP_Prev:          /* jump */
  5192   5178   case OP_Next:          /* jump */
  5193   5179     assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  5194   5180     assert( pOp->p5<ArraySize(p->aCounter) );
  5195   5181     pC = p->apCsr[pOp->p1];
  5196   5182     assert( pC!=0 );
  5197   5183     assert( pC->deferredMoveto==0 );
  5198   5184     assert( pC->eCurType==CURTYPE_BTREE );
  5199   5185     assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
  5200   5186     assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
  5201         -  assert( pOp->opcode!=OP_NextIfOpen || pOp->p4.xAdvance==sqlite3BtreeNext );
  5202         -  assert( pOp->opcode!=OP_PrevIfOpen || pOp->p4.xAdvance==sqlite3BtreePrevious);
  5203   5187   
         5188  +#if 0
  5204   5189     /* The Next opcode is only used after SeekGT, SeekGE, and Rewind.
  5205   5190     ** The Prev opcode is only used after SeekLT, SeekLE, and Last. */
  5206         -  assert( pOp->opcode!=OP_Next || pOp->opcode!=OP_NextIfOpen
         5191  +  assert( pOp->opcode!=OP_Next
  5207   5192          || pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE
  5208   5193          || pC->seekOp==OP_Rewind || pC->seekOp==OP_Found);
  5209         -  assert( pOp->opcode!=OP_Prev || pOp->opcode!=OP_PrevIfOpen
         5194  +  assert( pOp->opcode!=OP_Prev
  5210   5195          || pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE
  5211   5196          || pC->seekOp==OP_Last );
         5197  +#endif
  5212   5198   
  5213   5199     rc = pOp->p4.xAdvance(pC->uc.pCursor, pOp->p3);
  5214   5200   next_tail:
  5215   5201     pC->cacheStatus = CACHE_STALE;
  5216   5202     VdbeBranchTaken(rc==SQLITE_OK,2);
  5217   5203     if( rc==SQLITE_OK ){
  5218   5204       pC->nullRow = 0;

Changes to src/vdbeaux.c.

   685    685           case OP_Vacuum:
   686    686           case OP_JournalMode: {
   687    687             p->readOnly = 0;
   688    688             p->bIsReader = 1;
   689    689             break;
   690    690           }
   691    691           case OP_Next:
   692         -        case OP_NextIfOpen:
   693    692           case OP_SorterNext: {
   694    693             pOp->p4.xAdvance = sqlite3BtreeNext;
   695    694             pOp->p4type = P4_ADVANCE;
   696    695             /* The code generator never codes any of these opcodes as a jump
   697    696             ** to a label.  They are always coded as a jump backwards to a 
   698    697             ** known address */
   699    698             assert( pOp->p2>=0 );
   700    699             break;
   701    700           }
   702         -        case OP_Prev:
   703         -        case OP_PrevIfOpen: {
          701  +        case OP_Prev: {
   704    702             pOp->p4.xAdvance = sqlite3BtreePrevious;
   705    703             pOp->p4type = P4_ADVANCE;
   706    704             /* The code generator never codes any of these opcodes as a jump
   707    705             ** to a label.  They are always coded as a jump backwards to a 
   708    706             ** known address */
   709    707             assert( pOp->p2>=0 );
   710    708             break;

Changes to src/where.c.

  5088   5088               sqlite3VdbeAddOp4Int(v, OP_IfNoHope, pLevel->iIdxCur,
  5089   5089                                 sqlite3VdbeCurrentAddr(v)+2,
  5090   5090                                 pIn->iBase, pIn->nPrefix);
  5091   5091               VdbeCoverage(v);
  5092   5092             }
  5093   5093             sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
  5094   5094             VdbeCoverage(v);
  5095         -          VdbeCoverageIf(v, pIn->eEndLoopOp==OP_PrevIfOpen);
  5096         -          VdbeCoverageIf(v, pIn->eEndLoopOp==OP_NextIfOpen);
         5095  +          VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Prev);
         5096  +          VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Next);
  5097   5097           }
  5098   5098           sqlite3VdbeJumpHere(v, pIn->addrInTop-1);
  5099   5099         }
  5100   5100       }
  5101   5101       sqlite3VdbeResolveLabel(v, pLevel->addrBrk);
  5102   5102       if( pLevel->addrSkip ){
  5103   5103         sqlite3VdbeGoto(v, pLevel->addrSkip);

Changes to src/wherecode.c.

   587    587             }else{
   588    588               int iCol = aiMap ? aiMap[iMap++] : 0;
   589    589               pIn->addrInTop = sqlite3VdbeAddOp3(v,OP_Column,iTab, iCol, iOut);
   590    590             }
   591    591             sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v);
   592    592             if( i==iEq ){
   593    593               pIn->iCur = iTab;
   594         -            pIn->eEndLoopOp = bRev ? OP_PrevIfOpen : OP_NextIfOpen;
          594  +            pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
   595    595               if( iEq>0 && (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 ){
   596    596                 pIn->iBase = iReg - i;
   597    597                 pIn->nPrefix = i;
   598    598                 pLoop->wsFlags |= WHERE_IN_EARLYOUT;
   599    599               }else{
   600    600                 pIn->nPrefix = 0;
   601    601               }