Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Further improvements to bytecode branch testing. Fix cases where the macros said a branch could not be taken when in fact it could be. Alter some window function branch coverage macros to indicate that comparison operands cannot be NULL. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
76e42b7071a71137c0da4f10db4e653a |
User & Date: | drh 2018-07-10 17:10:44.627 |
Context
2018-07-10
| ||
17:26 | Fix a problem with using scalar sub-selects in window function queries. (check-in: 687fe532c2 user: dan tags: trunk) | |
17:10 | Further improvements to bytecode branch testing. Fix cases where the macros said a branch could not be taken when in fact it could be. Alter some window function branch coverage macros to indicate that comparison operands cannot be NULL. (check-in: 76e42b7071 user: drh tags: trunk) | |
16:04 | Enhancements and improved documentation to the byte-code branch coverage testing logic. Provide new macros that allow the code to specify that some branch instructions can never take the NULL path and that the OP_Jump opcode is only interested in equal/not-equal. The SQLITE_TESTCTRL_VDBE_COVERAGE file control callback now works slightly differently (it provides the callback with a bitmask of the branch action, rather than an integer). (check-in: cd2da7e1ba user: drh tags: trunk) | |
Changes
Changes to src/analyze.c.
︙ | ︙ | |||
1270 1271 1272 1273 1274 1275 1276 | callStatGet(v, regStat4, STAT_GET_ROWID, regSampleRowid); addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regSampleRowid); VdbeCoverage(v); callStatGet(v, regStat4, STAT_GET_NEQ, regEq); callStatGet(v, regStat4, STAT_GET_NLT, regLt); callStatGet(v, regStat4, STAT_GET_NDLT, regDLt); sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0); | < < < | | 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 | callStatGet(v, regStat4, STAT_GET_ROWID, regSampleRowid); addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regSampleRowid); VdbeCoverage(v); callStatGet(v, regStat4, STAT_GET_NEQ, regEq); callStatGet(v, regStat4, STAT_GET_NLT, regLt); callStatGet(v, regStat4, STAT_GET_NDLT, regDLt); sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0); VdbeCoverage(v); #ifdef SQLITE_ENABLE_STAT3 sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iTabCur, 0, regSample); #else for(i=0; i<nCol; i++){ sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iTabCur, i, regCol+i); } sqlite3VdbeAddOp3(v, OP_MakeRecord, regCol, nCol, regSample); |
︙ | ︙ |
Changes to src/update.c.
︙ | ︙ | |||
519 520 521 522 523 524 525 | } /* Top of the update loop */ if( eOnePass!=ONEPASS_OFF ){ if( !isView && aiCurOnePass[0]!=iDataCur && aiCurOnePass[1]!=iDataCur ){ assert( pPk ); sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey,nKey); | | | 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 | } /* Top of the update loop */ if( eOnePass!=ONEPASS_OFF ){ if( !isView && aiCurOnePass[0]!=iDataCur && aiCurOnePass[1]!=iDataCur ){ assert( pPk ); sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey,nKey); VdbeCoverage(v); } if( eOnePass!=ONEPASS_SINGLE ){ labelContinue = sqlite3VdbeMakeLabel(v); } sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak); VdbeCoverageIf(v, pPk==0); VdbeCoverageIf(v, pPk!=0); |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
176 177 178 179 180 181 182 | mNever = iSrcLine >> 24; assert( (I & mNever)==0 ); if( sqlite3GlobalConfig.xVdbeBranch==0 ) return; /*NO_TEST*/ I |= mNever; if( M==2 ) I |= 0x04; if( M==4 ){ I |= 0x08; | | | 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | mNever = iSrcLine >> 24; assert( (I & mNever)==0 ); if( sqlite3GlobalConfig.xVdbeBranch==0 ) return; /*NO_TEST*/ I |= mNever; if( M==2 ) I |= 0x04; if( M==4 ){ I |= 0x08; if( (mNever&0x08)!=0 && (I&0x05)!=0) I |= 0x05; /*NO_TEST*/ } sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg, iSrcLine&0xffffff, I, M); } #endif /* |
︙ | ︙ |
Changes to src/vdbe.h.
︙ | ︙ | |||
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 | # define VdbeCoverageIf(v,x) if(x)sqlite3VdbeSetLineNumber(v,__LINE__) # define VdbeCoverageAlwaysTaken(v) \ sqlite3VdbeSetLineNumber(v,__LINE__|0x5000000); # define VdbeCoverageNeverTaken(v) \ sqlite3VdbeSetLineNumber(v,__LINE__|0x6000000); # define VdbeCoverageNeverNull(v) \ sqlite3VdbeSetLineNumber(v,__LINE__|0x4000000); # define VdbeCoverageEqNe(v) \ sqlite3VdbeSetLineNumber(v,__LINE__|0x8000000); # define VDBE_OFFSET_LINENO(x) (__LINE__+x) #else # define VdbeCoverage(v) # define VdbeCoverageIf(v,x) # define VdbeCoverageAlwaysTaken(v) # define VdbeCoverageNeverTaken(v) # define VdbeCoverageNeverNull(v) # define VdbeCoverageEqNe(v) # define VDBE_OFFSET_LINENO(x) 0 #endif #ifdef SQLITE_ENABLE_STMT_SCANSTATUS void sqlite3VdbeScanStatus(Vdbe*, int, int, int, LogEst, const char*); #else | > > > | 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 | # define VdbeCoverageIf(v,x) if(x)sqlite3VdbeSetLineNumber(v,__LINE__) # define VdbeCoverageAlwaysTaken(v) \ sqlite3VdbeSetLineNumber(v,__LINE__|0x5000000); # define VdbeCoverageNeverTaken(v) \ sqlite3VdbeSetLineNumber(v,__LINE__|0x6000000); # define VdbeCoverageNeverNull(v) \ sqlite3VdbeSetLineNumber(v,__LINE__|0x4000000); # define VdbeCoverageNeverNullIf(v,x) \ if(x)sqlite3VdbeSetLineNumber(v,__LINE__|0x4000000); # define VdbeCoverageEqNe(v) \ sqlite3VdbeSetLineNumber(v,__LINE__|0x8000000); # define VDBE_OFFSET_LINENO(x) (__LINE__+x) #else # define VdbeCoverage(v) # define VdbeCoverageIf(v,x) # define VdbeCoverageAlwaysTaken(v) # define VdbeCoverageNeverTaken(v) # define VdbeCoverageNeverNull(v) # define VdbeCoverageNeverNullIf(v,x) # define VdbeCoverageEqNe(v) # define VDBE_OFFSET_LINENO(x) 0 #endif #ifdef SQLITE_ENABLE_STMT_SCANSTATUS void sqlite3VdbeScanStatus(Vdbe*, int, int, int, LogEst, const char*); #else |
︙ | ︙ |
Changes to src/window.c.
︙ | ︙ | |||
1034 1035 1036 1037 1038 1039 1040 | assert( eCond==0 || eCond==1 || eCond==2 ); sqlite3VdbeAddOp2(v, OP_Integer, 0, regZero); sqlite3VdbeAddOp2(v, OP_MustBeInt, reg, sqlite3VdbeCurrentAddr(v)+2); VdbeCoverageIf(v, eCond==0); VdbeCoverageIf(v, eCond==1); VdbeCoverageIf(v, eCond==2); sqlite3VdbeAddOp3(v, aOp[eCond], regZero, sqlite3VdbeCurrentAddr(v)+2, reg); | | | | | 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 | assert( eCond==0 || eCond==1 || eCond==2 ); sqlite3VdbeAddOp2(v, OP_Integer, 0, regZero); sqlite3VdbeAddOp2(v, OP_MustBeInt, reg, sqlite3VdbeCurrentAddr(v)+2); VdbeCoverageIf(v, eCond==0); VdbeCoverageIf(v, eCond==1); VdbeCoverageIf(v, eCond==2); sqlite3VdbeAddOp3(v, aOp[eCond], regZero, sqlite3VdbeCurrentAddr(v)+2, reg); VdbeCoverageNeverNullIf(v, eCond==0); VdbeCoverageNeverNullIf(v, eCond==1); VdbeCoverageNeverNullIf(v, eCond==2); sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_ERROR, OE_Abort); sqlite3VdbeAppendP4(v, (void*)azErr[eCond], P4_STATIC); sqlite3ReleaseTempReg(pParse, regZero); } /* ** Return the number of arguments passed to the window-function associated |
︙ | ︙ | |||
1304 1305 1306 1307 1308 1309 1310 | sqlite3VdbeAddOp3(v, OP_Column, pMWin->iEphCsr, pWin->iArgCol+1,tmpReg); windowCheckIntValue(pParse, tmpReg, 2); }else{ sqlite3VdbeAddOp2(v, OP_Integer, 1, tmpReg); } sqlite3VdbeAddOp3(v, OP_Add, tmpReg, pWin->regApp, tmpReg); sqlite3VdbeAddOp3(v, OP_Gt, pWin->regApp+1, lbl, tmpReg); | | | 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 | sqlite3VdbeAddOp3(v, OP_Column, pMWin->iEphCsr, pWin->iArgCol+1,tmpReg); windowCheckIntValue(pParse, tmpReg, 2); }else{ sqlite3VdbeAddOp2(v, OP_Integer, 1, tmpReg); } sqlite3VdbeAddOp3(v, OP_Add, tmpReg, pWin->regApp, tmpReg); sqlite3VdbeAddOp3(v, OP_Gt, pWin->regApp+1, lbl, tmpReg); VdbeCoverageNeverNull(v); sqlite3VdbeAddOp3(v, OP_SeekRowid, csr, lbl, tmpReg); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol, pWin->regResult); sqlite3VdbeResolveLabel(v, lbl); sqlite3ReleaseTempReg(pParse, tmpReg); } else if( pFunc->zName==leadName || pFunc->zName==lagName ){ |
︙ | ︙ | |||
1617 1618 1619 1620 1621 1622 1623 | ** } ** regEnd = regEnd - regStart; */ if( pMWin->pEnd && pMWin->eStart==TK_FOLLOWING ){ assert( pMWin->pStart!=0 ); assert( pMWin->eEnd==TK_FOLLOWING ); sqlite3VdbeAddOp3(v, OP_Ge, regStart, sqlite3VdbeCurrentAddr(v)+2, regEnd); | | | | 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 | ** } ** regEnd = regEnd - regStart; */ if( pMWin->pEnd && pMWin->eStart==TK_FOLLOWING ){ assert( pMWin->pStart!=0 ); assert( pMWin->eEnd==TK_FOLLOWING ); sqlite3VdbeAddOp3(v, OP_Ge, regStart, sqlite3VdbeCurrentAddr(v)+2, regEnd); VdbeCoverageNeverNull(v); sqlite3VdbeAddOp2(v, OP_Copy, regSize, regStart); sqlite3VdbeAddOp3(v, OP_Subtract, regStart, regEnd, regEnd); } if( pMWin->pStart && pMWin->eEnd==TK_PRECEDING ){ assert( pMWin->pEnd!=0 ); assert( pMWin->eStart==TK_PRECEDING ); sqlite3VdbeAddOp3(v, OP_Le, regStart, sqlite3VdbeCurrentAddr(v)+3, regEnd); VdbeCoverageNeverNull(v); sqlite3VdbeAddOp2(v, OP_Copy, regSize, regStart); sqlite3VdbeAddOp2(v, OP_Copy, regSize, regEnd); } /* Initialize the accumulator register for each window function to NULL */ regArg = windowInitAccum(pParse, pMWin); |
︙ | ︙ |