/ Check-in [b6bea903]
Login

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

Overview
Comment:Add OP_IdxGT and OP_IdxLE as distinct opcodes. Formerly these operations where done using OP_IdxGE and OP_IdxLT with the P5 flag set. But VDBE code is easier to read with distinct opcode names. Also change OP_SeekGe to OP_SeekGE, and so forth, so that the capitalization is consistent. The whole point of this change is to improve the readability of VDBE listings.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: b6bea903ac8e1717ed50b221d73bd0be061c7663
User & Date: drh 2014-02-14 15:13:36
Context
2014-02-14
20:59
Reduce the number of cases where it is necessary to check for NULL after the loop terminating condition. check-in: 3c1ae447 user: drh tags: trunk
15:13
Add OP_IdxGT and OP_IdxLE as distinct opcodes. Formerly these operations where done using OP_IdxGE and OP_IdxLT with the P5 flag set. But VDBE code is easier to read with distinct opcode names. Also change OP_SeekGe to OP_SeekGE, and so forth, so that the capitalization is consistent. The whole point of this change is to improve the readability of VDBE listings. check-in: b6bea903 user: drh tags: trunk
00:25
Revise how the Tcl system encoding is handled by the test suite. check-in: 9e573198 user: mistachkin tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/vdbe.c.

  3421   3421   **
  3422   3422   ** Reposition cursor P1 so that it points to the largest entry that 
  3423   3423   ** is less than or equal to the key value. If there are no records 
  3424   3424   ** less than or equal to the key and P2 is not zero, then jump to P2.
  3425   3425   **
  3426   3426   ** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLt
  3427   3427   */
  3428         -case OP_SeekLt:         /* jump, in3 */
  3429         -case OP_SeekLe:         /* jump, in3 */
  3430         -case OP_SeekGe:         /* jump, in3 */
  3431         -case OP_SeekGt: {       /* jump, in3 */
         3428  +case OP_SeekLT:         /* jump, in3 */
         3429  +case OP_SeekLE:         /* jump, in3 */
         3430  +case OP_SeekGE:         /* jump, in3 */
         3431  +case OP_SeekGT: {       /* jump, in3 */
  3432   3432     int res;
  3433   3433     int oc;
  3434   3434     VdbeCursor *pC;
  3435   3435     UnpackedRecord r;
  3436   3436     int nField;
  3437   3437     i64 iKey;      /* The rowid we are to seek to */
  3438   3438   
  3439   3439     assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  3440   3440     assert( pOp->p2!=0 );
  3441   3441     pC = p->apCsr[pOp->p1];
  3442   3442     assert( pC!=0 );
  3443   3443     assert( pC->pseudoTableReg==0 );
  3444         -  assert( OP_SeekLe == OP_SeekLt+1 );
  3445         -  assert( OP_SeekGe == OP_SeekLt+2 );
  3446         -  assert( OP_SeekGt == OP_SeekLt+3 );
         3444  +  assert( OP_SeekLE == OP_SeekLT+1 );
         3445  +  assert( OP_SeekGE == OP_SeekLT+2 );
         3446  +  assert( OP_SeekGT == OP_SeekLT+3 );
  3447   3447     assert( pC->isOrdered );
  3448   3448     assert( pC->pCursor!=0 );
  3449   3449     oc = pOp->opcode;
  3450   3450     pC->nullRow = 0;
  3451   3451     if( pC->isTable ){
  3452   3452       /* The input value in P3 might be of any type: integer, real, string,
  3453   3453       ** blob, or NULL.  But it needs to be an integer before we can do
................................................................................
  3471   3471         ** term, substitute >= for > and < for <=. e.g. if the search term
  3472   3472         ** is 4.9 and the integer approximation 5:
  3473   3473         **
  3474   3474         **        (x >  4.9)    ->     (x >= 5)
  3475   3475         **        (x <= 4.9)    ->     (x <  5)
  3476   3476         */
  3477   3477         if( pIn3->r<(double)iKey ){
  3478         -        assert( OP_SeekGe==(OP_SeekGt-1) );
  3479         -        assert( OP_SeekLt==(OP_SeekLe-1) );
  3480         -        assert( (OP_SeekLe & 0x0001)==(OP_SeekGt & 0x0001) );
  3481         -        if( (oc & 0x0001)==(OP_SeekGt & 0x0001) ) oc--;
         3478  +        assert( OP_SeekGE==(OP_SeekGT-1) );
         3479  +        assert( OP_SeekLT==(OP_SeekLE-1) );
         3480  +        assert( (OP_SeekLE & 0x0001)==(OP_SeekGT & 0x0001) );
         3481  +        if( (oc & 0x0001)==(OP_SeekGT & 0x0001) ) oc--;
  3482   3482         }
  3483   3483   
  3484   3484         /* If the approximation iKey is smaller than the actual real search
  3485   3485         ** term, substitute <= for < and > for >=.  */
  3486   3486         else if( pIn3->r>(double)iKey ){
  3487         -        assert( OP_SeekLe==(OP_SeekLt+1) );
  3488         -        assert( OP_SeekGt==(OP_SeekGe+1) );
  3489         -        assert( (OP_SeekLt & 0x0001)==(OP_SeekGe & 0x0001) );
  3490         -        if( (oc & 0x0001)==(OP_SeekLt & 0x0001) ) oc++;
         3487  +        assert( OP_SeekLE==(OP_SeekLT+1) );
         3488  +        assert( OP_SeekGT==(OP_SeekGE+1) );
         3489  +        assert( (OP_SeekLT & 0x0001)==(OP_SeekGE & 0x0001) );
         3490  +        if( (oc & 0x0001)==(OP_SeekLT & 0x0001) ) oc++;
  3491   3491         }
  3492   3492       } 
  3493   3493       rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)iKey, 0, &res);
  3494   3494       if( rc!=SQLITE_OK ){
  3495   3495         goto abort_due_to_error;
  3496   3496       }
  3497   3497       if( res==0 ){
................................................................................
  3502   3502       nField = pOp->p4.i;
  3503   3503       assert( pOp->p4type==P4_INT32 );
  3504   3504       assert( nField>0 );
  3505   3505       r.pKeyInfo = pC->pKeyInfo;
  3506   3506       r.nField = (u16)nField;
  3507   3507   
  3508   3508       /* The next line of code computes as follows, only faster:
  3509         -    **   if( oc==OP_SeekGt || oc==OP_SeekLe ){
         3509  +    **   if( oc==OP_SeekGT || oc==OP_SeekLE ){
  3510   3510       **     r.flags = UNPACKED_INCRKEY;
  3511   3511       **   }else{
  3512   3512       **     r.flags = 0;
  3513   3513       **   }
  3514   3514       */
  3515         -    r.flags = (u8)(UNPACKED_INCRKEY * (1 & (oc - OP_SeekLt)));
  3516         -    assert( oc!=OP_SeekGt || r.flags==UNPACKED_INCRKEY );
  3517         -    assert( oc!=OP_SeekLe || r.flags==UNPACKED_INCRKEY );
  3518         -    assert( oc!=OP_SeekGe || r.flags==0 );
  3519         -    assert( oc!=OP_SeekLt || r.flags==0 );
         3515  +    r.flags = (u8)(UNPACKED_INCRKEY * (1 & (oc - OP_SeekLT)));
         3516  +    assert( oc!=OP_SeekGT || r.flags==UNPACKED_INCRKEY );
         3517  +    assert( oc!=OP_SeekLE || r.flags==UNPACKED_INCRKEY );
         3518  +    assert( oc!=OP_SeekGE || r.flags==0 );
         3519  +    assert( oc!=OP_SeekLT || r.flags==0 );
  3520   3520   
  3521   3521       r.aMem = &aMem[pOp->p3];
  3522   3522   #ifdef SQLITE_DEBUG
  3523   3523       { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
  3524   3524   #endif
  3525   3525       ExpandBlob(r.aMem);
  3526   3526       rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, &r, 0, 0, &res);
................................................................................
  3530   3530       pC->rowidIsValid = 0;
  3531   3531     }
  3532   3532     pC->deferredMoveto = 0;
  3533   3533     pC->cacheStatus = CACHE_STALE;
  3534   3534   #ifdef SQLITE_TEST
  3535   3535     sqlite3_search_count++;
  3536   3536   #endif
  3537         -  if( oc>=OP_SeekGe ){  assert( oc==OP_SeekGe || oc==OP_SeekGt );
  3538         -    if( res<0 || (res==0 && oc==OP_SeekGt) ){
         3537  +  if( oc>=OP_SeekGE ){  assert( oc==OP_SeekGE || oc==OP_SeekGT );
         3538  +    if( res<0 || (res==0 && oc==OP_SeekGT) ){
  3539   3539         res = 0;
  3540   3540         rc = sqlite3BtreeNext(pC->pCursor, &res);
  3541   3541         if( rc!=SQLITE_OK ) goto abort_due_to_error;
  3542   3542         pC->rowidIsValid = 0;
  3543   3543       }else{
  3544   3544         res = 0;
  3545   3545       }
  3546   3546     }else{
  3547         -    assert( oc==OP_SeekLt || oc==OP_SeekLe );
  3548         -    if( res>0 || (res==0 && oc==OP_SeekLt) ){
         3547  +    assert( oc==OP_SeekLT || oc==OP_SeekLE );
         3548  +    if( res>0 || (res==0 && oc==OP_SeekLT) ){
  3549   3549         res = 0;
  3550   3550         rc = sqlite3BtreePrevious(pC->pCursor, &res);
  3551   3551         if( rc!=SQLITE_OK ) goto abort_due_to_error;
  3552   3552         pC->rowidIsValid = 0;
  3553   3553       }else{
  3554   3554         /* res might be negative because the table is empty.  Check to
  3555   3555         ** see if this is the case.
................................................................................
  4616   4616     break;
  4617   4617   }
  4618   4618   
  4619   4619   /* Opcode: IdxGE P1 P2 P3 P4 P5
  4620   4620   ** Synopsis: key=r[P3@P4]
  4621   4621   **
  4622   4622   ** The P4 register values beginning with P3 form an unpacked index 
  4623         -** key that omits the ROWID.  Compare this key value against the index 
  4624         -** that P1 is currently pointing to, ignoring the ROWID on the P1 index.
         4623  +** key that omits the PRIMARY KEY.  Compare this key value against the index 
         4624  +** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID 
         4625  +** fields at the end.
  4625   4626   **
  4626   4627   ** If the P1 index entry is greater than or equal to the key value
  4627   4628   ** then jump to P2.  Otherwise fall through to the next instruction.
         4629  +*/
         4630  +/* Opcode: IdxGT P1 P2 P3 P4 P5
         4631  +** Synopsis: key=r[P3@P4]
  4628   4632   **
  4629         -** If P5 is non-zero then the key value is increased by an epsilon 
  4630         -** prior to the comparison.  This make the opcode work like IdxGT except
  4631         -** that if the key from register P3 is a prefix of the key in the cursor,
  4632         -** the result is false whereas it would be true with IdxGT.
         4633  +** The P4 register values beginning with P3 form an unpacked index 
         4634  +** key that omits the PRIMARY KEY.  Compare this key value against the index 
         4635  +** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID 
         4636  +** fields at the end.
         4637  +**
         4638  +** If the P1 index entry is greater than the key value
         4639  +** then jump to P2.  Otherwise fall through to the next instruction.
  4633   4640   */
  4634   4641   /* Opcode: IdxLT P1 P2 P3 P4 P5
  4635   4642   ** Synopsis: key=r[P3@P4]
  4636   4643   **
  4637   4644   ** The P4 register values beginning with P3 form an unpacked index 
  4638         -** key that omits the ROWID.  Compare this key value against the index 
  4639         -** that P1 is currently pointing to, ignoring the ROWID on the P1 index.
         4645  +** key that omits the PRIMARY KEY or ROWID.  Compare this key value against
         4646  +** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or
         4647  +** ROWID on the P1 index.
  4640   4648   **
  4641   4649   ** If the P1 index entry is less than the key value then jump to P2.
  4642   4650   ** Otherwise fall through to the next instruction.
         4651  +*/
         4652  +/* Opcode: IdxLE P1 P2 P3 P4 P5
         4653  +** Synopsis: key=r[P3@P4]
  4643   4654   **
  4644         -** If P5 is non-zero then the key value is increased by an epsilon prior 
  4645         -** to the comparison.  This makes the opcode work like IdxLE.
         4655  +** The P4 register values beginning with P3 form an unpacked index 
         4656  +** key that omits the PRIMARY KEY or ROWID.  Compare this key value against
         4657  +** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or
         4658  +** ROWID on the P1 index.
         4659  +**
         4660  +** If the P1 index entry is less than or equal to the key value then jump
         4661  +** to P2. Otherwise fall through to the next instruction.
  4646   4662   */
         4663  +case OP_IdxLE:          /* jump */
         4664  +case OP_IdxGT:          /* jump */
  4647   4665   case OP_IdxLT:          /* jump */
  4648         -case OP_IdxGE: {        /* jump */
         4666  +case OP_IdxGE:  {       /* jump */
  4649   4667     VdbeCursor *pC;
  4650   4668     int res;
  4651   4669     UnpackedRecord r;
  4652   4670   
  4653   4671     assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  4654   4672     pC = p->apCsr[pOp->p1];
  4655   4673     assert( pC!=0 );
................................................................................
  4656   4674     assert( pC->isOrdered );
  4657   4675     assert( pC->pCursor!=0);
  4658   4676     assert( pC->deferredMoveto==0 );
  4659   4677     assert( pOp->p5==0 || pOp->p5==1 );
  4660   4678     assert( pOp->p4type==P4_INT32 );
  4661   4679     r.pKeyInfo = pC->pKeyInfo;
  4662   4680     r.nField = (u16)pOp->p4.i;
  4663         -  if( pOp->p5 ){
         4681  +  if( pOp->opcode<OP_IdxLT ){
         4682  +    assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxGT );
  4664   4683       r.flags = UNPACKED_INCRKEY | UNPACKED_PREFIX_MATCH;
  4665   4684     }else{
         4685  +    assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxLT );
  4666   4686       r.flags = UNPACKED_PREFIX_MATCH;
  4667   4687     }
  4668   4688     r.aMem = &aMem[pOp->p3];
  4669   4689   #ifdef SQLITE_DEBUG
  4670   4690     { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
  4671   4691   #endif
  4672   4692     res = 0;  /* Not needed.  Only used to silence a warning. */
  4673   4693     rc = sqlite3VdbeIdxKeyCompare(pC, &r, &res);
  4674         -  if( pOp->opcode==OP_IdxLT ){
         4694  +  assert( (OP_IdxLE&1)==(OP_IdxLT&1) && (OP_IdxGE&1)==(OP_IdxGT&1) );
         4695  +  if( (pOp->opcode&1)==(OP_IdxLT&1) ){
         4696  +    assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxLT );
  4675   4697       res = -res;
  4676   4698     }else{
  4677         -    assert( pOp->opcode==OP_IdxGE );
         4699  +    assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxGT );
  4678   4700       res++;
  4679   4701     }
  4680   4702     if( res>0 ){
  4681   4703       pc = pOp->p2 - 1 ;
  4682   4704     }
  4683   4705     break;
  4684   4706   }

Changes to src/where.c.

  2501   2501     }
  2502   2502   
  2503   2503     if( nSkip ){
  2504   2504       int iIdxCur = pLevel->iIdxCur;
  2505   2505       sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur);
  2506   2506       VdbeComment((v, "begin skip-scan on %s", pIdx->zName));
  2507   2507       j = sqlite3VdbeAddOp0(v, OP_Goto);
  2508         -    pLevel->addrSkip = sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLt:OP_SeekGt),
         2508  +    pLevel->addrSkip = sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLT:OP_SeekGT),
  2509   2509                               iIdxCur, 0, regBase, nSkip);
  2510   2510       sqlite3VdbeJumpHere(v, j);
  2511   2511       for(j=0; j<nSkip; j++){
  2512   2512         sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, j, regBase+j);
  2513   2513         assert( pIdx->aiColumn[j]>=0 );
  2514   2514         VdbeComment((v, "%s", pIdx->pTable->aCol[pIdx->aiColumn[j]].zName));
  2515   2515       }
