/ Check-in [6854a34e]
Login

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

Overview
Comment:Optimizations to the Walker object and its methods to make the code a little smaller and to help it run a little faster.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 6854a34ed708259f2280f7ee56cec09f7fc99810dc739dc2814ddeae286aa2c4
User & Date: drh 2017-05-29 14:26:07
Context
2017-05-29
14:30
Fix a typo in a comment. No code changes. check-in: cb29b838 user: drh tags: trunk
14:26
Optimizations to the Walker object and its methods to make the code a little smaller and to help it run a little faster. check-in: 6854a34e user: drh tags: trunk
13:09
Correctly initialize the iSelectId of FROM clause terms that are a self join of a reused materialized subquery. Without this, the EXPLAIN QUERY PLAN output for the query will identify the subquery using the uninitialized (and arbitrary) iSelectId. check-in: 43c9ae37 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/expr.c.

  1768   1768   static int selectNodeIsConstant(Walker *pWalker, Select *NotUsed){
  1769   1769     UNUSED_PARAMETER(NotUsed);
  1770   1770     pWalker->eCode = 0;
  1771   1771     return WRC_Abort;
  1772   1772   }
  1773   1773   static int exprIsConst(Expr *p, int initFlag, int iCur){
  1774   1774     Walker w;
  1775         -  memset(&w, 0, sizeof(w));
  1776   1775     w.eCode = initFlag;
  1777   1776     w.xExprCallback = exprNodeIsConstant;
  1778   1777     w.xSelectCallback = selectNodeIsConstant;
         1778  +#ifdef SQLITE_DEBUG
         1779  +  w.xSelectCallback2 = sqlite3SelectWalkAssert2;
         1780  +#endif
  1779   1781     w.u.iCur = iCur;
  1780   1782     sqlite3WalkExpr(&w, p);
  1781   1783     return w.eCode;
  1782   1784   }
  1783   1785   
  1784   1786   /*
  1785   1787   ** Walk an expression tree.  Return non-zero if the expression is constant
................................................................................
  1859   1861   ** sequence as the GROUP BY term, but that is much harder to check,
  1860   1862   ** alternative collating sequences are uncommon, and this is only an
  1861   1863   ** optimization, so we take the easy way out and simply require the
  1862   1864   ** GROUP BY to use the BINARY collating sequence.
  1863   1865   */
  1864   1866   int sqlite3ExprIsConstantOrGroupBy(Parse *pParse, Expr *p, ExprList *pGroupBy){
  1865   1867     Walker w;
  1866         -  memset(&w, 0, sizeof(w));
  1867   1868     w.eCode = 1;
  1868   1869     w.xExprCallback = exprNodeIsConstantOrGroupBy;
         1870  +  w.xSelectCallback = 0;
  1869   1871     w.u.pGroupBy = pGroupBy;
  1870   1872     w.pParse = pParse;
  1871   1873     sqlite3WalkExpr(&w, p);
  1872   1874     return w.eCode;
  1873   1875   }
  1874   1876   
  1875   1877   /*
................................................................................
  1889   1891   #ifdef SQLITE_ENABLE_CURSOR_HINTS
  1890   1892   /*
  1891   1893   ** Walk an expression tree.  Return 1 if the expression contains a
  1892   1894   ** subquery of some kind.  Return 0 if there are no subqueries.
  1893   1895   */
  1894   1896   int sqlite3ExprContainsSubquery(Expr *p){
  1895   1897     Walker w;
  1896         -  memset(&w, 0, sizeof(w));
  1897   1898     w.eCode = 1;
  1898   1899     w.xExprCallback = sqlite3ExprWalkNoop;
  1899   1900     w.xSelectCallback = selectNodeIsConstant;
         1901  +#ifdef SQLITE_DEBUG
         1902  +  w.xSelectCallback2 = sqlite3SelectWalkAssert2;
         1903  +#endif
  1900   1904     sqlite3WalkExpr(&w, p);
  1901   1905     return w.eCode==0;
  1902   1906   }
  1903   1907   #endif
  1904   1908   
  1905   1909   /*
  1906   1910   ** If the expression p codes a constant integer that is small enough
................................................................................
  4897   4901   ** has no arguments or has only constant arguments.  Return false if pExpr
  4898   4902   ** references columns but not columns of tables found in pSrcList.
  4899   4903   */
  4900   4904   int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){
  4901   4905     Walker w;
  4902   4906     struct SrcCount cnt;
  4903   4907     assert( pExpr->op==TK_AGG_FUNCTION );
  4904         -  memset(&w, 0, sizeof(w));
  4905   4908     w.xExprCallback = exprSrcCount;
         4909  +  w.xSelectCallback = 0;
  4906   4910     w.u.pSrcCount = &cnt;
  4907   4911     cnt.pSrc = pSrcList;
  4908   4912     cnt.nThis = 0;
  4909   4913     cnt.nOther = 0;
  4910   4914     sqlite3WalkExprList(&w, pExpr->x.pList);
  4911   4915     return cnt.nThis>0 || cnt.nOther==0;
  4912   4916   }
