/ Check-in [dfc028cf]
Login

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

Overview
Comment:Attempt to simplify the logic and generated code for vector comparisons. Basic comparison operators are working, but there are many indexing test failures still to be worked through.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | vector-compare
Files: files | file ages | folders
SHA1: dfc028cfbe7657d20727a2670ecadb1575eb8cbb
User & Date: drh 2016-08-13 10:02:17
Context
2016-08-13
12:37
Fix to the vector less-than operator. All legacy tests passing now. check-in: ec70a67e user: drh tags: vector-compare
10:02
Attempt to simplify the logic and generated code for vector comparisons. Basic comparison operators are working, but there are many indexing test failures still to be worked through. check-in: dfc028cf user: drh tags: vector-compare
2016-08-12
11:25
Add VdbeCoverage() macros on newly added VDBE branch operations. check-in: 381aa731 user: drh tags: rowvalue
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/expr.c.

405
406
407
408
409
410
411
412







413
414






415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431

432
433
434
435
436
437
438

439
440
441
442



443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
....
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
  }
  *ppExpr = pVector->x.pList->a[iField].pExpr;
  return sqlite3ExprCodeTemp(pParse, *ppExpr, pRegFree);
}

/*
** Expression pExpr is a comparison between two vector values. Compute
** the result of the comparison and write it to register dest.







*/
static void codeVectorCompare(Parse *pParse, Expr *pExpr, int dest){






  Vdbe *v = pParse->pVdbe;
  Expr *pLeft = pExpr->pLeft;
  Expr *pRight = pExpr->pRight;
  int nLeft = sqlite3ExprVectorSize(pLeft);
  int nRight = sqlite3ExprVectorSize(pRight);
  int addr = sqlite3VdbeMakeLabel(v);

  /* Check that both sides of the comparison are vectors, and that
  ** both are the same length.  */
  if( nLeft!=nRight ){
    sqlite3ErrorMsg(pParse, "invalid use of row value");
  }else{
    int p5 = (pExpr->op==TK_IS || pExpr->op==TK_ISNOT) ? SQLITE_NULLEQ : 0;
    int i;
    int regLeft = 0;
    int regRight = 0;
    int regTmp = 0;


    assert( pExpr->op==TK_EQ || pExpr->op==TK_NE 
         || pExpr->op==TK_IS || pExpr->op==TK_ISNOT 
         || pExpr->op==TK_LT || pExpr->op==TK_GT 
         || pExpr->op==TK_LE || pExpr->op==TK_GE 
    );


    if( pExpr->op==TK_EQ || pExpr->op==TK_NE ){
      regTmp = sqlite3GetTempReg(pParse);
      sqlite3VdbeAddOp2(v, OP_Integer, (pExpr->op==TK_EQ), dest);
    }




    regLeft = exprCodeSubselect(pParse, pLeft);
    regRight = exprCodeSubselect(pParse, pRight);

    for(i=0; i<nLeft; i++){
      int regFree1 = 0, regFree2 = 0;
      Expr *pL, *pR; 
      int r1, r2;
      if( i ) sqlite3ExprCachePush(pParse);
      r1 = exprVectorRegister(pParse, pLeft, i, regLeft, &pL, &regFree1);
      r2 = exprVectorRegister(pParse, pRight, i, regRight, &pR, &regFree2);

      switch( pExpr->op ){
        case TK_IS:
          codeCompare(
              pParse, pL, pR, OP_Eq, r1, r2, dest, SQLITE_STOREP2|SQLITE_NULLEQ
          );
          sqlite3VdbeAddOp3(v, OP_IfNot, dest, addr, 1);
          VdbeCoverage(v);
          break;

        case TK_ISNOT:
          codeCompare(
              pParse, pL, pR, OP_Ne, r1, r2, dest, SQLITE_STOREP2|SQLITE_NULLEQ
          );
          sqlite3VdbeAddOp3(v, OP_If, dest, addr, 1);
          VdbeCoverage(v);
          break;

        case TK_EQ:
        case TK_NE:
          codeCompare(pParse, pL, pR, OP_Cmp, r1, r2, regTmp,SQLITE_STOREP2|p5);
          sqlite3VdbeAddOp4Int(
              v, OP_CmpTest, regTmp, addr, dest, pExpr->op==TK_NE
          );
          VdbeCoverage(v);
          break;

        case TK_LT:
        case TK_LE:
        case TK_GT:
        case TK_GE:
          codeCompare(pParse, pL, pR, OP_Cmp, r1, r2, dest, SQLITE_STOREP2|p5);
          sqlite3VdbeAddOp4Int(v, OP_CmpTest, dest, addr, 0, pExpr->op);
          VdbeCoverage(v);
          break;
      }

      sqlite3ReleaseTempReg(pParse, regFree1);
      sqlite3ReleaseTempReg(pParse, regFree2);
      if( i ) sqlite3ExprCachePop(pParse);
    }

    sqlite3ReleaseTempReg(pParse, regTmp);
  }

  sqlite3VdbeResolveLabel(v, addr);
}

