/ 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 Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/expr.c.

   529    529         pRoot->pLeft = pLeft;
   530    530         pRoot->flags |= EP_Propagate & pLeft->flags;
   531    531       }
   532    532       exprSetHeight(pRoot);
   533    533     }
   534    534   }
   535    535   
   536         -/*
   537         -** Allocate an Expr node which joins as many as two subtrees.
   538         -**
   539         -** One or both of the subtrees can be NULL.  Return a pointer to the new
   540         -** Expr node.  Or, if an OOM error occurs, set pParse->db->mallocFailed,
   541         -** free the subtrees and return NULL.
   542         -*/
   543         -Expr *sqlite3PExpr(
   544         -  Parse *pParse,          /* Parsing context */
   545         -  int op,                 /* Expression opcode */
   546         -  Expr *pLeft,            /* Left operand */
   547         -  Expr *pRight,           /* Right operand */
   548         -  const Token *pToken     /* Argument token */
   549         -){
   550         -  Expr *p;
   551         -  if( op==TK_AND && pParse->nErr==0 ){
   552         -    /* Take advantage of short-circuit false optimization for AND */
   553         -    p = sqlite3ExprAnd(pParse->db, pLeft, pRight);
   554         -  }else{
   555         -    p = sqlite3ExprAlloc(pParse->db, op & TKFLG_MASK, pToken, 1);
   556         -    sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight);
   557         -  }
   558         -  if( p ) {
   559         -    sqlite3ExprCheckHeight(pParse, p->nHeight);
   560         -  }
   561         -  return p;
   562         -}
   563         -
   564    536   /*
   565    537   ** If the expression is always either TRUE or FALSE (respectively),
   566    538   ** then return 1.  If one cannot determine the truth value of the
   567    539   ** expression at compile-time return 0.
   568    540   **
   569    541   ** This is an optimization.  If is OK to return 0 here even if
   570    542   ** the expression really is always false or false (a false negative).
................................................................................
   607    579       return sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0], 0);
   608    580     }else{
   609    581       Expr *pNew = sqlite3ExprAlloc(db, TK_AND, 0, 0);
   610    582       sqlite3ExprAttachSubtrees(db, pNew, pLeft, pRight);
   611    583       return pNew;
   612    584     }
   613    585   }
          586  +
          587  +/* Join expressions pLeft and pRight using OR.  Apply constant-folding
          588  +** style optimizations.  For example,  "x OR 1" becomes just "1".
          589  +*/
          590  +static Expr *sqlite3ExprOr(sqlite3 *db, Expr *pLeft, Expr *pRight){
          591  +  if( pLeft && exprAlwaysFalse(pLeft) ){
          592  +    sqlite3ExprDelete(db, pLeft);
          593  +    pLeft = 0;
          594  +  }
          595  +  if( pRight==0 || exprAlwaysFalse(pRight) ){
          596  +    sqlite3ExprDelete(db, pRight);
          597  +    if( pLeft ) return pLeft;
          598  +    return sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0], 0);
          599  +  }
          600  +  if( pLeft==0 ) return pRight;
          601  +  if( exprAlwaysTrue(pLeft) || exprAlwaysTrue(pRight) ){
          602  +    sqlite3ExprDelete(db, pLeft);
          603  +    sqlite3ExprDelete(db, pRight);
          604  +    return sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[1], 0);
          605  +  }else{
          606  +    Expr *pNew = sqlite3ExprAlloc(db, TK_OR, 0, 0);
          607  +    sqlite3ExprAttachSubtrees(db, pNew, pLeft, pRight);
          608  +    return pNew;
          609  +  }
          610  +}
          611  +
          612  +/*
          613  +** Allocate an Expr node which joins as many as two subtrees.
          614  +**
          615  +** One or both of the subtrees can be NULL.  Return a pointer to the new
          616  +** Expr node.  Or, if an OOM error occurs, set pParse->db->mallocFailed,
          617  +** free the subtrees and return NULL.
          618  +*/
          619  +Expr *sqlite3PExpr(
          620  +  Parse *pParse,          /* Parsing context */
          621  +  int op,                 /* Expression opcode */
          622  +  Expr *pLeft,            /* Left operand */
          623  +  Expr *pRight,           /* Right operand */
          624  +  const Token *pToken     /* Argument token */
          625  +){
          626  +  Expr *p;
          627  +  if( pParse->nErr==0 && op==TK_AND ){
          628  +    /* Take advantage of short-circuit false optimization for AND */
          629  +    p = sqlite3ExprAnd(pParse->db, pLeft, pRight);
          630  +  }else if( pParse->nErr==0 && op==TK_OR ){
          631  +    /* Take advantage of short-circuit false optimization for OR */
          632  +    p = sqlite3ExprOr(pParse->db, pLeft, pRight);
          633  +  }else{
          634  +    p = sqlite3ExprAlloc(pParse->db, op & TKFLG_MASK, pToken, 1);
          635  +    sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight);
          636  +  }
          637  +  if( p ) {
          638  +    sqlite3ExprCheckHeight(pParse, p->nHeight);
          639  +  }
          640  +  return p;
          641  +}
   614    642   
   615    643   /*
   616    644   ** Construct a new expression node for a function with multiple
   617    645   ** arguments.
   618    646   */
   619    647   Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){
   620    648     Expr *pNew;

Changes to test/where2.test.

   294    294       }
   295    295     } {99 6 10000 10006 nosort t1 i1w}
   296    296   }
   297    297   
   298    298   # Verify that OR clauses get translated into IN operators.
   299    299   #
   300    300   set ::idx {}
          301  +exit
   301    302   ifcapable subquery {set ::idx i1w}
   302    303   do_test where2-6.1.1 {
   303    304     queryplan {
   304    305       SELECT * FROM t1 WHERE w=99 OR w=100 ORDER BY +w
   305    306     }
   306    307   } [list 99 6 10000 10006 100 6 10201 10207 sort t1 $::idx]
   307    308   do_test where2-6.1.2 {