................................................................................
  5070   5074           return WRC_Continue;
  5071   5075         }
  5072   5076       }
  5073   5077     }
  5074   5078     return WRC_Continue;
  5075   5079   }
  5076   5080   static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
  5077         -  UNUSED_PARAMETER(pWalker);
  5078   5081     UNUSED_PARAMETER(pSelect);
         5082  +  pWalker->walkerDepth++;
  5079   5083     return WRC_Continue;
         5084  +}
         5085  +static void analyzeAggregatesInSelectEnd(Walker *pWalker, Select *pSelect){
         5086  +  UNUSED_PARAMETER(pSelect);
         5087  +  pWalker->walkerDepth--;
  5080   5088   }
  5081   5089   
  5082   5090   /*
  5083   5091   ** Analyze the pExpr expression looking for aggregate functions and
  5084   5092   ** for variables that need to be added to AggInfo object that pNC->pAggInfo
  5085   5093   ** points to.  Additional entries are made on the AggInfo object as
  5086   5094   ** necessary.
  5087   5095   **
  5088   5096   ** This routine should only be called after the expression has been
  5089   5097   ** analyzed by sqlite3ResolveExprNames().
  5090   5098   */
  5091   5099   void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
  5092   5100     Walker w;
  5093         -  memset(&w, 0, sizeof(w));
  5094   5101     w.xExprCallback = analyzeAggregate;
  5095   5102     w.xSelectCallback = analyzeAggregatesInSelect;
         5103  +  w.xSelectCallback2 = analyzeAggregatesInSelectEnd;
         5104  +  w.walkerDepth = 0;
  5096   5105     w.u.pNC = pNC;
  5097   5106     assert( pNC->pSrcList!=0 );
  5098   5107     sqlite3WalkExpr(&w, pExpr);
  5099   5108   }
  5100   5109   
  5101   5110   /*
  5102   5111   ** Call sqlite3ExprAnalyzeAggregates() for every expression in an

Changes to src/resolve.c.

  1442   1442   #endif
  1443   1443     savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg);
  1444   1444     pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg);
  1445   1445     w.pParse = pNC->pParse;
  1446   1446     w.xExprCallback = resolveExprStep;
  1447   1447     w.xSelectCallback = resolveSelectStep;
  1448   1448     w.xSelectCallback2 = 0;
  1449         -  w.walkerDepth = 0;
  1450         -  w.eCode = 0;
  1451   1449     w.u.pNC = pNC;
  1452   1450     sqlite3WalkExpr(&w, pExpr);
  1453   1451   #if SQLITE_MAX_EXPR_DEPTH>0
  1454   1452     pNC->pParse->nHeight -= pExpr->nHeight;
  1455   1453   #endif
  1456   1454     if( pNC->nErr>0 || w.pParse->nErr>0 ){
  1457   1455       ExprSetProperty(pExpr, EP_Error);
................................................................................
  1497   1495     Parse *pParse,         /* The parser context */
  1498   1496     Select *p,             /* The SELECT statement being coded. */
  1499   1497     NameContext *pOuterNC  /* Name context for parent SELECT statement */
  1500   1498   ){
  1501   1499     Walker w;
  1502   1500   
  1503   1501     assert( p!=0 );
  1504         -  memset(&w, 0, sizeof(w));
  1505   1502     w.xExprCallback = resolveExprStep;
  1506   1503     w.xSelectCallback = resolveSelectStep;
         1504  +  w.xSelectCallback2 = 0;
  1507   1505     w.pParse = pParse;
  1508   1506     w.u.pNC = pOuterNC;
  1509   1507     sqlite3WalkSelect(&w, p);
  1510   1508   }
  1511   1509   
  1512   1510   /*
  1513   1511   ** Resolve names in expressions that can only reference a single table:

Changes to src/select.c.

  4606   4606   ** subquery in the parser tree.
  4607   4607   */
  4608   4608   int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
  4609   4609     UNUSED_PARAMETER2(NotUsed, NotUsed2);
  4610   4610     return WRC_Continue;
  4611   4611   }
  4612   4612   
         4613  +/*
         4614  +** No-op routine for the parse-tree walker for SELECT statements.
         4615  +** subquery in the parser tree.
         4616  +*/
         4617  +int sqlite3SelectWalkNoop(Walker *NotUsed, Select *NotUsed2){
         4618  +  UNUSED_PARAMETER2(NotUsed, NotUsed2);
         4619  +  return WRC_Continue;
         4620  +}
         4621  +
         4622  +#if SQLITE_DEBUG
         4623  +/*
         4624  +** Always assert.  This xSelectCallback2 implementation proves that the
         4625  +** xSelectCallback2 is never invoked.
         4626  +*/
         4627  +void sqlite3SelectWalkAssert2(Walker *NotUsed, Select *NotUsed2){
         4628  +  UNUSED_PARAMETER2(NotUsed, NotUsed2);
         4629  +  assert( 0 );
         4630  +}
         4631  +#endif
  4613   4632   /*
  4614   4633   ** This routine "expands" a SELECT statement and all of its subqueries.
  4615   4634   ** For additional information on what it means to "expand" a SELECT
  4616   4635   ** statement, see the comment on the selectExpand worker callback above.
  4617   4636   **
  4618   4637   ** Expanding a SELECT statement is the first step in processing a
  4619   4638   ** SELECT statement.  The SELECT statement must be expanded before
................................................................................
  4621   4640   **
  4622   4641   ** If anything goes wrong, an error message is written into pParse.
  4623   4642   ** The calling function can detect the problem by looking at pParse->nErr
  4624   4643   ** and/or pParse->db->mallocFailed.
  4625   4644   */
  4626   4645   static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
  4627   4646     Walker w;
  4628         -  memset(&w, 0, sizeof(w));
  4629   4647     w.xExprCallback = sqlite3ExprWalkNoop;
  4630   4648     w.pParse = pParse;
  4631   4649     if( pParse->hasCompound ){
  4632   4650       w.xSelectCallback = convertCompoundSelectToSubquery;
         4651  +    w.xSelectCallback2 = 0;
  4633   4652       sqlite3WalkSelect(&w, pSelect);
  4634   4653     }
  4635   4654     w.xSelectCallback = selectExpander;
  4636   4655     w.xSelectCallback2 = selectPopWith;
  4637   4656     sqlite3WalkSelect(&w, pSelect);
  4638   4657   }
  4639   4658   