#if SQLITE_MAX_EXPR_DEPTH>0
/*
** Check that argument nHeight is less than or equal to the maximum
** expression depth allowed. If it is not, leave an error message in
** pParse.
................................................................................
    case TK_LE:
    case TK_GT:
    case TK_GE:
    case TK_NE:
    case TK_EQ: {
      Expr *pLeft = pExpr->pLeft;
      if( sqlite3ExprIsVector(pLeft) ){
        codeVectorCompare(pParse, pExpr, target);
      }else{
        r1 = sqlite3ExprCodeTemp(pParse, pLeft, &regFree1);
        r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
        codeCompare(pParse, pLeft, pExpr->pRight, op,
            r1, r2, inReg, SQLITE_STOREP2 | p5);
        assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
        assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);







|
>
>
>
>
>
>
>

|
>
>
>
>
>
>





<






<



|
>






<
>
|
|
|
|
>
>
>








|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<







 







|







405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432

433
434
435
436
437
438

439
440
441
442
443
444
445
446
447
448
449

450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502












503
504
505
506
507
508
509
....
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
  }
  *ppExpr = pVector->x.pList->a[iField].pExpr;
  return sqlite3ExprCodeTemp(pParse, *ppExpr, pRegFree);
}

/*
** Expression pExpr is a comparison between two vector values. Compute
** the result of the comparison (1, 0, or NULL) and write that
** result into register dest.
**
** The caller must satisfy the following preconditions:
**
**    if pExpr->op==TK_IS:      op==TK_EQ and p5==SQLITE_NULLEQ
**    if pExpr->op==TK_ISNOT:   op==TK_NE and p5==SQLITE_NULLEQ
**    otherwise:                op==pExpr->op and p5==0
*/
static void codeVectorCompare(
  Parse *pParse,        /* Code generator context */
  Expr *pExpr,          /* The comparison operation */
  int dest,             /* Write results into this register */
  u8 op,                /* Comparison operator */
  u8 p5                 /* SQLITE_NULLEQ or zero */
){
  Vdbe *v = pParse->pVdbe;
  Expr *pLeft = pExpr->pLeft;
  Expr *pRight = pExpr->pRight;
  int nLeft = sqlite3ExprVectorSize(pLeft);
  int nRight = sqlite3ExprVectorSize(pRight);


  /* Check that both sides of the comparison are vectors, and that
  ** both are the same length.  */
  if( nLeft!=nRight ){
    sqlite3ErrorMsg(pParse, "invalid use of row value");
  }else{

    int i;
    int regLeft = 0;
    int regRight = 0;
    u8 opx = op;
    int addrDone = sqlite3VdbeMakeLabel(v);

    assert( pExpr->op==TK_EQ || pExpr->op==TK_NE 
         || pExpr->op==TK_IS || pExpr->op==TK_ISNOT 
         || pExpr->op==TK_LT || pExpr->op==TK_GT 
         || pExpr->op==TK_LE || pExpr->op==TK_GE 
    );

    assert( pExpr->op==op || (pExpr->op==TK_IS && op==TK_EQ)
              || (pExpr->op==TK_ISNOT && op==TK_NE) );
    assert( p5==0 || pExpr->op!=op );
    assert( p5==SQLITE_NULLEQ || pExpr->op==op );

    p5 |= SQLITE_STOREP2;
    if( opx==TK_LE ) opx = TK_LT;
    if( opx==TK_GE ) opx = TK_GT;

    regLeft = exprCodeSubselect(pParse, pLeft);
    regRight = exprCodeSubselect(pParse, pRight);

    for(i=0; i<nLeft; i++){
      int regFree1 = 0, regFree2 = 0;
      Expr *pL, *pR; 
      int r1, r2;
      if( i>0 ) sqlite3ExprCachePush(pParse);
      r1 = exprVectorRegister(pParse, pLeft, i, regLeft, &pL, &regFree1);
      r2 = exprVectorRegister(pParse, pRight, i, regRight, &pR, &regFree2);
      codeCompare(pParse, pL, pR, opx, r1, r2, dest, p5);
      testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
      testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
      testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
      testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge);
      testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq);
      testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne);
      sqlite3ReleaseTempReg(pParse, regFree1);
      sqlite3ReleaseTempReg(pParse, regFree2);
      if( i>0 ) sqlite3ExprCachePop(pParse);
      if( i==nLeft-1 ){
        break;
      }
      if( opx==TK_EQ ){
        sqlite3VdbeAddOp2(v, OP_IfNot, dest, addrDone); VdbeCoverage(v);
        p5 |= SQLITE_KEEPNULL;
      }else if( opx==TK_NE ){
        sqlite3VdbeAddOp2(v, OP_If, dest, addrDone); VdbeCoverage(v);
        p5 |= SQLITE_KEEPNULL;
      }else if( opx==op ){
        assert( op==TK_LT || op==TK_GT );
        sqlite3VdbeAddOp3(v, OP_If, dest, addrDone, 1);
        VdbeCoverageIf(v, op==TK_LT);
        VdbeCoverageIf(v, op==TK_GT);
      }else{
        assert( op==TK_LE || op==TK_GE );
        sqlite3VdbeAddOp2(v, OP_ElseNotEq, 0, addrDone);
        VdbeCoverageIf(v, op==TK_LE);
        VdbeCoverageIf(v, op==TK_GE);
        if( i==nLeft-2 ) opx = op;
      }
    }
    sqlite3VdbeResolveLabel(v, addrDone);
  }












}