................................................................................
  2881   2881         Expr *pX;             /* The expression that defines the start bound */
  2882   2882         int r1, rTemp;        /* Registers for holding the start boundary */
  2883   2883   
  2884   2884         /* The following constant maps TK_xx codes into corresponding 
  2885   2885         ** seek opcodes.  It depends on a particular ordering of TK_xx
  2886   2886         */
  2887   2887         const u8 aMoveOp[] = {
  2888         -           /* TK_GT */  OP_SeekGt,
  2889         -           /* TK_LE */  OP_SeekLe,
  2890         -           /* TK_LT */  OP_SeekLt,
  2891         -           /* TK_GE */  OP_SeekGe
         2888  +           /* TK_GT */  OP_SeekGT,
         2889  +           /* TK_LE */  OP_SeekLE,
         2890  +           /* TK_LT */  OP_SeekLT,
         2891  +           /* TK_GE */  OP_SeekGE
  2892   2892         };
  2893   2893         assert( TK_LE==TK_GT+1 );      /* Make sure the ordering.. */
  2894   2894         assert( TK_LT==TK_GT+2 );      /*  ... of the TK_xx values... */
  2895   2895         assert( TK_GE==TK_GT+3 );      /*  ... is correcct. */
  2896   2896   
  2897   2897         assert( (pStart->wtFlags & TERM_VNULL)==0 );
  2898   2898         testcase( pStart->wtFlags & TERM_VIRTUAL );
