/ Check-in [1383680d]
Login

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

Overview
Comment:Additional simplifications of the WHERE loop code generator logic for NULLS LAST.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | nulls-last
Files: files | file ages | folders
SHA3-256: 1383680d927d7d703933be7653c0019199845e7f7e82bcc76d9ca3808093e9d8
User & Date: drh 2019-08-23 17:00:22
Context
2019-08-23
17:09
Revise the VDBE comments for NULL-scan so that they also work make sense when reading a NULLS FIRST plan. check-in: bfe79378 user: drh tags: nulls-last
17:00
Additional simplifications of the WHERE loop code generator logic for NULLS LAST. check-in: 1383680d user: drh tags: nulls-last
16:12
Simplification of the WHERE loop code generator for NULLS LAST saves a few CPU cycles and about a hundred bytes of code space. check-in: e3ed2f49 user: drh tags: nulls-last
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/wherecode.c.

  1704   1704         VdbeCoverageIf(v, op==OP_SeekGE);  testcase( op==OP_SeekGE );
  1705   1705         VdbeCoverageIf(v, op==OP_SeekLE);  testcase( op==OP_SeekLE );
  1706   1706         VdbeCoverageIf(v, op==OP_SeekLT);  testcase( op==OP_SeekLT );
  1707   1707   
  1708   1708         assert( bSeekPastNull==0 || bStopAtNull==0 );
  1709   1709         if( regBignull ){
  1710   1710           assert( bSeekPastNull==1 || bStopAtNull==1 );
         1711  +        assert( bSeekPastNull==!bStopAtNull );
  1711   1712           assert( bStopAtNull==startEq );
  1712   1713           sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+2);
  1713   1714           op = aStartOp[(nConstraint>1)*4 + 2 + bRev];
  1714   1715           sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, 
  1715   1716                                nConstraint-startEq);
  1716   1717           VdbeCoverage(v);
  1717   1718           VdbeCoverageIf(v, op==OP_Rewind);  testcase( op==OP_Rewind );
................................................................................
  1762   1763   
  1763   1764       /* Top of the loop body */
  1764   1765       pLevel->p2 = sqlite3VdbeCurrentAddr(v);
  1765   1766   
  1766   1767       /* Check if the index cursor is past the end of the range. */
  1767   1768       if( nConstraint ){
  1768   1769         if( regBignull ){
         1770  +        /* Except, skip the end-of-range check while doing the NULL-scan */
  1769   1771           sqlite3VdbeAddOp2(v, OP_IfNot, regBignull, sqlite3VdbeCurrentAddr(v)+3);
  1770   1772           VdbeComment((v, "If NULL-scan active"));
  1771   1773           VdbeCoverage(v);
  1772   1774         }
  1773   1775         op = aEndOp[bRev*2 + endEq];
  1774   1776         sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
  1775   1777         testcase( op==OP_IdxGT );  VdbeCoverageIf(v, op==OP_IdxGT );
  1776   1778         testcase( op==OP_IdxGE );  VdbeCoverageIf(v, op==OP_IdxGE );
  1777   1779         testcase( op==OP_IdxLT );  VdbeCoverageIf(v, op==OP_IdxLT );
  1778   1780         testcase( op==OP_IdxLE );  VdbeCoverageIf(v, op==OP_IdxLE );
  1779   1781       }
  1780   1782       if( regBignull ){
         1783  +      /* During a NULL-scan, check to see if we have reached the end of
         1784  +      ** the NULLs */
         1785  +      assert( bSeekPastNull==!bStopAtNull );
         1786  +      assert( bSeekPastNull+bStopAtNull==1 );
         1787  +      assert( nConstraint+bSeekPastNull>0 );
  1781   1788         sqlite3VdbeAddOp2(v, OP_If, regBignull, sqlite3VdbeCurrentAddr(v)+2);
  1782   1789         VdbeComment((v, "If NULL-scan pending"));
  1783   1790         VdbeCoverage(v);
  1784         -      if( bStopAtNull ){
  1785         -        op = aEndOp[bRev*2 + 0];
  1786         -        assert( op==OP_IdxGE || op==OP_IdxLE );
  1787         -        sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
  1788         -        testcase( op==OP_IdxGE );  VdbeCoverageIf(v, op==OP_IdxGE );
  1789         -        testcase( op==OP_IdxLE );  VdbeCoverageIf(v, op==OP_IdxLE );
  1790         -      }else{
  1791         -        op = aEndOp[bRev*2 + endEq];
  1792         -        sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint+1);
  1793         -        testcase( op==OP_IdxGT );  VdbeCoverageIf(v, op==OP_IdxGT );
  1794         -        testcase( op==OP_IdxGE );  VdbeCoverageIf(v, op==OP_IdxGE );
  1795         -        testcase( op==OP_IdxLT );  VdbeCoverageIf(v, op==OP_IdxLT );
  1796         -        testcase( op==OP_IdxLE );  VdbeCoverageIf(v, op==OP_IdxLE );
  1797         -      }
         1791  +      op = aEndOp[bRev*2 + bSeekPastNull];
         1792  +      sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase,
         1793  +                           nConstraint+bSeekPastNull);
         1794  +      testcase( op==OP_IdxGT );  VdbeCoverageIf(v, op==OP_IdxGT );
         1795  +      testcase( op==OP_IdxGE );  VdbeCoverageIf(v, op==OP_IdxGE );
         1796  +      testcase( op==OP_IdxLT );  VdbeCoverageIf(v, op==OP_IdxLT );
         1797  +      testcase( op==OP_IdxLE );  VdbeCoverageIf(v, op==OP_IdxLE );
  1798   1798       }
  1799   1799   
  1800   1800       if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){
  1801   1801         sqlite3VdbeAddOp2(v, OP_SeekHit, iIdxCur, 1);
  1802   1802       }
  1803   1803   
  1804   1804       /* Seek the table cursor, if required */