................................................................................
  4685   4704   ** SELECT statement.
  4686   4705   **
  4687   4706   ** Use this routine after name resolution.
  4688   4707   */
  4689   4708   static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){
  4690   4709   #ifndef SQLITE_OMIT_SUBQUERY
  4691   4710     Walker w;
  4692         -  memset(&w, 0, sizeof(w));
         4711  +  w.xSelectCallback = sqlite3SelectWalkNoop;
  4693   4712     w.xSelectCallback2 = selectAddSubqueryTypeInfo;
  4694   4713     w.xExprCallback = sqlite3ExprWalkNoop;
  4695   4714     w.pParse = pParse;
  4696   4715     sqlite3WalkSelect(&w, pSelect);
  4697   4716   #endif
  4698   4717   }
  4699   4718   

Changes to src/sqliteInt.h.

  3333   3333   /* Forward declarations */
  3334   3334   int sqlite3WalkExpr(Walker*, Expr*);
  3335   3335   int sqlite3WalkExprList(Walker*, ExprList*);
  3336   3336   int sqlite3WalkSelect(Walker*, Select*);
  3337   3337   int sqlite3WalkSelectExpr(Walker*, Select*);
  3338   3338   int sqlite3WalkSelectFrom(Walker*, Select*);
  3339   3339   int sqlite3ExprWalkNoop(Walker*, Expr*);
         3340  +int sqlite3SelectWalkNoop(Walker*, Select*);
         3341  +#ifdef SQLITE_DEBUG
         3342  +void sqlite3SelectWalkAssert2(Walker*, Select*);
         3343  +#endif
  3340   3344   
  3341   3345   /*
  3342   3346   ** Return code from the parse-tree walking primitives and their
  3343   3347   ** callbacks.
  3344   3348   */
  3345   3349   #define WRC_Continue    0   /* Continue down into children */
  3346   3350   #define WRC_Prune       1   /* Omit children but continue walking siblings */