#if SQLITE_MAX_EXPR_DEPTH>0
/*
** Check that argument nHeight is less than or equal to the maximum
** expression depth allowed. If it is not, leave an error message in
** pParse.
................................................................................
    case TK_LE:
    case TK_GT:
    case TK_GE:
    case TK_NE:
    case TK_EQ: {
      Expr *pLeft = pExpr->pLeft;
      if( sqlite3ExprIsVector(pLeft) ){
        codeVectorCompare(pParse, pExpr, target, op, p5);
      }else{
        r1 = sqlite3ExprCodeTemp(pParse, pLeft, &regFree1);
        r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
        codeCompare(pParse, pLeft, pExpr->pRight, op,
            r1, r2, inReg, SQLITE_STOREP2 | p5);
        assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
        assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);

Changes to src/sqliteInt.h.

1729
1730
1731
1732
1733
1734
1735

1736
1737
1738
1739
1740
1741
1742
** changing the affinity.
**
** The SQLITE_NOTNULL flag is a combination of NULLEQ and JUMPIFNULL.
** It causes an assert() to fire if either operand to a comparison
** operator is NULL.  It is added to certain comparison operators to
** prove that the operands are always NOT NULL.
*/

#define SQLITE_JUMPIFNULL   0x10  /* jumps if either operand is NULL */
#define SQLITE_STOREP2      0x20  /* Store result in reg[P2] rather than jump */
#define SQLITE_NULLEQ       0x80  /* NULL=NULL */
#define SQLITE_NOTNULL      0x90  /* Assert that operands are never NULL */

/*
** An object of this type is created for each virtual table present in







>







1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
** changing the affinity.
**
** The SQLITE_NOTNULL flag is a combination of NULLEQ and JUMPIFNULL.
** It causes an assert() to fire if either operand to a comparison
** operator is NULL.  It is added to certain comparison operators to
** prove that the operands are always NOT NULL.
*/
#define SQLITE_KEEPNULL     0x08  /* Used by vector == or <> */
#define SQLITE_JUMPIFNULL   0x10  /* jumps if either operand is NULL */
#define SQLITE_STOREP2      0x20  /* Store result in reg[P2] rather than jump */
#define SQLITE_NULLEQ       0x80  /* NULL=NULL */
#define SQLITE_NOTNULL      0x90  /* Assert that operands are never NULL */

