/ Check-in [d533e23f]
Login

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

Overview
Comment:Apply optimizations to simplify OR clauses that contain constant terms.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | simplify-or-clause
Files: files | file ages | folders
SHA1:d533e23f059621364bd5dac5fae794f5973b1349
User & Date: drh 2015-10-29 12:27:38
Context
2015-10-29
14:29
The optimization on this branch is logically incorrect. It changes the return value of "SELECT 0 OR 'xyzzy'" FROM 0 to 'xyzzy'. Closed-Leaf check-in: a0c08d26 user: drh tags: simplify-or-clause
12:27
Apply optimizations to simplify OR clauses that contain constant terms. check-in: d533e23f user: drh tags: simplify-or-clause
01:11
Enhance comments in the MSVC batch build tool. check-in: 2964ce25 user: mistachkin tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/expr.c.

529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
...
607
608
609
610
611
612
613
























































614
615
616
617
618
619
620
      pRoot->pLeft = pLeft;
      pRoot->flags |= EP_Propagate & pLeft->flags;
    }
    exprSetHeight(pRoot);
  }
}

/*
** Allocate an Expr node which joins as many as two subtrees.
**
** One or both of the subtrees can be NULL.  Return a pointer to the new
** Expr node.  Or, if an OOM error occurs, set pParse->db->mallocFailed,
** free the subtrees and return NULL.
*/
Expr *sqlite3PExpr(
  Parse *pParse,          /* Parsing context */
  int op,                 /* Expression opcode */
  Expr *pLeft,            /* Left operand */
  Expr *pRight,           /* Right operand */
  const Token *pToken     /* Argument token */
){
  Expr *p;
  if( op==TK_AND && pParse->nErr==0 ){
    /* Take advantage of short-circuit false optimization for AND */
    p = sqlite3ExprAnd(pParse->db, pLeft, pRight);
  }else{
    p = sqlite3ExprAlloc(pParse->db, op & TKFLG_MASK, pToken, 1);
    sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight);
  }
  if( p ) {
    sqlite3ExprCheckHeight(pParse, p->nHeight);
  }
  return p;
}

/*
** If the expression is always either TRUE or FALSE (respectively),
** then return 1.  If one cannot determine the truth value of the
** expression at compile-time return 0.
**
** This is an optimization.  If is OK to return 0 here even if
** the expression really is always false or false (a false negative).
................................................................................
    return sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0], 0);
  }else{
    Expr *pNew = sqlite3ExprAlloc(db, TK_AND, 0, 0);
    sqlite3ExprAttachSubtrees(db, pNew, pLeft, pRight);
    return pNew;
  }
}

























































/*
** Construct a new expression node for a function with multiple
** arguments.
*/
Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){
  Expr *pNew;







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







 







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







529
530
531
532
533
534
535




























536
537
538
539
540
541
542
...
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
      pRoot->pLeft = pLeft;
      pRoot->flags |= EP_Propagate & pLeft->flags;
    }
    exprSetHeight(pRoot);
  }
}





























/*
** If the expression is always either TRUE or FALSE (respectively),
** then return 1.  If one cannot determine the truth value of the
** expression at compile-time return 0.
**
** This is an optimization.  If is OK to return 0 here even if
** the expression really is always false or false (a false negative).
................................................................................
    return sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0], 0);
  }else{
    Expr *pNew = sqlite3ExprAlloc(db, TK_AND, 0, 0);
    sqlite3ExprAttachSubtrees(db, pNew, pLeft, pRight);
    return pNew;
  }
}

/* Join expressions pLeft and pRight using OR.  Apply constant-folding
** style optimizations.  For example,  "x OR 1" becomes just "1".
*/
static Expr *sqlite3ExprOr(sqlite3 *db, Expr *pLeft, Expr *pRight){
  if( pLeft && exprAlwaysFalse(pLeft) ){
    sqlite3ExprDelete(db, pLeft);
    pLeft = 0;
  }
  if( pRight==0 || exprAlwaysFalse(pRight) ){
    sqlite3ExprDelete(db, pRight);
    if( pLeft ) return pLeft;
    return sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0], 0);
  }
  if( pLeft==0 ) return pRight;
  if( exprAlwaysTrue(pLeft) || exprAlwaysTrue(pRight) ){
    sqlite3ExprDelete(db, pLeft);
    sqlite3ExprDelete(db, pRight);
    return sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[1], 0);
  }else{
    Expr *pNew = sqlite3ExprAlloc(db, TK_OR, 0, 0);
    sqlite3ExprAttachSubtrees(db, pNew, pLeft, pRight);
    return pNew;
  }
}

/*
** Allocate an Expr node which joins as many as two subtrees.
**
** One or both of the subtrees can be NULL.  Return a pointer to the new
** Expr node.  Or, if an OOM error occurs, set pParse->db->mallocFailed,
** free the subtrees and return NULL.
*/
Expr *sqlite3PExpr(
  Parse *pParse,          /* Parsing context */
  int op,                 /* Expression opcode */
  Expr *pLeft,            /* Left operand */
  Expr *pRight,           /* Right operand */
  const Token *pToken     /* Argument token */
){
  Expr *p;
  if( pParse->nErr==0 && op==TK_AND ){
    /* Take advantage of short-circuit false optimization for AND */
    p = sqlite3ExprAnd(pParse->db, pLeft, pRight);
  }else if( pParse->nErr==0 && op==TK_OR ){
    /* Take advantage of short-circuit false optimization for OR */
    p = sqlite3ExprOr(pParse->db, pLeft, pRight);
  }else{
    p = sqlite3ExprAlloc(pParse->db, op & TKFLG_MASK, pToken, 1);
    sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight);
  }
  if( p ) {
    sqlite3ExprCheckHeight(pParse, p->nHeight);
  }
  return p;
}

/*
** Construct a new expression node for a function with multiple
** arguments.
*/
Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){
  Expr *pNew;

Changes to test/where2.test.

294
295
296
297
298
299
300

301
302
303
304
305
306
307
    }
  } {99 6 10000 10006 nosort t1 i1w}
}

# Verify that OR clauses get translated into IN operators.
#
set ::idx {}

ifcapable subquery {set ::idx i1w}
do_test where2-6.1.1 {
  queryplan {
    SELECT * FROM t1 WHERE w=99 OR w=100 ORDER BY +w
  }
} [list 99 6 10000 10006 100 6 10201 10207 sort t1 $::idx]
do_test where2-6.1.2 {







>







294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
    }
  } {99 6 10000 10006 nosort t1 i1w}
}

# Verify that OR clauses get translated into IN operators.
#
set ::idx {}
exit
ifcapable subquery {set ::idx i1w}
do_test where2-6.1.1 {
  queryplan {
    SELECT * FROM t1 WHERE w=99 OR w=100 ORDER BY +w
  }
} [list 99 6 10000 10006 100 6 10201 10207 sort t1 $::idx]
do_test where2-6.1.2 {