Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Extra VDBE comments in the NULLS LAST logic provide landmarks to help understand the EXPLAIN output. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | nulls-last |
Files: | files | file ages | folders |
SHA3-256: |
649b08ead50f10a9ec0357a5e1ed0201 |
User & Date: | drh 2019-08-23 13:08:49.776 |
Context
2019-08-23
| ||
13:32 | Invert the meaning of the regBignull flag so that it is 1 when doing the normal scan and 1 when scanning nulls. This enables the re-do jump at the bottom of the loop to be coded with a single OP_IfNotZero opcode, rather than a sequence of OP_If, OP_Integer, OP_Goto. (check-in: bf875e1a25 user: drh tags: nulls-last) | |
13:08 | Extra VDBE comments in the NULLS LAST logic provide landmarks to help understand the EXPLAIN output. (check-in: 649b08ead5 user: drh tags: nulls-last) | |
2019-08-22
| ||
21:13 | Add additional VDBE coverage macros. (check-in: d3531f5be7 user: drh tags: nulls-last) | |
Changes
Changes to src/where.c.
︙ | ︙ | |||
5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 | VdbeCoverage(v); VdbeCoverageIf(v, pLevel->op==OP_Next); VdbeCoverageIf(v, pLevel->op==OP_Prev); VdbeCoverageIf(v, pLevel->op==OP_VNext); if( pLevel->regBignull ){ sqlite3VdbeResolveLabel(v, pLevel->addrBignull); addr = sqlite3VdbeAddOp1(v, OP_If, pLevel->regBignull); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->regBignull); sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->p2-1); sqlite3VdbeJumpHere(v, addr); } #ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT if( addrSeek ) sqlite3VdbeJumpHere(v, addrSeek); #endif }else{ sqlite3VdbeResolveLabel(v, pLevel->addrCont); | > > | 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 | VdbeCoverage(v); VdbeCoverageIf(v, pLevel->op==OP_Next); VdbeCoverageIf(v, pLevel->op==OP_Prev); VdbeCoverageIf(v, pLevel->op==OP_VNext); if( pLevel->regBignull ){ sqlite3VdbeResolveLabel(v, pLevel->addrBignull); addr = sqlite3VdbeAddOp1(v, OP_If, pLevel->regBignull); VdbeComment((v, "If NULL-scan done")); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->regBignull); sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->p2-1); VdbeComment((v, "Do the NULL-scan")); sqlite3VdbeJumpHere(v, addr); } #ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT if( addrSeek ) sqlite3VdbeJumpHere(v, addrSeek); #endif }else{ sqlite3VdbeResolveLabel(v, pLevel->addrCont); |
︙ | ︙ |
Changes to src/whereInt.h.
︙ | ︙ | |||
67 68 69 70 71 72 73 | int iIdxCur; /* The VDBE cursor used to access pIdx */ int addrBrk; /* Jump here to break out of the loop */ int addrNxt; /* Jump here to start the next IN combination */ int addrSkip; /* Jump here for next iteration of skip-scan */ int addrCont; /* Jump here to continue with the next loop cycle */ int addrFirst; /* First instruction of interior of the loop */ int addrBody; /* Beginning of the body of this loop */ | | | 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | int iIdxCur; /* The VDBE cursor used to access pIdx */ int addrBrk; /* Jump here to break out of the loop */ int addrNxt; /* Jump here to start the next IN combination */ int addrSkip; /* Jump here for next iteration of skip-scan */ int addrCont; /* Jump here to continue with the next loop cycle */ int addrFirst; /* First instruction of interior of the loop */ int addrBody; /* Beginning of the body of this loop */ int regBignull; /* big-null flag reg. True if NULLs not yet scanned */ int addrBignull; /* Jump here for next part of big-null scan */ #ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS u32 iLikeRepCntr; /* LIKE range processing counter register (times 2) */ int addrLikeRep; /* LIKE range processing address */ #endif u8 iFrom; /* Which entry in the FROM clause */ u8 op, p3, p5; /* Opcode, P3 & P5 of the opcode that ends the loop */ |
︙ | ︙ |
Changes to src/wherecode.c.
︙ | ︙ | |||
1546 1547 1548 1549 1550 1551 1552 | int nExtraReg = 0; /* Number of extra registers needed */ int op; /* Instruction opcode */ char *zStartAff; /* Affinity for start of range constraint */ char *zEndAff = 0; /* Affinity for end of range constraint */ u8 bSeekPastNull = 0; /* True to seek past initial nulls */ u8 bStopAtNull = 0; /* Add condition to terminate at NULLs */ int omitTable; /* True if we use the index only */ | | | 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 | int nExtraReg = 0; /* Number of extra registers needed */ int op; /* Instruction opcode */ char *zStartAff; /* Affinity for start of range constraint */ char *zEndAff = 0; /* Affinity for end of range constraint */ u8 bSeekPastNull = 0; /* True to seek past initial nulls */ u8 bStopAtNull = 0; /* Add condition to terminate at NULLs */ int omitTable; /* True if we use the index only */ int regBignull = 0; /* big-null flag register */ pIdx = pLoop->u.btree.pIndex; iIdxCur = pLevel->iIdxCur; assert( nEq>=pLoop->nSkip ); /* Find any inequality constraint terms for the start and end ** of the range. |
︙ | ︙ | |||
1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 | ** so no further seeking is needed */ }else{ if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){ sqlite3VdbeAddOp1(v, OP_SeekHit, iIdxCur); } if( regBignull ){ sqlite3VdbeAddOp2(v, OP_Integer, 0, regBignull); } op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev]; assert( op!=0 ); sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); VdbeCoverage(v); VdbeCoverageIf(v, op==OP_Rewind); testcase( op==OP_Rewind ); | > | 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 | ** so no further seeking is needed */ }else{ if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){ sqlite3VdbeAddOp1(v, OP_SeekHit, iIdxCur); } if( regBignull ){ sqlite3VdbeAddOp2(v, OP_Integer, 0, regBignull); VdbeComment((v, "NULL-scan flag")); } op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev]; assert( op!=0 ); sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); VdbeCoverage(v); VdbeCoverageIf(v, op==OP_Rewind); testcase( op==OP_Rewind ); |
︙ | ︙ | |||
1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 | /* Top of the loop body */ pLevel->p2 = sqlite3VdbeCurrentAddr(v); /* Check if the index cursor is past the end of the range. */ if( nConstraint ){ if( regBignull ){ sqlite3VdbeAddOp2(v, OP_If, regBignull, sqlite3VdbeCurrentAddr(v)+3); VdbeCoverage(v); } op = aEndOp[bRev*2 + endEq]; sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); testcase( op==OP_IdxGT ); VdbeCoverageIf(v, op==OP_IdxGT ); testcase( op==OP_IdxGE ); VdbeCoverageIf(v, op==OP_IdxGE ); testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT ); testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE ); } if( regBignull ){ sqlite3VdbeAddOp2(v, OP_IfNot, regBignull, sqlite3VdbeCurrentAddr(v)+2); VdbeCoverage(v); if( bStopAtNull ){ op = aEndOp[bRev*2 + 0]; assert( op==OP_IdxGE || op==OP_IdxLE ); sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); testcase( op==OP_IdxGE ); VdbeCoverageIf(v, op==OP_IdxGE ); testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE ); | > > | 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 | /* Top of the loop body */ pLevel->p2 = sqlite3VdbeCurrentAddr(v); /* Check if the index cursor is past the end of the range. */ if( nConstraint ){ if( regBignull ){ sqlite3VdbeAddOp2(v, OP_If, regBignull, sqlite3VdbeCurrentAddr(v)+3); VdbeComment((v, "If in NULL-scan")); VdbeCoverage(v); } op = aEndOp[bRev*2 + endEq]; sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); testcase( op==OP_IdxGT ); VdbeCoverageIf(v, op==OP_IdxGT ); testcase( op==OP_IdxGE ); VdbeCoverageIf(v, op==OP_IdxGE ); testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT ); testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE ); } if( regBignull ){ sqlite3VdbeAddOp2(v, OP_IfNot, regBignull, sqlite3VdbeCurrentAddr(v)+2); VdbeComment((v, "If not in NULL-scan")); VdbeCoverage(v); if( bStopAtNull ){ op = aEndOp[bRev*2 + 0]; assert( op==OP_IdxGE || op==OP_IdxLE ); sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); testcase( op==OP_IdxGE ); VdbeCoverageIf(v, op==OP_IdxGE ); testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE ); |
︙ | ︙ |