/*
** An object of this type is created for each virtual table present in

Changes to src/vdbe.c.

581
582
583
584
585
586
587

588
589
590
591
592
593
594
....
1876
1877
1878
1879
1880
1881
1882












































1883
1884
1885
1886
1887

1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
....
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
....
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
....
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013

2014
2015
2016
2017
2018
2019
2020
....
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085







2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
















2099
2100
2101
2102
2103
2104
2105
....
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
  Mem *aMem = p->aMem;       /* Copy of p->aMem */
  Mem *pIn1 = 0;             /* 1st input operand */
  Mem *pIn2 = 0;             /* 2nd input operand */
  Mem *pIn3 = 0;             /* 3rd input operand */
  Mem *pOut = 0;             /* Output operand */
  int *aPermute = 0;         /* Permutation of columns for OP_Compare */
  i64 lastRowid = db->lastRowid;  /* Saved value of the last insert ROWID */

#ifdef VDBE_PROFILE
  u64 start;                 /* CPU clock count at start of opcode */
#endif
  /*** INSERT STACK UNION HERE ***/

  assert( p->magic==VDBE_MAGIC_RUN );  /* sqlite3_step() verifies this */
  sqlite3VdbeEnter(p);
................................................................................
  sqlite3VdbeMemCast(pIn1, pOp->p2, encoding);
  UPDATE_MAX_BLOBSIZE(pIn1);
  if( rc ) goto abort_due_to_error;
  break;
}
#endif /* SQLITE_OMIT_CAST */













































