/ Check-in [76e42b70]
Login

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 | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 76e42b7071a71137c0da4f10db4e653ae94a89b56e95cd3f036bff08c9500d08
User & Date: drh 2018-07-10 17:10:44
Context
2018-07-10
17:26
Fix a problem with using scalar sub-selects in window function queries. check-in: 687fe532 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: 76e42b70 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: cd2da7e1 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/analyze.c.

  1270   1270         callStatGet(v, regStat4, STAT_GET_ROWID, regSampleRowid);
  1271   1271         addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regSampleRowid);
  1272   1272         VdbeCoverage(v);
  1273   1273         callStatGet(v, regStat4, STAT_GET_NEQ, regEq);
  1274   1274         callStatGet(v, regStat4, STAT_GET_NLT, regLt);
  1275   1275         callStatGet(v, regStat4, STAT_GET_NDLT, regDLt);
  1276   1276         sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0);
  1277         -      /* We know that the regSampleRowid row exists because it was read by
  1278         -      ** the previous loop.  Thus the not-found jump of seekOp will never
  1279         -      ** be taken */
  1280         -      VdbeCoverageNeverTaken(v);
         1277  +      VdbeCoverage(v);
  1281   1278   #ifdef SQLITE_ENABLE_STAT3
  1282   1279         sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iTabCur, 0, regSample);
  1283   1280   #else
  1284   1281         for(i=0; i<nCol; i++){
  1285   1282           sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iTabCur, i, regCol+i);
  1286   1283         }
  1287   1284         sqlite3VdbeAddOp3(v, OP_MakeRecord, regCol, nCol, regSample);

Changes to src/update.c.

   519    519       }
   520    520     
   521    521       /* Top of the update loop */
   522    522       if( eOnePass!=ONEPASS_OFF ){
   523    523         if( !isView && aiCurOnePass[0]!=iDataCur && aiCurOnePass[1]!=iDataCur ){
   524    524           assert( pPk );
   525    525           sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey,nKey);
   526         -        VdbeCoverageNeverTaken(v);
          526  +        VdbeCoverage(v);
   527    527         }
   528    528         if( eOnePass!=ONEPASS_SINGLE ){
   529    529           labelContinue = sqlite3VdbeMakeLabel(v);
   530    530         }
   531    531         sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak);
   532    532         VdbeCoverageIf(v, pPk==0);
   533    533         VdbeCoverageIf(v, pPk!=0);

