/ Check-in [7713996a]
Login

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

Overview
Comment:Streamline the processing of the AND operator. Slightly smaller and faster.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 7713996aa99ce6dd35b5a2db74dd26658fb8d9817169b2a7531cdef6edb41403
User & Date: drh 2019-04-19 13:38:34
Context
2019-04-19
16:21
Use macros to determine if an expression is always true or always false. check-in: 6de980a0 user: drh tags: trunk
13:38
Streamline the processing of the AND operator. Slightly smaller and faster. check-in: 7713996a user: drh tags: trunk
2019-04-17
21:12
Small performance and size optimization in sqlite3WalFindFrame(). check-in: 03f2e788 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Show Whitespace Changes Patch

Changes to src/expr.c.

   846    846   Expr *sqlite3PExpr(
   847    847     Parse *pParse,          /* Parsing context */
   848    848     int op,                 /* Expression opcode */
   849    849     Expr *pLeft,            /* Left operand */
   850    850     Expr *pRight            /* Right operand */
   851    851   ){
   852    852     Expr *p;
   853         -  if( op==TK_AND && pParse->nErr==0 && !IN_RENAME_OBJECT ){
   854         -    /* Take advantage of short-circuit false optimization for AND */
   855         -    p = sqlite3ExprAnd(pParse->db, pLeft, pRight);
   856         -  }else{
   857    853       p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr));
   858    854       if( p ){
   859    855         memset(p, 0, sizeof(Expr));
   860    856         p->op = op & 0xff;
   861    857         p->iAgg = -1;
   862         -    }
   863    858       sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight);
   864         -  }
   865         -  if( p ) {
   866    859       sqlite3ExprCheckHeight(pParse, p->nHeight);
          860  +  }else{
          861  +    sqlite3ExprDelete(pParse->db, pLeft);
          862  +    sqlite3ExprDelete(pParse->db, pRight);
   867    863     }
   868    864     return p;
   869    865   }
   870    866   
   871    867   /*
   872    868   ** Add pSelect to the Expr.x.pSelect field.  Or, if pExpr is NULL (due
   873    869   ** do a memory allocation failure) then delete the pSelect object.
................................................................................
   915    911   ** Join two expressions using an AND operator.  If either expression is
   916    912   ** NULL, then just return the other expression.
   917    913   **
   918    914   ** If one side or the other of the AND is known to be false, then instead
   919    915   ** of returning an AND expression, just return a constant expression with
   920    916   ** a value of false.
   921    917   */
   922         -Expr *sqlite3ExprAnd(sqlite3 *db, Expr *pLeft, Expr *pRight){
          918  +Expr *sqlite3ExprAnd(Parse *pParse, Expr *pLeft, Expr *pRight){
          919  +  sqlite3 *db = pParse->db;
   923    920     if( pLeft==0 ){
   924    921       return pRight;
   925    922     }else if( pRight==0 ){
   926    923       return pLeft;
          924  +  }else if( pParse->nErr || IN_RENAME_OBJECT ){
          925  +    return sqlite3PExpr(pParse, TK_AND, pLeft, pRight);
   927    926     }else if( exprAlwaysFalse(pLeft) || exprAlwaysFalse(pRight) ){
   928    927       sqlite3ExprDelete(db, pLeft);
   929    928       sqlite3ExprDelete(db, pRight);
   930    929       return sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0], 0);
   931    930     }else{
   932         -    Expr *pNew = sqlite3ExprAlloc(db, TK_AND, 0, 0);
   933         -    sqlite3ExprAttachSubtrees(db, pNew, pLeft, pRight);
   934         -    return pNew;
          931  +    return sqlite3PExpr(pParse, TK_AND, pLeft, pRight);
   935    932     }
   936    933   }
   937    934   
   938    935   /*
   939    936   ** Construct a new expression node for a function with multiple
   940    937   ** arguments.
   941    938   */