................................................................................
  2969   2969       **         to force the output order to conform to an ORDER BY.
  2970   2970       */  
  2971   2971       static const u8 aStartOp[] = {
  2972   2972         0,
  2973   2973         0,
  2974   2974         OP_Rewind,           /* 2: (!start_constraints && startEq &&  !bRev) */
  2975   2975         OP_Last,             /* 3: (!start_constraints && startEq &&   bRev) */
  2976         -      OP_SeekGt,           /* 4: (start_constraints  && !startEq && !bRev) */
  2977         -      OP_SeekLt,           /* 5: (start_constraints  && !startEq &&  bRev) */
  2978         -      OP_SeekGe,           /* 6: (start_constraints  &&  startEq && !bRev) */
  2979         -      OP_SeekLe            /* 7: (start_constraints  &&  startEq &&  bRev) */
         2976  +      OP_SeekGT,           /* 4: (start_constraints  && !startEq && !bRev) */
         2977  +      OP_SeekLT,           /* 5: (start_constraints  && !startEq &&  bRev) */
         2978  +      OP_SeekGE,           /* 6: (start_constraints  &&  startEq && !bRev) */
         2979  +      OP_SeekLE            /* 7: (start_constraints  &&  startEq &&  bRev) */
  2980   2980       };
  2981   2981       static const u8 aEndOp[] = {
  2982         -      OP_Noop,             /* 0: (!end_constraints) */
  2983         -      OP_IdxGE,            /* 1: (end_constraints && !bRev) */
  2984         -      OP_IdxLT             /* 2: (end_constraints && bRev) */
         2982  +      OP_IdxGE,            /* 0: (end_constraints && !bRev && !endEq) */
         2983  +      OP_IdxGT,            /* 1: (end_constraints && !bRev &&  endEq) */
         2984  +      OP_IdxLE,            /* 2: (end_constraints &&  bRev && !endEq) */
         2985  +      OP_IdxLT,            /* 3: (end_constraints &&  bRev &&  endEq) */
  2985   2986       };
  2986   2987       u16 nEq = pLoop->u.btree.nEq;     /* Number of == or IN terms */
  2987   2988       int isMinQuery = 0;          /* If this is an optimized SELECT min(x).. */
  2988   2989       int regBase;                 /* Base register holding constraint values */
  2989   2990       int r1;                      /* Temp register */
  2990   2991       WhereTerm *pRangeStart = 0;  /* Inequality constraint at range start */
  2991   2992       WhereTerm *pRangeEnd = 0;    /* Inequality constraint at range end */
