SQLite

Check-in [7ae504e62e]
Login

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

Overview
Comment:Simplified VDBE code for the vector NOT IN null-scanning loop.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | rowvalue
Files: files | file ages | folders
SHA1: 7ae504e62e9bbbbd85a676f3c3922b7fd0cc73d2
User & Date: drh 2016-08-24 21:54:47.055
Context
2016-08-25
14:00
Add notes on the implementation of the IN operator. (check-in: d256b2caeb user: drh tags: rowvalue)
2016-08-24
21:54
Simplified VDBE code for the vector NOT IN null-scanning loop. (check-in: 7ae504e62e user: drh tags: rowvalue)
21:24
Improved extended comments of comparison operators when the SQLITE_STOREP2 flags is set on P5. No changes to non-debug code. (check-in: bbc1b01616 user: drh tags: rowvalue)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/expr.c.
2778
2779
2780
2781
2782
2783
2784
2785
2786

2787
2788
2789
2790
2791
2792
2793
2794
2795
2796

2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815




2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
    }else{
      /* In this case, the RHS is an index b-tree. Apply the comparison
      ** affinities to each value on the LHS of the operator.  */
      sqlite3VdbeAddOp4(v, OP_Affinity, r1, nVector, 0, zAff, nVector);
      
      if( nVector>1 && destIfNull!=destIfFalse ){
        int iIdx = pExpr->iTable;
        int addr;
        int addrNext;


        /* Search the index for the key. */
        addr = sqlite3VdbeAddOp4Int(v, OP_Found, iIdx, 0, r1, nVector);
        VdbeCoverage(v);

        /* At this point the specified key is not present in the index, 
        ** so the result of the IN(..) operator must be either NULL or
        ** 0. The vdbe code generated below figures out which.  */
        addrNext = 1+sqlite3VdbeAddOp2(v, OP_Rewind, iIdx, destIfFalse);
        VdbeCoverage(v);


        for(i=0; i<nVector; i++){
          Expr *p;
          CollSeq *pColl;
          int r2 = sqlite3GetTempReg(pParse);
          p = sqlite3VectorFieldSubexpr(pLeft, i);
          pColl = sqlite3ExprCollSeq(pParse, p);

          sqlite3VdbeAddOp3(v, OP_Column, iIdx, i, r2);
          sqlite3VdbeAddOp4(v, OP_Eq, r1+i, 0, r2, (void*)pColl,P4_COLLSEQ);
          sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL);
          VdbeCoverage(v);
          sqlite3VdbeAddOp2(v, OP_Next, iIdx, addrNext);
          VdbeCoverage(v);
          sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse);
          sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-3);
          sqlite3ReleaseTempReg(pParse, r2);
        }
        sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull);





        /* The key was found in the index. If it contains any NULL values,
        ** then the result of the IN(...) operator is NULL. Otherwise, the
        ** result is 1.  */
        sqlite3VdbeJumpHere(v, addr);
        for(i=0; i<nVector; i++){
          Expr *p = sqlite3VectorFieldSubexpr(pExpr->pLeft, i);
          if( sqlite3ExprCanBeNull(p) ){
            sqlite3VdbeAddOp2(v, OP_IsNull, r1+aiMap[i], destIfNull);
            VdbeCoverage(v);
          }
        }







|

>


|





|

>









|
<
|
<

<
<



>
>
>
>




|







2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808

2809

2810


2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
    }else{
      /* In this case, the RHS is an index b-tree. Apply the comparison
      ** affinities to each value on the LHS of the operator.  */
      sqlite3VdbeAddOp4(v, OP_Affinity, r1, nVector, 0, zAff, nVector);
      
      if( nVector>1 && destIfNull!=destIfFalse ){
        int iIdx = pExpr->iTable;
        int addrTop;
        int addrNext;
        int addrFound;

        /* Search the index for the key. */
        addrFound = sqlite3VdbeAddOp4Int(v, OP_Found, iIdx, 0, r1, nVector);
        VdbeCoverage(v);

        /* At this point the specified key is not present in the index, 
        ** so the result of the IN(..) operator must be either NULL or
        ** 0. The vdbe code generated below figures out which.  */
        addrTop = 1+sqlite3VdbeAddOp2(v, OP_Rewind, iIdx, destIfFalse);
        VdbeCoverage(v);
        addrNext = sqlite3VdbeMakeLabel(v);

        for(i=0; i<nVector; i++){
          Expr *p;
          CollSeq *pColl;
          int r2 = sqlite3GetTempReg(pParse);
          p = sqlite3VectorFieldSubexpr(pLeft, i);
          pColl = sqlite3ExprCollSeq(pParse, p);

          sqlite3VdbeAddOp3(v, OP_Column, iIdx, i, r2);
          sqlite3VdbeAddOp4(v, OP_Ne, r1+i, addrNext, r2,

                            (void*)pColl, P4_COLLSEQ);

          VdbeCoverage(v);


          sqlite3ReleaseTempReg(pParse, r2);
        }
        sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull);
        sqlite3VdbeResolveLabel(v, addrNext);
        sqlite3VdbeAddOp2(v, OP_Next, iIdx, addrTop);
        VdbeCoverage(v);
        sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse);

        /* The key was found in the index. If it contains any NULL values,
        ** then the result of the IN(...) operator is NULL. Otherwise, the
        ** result is 1.  */
        sqlite3VdbeJumpHere(v, addrFound);
        for(i=0; i<nVector; i++){
          Expr *p = sqlite3VectorFieldSubexpr(pExpr->pLeft, i);
          if( sqlite3ExprCanBeNull(p) ){
            sqlite3VdbeAddOp2(v, OP_IsNull, r1+aiMap[i], destIfNull);
            VdbeCoverage(v);
          }
        }