SQLite

Check-in [0f5b147d1f]
Login

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

Overview
Comment:The OPFLAG_SEEKEQ optimization is only applicable to equality comparisons against an index, not against a rowid table.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 0f5b147d1fe83c34d0fbeacc7422be94d8441bc1
User & Date: drh 2015-11-07 01:19:00.997
Context
2015-11-07
18:07
Fix a bug in CTE handling discovered by LibFuzzer that can cause an infinite loop in the query planner. (check-in: 088009efdd user: dan tags: trunk)
15:19
Enhance TreeView to show WITH clauses. Add an assert to detect the infinite loop behavior when certain kinds of errors occur on a nested WITH clause. (check-in: 2040d88e87 user: drh tags: infinite-with-loop-bug)
01:57
Merge recent enhancements and fixes from trunk. (check-in: 5429f99b98 user: drh tags: apple-osx)
01:33
Merge recent enhancements and bug fixes from trunk. (check-in: 78bc42e664 user: drh tags: sessions)
01:19
The OPFLAG_SEEKEQ optimization is only applicable to equality comparisons against an index, not against a rowid table. (check-in: 0f5b147d1f user: drh tags: trunk)
00:51
Fix a harmless sanitizer warning in the ieee754 extension. (check-in: dd9a26ecde user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/vdbe.c.
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696

3697
3698
3699
3700
3701

3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
case OP_SeekGT: {       /* jump, in3 */
  int res;           /* Comparison result */
  int oc;            /* Opcode */
  VdbeCursor *pC;    /* The cursor to seek */
  UnpackedRecord r;  /* The key to seek for */
  int nField;        /* Number of columns or fields in the key */
  i64 iKey;          /* The rowid we are to seek to */
  int eqOnly = 0;    /* Only interested in == results */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( pOp->p2!=0 );
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
  assert( pC->pseudoTableReg==0 );
  assert( OP_SeekLE == OP_SeekLT+1 );
  assert( OP_SeekGE == OP_SeekLT+2 );
  assert( OP_SeekGT == OP_SeekLT+3 );
  assert( pC->isOrdered );
  assert( pC->pCursor!=0 );
  oc = pOp->opcode;

  pC->nullRow = 0;
#ifdef SQLITE_DEBUG
  pC->seekOp = pOp->opcode;
#endif


  /* For a cursor with the BTREE_SEEK_EQ hint, only the OP_SeekGE and
  ** OP_SeekLE opcodes are allowed, and these must be immediately followed
  ** by an OP_IdxGT or OP_IdxLT opcode, respectively, with the same key.
  */
  if( sqlite3BtreeCursorHasHint(pC->pCursor, BTREE_SEEK_EQ) ){
    eqOnly = 1;
    assert( pOp->opcode==OP_SeekGE || pOp->opcode==OP_SeekLE );
    assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT );
    assert( pOp[1].p1==pOp[0].p1 );
    assert( pOp[1].p2==pOp[0].p2 );
    assert( pOp[1].p3==pOp[0].p3 );
    assert( pOp[1].p4.i==pOp[0].p4.i );
  }
 
  if( pC->isTable ){
    /* The input value in P3 might be of any type: integer, real, string,
    ** blob, or NULL.  But it needs to be an integer before we can do
    ** the seek, so convert it. */
    pIn3 = &aMem[pOp->p3];
    if( (pIn3->flags & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
      applyNumericAffinity(pIn3, 0);
    }







|












>





>
|
<
<
<
|
<
<
<
<
<
<
<
|
<
<







3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704



3705







3706


3707
3708
3709
3710
3711
3712
3713
case OP_SeekGT: {       /* jump, in3 */
  int res;           /* Comparison result */
  int oc;            /* Opcode */
  VdbeCursor *pC;    /* The cursor to seek */
  UnpackedRecord r;  /* The key to seek for */
  int nField;        /* Number of columns or fields in the key */
  i64 iKey;          /* The rowid we are to seek to */
  int eqOnly;        /* Only interested in == results */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( pOp->p2!=0 );
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
  assert( pC->pseudoTableReg==0 );
  assert( OP_SeekLE == OP_SeekLT+1 );
  assert( OP_SeekGE == OP_SeekLT+2 );
  assert( OP_SeekGT == OP_SeekLT+3 );
  assert( pC->isOrdered );
  assert( pC->pCursor!=0 );
  oc = pOp->opcode;
  eqOnly = 0;
  pC->nullRow = 0;
#ifdef SQLITE_DEBUG
  pC->seekOp = pOp->opcode;
#endif

  if( pC->isTable ){
    /* The BTREE_SEEK_EQ flag is only set on index cursors */



    assert( sqlite3BtreeCursorHasHint(pC->pCursor, BTREE_SEEK_EQ)==0 );










    /* The input value in P3 might be of any type: integer, real, string,
    ** blob, or NULL.  But it needs to be an integer before we can do
    ** the seek, so convert it. */
    pIn3 = &aMem[pOp->p3];
    if( (pIn3->flags & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
      applyNumericAffinity(pIn3, 0);
    }
3757
3758
3759
3760
3761
3762
3763
3764
3765














3766
3767
3768
3769
3770
3771
3772
      }
    } 
    rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)iKey, 0, &res);
    pC->movetoTarget = iKey;  /* Used by OP_Delete */
    if( rc!=SQLITE_OK ){
      goto abort_due_to_error;
    }
    if( eqOnly && res ) goto seek_not_found;
  }else{














    nField = pOp->p4.i;
    assert( pOp->p4type==P4_INT32 );
    assert( nField>0 );
    r.pKeyInfo = pC->pKeyInfo;
    r.nField = (u16)nField;

    /* The next line of code computes as follows, only faster:







<

>
>
>
>
>
>
>
>
>
>
>
>
>
>







3747
3748
3749
3750
3751
3752
3753

3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
      }
    } 
    rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)iKey, 0, &res);
    pC->movetoTarget = iKey;  /* Used by OP_Delete */
    if( rc!=SQLITE_OK ){
      goto abort_due_to_error;
    }

  }else{
    /* For a cursor with the BTREE_SEEK_EQ hint, only the OP_SeekGE and
    ** OP_SeekLE opcodes are allowed, and these must be immediately followed
    ** by an OP_IdxGT or OP_IdxLT opcode, respectively, with the same key.
    */
    if( sqlite3BtreeCursorHasHint(pC->pCursor, BTREE_SEEK_EQ) ){
      eqOnly = 1;
      assert( pOp->opcode==OP_SeekGE || pOp->opcode==OP_SeekLE );
      assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT );
      assert( pOp[1].p1==pOp[0].p1 );
      assert( pOp[1].p2==pOp[0].p2 );
      assert( pOp[1].p3==pOp[0].p3 );
      assert( pOp[1].p4.i==pOp[0].p4.i );
    }

    nField = pOp->p4.i;
    assert( pOp->p4type==P4_INT32 );
    assert( nField>0 );
    r.pKeyInfo = pC->pKeyInfo;
    r.nField = (u16)nField;

    /* The next line of code computes as follows, only faster: