/ Check-in [7fdf26da]
Login

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

Overview
Comment:Further enhancements to IN-operator processing.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | IN-operator-improvements
Files: files | file ages | folders
SHA1:7fdf26da1d2f40b80f9e44ff6f5af22ace8f95f3
User & Date: drh 2014-08-04 18:50:54
Context
2014-08-04
21:26
Part of the change in the previous check-in was incorrect and can result in an incorrect UPDATE for WITHOUT ROWID tables. This check-in fixes the problem. check-in: ee5f6eae user: drh tags: IN-operator-improvements
18:50
Further enhancements to IN-operator processing. check-in: 7fdf26da user: drh tags: IN-operator-improvements
16:39
Refinements to the enhanced IN-operator logic. check-in: 92ba2821 user: drh tags: IN-operator-improvements
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/expr.c.

1364
1365
1366
1367
1368
1369
1370



1371
1372
1373
1374
1375
1376
1377
....
2034
2035
2036
2037
2038
2039
2040

2041
2042
2043
2044
2045
2046
2047
2048
2049
2050

2051
2052
2053
2054
2055
2056
2057
  if( op==TK_REGISTER ) op = p->op2;
  switch( op ){
    case TK_INTEGER:
    case TK_STRING:
    case TK_FLOAT:
    case TK_BLOB:
      return 0;



    default:
      return 1;
  }
}

/*
** Return TRUE if the given expression is a constant which would be
................................................................................
    sqlite3VdbeResolveLabel(v, labelOk);
    sqlite3ReleaseTempReg(pParse, regCkNull);
  }else{
  
    /* If the LHS is NULL, then the result is either false or NULL depending
    ** on whether the RHS is empty or not, respectively.
    */

    if( destIfNull==destIfFalse ){
      /* Shortcut for the common case where the false and NULL outcomes are
      ** the same. */
      sqlite3VdbeAddOp2(v, OP_IsNull, r1, destIfNull); VdbeCoverage(v);
    }else{
      int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1); VdbeCoverage(v);
      sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse);
      VdbeCoverage(v);
      sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull);
      sqlite3VdbeJumpHere(v, addr1);

    }
  
    if( eType==IN_INDEX_ROWID ){
      /* In this case, the RHS is the ROWID of table b-tree
      */
      sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, destIfFalse); VdbeCoverage(v);
      sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, destIfFalse, r1);







>
>
>







 







>
|
|
|
|
|
|
|
|
|
|
>







1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
....
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
  if( op==TK_REGISTER ) op = p->op2;
  switch( op ){
    case TK_INTEGER:
    case TK_STRING:
    case TK_FLOAT:
    case TK_BLOB:
      return 0;
    case TK_COLUMN:
      assert( p->pTab!=0 );
      return p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0;
    default:
      return 1;
  }
}

/*
** Return TRUE if the given expression is a constant which would be
................................................................................
    sqlite3VdbeResolveLabel(v, labelOk);
    sqlite3ReleaseTempReg(pParse, regCkNull);
  }else{
  
    /* If the LHS is NULL, then the result is either false or NULL depending
    ** on whether the RHS is empty or not, respectively.
    */
    if( sqlite3ExprCanBeNull(pExpr->pLeft) ){
      if( destIfNull==destIfFalse ){
        /* Shortcut for the common case where the false and NULL outcomes are
        ** the same. */
        sqlite3VdbeAddOp2(v, OP_IsNull, r1, destIfNull); VdbeCoverage(v);
      }else{
        int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1); VdbeCoverage(v);
        sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse);
        VdbeCoverage(v);
        sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull);
        sqlite3VdbeJumpHere(v, addr1);
      }
    }
  
    if( eType==IN_INDEX_ROWID ){
      /* In this case, the RHS is the ROWID of table b-tree
      */
      sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, destIfFalse); VdbeCoverage(v);
      sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, destIfFalse, r1);

Changes to src/update.c.

433
434
435
436
437
438
439
440
441

442
443
444
445
446
447
448
  if( okOnePass ){
    if( aToOpen[iDataCur-iBaseCur] ){
      assert( pPk!=0 );
      sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey);
      VdbeCoverageNeverTaken(v);
    }
    labelContinue = labelBreak;
    sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak);
    VdbeCoverage(v);

  }else if( pPk ){
    labelContinue = sqlite3VdbeMakeLabel(v);
    sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v);
    addrTop = sqlite3VdbeAddOp2(v, OP_RowKey, iEph, regKey);
    sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0);
    VdbeCoverage(v);
  }else{







|
|
>







433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
  if( okOnePass ){
    if( aToOpen[iDataCur-iBaseCur] ){
      assert( pPk!=0 );
      sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey);
      VdbeCoverageNeverTaken(v);
    }
    labelContinue = labelBreak;
    if( pPk==0 ){
      sqlite3VdbeAddOp2(v, OP_IsNull, regOldRowid, labelBreak); VdbeCoverage(v);
    }
  }else if( pPk ){
    labelContinue = sqlite3VdbeMakeLabel(v);
    sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v);
    addrTop = sqlite3VdbeAddOp2(v, OP_RowKey, iEph, regKey);
    sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0);
    VdbeCoverage(v);
  }else{