/* Opcode: Lt P1 P2 P3 P4 P5
** Synopsis: if r[P1]<r[P3] goto P2
**
** Compare the values in register P1 and P3.  If reg(P3)<reg(P1) then
** jump to address P2.  

**
** If the SQLITE_JUMPIFNULL bit of P5 is set and either reg(P1) or
** reg(P3) is NULL then take the jump.  If the SQLITE_JUMPIFNULL 
** bit is clear then fall through if either operand is NULL.
**
** The SQLITE_AFF_MASK portion of P5 must be an affinity character -
** SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER, and so forth. An attempt is made 
** to coerce both inputs according to this affinity before the
** comparison is made. If the SQLITE_AFF_MASK is 0x00, then numeric
** affinity is used. Note that the affinity conversions are stored
................................................................................
** used to determine the results of the comparison.  If both values
** are text, then the appropriate collating function specified in
** P4 is  used to do the comparison.  If P4 is not specified then
** memcmp() is used to compare text string.  If both values are
** numeric, then a numeric comparison is used. If the two values
** are of different types, then numbers are considered less than
** strings and strings are considered less than blobs.
**
** If the SQLITE_STOREP2 bit of P5 is set, then do not jump.  Instead,
** store a boolean result (either 0, or 1, or NULL) in register P2.
**
** If the SQLITE_NULLEQ bit is set in P5, then NULL values are considered
** equal to one another, provided that they do not have their MEM_Cleared
** bit set.
*/
/* Opcode: Ne P1 P2 P3 P4 P5
** Synopsis: if r[P1]!=r[P3] goto P2
**
** This works just like the Lt opcode except that the jump is taken if
** the operands in registers P1 and P3 are not equal.  See the Lt opcode for
** additional information.
**
** If SQLITE_NULLEQ is set in P5 then the result of comparison is always either
** true or false and is never NULL.  If both operands are NULL then the result
** of comparison is false.  If either operand is NULL then the result is true.
** If neither operand is NULL the result is the same as it would be if
** the SQLITE_NULLEQ flag were omitted from P5.
*/
/* Opcode: Eq P1 P2 P3 P4 P5
** Synopsis: if r[P1]==r[P3] goto P2
**
** This works just like the Lt opcode except that the jump is taken if
** the operands in registers P1 and P3 are equal.
** See the Lt opcode for additional information.
**
** If SQLITE_NULLEQ is set in P5 then the result of comparison is always either
** true or false and is never NULL.  If both operands are NULL then the result
** of comparison is true.  If either operand is NULL then the result is false.
** If neither operand is NULL the result is the same as it would be if
** the SQLITE_NULLEQ flag were omitted from P5.
*/
/* Opcode: Le P1 P2 P3 P4 P5
** Synopsis: if r[P1]<=r[P3] goto P2
**
** This works just like the Lt opcode except that the jump is taken if
** the content of register P3 is less than or equal to the content of
** register P1.  See the Lt opcode for additional information.
................................................................................
*/
/* Opcode: Ge P1 P2 P3 P4 P5
** Synopsis: if r[P1]>=r[P3] goto P2
**
** This works just like the Lt opcode except that the jump is taken if
** the content of register P3 is greater than or equal to the content of
** register P1.  See the Lt opcode for additional information.
**
** Opcode: Cmp P1 P2 P3 P4 P5
** Synopsis: P2 = cmp(P1, P3)
**
** The SQLITE_STOREP2 flag must be set for this opcode. It compares the
** values in registers P1 and P3 and stores the result of the comparison
** in register P2. The results is NULL if either of the two operands are
** NULL. Otherwise, it is an integer value less than zero, zero or greater 
** than zero if P3 is less than, equal to or greater than P1, respectively.
*/
case OP_Cmp:              /* in1, in3 */
case OP_Eq:               /* same as TK_EQ, jump, in1, in3 */
case OP_Ne:               /* same as TK_NE, jump, in1, in3 */
case OP_Lt:               /* same as TK_LT, jump, in1, in3 */
case OP_Le:               /* same as TK_LE, jump, in1, in3 */
case OP_Gt:               /* same as TK_GT, jump, in1, in3 */
case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
  int res;            /* Result of the comparison of pIn1 against pIn3 */
  char affinity;      /* Affinity to use for comparison */
  u16 flags1;         /* Copy of initial value of pIn1->flags */
  u16 flags3;         /* Copy of initial value of pIn3->flags */

  assert( pOp->opcode!=OP_Cmp || (pOp->p5 & SQLITE_STOREP2) );
  pIn1 = &aMem[pOp->p1];
  pIn3 = &aMem[pOp->p3];
  flags1 = pIn1->flags;
  flags3 = pIn3->flags;
  if( (flags1 | flags3)&MEM_Null ){
    /* One or both operands are NULL */
    if( pOp->p5 & SQLITE_NULLEQ ){
................................................................................
      assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne );
      assert( (flags1 & MEM_Cleared)==0 );
      assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 );
      if( (flags1&MEM_Null)!=0
       && (flags3&MEM_Null)!=0
       && (flags3&MEM_Cleared)==0
      ){
        res = 0;  /* Results are equal */
      }else{
        res = 1;  /* Results are not equal */
      }
    }else{
      /* SQLITE_NULLEQ is clear and at least one operand is NULL,
      ** then the result is always NULL.
      ** The jump is taken if the SQLITE_JUMPIFNULL bit is set.
      */

      if( pOp->p5 & SQLITE_STOREP2 ){
        pOut = &aMem[pOp->p2];
        memAboutToChange(p, pOut);
        MemSetTypeFlag(pOut, MEM_Null);
        REGISTER_TRACE(pOp->p2, pOut);
      }else{
        VdbeBranchTaken(2,3);
................................................................................
      sqlite3VdbeMemExpandBlob(pIn1);
      flags1 &= ~MEM_Zero;
    }
    if( flags3 & MEM_Zero ){
      sqlite3VdbeMemExpandBlob(pIn3);
      flags3 &= ~MEM_Zero;
    }
    res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
  }
  switch( pOp->opcode ){
    case OP_Eq:    res = res==0;     break;
    case OP_Ne:    res = res!=0;     break;
    case OP_Lt:    res = res<0;      break;
    case OP_Le:    res = res<=0;     break;
    case OP_Gt:    res = res>0;      break;
    case OP_Ge:    res = res>=0;     break;
    default: assert( pOp->opcode==OP_Cmp ); break;
  }

  /* Undo any changes made by applyAffinity() to the input registers. */
  assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
  pIn1->flags = flags1;
  assert( (pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn) );
  pIn3->flags = flags3;

  if( pOp->p5 & SQLITE_STOREP2 ){
    pOut = &aMem[pOp->p2];







    memAboutToChange(p, pOut);
    MemSetTypeFlag(pOut, MEM_Int);
    pOut->u.i = res;
    REGISTER_TRACE(pOp->p2, pOut);
  }else{
    assert( pOp->opcode!=OP_Cmp );
    VdbeBranchTaken(res!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
    if( res ){
      goto jump_to_p2;
    }
  }
  break;
}

















/* Opcode: Permutation * * * P4 *
**
** Set the permutation used by the OP_Compare operator to be the array
** of integers in P4.
**
** The permutation is only valid until the next OP_Compare that has
................................................................................
  }else if( eqOnly ){
    assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT );
    pOp++; /* Skip the OP_IdxLt or OP_IdxGT that follows */
  }
  break;
}