................................................................................
  3089   3090         start_constraints = 1;
  3090   3091       }
  3091   3092       codeApplyAffinity(pParse, regBase, nConstraint, zStartAff);
  3092   3093       op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
  3093   3094       assert( op!=0 );
  3094   3095       testcase( op==OP_Rewind );
  3095   3096       testcase( op==OP_Last );
  3096         -    testcase( op==OP_SeekGt );
  3097         -    testcase( op==OP_SeekGe );
  3098         -    testcase( op==OP_SeekLe );
  3099         -    testcase( op==OP_SeekLt );
         3097  +    testcase( op==OP_SeekGT );
         3098  +    testcase( op==OP_SeekGE );
         3099  +    testcase( op==OP_SeekLE );
         3100  +    testcase( op==OP_SeekLT );
  3100   3101       sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
  3101   3102   
  3102   3103       /* Load the value for the inequality constraint at the end of the
  3103   3104       ** range (if any).
  3104   3105       */
  3105   3106       nConstraint = nEq;
  3106   3107       if( pRangeEnd ){
................................................................................
  3120   3121       }
  3121   3122       sqlite3DbFree(db, zStartAff);
  3122   3123   
  3123   3124       /* Top of the loop body */
  3124   3125       pLevel->p2 = sqlite3VdbeCurrentAddr(v);
  3125   3126   
  3126   3127       /* Check if the index cursor is past the end of the range. */
  3127         -    op = aEndOp[(pRangeEnd || nEq) * (1 + bRev)];
  3128         -    testcase( op==OP_Noop );
  3129         -    testcase( op==OP_IdxGE );
  3130         -    testcase( op==OP_IdxLT );
  3131         -    if( op!=OP_Noop ){
         3128  +    if( pRangeEnd || nEq ){
         3129  +      op = aEndOp[bRev*2 + endEq];
         3130  +      testcase( op==OP_IdxGT );
         3131  +      testcase( op==OP_IdxGE );
         3132  +      testcase( op==OP_IdxLT );
         3133  +      testcase( op==OP_IdxLE );
  3132   3134         sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
  3133         -      sqlite3VdbeChangeP5(v, endEq!=bRev ?1:0);
  3134   3135       }
  3135   3136   
  3136   3137       /* If there are inequality constraints, check that the value
  3137   3138       ** of the table column that the inequality contrains is not NULL.
  3138   3139       ** If it is, jump to the next iteration of the loop.
  3139   3140       */
  3140   3141       r1 = sqlite3GetTempReg(pParse);