/ Check-in [041df7c2]
Login

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

Overview
Comment:Simplifications to the VDBE bytecode that handles LIMIT and OFFSET.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 041df7c2f14b95868a08090354ebb3308050790e
User & Date: drh 2015-10-06 21:07:06
Context
2015-10-06
21:49
Fix typo in comments. No changes to code. check-in: a05f903c user: mistachkin tags: trunk
21:07
Simplifications to the VDBE bytecode that handles LIMIT and OFFSET. check-in: 041df7c2 user: drh tags: trunk
20:53
Optimizations for fts5 expressions that filter on column. More still to come. check-in: bf1607ac user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/pragma.c.

  1357   1357   
  1358   1358       /* Code that appears at the end of the integrity check.  If no error
  1359   1359       ** messages have been generated, output OK.  Otherwise output the
  1360   1360       ** error message
  1361   1361       */
  1362   1362       static const int iLn = VDBE_OFFSET_LINENO(2);
  1363   1363       static const VdbeOpList endCode[] = {
  1364         -      { OP_IfNeg,       1, 0,        0},    /* 0 */
  1365         -      { OP_String8,     0, 3,        0},    /* 1 */
         1364  +      { OP_AddImm,      1, 0,        0},    /* 0 */
         1365  +      { OP_If,          1, 0,        0},    /* 1 */
         1366  +      { OP_String8,     0, 3,        0},    /* 2 */
  1366   1367         { OP_ResultRow,   3, 1,        0},
  1367   1368       };
  1368   1369   
  1369   1370       int isQuick = (sqlite3Tolower(zLeft[0])=='q');
  1370   1371   
  1371   1372       /* If the PRAGMA command was of the form "PRAGMA <db>.integrity_check",
  1372   1373       ** then iDb is set to the index of the database identified by <db>.
................................................................................
  1559   1560             sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7);
  1560   1561             sqlite3VdbeAddOp2(v, OP_ResultRow, 7, 1);
  1561   1562           }
  1562   1563   #endif /* SQLITE_OMIT_BTREECOUNT */
  1563   1564         } 
  1564   1565       }
  1565   1566       addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn);
  1566         -    sqlite3VdbeChangeP3(v, addr, -mxErr);
  1567         -    sqlite3VdbeJumpHere(v, addr);
  1568         -    sqlite3VdbeChangeP4(v, addr+1, "ok", P4_STATIC);
         1567  +    sqlite3VdbeChangeP2(v, addr, -mxErr);
         1568  +    sqlite3VdbeJumpHere(v, addr+1);
         1569  +    sqlite3VdbeChangeP4(v, addr+2, "ok", P4_STATIC);
  1569   1570     }
  1570   1571     break;
  1571   1572   #endif /* SQLITE_OMIT_INTEGRITY_CHECK */
  1572   1573   
  1573   1574   #ifndef SQLITE_OMIT_UTF16
  1574   1575     /*
  1575   1576     **   PRAGMA encoding

Changes to src/select.c.

   575    575       int addr;
   576    576       int iLimit;
   577    577       if( pSelect->iOffset ){
   578    578         iLimit = pSelect->iOffset+1;
   579    579       }else{
   580    580         iLimit = pSelect->iLimit;
   581    581       }
   582         -    addr = sqlite3VdbeAddOp3(v, OP_IfNotZero, iLimit, 0, -1); VdbeCoverage(v);
          582  +    addr = sqlite3VdbeAddOp3(v, OP_IfNotZero, iLimit, 0, 1); VdbeCoverage(v);
   583    583       sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor);
   584    584       sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor);
   585    585       sqlite3VdbeJumpHere(v, addr);
   586    586     }
   587    587   }
   588    588   
   589    589   /*
................................................................................
   591    591   */
   592    592   static void codeOffset(
   593    593     Vdbe *v,          /* Generate code into this VM */
   594    594     int iOffset,      /* Register holding the offset counter */
   595    595     int iContinue     /* Jump here to skip the current record */
   596    596   ){
   597    597     if( iOffset>0 ){
   598         -    int addr;
   599         -    addr = sqlite3VdbeAddOp3(v, OP_IfNeg, iOffset, 0, -1); VdbeCoverage(v);
   600         -    sqlite3VdbeGoto(v, iContinue);
   601         -    VdbeComment((v, "skip OFFSET records"));
   602         -    sqlite3VdbeJumpHere(v, addr);
          598  +    sqlite3VdbeAddOp3(v, OP_IfPos, iOffset, iContinue, 1); VdbeCoverage(v);
          599  +    VdbeComment((v, "OFFSET"));
   603    600     }
   604    601   }
   605    602   
   606    603   /*
   607    604   ** Add code that will check to make sure the N registers starting at iMem
   608    605   ** form a distinct entry.  iTab is a sorting index that holds previously
   609    606   ** seen combinations of the N values.  A new entry is made in iTab
................................................................................
  1811   1808   ** the reuse of the same limit and offset registers across multiple
  1812   1809   ** SELECT statements.
  1813   1810   */
  1814   1811   static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
  1815   1812     Vdbe *v = 0;
  1816   1813     int iLimit = 0;
  1817   1814     int iOffset;
  1818         -  int addr1, n;
         1815  +  int n;
  1819   1816     if( p->iLimit ) return;
  1820   1817   
  1821   1818     /* 
  1822   1819     ** "LIMIT -1" always shows all rows.  There is some
  1823   1820     ** controversy about what the correct behavior should be.
  1824   1821     ** The current implementation interprets "LIMIT 0" to mean
  1825   1822     ** no rows.
................................................................................
  1846   1843       }
  1847   1844       if( p->pOffset ){
  1848   1845         p->iOffset = iOffset = ++pParse->nMem;
  1849   1846         pParse->nMem++;   /* Allocate an extra register for limit+offset */
  1850   1847         sqlite3ExprCode(pParse, p->pOffset, iOffset);
  1851   1848         sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v);
  1852   1849         VdbeComment((v, "OFFSET counter"));
  1853         -      addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iOffset); VdbeCoverage(v);
  1854         -      sqlite3VdbeAddOp2(v, OP_Integer, 0, iOffset);
  1855         -      sqlite3VdbeJumpHere(v, addr1);
         1850  +      sqlite3VdbeAddOp3(v, OP_SetIfNotPos, iOffset, iOffset, 0);
  1856   1851         sqlite3VdbeAddOp3(v, OP_Add, iLimit, iOffset, iOffset+1);
  1857   1852         VdbeComment((v, "LIMIT+OFFSET"));
  1858         -      addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iLimit); VdbeCoverage(v);
  1859         -      sqlite3VdbeAddOp2(v, OP_Integer, -1, iOffset+1);
  1860         -      sqlite3VdbeJumpHere(v, addr1);
         1853  +      sqlite3VdbeAddOp3(v, OP_SetIfNotPos, iLimit, iOffset+1, -1);
  1861   1854       }
  1862   1855     }
  1863   1856   }
  1864   1857   
  1865   1858   #ifndef SQLITE_OMIT_COMPOUND_SELECT
  1866   1859   /*
  1867   1860   ** Return the appropriate collating sequence for the iCol-th column of
................................................................................
  2270   2263         p->pPrior = 0;
  2271   2264         p->iLimit = pPrior->iLimit;
  2272   2265         p->iOffset = pPrior->iOffset;
  2273   2266         if( p->iLimit ){
  2274   2267           addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v);
  2275   2268           VdbeComment((v, "Jump ahead if LIMIT reached"));
  2276   2269           if( p->iOffset ){
  2277         -          int addr2;
         2270  +          sqlite3VdbeAddOp3(v, OP_SetIfNotPos, p->iOffset, p->iOffset, 0);
  2278   2271             sqlite3VdbeAddOp3(v, OP_Add, p->iLimit, p->iOffset, p->iOffset+1);
  2279         -          addr2 = sqlite3VdbeAddOp1(v, OP_IfPos, p->iOffset); VdbeCoverage(v);
  2280         -          sqlite3VdbeAddOp2(v, OP_SCopy, p->iLimit, p->iOffset+1);
  2281         -          sqlite3VdbeJumpHere(v, addr2);
  2282         -          addr2 = sqlite3VdbeAddOp1(v, OP_IfPos, p->iLimit); VdbeCoverage(v);
  2283         -          sqlite3VdbeAddOp2(v, OP_Integer, -1, p->iOffset+1);
  2284         -          sqlite3VdbeJumpHere(v, addr2);
         2272  +          sqlite3VdbeAddOp3(v, OP_SetIfNotPos, p->iLimit, p->iOffset+1, -1);
  2285   2273           }
  2286   2274         }
  2287   2275         explainSetInteger(iSub2, pParse->iNextSelectId);
  2288   2276         rc = sqlite3Select(pParse, p, &dest);
  2289   2277         testcase( rc!=SQLITE_OK );
  2290   2278         pDelete = p->pPrior;
  2291   2279         p->pPrior = pPrior;

Changes to src/vdbe.c.

  5667   5667     if( pIn1->u.i<pIn2->u.i){
  5668   5668       pIn1->u.i = pIn2->u.i;
  5669   5669     }
  5670   5670     break;
  5671   5671   }
  5672   5672   #endif /* SQLITE_OMIT_AUTOINCREMENT */
  5673   5673   
  5674         -/* Opcode: IfPos P1 P2 * * *
  5675         -** Synopsis: if r[P1]>0 goto P2
         5674  +/* Opcode: IfPos P1 P2 P3 * *
         5675  +** Synopsis: if r[P1]>0 then r[P1]-=P3, goto P2
  5676   5676   **
  5677   5677   ** Register P1 must contain an integer.
  5678         -** If the value of register P1 is 1 or greater, jump to P2 and
  5679         -** add the literal value P3 to register P1.
         5678  +** If the value of register P1 is 1 or greater, subtrace P3 from the
         5679  +** value in P1 and jump to P2.
  5680   5680   **
  5681   5681   ** If the initial value of register P1 is less than 1, then the
  5682   5682   ** value is unchanged and control passes through to the next instruction.
  5683   5683   */
  5684   5684   case OP_IfPos: {        /* jump, in1 */
  5685   5685     pIn1 = &aMem[pOp->p1];
  5686   5686     assert( pIn1->flags&MEM_Int );
  5687   5687     VdbeBranchTaken( pIn1->u.i>0, 2);
  5688         -  if( pIn1->u.i>0 ) goto jump_to_p2;
         5688  +  if( pIn1->u.i>0 ){
         5689  +    pIn1->u.i -= pOp->p3;
         5690  +    goto jump_to_p2;
         5691  +  }
  5689   5692     break;
  5690   5693   }
  5691   5694   
  5692         -/* Opcode: IfNeg P1 P2 P3 * *
  5693         -** Synopsis: r[P1]+=P3, if r[P1]<0 goto P2
         5695  +/* Opcode: SetIfNotPos P1 P2 P3 * *
         5696  +** Synopsis: if r[P1]<=0 then r[P2]=P3
  5694   5697   **
  5695         -** Register P1 must contain an integer.  Add literal P3 to the value in
  5696         -** register P1 then if the value of register P1 is less than zero, jump to P2. 
         5698  +** Register P1 must contain an integer.
         5699  +** If the value of register P1 is not positive (if it is less than 1) then
         5700  +** set the value of register P2 to be the integer P3.
  5697   5701   */
  5698         -case OP_IfNeg: {        /* jump, in1 */
         5702  +case OP_SetIfNotPos: {        /* in1, in2 */
  5699   5703     pIn1 = &aMem[pOp->p1];
  5700   5704     assert( pIn1->flags&MEM_Int );
  5701         -  pIn1->u.i += pOp->p3;
  5702         -  VdbeBranchTaken(pIn1->u.i<0, 2);
  5703         -  if( pIn1->u.i<0 ) goto jump_to_p2;
         5705  +  if( pIn1->u.i<=0 ){
         5706  +    pOut = out2Prerelease(p, pOp);
         5707  +    pOut->u.i = pOp->p3;
         5708  +  }
  5704   5709     break;
  5705   5710   }
  5706   5711   
  5707   5712   /* Opcode: IfNotZero P1 P2 P3 * *
  5708         -** Synopsis: if r[P1]!=0 then r[P1]+=P3, goto P2
         5713  +** Synopsis: if r[P1]!=0 then r[P1]-=P3, goto P2
  5709   5714   **
  5710   5715   ** Register P1 must contain an integer.  If the content of register P1 is
  5711         -** initially nonzero, then add P3 to P1 and jump to P2.  If register P1 is
  5712         -** initially zero, leave it unchanged and fall through.
         5716  +** initially nonzero, then subtrace P3 from the value in register P1 and
         5717  +** jump to P2.  If register P1 is initially zero, leave it unchanged
         5718  +** and fall through.
  5713   5719   */
  5714   5720   case OP_IfNotZero: {        /* jump, in1 */
  5715   5721     pIn1 = &aMem[pOp->p1];
  5716   5722     assert( pIn1->flags&MEM_Int );
  5717   5723     VdbeBranchTaken(pIn1->u.i<0, 2);
  5718   5724     if( pIn1->u.i ){
  5719         -     pIn1->u.i += pOp->p3;
         5725  +     pIn1->u.i -= pOp->p3;
  5720   5726        goto jump_to_p2;
  5721   5727     }
  5722   5728     break;
  5723   5729   }
  5724   5730   
  5725   5731   /* Opcode: DecrJumpZero P1 P2 * * *
  5726   5732   ** Synopsis: if (--r[P1])==0 goto P2