/* Opcode: CmpTest P1 P2 P3 P4 *
**
** P2 is a jump destination. Register P1 is guaranteed to contain either
** an integer value or a NULL. 
**
** If P3 is non-zero, it identifies an output register. In this case, if
** P1 is NULL, P3 is also set to NULL. Or, if P1 is any integer value 
** other than 0, P3 is set to the value of P4 and a jump to P2 is taken.
**
** If P3 is 0, the jump is taken if P1 contains any value other than 0 (i.e.
** NULL does cause a jump). Additionally, if P1 is not NULL, its value is
** modified to integer value 0 or 1 according to the value of the P4 integer
** operand:
**
**   P4            modification
**   --------------------------
**   OP_Lt         (P1 = (P1 < 0))
**   OP_Le         (P1 = (P1 <= 0))
**   OP_Gt         (P1 = (P1 > 0))
**   OP_Ge         (P1 = (P1 >= 0))
*/
case OP_CmpTest: {                /* in1, jump */
  int bJump;
  pIn1 = &aMem[pOp->p1];

  if( pOp->p3 ){
    bJump = 0;
    if( pIn1->flags & MEM_Null ){
      memAboutToChange(p, &aMem[pOp->p3]);
      MemSetTypeFlag(&aMem[pOp->p3], MEM_Null);
    }else if( pIn1->u.i!=0 ){
      memAboutToChange(p, &aMem[pOp->p3]);
      MemSetTypeFlag(&aMem[pOp->p3], MEM_Int);
      aMem[pOp->p3].u.i = pOp->p4.i;
      bJump = 1;
    }
  }else{
    if( (pIn1->flags & MEM_Int) ){
      bJump = (pIn1->u.i!=0);
      switch( pOp->p4.i ){
        case OP_Lt: pIn1->u.i = (pIn1->u.i < 0); break;
        case OP_Le: pIn1->u.i = (pIn1->u.i <= 0); break;
        case OP_Gt: pIn1->u.i = (pIn1->u.i > 0); break;
        default: 
          assert( pOp->p4.i==OP_Ge ); 
          pIn1->u.i = (pIn1->u.i >= 0); 
          break;
      }
    }else{
      bJump = 1;
    }
  }

  if( bJump ) goto jump_to_p2;
  break;
}

/* Opcode: Found P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** If P4==0 then register P3 holds a blob constructed by MakeRecord.  If
** P4>0 then register P3 is the first of P4 registers that form an unpacked
** record.
**







>







 







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




|
>


|







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







<
<
<
<
<
<
<
<
<

<











<







 







|

|






>







 







|


|
|
|
|
|
|
<










>
>
>
>
>
>
>





<







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







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
....
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
....
1949
1950
1951
1952
1953
1954
1955

































1956
1957
1958
1959
1960
1961
1962
....
1970
1971
1972
1973
1974
1975
1976









1977

1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988

1989
1990
1991
1992
1993
1994
1995
....
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
....
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077

2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099

2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
....
3905
3906
3907
3908
3909
3910
3911

























































3912
3913
3914
3915
3916
3917
3918
  Mem *aMem = p->aMem;       /* Copy of p->aMem */
  Mem *pIn1 = 0;             /* 1st input operand */
  Mem *pIn2 = 0;             /* 2nd input operand */
  Mem *pIn3 = 0;             /* 3rd input operand */
  Mem *pOut = 0;             /* Output operand */
  int *aPermute = 0;         /* Permutation of columns for OP_Compare */
  i64 lastRowid = db->lastRowid;  /* Saved value of the last insert ROWID */
  int cmpRes;                /* Result of last comparison operation */
#ifdef VDBE_PROFILE
  u64 start;                 /* CPU clock count at start of opcode */
#endif
  /*** INSERT STACK UNION HERE ***/

  assert( p->magic==VDBE_MAGIC_RUN );  /* sqlite3_step() verifies this */
  sqlite3VdbeEnter(p);
................................................................................
  sqlite3VdbeMemCast(pIn1, pOp->p2, encoding);
  UPDATE_MAX_BLOBSIZE(pIn1);
  if( rc ) goto abort_due_to_error;
  break;
}
#endif /* SQLITE_OMIT_CAST */