Changes to src/fkey.c.

   587    587       iCol = pIdx ? pIdx->aiColumn[i] : -1;
   588    588       pLeft = exprTableRegister(pParse, pTab, regData, iCol);
   589    589       iCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
   590    590       assert( iCol>=0 );
   591    591       zCol = pFKey->pFrom->aCol[iCol].zName;
   592    592       pRight = sqlite3Expr(db, TK_ID, zCol);
   593    593       pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight);
   594         -    pWhere = sqlite3ExprAnd(db, pWhere, pEq);
          594  +    pWhere = sqlite3ExprAnd(pParse, pWhere, pEq);
   595    595     }
   596    596   
   597    597     /* If the child table is the same as the parent table, then add terms
   598    598     ** to the WHERE clause that prevent this entry from being scanned.
   599    599     ** The added WHERE clause terms are like this:
   600    600     **
   601    601     **     $current_rowid!=rowid
................................................................................
   621    621         assert( pIdx!=0 );
   622    622         for(i=0; i<pIdx->nKeyCol; i++){
   623    623           i16 iCol = pIdx->aiColumn[i];
   624    624           assert( iCol>=0 );
   625    625           pLeft = exprTableRegister(pParse, pTab, regData, iCol);
   626    626           pRight = sqlite3Expr(db, TK_ID, pTab->aCol[iCol].zName);
   627    627           pEq = sqlite3PExpr(pParse, TK_IS, pLeft, pRight);
   628         -        pAll = sqlite3ExprAnd(db, pAll, pEq);
          628  +        pAll = sqlite3ExprAnd(pParse, pAll, pEq);
   629    629         }
   630    630         pNe = sqlite3PExpr(pParse, TK_NOT, pAll, 0);
   631    631       }
   632         -    pWhere = sqlite3ExprAnd(db, pWhere, pNe);
          632  +    pWhere = sqlite3ExprAnd(pParse, pWhere, pNe);
   633    633     }
   634    634   
   635    635     /* Resolve the references in the WHERE clause. */
   636    636     memset(&sNameContext, 0, sizeof(NameContext));
   637    637     sNameContext.pSrcList = pSrc;
   638    638     sNameContext.pParse = pParse;
   639    639     sqlite3ResolveExprNames(&sNameContext, pWhere);
