/ Check-in [45a70b2b]
Login

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

Overview
Comment:Fixes to the skip-ahead distinct logic. More issues remain.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | skip-ahead-distinct
Files: files | file ages | folders
SHA1:45a70b2bb8f7b465bab45d2eaad24d372b1afe61
User & Date: drh 2016-04-15 15:54:17
Context
2016-04-15
16:17
Skip-ahead does not always work. So we still have to check for redundancy. check-in: db5a2364 user: drh tags: skip-ahead-distinct
15:54
Fixes to the skip-ahead distinct logic. More issues remain. check-in: 45a70b2b user: drh tags: skip-ahead-distinct
15:06
Merge enhancements from trunk, especially the ".eqp full" enhancement to the command-line shell. check-in: 491f0dbd user: drh tags: skip-ahead-distinct
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/where.c.

4580
4581
4582
4583
4584
4585
4586




4587
4588
4589
4590

4591
4592
4593









4594




4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607

4608
4609
4610
4611
4612
4613
4614
    pLevel = &pWInfo->a[i];
    pLoop = pLevel->pWLoop;
    sqlite3VdbeResolveLabel(v, pLevel->addrCont);
    if( pLevel->op!=OP_Noop ){
      if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED
       && (pLoop->wsFlags & WHERE_INDEXED)!=0
      ){




        int j, k, op;
        int r1 = pParse->nMem+1;
        int n = 0;
        ExprList *pX = pWInfo->pDistinctSet;

        for(j=0; j<pX->nExpr; j++){
          Expr *pE = sqlite3ExprSkipCollate(pX->a[j].pExpr);
          if( pE->op==TK_COLUMN && pE->iTable==pLevel->iTabCur ) n++;









        }




        for(j=0; j<n; j++){
          sqlite3VdbeAddOp3(v, OP_Column, pLevel->iIdxCur, j, r1+j);
        }
        pParse->nMem += n;
        if( n>0 ){
          op = pLevel->op==OP_Prev ? OP_SeekLT : OP_SeekGT;
          k = sqlite3VdbeAddOp4Int(v, op, pLevel->iIdxCur, 0, r1, n);
          VdbeCoverageIf(v, op==OP_SeekLT);
          VdbeCoverageIf(v, op==OP_SeekGT);
          sqlite3VdbeAddOp2(v, OP_Goto, 1, pLevel->p2);
          sqlite3VdbeJumpHere(v, k);
        }
      }else{

        sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3);
        sqlite3VdbeChangeP5(v, pLevel->p5);
        VdbeCoverage(v);
        VdbeCoverageIf(v, pLevel->op==OP_Next);
        VdbeCoverageIf(v, pLevel->op==OP_Prev);
        VdbeCoverageIf(v, pLevel->op==OP_VNext);
      }







>
>
>
>


|

>


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








>







4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616

4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
    pLevel = &pWInfo->a[i];
    pLoop = pLevel->pWLoop;
    sqlite3VdbeResolveLabel(v, pLevel->addrCont);
    if( pLevel->op!=OP_Noop ){
      if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED
       && (pLoop->wsFlags & WHERE_INDEXED)!=0
      ){
        /* This is the Skip-ahead optimization.  When doing a DISTINCT query
        ** that has WHERE_DISTINCT_ORDERED, use OP_SkipGT/OP_SkipLT to skip
        ** over all duplicate entries, rather than visiting all duplicates
        ** using OP_Next/OP_Prev. */
        int j, k, op;
        int r1 = pParse->nMem+1;
        int n = -1;
        ExprList *pX = pWInfo->pDistinctSet;
        Index *pIdx = pLoop->u.btree.pIndex;
        for(j=0; j<pX->nExpr; j++){
          Expr *pE = sqlite3ExprSkipCollate(pX->a[j].pExpr);
          if( pE->op==TK_COLUMN ){
            if( pE->iTable!=pLevel->iTabCur ) continue;
            k = 1+sqlite3ColumnOfIndex(pIdx, pE->iColumn);
            if( k>n ) n = k;
          }else if( pIdx->aColExpr ){
            for(k=n+1; k<pIdx->nKeyCol; k++){
              Expr *pI = pIdx->aColExpr->a[k].pExpr;
              if( pI && sqlite3ExprCompare(pE,pI,0)<2 ){
                n = k+1;
                break;
              }
            }
          }
        }
        if( n>0 ){
          for(j=0; j<n; j++){
            sqlite3VdbeAddOp3(v, OP_Column, pLevel->iIdxCur, j, r1+j);
          }
          pParse->nMem += n;

          op = pLevel->op==OP_Prev ? OP_SeekLT : OP_SeekGT;
          k = sqlite3VdbeAddOp4Int(v, op, pLevel->iIdxCur, 0, r1, n);
          VdbeCoverageIf(v, op==OP_SeekLT);
          VdbeCoverageIf(v, op==OP_SeekGT);
          sqlite3VdbeAddOp2(v, OP_Goto, 1, pLevel->p2);
          sqlite3VdbeJumpHere(v, k);
        }
      }else{
        /* The common case: Advance to the next row */
        sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3);
        sqlite3VdbeChangeP5(v, pLevel->p5);
        VdbeCoverage(v);
        VdbeCoverageIf(v, pLevel->op==OP_Next);
        VdbeCoverageIf(v, pLevel->op==OP_Prev);
        VdbeCoverageIf(v, pLevel->op==OP_VNext);
      }