/* Opcode: Eq P1 P2 P3 P4 P5
** Synopsis: if r[P1]==r[P3] goto P2
**
** Compare the values in register P1 and P3.  If reg(P3)==reg(P1) then
** jump to address P2.  Or if the SQLITE_STOREP2 flag is set in P5, then
** store the result of comparison in register P2.
**
** The SQLITE_AFF_MASK portion of P5 must be an affinity character -
** SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER, and so forth. An attempt is made 
** to coerce both inputs according to this affinity before the
** comparison is made. If the SQLITE_AFF_MASK is 0x00, then numeric
** affinity is used. Note that the affinity conversions are stored
** back into the input registers P1 and P3.  So this opcode can cause
** persistent changes to registers P1 and P3.
**
** Once any conversions have taken place, and neither value is NULL, 
** the values are compared. If both values are blobs then memcmp() is
** used to determine the results of the comparison.  If both values
** are text, then the appropriate collating function specified in
** P4 is used to do the comparison.  If P4 is not specified then
** memcmp() is used to compare text string.  If both values are
** numeric, then a numeric comparison is used. If the two values
** are of different types, then numbers are considered less than
** strings and strings are considered less than blobs.
**
** If SQLITE_NULLEQ is set in P5 then the result of comparison is always either
** true or false and is never NULL.  If both operands are NULL then the result
** of comparison is true.  If either operand is NULL then the result is false.
** If neither operand is NULL the result is the same as it would be if
** the SQLITE_NULLEQ flag were omitted from P5.
**
** If both SQLITE_STOREP2 and SQLITE_KEEPNULL flags are set then the
** content of r[P2] is only set to 1 (true) if it was not previously NULL.
*/
/* Opcode: Ne P1 P2 P3 P4 P5
** Synopsis: if r[P1]!=r[P3] goto P2
**
** This works just like the Eq opcode except that the jump is taken if
** the operands in registers P1 and P3 are not equal.  See the Eq opcode for
** additional information.
**
** If both SQLITE_STOREP2 and SQLITE_KEEPNULL flags are set then the
** content of r[P2] is only set to 0 (false) if it was not previously NULL.
*/
/* Opcode: Lt P1 P2 P3 P4 P5
** Synopsis: if r[P1]<r[P3] goto P2
**
** Compare the values in register P1 and P3.  If reg(P3)<reg(P1) then
** jump to address P2.  Or if the SQLITE_STOREP2 flag is set in P5 store
** the result of comparison (0 or 1 or NULL) into register P2.
**
** If the SQLITE_JUMPIFNULL bit of P5 is set and either reg(P1) or
** reg(P3) is NULL then the take the jump.  If the SQLITE_JUMPIFNULL 
** bit is clear then fall through if either operand is NULL.
**
** The SQLITE_AFF_MASK portion of P5 must be an affinity character -
** SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER, and so forth. An attempt is made 
** to coerce both inputs according to this affinity before the
** comparison is made. If the SQLITE_AFF_MASK is 0x00, then numeric
** affinity is used. Note that the affinity conversions are stored
................................................................................
** used to determine the results of the comparison.  If both values
** are text, then the appropriate collating function specified in
** P4 is  used to do the comparison.  If P4 is not specified then
** memcmp() is used to compare text string.  If both values are
** numeric, then a numeric comparison is used. If the two values
** are of different types, then numbers are considered less than
** strings and strings are considered less than blobs.

































*/
/* Opcode: Le P1 P2 P3 P4 P5
** Synopsis: if r[P1]<=r[P3] goto P2
**
** This works just like the Lt opcode except that the jump is taken if
** the content of register P3 is less than or equal to the content of
** register P1.  See the Lt opcode for additional information.
................................................................................
*/
/* Opcode: Ge P1 P2 P3 P4 P5
** Synopsis: if r[P1]>=r[P3] goto P2
**
** This works just like the Lt opcode except that the jump is taken if
** the content of register P3 is greater than or equal to the content of
** register P1.  See the Lt opcode for additional information.









*/