................................................................................
  1231   1231         ** parent table are used for the comparison. */
  1232   1232         pEq = sqlite3PExpr(pParse, TK_EQ,
  1233   1233             sqlite3PExpr(pParse, TK_DOT, 
  1234   1234               sqlite3ExprAlloc(db, TK_ID, &tOld, 0),
  1235   1235               sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)),
  1236   1236             sqlite3ExprAlloc(db, TK_ID, &tFromCol, 0)
  1237   1237         );
  1238         -      pWhere = sqlite3ExprAnd(db, pWhere, pEq);
         1238  +      pWhere = sqlite3ExprAnd(pParse, pWhere, pEq);
  1239   1239   
  1240   1240         /* For ON UPDATE, construct the next term of the WHEN clause.
  1241   1241         ** The final WHEN clause will be like this:
  1242   1242         **
  1243   1243         **    WHEN NOT(old.col1 IS new.col1 AND ... AND old.colN IS new.colN)
  1244   1244         */
  1245   1245         if( pChanges ){
................................................................................
  1247   1247               sqlite3PExpr(pParse, TK_DOT, 
  1248   1248                 sqlite3ExprAlloc(db, TK_ID, &tOld, 0),
  1249   1249                 sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)),
  1250   1250               sqlite3PExpr(pParse, TK_DOT, 
  1251   1251                 sqlite3ExprAlloc(db, TK_ID, &tNew, 0),
  1252   1252                 sqlite3ExprAlloc(db, TK_ID, &tToCol, 0))
  1253   1253               );
  1254         -        pWhen = sqlite3ExprAnd(db, pWhen, pEq);
         1254  +        pWhen = sqlite3ExprAnd(pParse, pWhen, pEq);
  1255   1255         }
  1256   1256     
  1257   1257         if( action!=OE_Restrict && (action!=OE_Cascade || pChanges) ){
  1258   1258           Expr *pNew;
  1259   1259           if( action==OE_Cascade ){
  1260   1260             pNew = sqlite3PExpr(pParse, TK_DOT, 
  1261   1261               sqlite3ExprAlloc(db, TK_ID, &tNew, 0),

Changes to src/parse.y.

  1060   1060     if( A ){
  1061   1061       A->x.pList = pList;
  1062   1062     }else{
  1063   1063       sqlite3ExprListDelete(pParse->db, pList);
  1064   1064     }
  1065   1065   }
  1066   1066   
  1067         -expr(A) ::= expr(A) AND(OP) expr(Y).    {A=sqlite3PExpr(pParse,@OP,A,Y);}
         1067  +expr(A) ::= expr(A) AND expr(Y).        {A=sqlite3ExprAnd(pParse,A,Y);}
  1068   1068   expr(A) ::= expr(A) OR(OP) expr(Y).     {A=sqlite3PExpr(pParse,@OP,A,Y);}
  1069   1069   expr(A) ::= expr(A) LT|GT|GE|LE(OP) expr(Y).
  1070   1070                                           {A=sqlite3PExpr(pParse,@OP,A,Y);}
  1071   1071   expr(A) ::= expr(A) EQ|NE(OP) expr(Y).  {A=sqlite3PExpr(pParse,@OP,A,Y);}
  1072   1072   expr(A) ::= expr(A) BITAND|BITOR|LSHIFT|RSHIFT(OP) expr(Y).
  1073   1073                                           {A=sqlite3PExpr(pParse,@OP,A,Y);}
  1074   1074   expr(A) ::= expr(A) PLUS|MINUS(OP) expr(Y).

Changes to src/select.c.

   351    351     pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2);
   352    352     if( pEq && isOuterJoin ){
   353    353       ExprSetProperty(pEq, EP_FromJoin);
   354    354       assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) );
   355    355       ExprSetVVAProperty(pEq, EP_NoReduce);
   356    356       pEq->iRightJoinTable = (i16)pE2->iTable;
   357    357     }
   358         -  *ppWhere = sqlite3ExprAnd(db, *ppWhere, pEq);
          358  +  *ppWhere = sqlite3ExprAnd(pParse, *ppWhere, pEq);
   359    359   }
   360    360   
   361    361   /*
   362    362   ** Set the EP_FromJoin property on all terms of the given expression.
   363    363   ** And set the Expr.iRightJoinTable to iTable for every term in the
   364    364   ** expression.
   365    365   **
................................................................................
   485    485       }
   486    486   
   487    487       /* Add the ON clause to the end of the WHERE clause, connected by
   488    488       ** an AND operator.
   489    489       */
   490    490       if( pRight->pOn ){
   491    491         if( isOuter ) setJoinExpr(pRight->pOn, pRight->iCursor);
   492         -      p->pWhere = sqlite3ExprAnd(pParse->db, p->pWhere, pRight->pOn);
          492  +      p->pWhere = sqlite3ExprAnd(pParse, p->pWhere, pRight->pOn);
   493    493         pRight->pOn = 0;
   494    494       }
   495    495   
   496    496       /* Create extra terms on the WHERE clause for each column named
   497    497       ** in the USING clause.  Example: If the two tables to be joined are 
   498    498       ** A and B and the USING clause names X, Y, and Z, then add this
   499    499       ** to the WHERE clause:    A.X=B.X AND A.Y=B.Y AND A.Z=B.Z
................................................................................
  4030   4030         pSub->pOrderBy = 0;
  4031   4031       }
  4032   4032       pWhere = pSub->pWhere;
  4033   4033       pSub->pWhere = 0;
  4034   4034       if( isLeftJoin>0 ){
  4035   4035         setJoinExpr(pWhere, iNewParent);
  4036   4036       }
  4037         -    pParent->pWhere = sqlite3ExprAnd(db, pWhere, pParent->pWhere);
         4037  +    pParent->pWhere = sqlite3ExprAnd(pParse, pWhere, pParent->pWhere);
  4038   4038       if( db->mallocFailed==0 ){
  4039   4039         SubstContext x;
  4040   4040         x.pParse = pParse;
  4041   4041         x.iTable = iParent;
  4042   4042         x.iNewTable = iNewParent;
  4043   4043         x.isLeftJoin = isLeftJoin;
  4044   4044         x.pEList = pSub->pEList;
................................................................................
  4365   4365         x.pParse = pParse;
  4366   4366         x.iTable = iCursor;
  4367   4367         x.iNewTable = iCursor;
  4368   4368         x.isLeftJoin = 0;
  4369   4369         x.pEList = pSubq->pEList;
  4370   4370         pNew = substExpr(&x, pNew);
  4371   4371         if( pSubq->selFlags & SF_Aggregate ){
  4372         -        pSubq->pHaving = sqlite3ExprAnd(pParse->db, pSubq->pHaving, pNew);
         4372  +        pSubq->pHaving = sqlite3ExprAnd(pParse, pSubq->pHaving, pNew);
  4373   4373         }else{
  4374         -        pSubq->pWhere = sqlite3ExprAnd(pParse->db, pSubq->pWhere, pNew);
         4374  +        pSubq->pWhere = sqlite3ExprAnd(pParse, pSubq->pWhere, pNew);
  4375   4375         }
  4376   4376         pSubq = pSubq->pPrior;
  4377   4377       }
  4378   4378     }
  4379   4379     return nChng;
  4380   4380   }
  4381   4381   #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
................................................................................
  5414   5414       Select *pS = pWalker->u.pSelect;
  5415   5415       if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, pS->pGroupBy) ){
  5416   5416         sqlite3 *db = pWalker->pParse->db;
  5417   5417         Expr *pNew = sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[1], 0);
  5418   5418         if( pNew ){
  5419   5419           Expr *pWhere = pS->pWhere;
  5420   5420           SWAP(Expr, *pNew, *pExpr);
  5421         -        pNew = sqlite3ExprAnd(db, pWhere, pNew);
         5421  +        pNew = sqlite3ExprAnd(pWalker->pParse, pWhere, pNew);
  5422   5422           pS->pWhere = pNew;
  5423   5423           pWalker->eCode = 1;
  5424   5424         }
  5425   5425       }
  5426   5426       return WRC_Prune;
  5427   5427     }
  5428   5428     return WRC_Continue;

Changes to src/sqliteInt.h.

  3850   3850   int sqlite3NoTempsInRange(Parse*,int,int);
  3851   3851   #endif
  3852   3852   Expr *sqlite3ExprAlloc(sqlite3*,int,const Token*,int);
  3853   3853   Expr *sqlite3Expr(sqlite3*,int,const char*);
  3854   3854   void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*);
  3855   3855   Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*);
  3856   3856   void sqlite3PExprAddSelect(Parse*, Expr*, Select*);
  3857         -Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*);
         3857  +Expr *sqlite3ExprAnd(Parse*,Expr*, Expr*);
  3858   3858   Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*, int);
  3859   3859   void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
  3860   3860   void sqlite3ExprDelete(sqlite3*, Expr*);
  3861   3861   ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
  3862   3862   ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
  3863   3863   void sqlite3ExprListSetSortOrder(ExprList*,int);
  3864   3864   void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);

Changes to src/where.c.

   733    733       assert( !ExprHasProperty(pExpr, EP_FromJoin)    /* prereq always non-zero */
   734    734            || pExpr->iRightJoinTable!=pSrc->iCursor   /*   for the right-hand   */
   735    735            || pLoop->prereq!=0 );                     /*   table of a LEFT JOIN */
   736    736       if( pLoop->prereq==0
   737    737        && (pTerm->wtFlags & TERM_VIRTUAL)==0
   738    738        && !ExprHasProperty(pExpr, EP_FromJoin)
   739    739        && sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor) ){
   740         -      pPartial = sqlite3ExprAnd(pParse->db, pPartial,
          740  +      pPartial = sqlite3ExprAnd(pParse, pPartial,
   741    741                                   sqlite3ExprDup(pParse->db, pExpr, 0));
   742    742       }
   743    743       if( termCanDriveIndex(pTerm, pSrc, notReady) ){
   744    744         int iCol = pTerm->u.leftColumn;
   745    745         Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);
   746    746         testcase( iCol==BMS );
   747    747         testcase( iCol==BMS-1 );

Changes to src/wherecode.c.

   995    995         sWalker.eCode = 0;
   996    996         sWalker.xExprCallback = codeCursorHintCheckExpr;
   997    997         sqlite3WalkExpr(&sWalker, pTerm->pExpr);
   998    998         if( sWalker.eCode ) continue;
   999    999       }
  1000   1000   
  1001   1001       /* If we survive all prior tests, that means this term is worth hinting */
  1002         -    pExpr = sqlite3ExprAnd(db, pExpr, sqlite3ExprDup(db, pTerm->pExpr, 0));
         1002  +    pExpr = sqlite3ExprAnd(pParse, pExpr, sqlite3ExprDup(db, pTerm->pExpr, 0));
  1003   1003     }
  1004   1004     if( pExpr!=0 ){
  1005   1005       sWalker.xExprCallback = codeCursorHintFixExpr;
  1006   1006       sqlite3WalkExpr(&sWalker, pExpr);
  1007   1007       sqlite3VdbeAddOp4(v, OP_CursorHint, 
  1008   1008                         (sHint.pIdx ? sHint.iIdxCur : sHint.iTabCur), 0, 0,
  1009   1009                         (const char*)pExpr, P4_EXPR);
................................................................................
  1960   1960           if( &pWC->a[iTerm] == pTerm ) continue;
  1961   1961           testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL );
  1962   1962           testcase( pWC->a[iTerm].wtFlags & TERM_CODED );
  1963   1963           if( (pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_CODED))!=0 ) continue;
  1964   1964           if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
  1965   1965           testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO );
  1966   1966           pExpr = sqlite3ExprDup(db, pExpr, 0);
  1967         -        pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr);
         1967  +        pAndExpr = sqlite3ExprAnd(pParse, pAndExpr, pExpr);
  1968   1968         }
  1969   1969         if( pAndExpr ){
  1970   1970           /* The extra 0x10000 bit on the opcode is masked off and does not
  1971   1971           ** become part of the new Expr.op.  However, it does make the
  1972   1972           ** op==TK_AND comparison inside of sqlite3PExpr() false, and this
  1973   1973           ** prevents sqlite3PExpr() from implementing AND short-circuit 
  1974   1974           ** optimization, which we do not want here. */