Changes to src/walker.c.

   120    120   /*
   121    121   ** Call sqlite3WalkExpr() for every expression in Select statement p.
   122    122   ** Invoke sqlite3WalkSelect() for subqueries in the FROM clause and
   123    123   ** on the compound select chain, p->pPrior. 
   124    124   **
   125    125   ** If it is not NULL, the xSelectCallback() callback is invoked before
   126    126   ** the walk of the expressions and FROM clause. The xSelectCallback2()
   127         -** method, if it is not NULL, is invoked following the walk of the 
   128         -** expressions and FROM clause.
          127  +** method is invoked following the walk of the expressions and FROM clause,
          128  +** but only if both xSelectCallback and xSelectCallback2 are both non-NULL
          129  +** and if the expressions and FROM clause both return WRC_Continue;
   129    130   **
   130    131   ** Return WRC_Continue under normal conditions.  Return WRC_Abort if
   131    132   ** there is an abort request.
   132    133   **
   133    134   ** If the Walker does not have an xSelectCallback() then this routine
   134    135   ** is a no-op returning WRC_Continue.
   135    136   */
   136    137   int sqlite3WalkSelect(Walker *pWalker, Select *p){
   137    138     int rc;
   138         -  if( p==0 || (pWalker->xSelectCallback==0 && pWalker->xSelectCallback2==0) ){
   139         -    return WRC_Continue;
   140         -  }
   141         -  rc = WRC_Continue;
   142         -  pWalker->walkerDepth++;
   143         -  while( p ){
   144         -    if( pWalker->xSelectCallback ){
   145         -       rc = pWalker->xSelectCallback(pWalker, p);
   146         -       if( rc ) break;
   147         -    }
          139  +  if( p==0 || pWalker->xSelectCallback==0 ) return WRC_Continue;
          140  +  do{
          141  +    rc = pWalker->xSelectCallback(pWalker, p);
          142  +    if( rc ) return rc & WRC_Abort;
   148    143       if( sqlite3WalkSelectExpr(pWalker, p)
   149    144        || sqlite3WalkSelectFrom(pWalker, p)
   150    145       ){
   151         -      pWalker->walkerDepth--;
   152    146         return WRC_Abort;
   153    147       }
   154    148       if( pWalker->xSelectCallback2 ){
   155    149         pWalker->xSelectCallback2(pWalker, p);
   156    150       }
   157    151       p = p->pPrior;
   158         -  }
   159         -  pWalker->walkerDepth--;
   160         -  return rc & WRC_Abort;
          152  +  }while( p!=0 );
          153  +  return WRC_Continue;
   161    154   }