case OP_Eq:               /* same as TK_EQ, jump, in1, in3 */
case OP_Ne:               /* same as TK_NE, jump, in1, in3 */
case OP_Lt:               /* same as TK_LT, jump, in1, in3 */
case OP_Le:               /* same as TK_LE, jump, in1, in3 */
case OP_Gt:               /* same as TK_GT, jump, in1, in3 */
case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
  int res;            /* Result of the comparison of pIn1 against pIn3 */
  char affinity;      /* Affinity to use for comparison */
  u16 flags1;         /* Copy of initial value of pIn1->flags */
  u16 flags3;         /* Copy of initial value of pIn3->flags */


  pIn1 = &aMem[pOp->p1];
  pIn3 = &aMem[pOp->p3];
  flags1 = pIn1->flags;
  flags3 = pIn3->flags;
  if( (flags1 | flags3)&MEM_Null ){
    /* One or both operands are NULL */
    if( pOp->p5 & SQLITE_NULLEQ ){
................................................................................
      assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne );
      assert( (flags1 & MEM_Cleared)==0 );
      assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 );
      if( (flags1&MEM_Null)!=0
       && (flags3&MEM_Null)!=0
       && (flags3&MEM_Cleared)==0
      ){
        cmpRes = 0;  /* Results are equal */
      }else{
        cmpRes = 1;  /* Results are not equal */
      }
    }else{
      /* SQLITE_NULLEQ is clear and at least one operand is NULL,
      ** then the result is always NULL.
      ** The jump is taken if the SQLITE_JUMPIFNULL bit is set.
      */
      cmpRes = 1;
      if( pOp->p5 & SQLITE_STOREP2 ){
        pOut = &aMem[pOp->p2];
        memAboutToChange(p, pOut);
        MemSetTypeFlag(pOut, MEM_Null);
        REGISTER_TRACE(pOp->p2, pOut);
      }else{
        VdbeBranchTaken(2,3);
................................................................................
      sqlite3VdbeMemExpandBlob(pIn1);
      flags1 &= ~MEM_Zero;
    }
    if( flags3 & MEM_Zero ){
      sqlite3VdbeMemExpandBlob(pIn3);
      flags3 &= ~MEM_Zero;
    }
    cmpRes = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
  }
  switch( pOp->opcode ){
    case OP_Eq:    res = cmpRes==0;     break;
    case OP_Ne:    res = cmpRes!=0;     break;
    case OP_Lt:    res = cmpRes<0;      break;
    case OP_Le:    res = cmpRes<=0;     break;
    case OP_Gt:    res = cmpRes>0;      break;
    case OP_Ge:    res = cmpRes>=0;     break;

  }

  /* Undo any changes made by applyAffinity() to the input registers. */
  assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
  pIn1->flags = flags1;
  assert( (pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn) );
  pIn3->flags = flags3;

  if( pOp->p5 & SQLITE_STOREP2 ){
    pOut = &aMem[pOp->p2];
    if( (pOp->p5 & SQLITE_KEEPNULL)!=0 && (pOut->flags & MEM_Null)!=0 ){
      /* The KEEPNULL flag prevents OP_Eq from overwriting a NULL with 1
      ** and prevents OP_Ne from overwriting NULL with 0. */
      assert( pOp->opcode==OP_Ne || pOp->opcode==OP_Eq );
      assert( res==0 || res==1 );
      if( (pOp->opcode==OP_Eq)==res ) break;
    }
    memAboutToChange(p, pOut);
    MemSetTypeFlag(pOut, MEM_Int);
    pOut->u.i = res;
    REGISTER_TRACE(pOp->p2, pOut);
  }else{

    VdbeBranchTaken(res!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
    if( res ){
      goto jump_to_p2;
    }
  }
  break;
}

/* Opcode: ElseNotEq * P2 * * *
**
** This opcode must immediately follow an Lt or Gt comparison operator.
** If the operands in that previous comparison are not equal (possibly
** because one or the other is NULL) then jump to P2.  If the two operands
** of the prior comparison are equal, fall through.
*/
case OP_ElseNotEq: {       /* same as TK_ESCAPE, jump */
  assert( pOp>aOp );
  assert( pOp[-1].opcode==OP_Lt || pOp[-1].opcode==OP_Gt );
  VdbeBranchTaken(cmpRes!=0, 2);
  if( cmpRes!=0 ) goto jump_to_p2;
  break;
}


/* Opcode: Permutation * * * P4 *
**
** Set the permutation used by the OP_Compare operator to be the array
** of integers in P4.
**
** The permutation is only valid until the next OP_Compare that has
................................................................................
  }else if( eqOnly ){
    assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT );
    pOp++; /* Skip the OP_IdxLt or OP_IdxGT that follows */
  }
  break;
}


























































/* Opcode: Found P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** If P4==0 then register P3 holds a blob constructed by MakeRecord.  If
** P4>0 then register P3 is the first of P4 registers that form an unpacked
** record.
**