modernc.org/cc@v1.0.1/v2/testdata/_sqlite/src/walker.c (about)

     1  /*
     2  ** 2008 August 16
     3  **
     4  ** The author disclaims copyright to this source code.  In place of
     5  ** a legal notice, here is a blessing:
     6  **
     7  **    May you do good and not evil.
     8  **    May you find forgiveness for yourself and forgive others.
     9  **    May you share freely, never taking more than you give.
    10  **
    11  *************************************************************************
    12  ** This file contains routines used for walking the parser tree for
    13  ** an SQL statement.
    14  */
    15  #include "sqliteInt.h"
    16  #include <stdlib.h>
    17  #include <string.h>
    18  
    19  
    20  /*
    21  ** Walk an expression tree.  Invoke the callback once for each node
    22  ** of the expression, while descending.  (In other words, the callback
    23  ** is invoked before visiting children.)
    24  **
    25  ** The return value from the callback should be one of the WRC_*
    26  ** constants to specify how to proceed with the walk.
    27  **
    28  **    WRC_Continue      Continue descending down the tree.
    29  **
    30  **    WRC_Prune         Do not descend into child nodes, but allow
    31  **                      the walk to continue with sibling nodes.
    32  **
    33  **    WRC_Abort         Do no more callbacks.  Unwind the stack and
    34  **                      return from the top-level walk call.
    35  **
    36  ** The return value from this routine is WRC_Abort to abandon the tree walk
    37  ** and WRC_Continue to continue.
    38  */
    39  static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){
    40    int rc;
    41    testcase( ExprHasProperty(pExpr, EP_TokenOnly) );
    42    testcase( ExprHasProperty(pExpr, EP_Reduced) );
    43    while(1){
    44      rc = pWalker->xExprCallback(pWalker, pExpr);
    45      if( rc ) return rc & WRC_Abort;
    46      if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){
    47        if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
    48         assert( pExpr->x.pList==0 || pExpr->pRight==0 );
    49        if( pExpr->pRight ){
    50          pExpr = pExpr->pRight;
    51          continue;
    52        }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
    53          if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
    54        }else if( pExpr->x.pList ){
    55          if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
    56        }
    57      }
    58      break;
    59    }
    60    return WRC_Continue;
    61  }
    62  int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){
    63    return pExpr ? walkExpr(pWalker,pExpr) : WRC_Continue;
    64  }
    65  
    66  /*
    67  ** Call sqlite3WalkExpr() for every expression in list p or until
    68  ** an abort request is seen.
    69  */
    70  int sqlite3WalkExprList(Walker *pWalker, ExprList *p){
    71    int i;
    72    struct ExprList_item *pItem;
    73    if( p ){
    74      for(i=p->nExpr, pItem=p->a; i>0; i--, pItem++){
    75        if( sqlite3WalkExpr(pWalker, pItem->pExpr) ) return WRC_Abort;
    76      }
    77    }
    78    return WRC_Continue;
    79  }
    80  
    81  /*
    82  ** Walk all expressions associated with SELECT statement p.  Do
    83  ** not invoke the SELECT callback on p, but do (of course) invoke
    84  ** any expr callbacks and SELECT callbacks that come from subqueries.
    85  ** Return WRC_Abort or WRC_Continue.
    86  */
    87  int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
    88    if( sqlite3WalkExprList(pWalker, p->pEList) ) return WRC_Abort;
    89    if( sqlite3WalkExpr(pWalker, p->pWhere) ) return WRC_Abort;
    90    if( sqlite3WalkExprList(pWalker, p->pGroupBy) ) return WRC_Abort;
    91    if( sqlite3WalkExpr(pWalker, p->pHaving) ) return WRC_Abort;
    92    if( sqlite3WalkExprList(pWalker, p->pOrderBy) ) return WRC_Abort;
    93    if( sqlite3WalkExpr(pWalker, p->pLimit) ) return WRC_Abort;
    94    if( sqlite3WalkExpr(pWalker, p->pOffset) ) return WRC_Abort;
    95    return WRC_Continue;
    96  }
    97  
    98  /*
    99  ** Walk the parse trees associated with all subqueries in the
   100  ** FROM clause of SELECT statement p.  Do not invoke the select
   101  ** callback on p, but do invoke it on each FROM clause subquery
   102  ** and on any subqueries further down in the tree.  Return 
   103  ** WRC_Abort or WRC_Continue;
   104  */
   105  int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
   106    SrcList *pSrc;
   107    int i;
   108    struct SrcList_item *pItem;
   109  
   110    pSrc = p->pSrc;
   111    if( ALWAYS(pSrc) ){
   112      for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
   113        if( pItem->pSelect && sqlite3WalkSelect(pWalker, pItem->pSelect) ){
   114          return WRC_Abort;
   115        }
   116        if( pItem->fg.isTabFunc
   117         && sqlite3WalkExprList(pWalker, pItem->u1.pFuncArg)
   118        ){
   119          return WRC_Abort;
   120        }
   121      }
   122    }
   123    return WRC_Continue;
   124  } 
   125  
   126  /*
   127  ** Call sqlite3WalkExpr() for every expression in Select statement p.
   128  ** Invoke sqlite3WalkSelect() for subqueries in the FROM clause and
   129  ** on the compound select chain, p->pPrior. 
   130  **
   131  ** If it is not NULL, the xSelectCallback() callback is invoked before
   132  ** the walk of the expressions and FROM clause. The xSelectCallback2()
   133  ** method is invoked following the walk of the expressions and FROM clause,
   134  ** but only if both xSelectCallback and xSelectCallback2 are both non-NULL
   135  ** and if the expressions and FROM clause both return WRC_Continue;
   136  **
   137  ** Return WRC_Continue under normal conditions.  Return WRC_Abort if
   138  ** there is an abort request.
   139  **
   140  ** If the Walker does not have an xSelectCallback() then this routine
   141  ** is a no-op returning WRC_Continue.
   142  */
   143  int sqlite3WalkSelect(Walker *pWalker, Select *p){
   144    int rc;
   145    if( p==0 ) return WRC_Continue;
   146    if( pWalker->xSelectCallback==0 ) return WRC_Continue;
   147    do{
   148      rc = pWalker->xSelectCallback(pWalker, p);
   149      if( rc ) return rc & WRC_Abort;
   150      if( sqlite3WalkSelectExpr(pWalker, p)
   151       || sqlite3WalkSelectFrom(pWalker, p)
   152      ){
   153        return WRC_Abort;
   154      }
   155      if( pWalker->xSelectCallback2 ){
   156        pWalker->xSelectCallback2(pWalker, p);
   157      }
   158      p = p->pPrior;
   159    }while( p!=0 );
   160    return WRC_Continue;
   161  }