Changes to src/vdbe.c.

   176    176       mNever = iSrcLine >> 24;
   177    177       assert( (I & mNever)==0 );
   178    178       if( sqlite3GlobalConfig.xVdbeBranch==0 ) return;  /*NO_TEST*/
   179    179       I |= mNever;
   180    180       if( M==2 ) I |= 0x04;
   181    181       if( M==4 ){
   182    182         I |= 0x08;
   183         -      if( (I&0x05)!=0 ) I |= 0x05;
          183  +      if( (mNever&0x08)!=0 && (I&0x05)!=0) I |= 0x05; /*NO_TEST*/
   184    184       }
   185    185       sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg,
   186    186                                       iSrcLine&0xffffff, I, M);
   187    187     }
   188    188   #endif
   189    189   
   190    190   /*

Changes to src/vdbe.h.

   347    347   # define VdbeCoverageIf(v,x) if(x)sqlite3VdbeSetLineNumber(v,__LINE__)
   348    348   # define VdbeCoverageAlwaysTaken(v) \
   349    349            sqlite3VdbeSetLineNumber(v,__LINE__|0x5000000);
   350    350   # define VdbeCoverageNeverTaken(v) \
   351    351            sqlite3VdbeSetLineNumber(v,__LINE__|0x6000000);
   352    352   # define VdbeCoverageNeverNull(v) \
   353    353            sqlite3VdbeSetLineNumber(v,__LINE__|0x4000000);
          354  +# define VdbeCoverageNeverNullIf(v,x) \
          355  +         if(x)sqlite3VdbeSetLineNumber(v,__LINE__|0x4000000);
   354    356   # define VdbeCoverageEqNe(v) \
   355    357            sqlite3VdbeSetLineNumber(v,__LINE__|0x8000000);
   356    358   # define VDBE_OFFSET_LINENO(x) (__LINE__+x)
   357    359   #else
   358    360   # define VdbeCoverage(v)
   359    361   # define VdbeCoverageIf(v,x)
   360    362   # define VdbeCoverageAlwaysTaken(v)
   361    363   # define VdbeCoverageNeverTaken(v)
   362    364   # define VdbeCoverageNeverNull(v)
          365  +# define VdbeCoverageNeverNullIf(v,x)
   363    366   # define VdbeCoverageEqNe(v)
   364    367   # define VDBE_OFFSET_LINENO(x) 0
   365    368   #endif
   366    369   
   367    370   #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
   368    371   void sqlite3VdbeScanStatus(Vdbe*, int, int, int, LogEst, const char*);
   369    372   #else

Changes to src/window.c.

  1034   1034     assert( eCond==0 || eCond==1 || eCond==2 );
  1035   1035     sqlite3VdbeAddOp2(v, OP_Integer, 0, regZero);
  1036   1036     sqlite3VdbeAddOp2(v, OP_MustBeInt, reg, sqlite3VdbeCurrentAddr(v)+2);
  1037   1037     VdbeCoverageIf(v, eCond==0);
  1038   1038     VdbeCoverageIf(v, eCond==1);
  1039   1039     VdbeCoverageIf(v, eCond==2);
  1040   1040     sqlite3VdbeAddOp3(v, aOp[eCond], regZero, sqlite3VdbeCurrentAddr(v)+2, reg);
  1041         -  VdbeCoverageIf(v, eCond==0);
  1042         -  VdbeCoverageIf(v, eCond==1);
  1043         -  VdbeCoverageIf(v, eCond==2);
         1041  +  VdbeCoverageNeverNullIf(v, eCond==0);
         1042  +  VdbeCoverageNeverNullIf(v, eCond==1);
         1043  +  VdbeCoverageNeverNullIf(v, eCond==2);
  1044   1044     sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_ERROR, OE_Abort);
  1045   1045     sqlite3VdbeAppendP4(v, (void*)azErr[eCond], P4_STATIC);
  1046   1046     sqlite3ReleaseTempReg(pParse, regZero);
  1047   1047   }
  1048   1048   
  1049   1049   /*
  1050   1050   ** Return the number of arguments passed to the window-function associated
................................................................................
  1304   1304           sqlite3VdbeAddOp3(v, OP_Column, pMWin->iEphCsr, pWin->iArgCol+1,tmpReg);
  1305   1305           windowCheckIntValue(pParse, tmpReg, 2);
  1306   1306         }else{
  1307   1307           sqlite3VdbeAddOp2(v, OP_Integer, 1, tmpReg);
  1308   1308         }
  1309   1309         sqlite3VdbeAddOp3(v, OP_Add, tmpReg, pWin->regApp, tmpReg);
  1310   1310         sqlite3VdbeAddOp3(v, OP_Gt, pWin->regApp+1, lbl, tmpReg);
  1311         -      VdbeCoverage(v);
         1311  +      VdbeCoverageNeverNull(v);
  1312   1312         sqlite3VdbeAddOp3(v, OP_SeekRowid, csr, lbl, tmpReg);
  1313   1313         VdbeCoverage(v);
  1314   1314         sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol, pWin->regResult);
  1315   1315         sqlite3VdbeResolveLabel(v, lbl);
  1316   1316         sqlite3ReleaseTempReg(pParse, tmpReg);
  1317   1317       }
  1318   1318       else if( pFunc->zName==leadName || pFunc->zName==lagName ){
................................................................................
  1617   1617     **   }
  1618   1618     **   regEnd = regEnd - regStart;
  1619   1619     */
  1620   1620     if( pMWin->pEnd && pMWin->eStart==TK_FOLLOWING ){
  1621   1621       assert( pMWin->pStart!=0 );
  1622   1622       assert( pMWin->eEnd==TK_FOLLOWING );
  1623   1623       sqlite3VdbeAddOp3(v, OP_Ge, regStart, sqlite3VdbeCurrentAddr(v)+2, regEnd);
  1624         -    VdbeCoverage(v);
         1624  +    VdbeCoverageNeverNull(v);
  1625   1625       sqlite3VdbeAddOp2(v, OP_Copy, regSize, regStart);
  1626   1626       sqlite3VdbeAddOp3(v, OP_Subtract, regStart, regEnd, regEnd);
  1627   1627     }
  1628   1628   
  1629   1629     if( pMWin->pStart && pMWin->eEnd==TK_PRECEDING ){
  1630   1630       assert( pMWin->pEnd!=0 );
  1631   1631       assert( pMWin->eStart==TK_PRECEDING );
  1632   1632       sqlite3VdbeAddOp3(v, OP_Le, regStart, sqlite3VdbeCurrentAddr(v)+3, regEnd);
  1633         -    VdbeCoverage(v);
         1633  +    VdbeCoverageNeverNull(v);
  1634   1634       sqlite3VdbeAddOp2(v, OP_Copy, regSize, regStart);
  1635   1635       sqlite3VdbeAddOp2(v, OP_Copy, regSize, regEnd);
  1636   1636     }
  1637   1637   
  1638   1638     /* Initialize the accumulator register for each window function to NULL */
  1639   1639     regArg = windowInitAccum(pParse, pMWin);
  1640   1640