using System; using System.Diagnostics; using System.Text; using Bitmask = System.UInt64; using u32 = System.UInt32; namespace Community.CsharpSqlite { public partial class Sqlite3 { /* ** 2008 August 16 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for walking the parser tree for ** an SQL statement. ************************************************************************* ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart ** C#-SQLite is an independent reimplementation of the SQLite software library ** ** SQLITE_SOURCE_ID: 2010-08-23 18:52:01 42537b60566f288167f1b5864a5435986838e3a3 ** ************************************************************************* */ //#include "sqliteInt.h" //#include //#include /* ** Walk an expression tree. Invoke the callback once for each node ** of the expression, while decending. (In other words, the callback ** is invoked before visiting children.) ** ** The return value from the callback should be one of the WRC_* ** constants to specify how to proceed with the walk. ** ** WRC_Continue Continue descending down the tree. ** ** WRC_Prune Do not descend into child nodes. But allow ** the walk to continue with sibling nodes. ** ** WRC_Abort Do no more callbacks. Unwind the stack and ** return the top-level walk call. ** ** The return value from this routine is WRC_Abort to abandon the tree walk ** and WRC_Continue to continue. */ static int sqlite3WalkExpr( Walker pWalker, ref Expr pExpr ) { int rc; if ( pExpr == null ) return WRC_Continue; testcase( ExprHasProperty( pExpr, EP_TokenOnly ) ); testcase( ExprHasProperty( pExpr, EP_Reduced ) ); rc = pWalker.xExprCallback( pWalker, ref pExpr ); if ( rc == WRC_Continue && !ExprHasAnyProperty( pExpr, EP_TokenOnly ) ) { if ( sqlite3WalkExpr( pWalker, ref pExpr.pLeft ) != 0 ) return WRC_Abort; if ( sqlite3WalkExpr( pWalker, ref pExpr.pRight ) != 0 ) return WRC_Abort; if ( ExprHasProperty( pExpr, EP_xIsSelect ) ) { if ( sqlite3WalkSelect( pWalker, pExpr.x.pSelect ) != 0 ) return WRC_Abort; } else { if ( sqlite3WalkExprList( pWalker, pExpr.x.pList ) != 0 ) return WRC_Abort; } } return rc & WRC_Abort; } /* ** Call sqlite3WalkExpr() for every expression in list p or until ** an abort request is seen. */ static int sqlite3WalkExprList( Walker pWalker, ExprList p ) { int i; ExprList_item pItem; if ( p != null ) { for ( i = p.nExpr; i > 0; i-- ) {//, pItem++){ pItem = p.a[p.nExpr - i]; if ( sqlite3WalkExpr( pWalker, ref pItem.pExpr ) != 0 ) return WRC_Abort; } } return WRC_Continue; } /* ** Walk all expressions associated with SELECT statement p. Do ** not invoke the SELECT callback on p, but do (of course) invoke ** any expr callbacks and SELECT callbacks that come from subqueries. ** Return WRC_Abort or WRC_Continue. */ static int sqlite3WalkSelectExpr( Walker pWalker, Select p ) { if ( sqlite3WalkExprList( pWalker, p.pEList ) != 0 ) return WRC_Abort; if ( sqlite3WalkExpr( pWalker, ref p.pWhere ) != 0 ) return WRC_Abort; if ( sqlite3WalkExprList( pWalker, p.pGroupBy ) != 0 ) return WRC_Abort; if ( sqlite3WalkExpr( pWalker, ref p.pHaving ) != 0 ) return WRC_Abort; if ( sqlite3WalkExprList( pWalker, p.pOrderBy ) != 0 ) return WRC_Abort; if ( sqlite3WalkExpr( pWalker, ref p.pLimit ) != 0 ) return WRC_Abort; if ( sqlite3WalkExpr( pWalker, ref p.pOffset ) != 0 ) return WRC_Abort; return WRC_Continue; } /* ** Walk the parse trees associated with all subqueries in the ** FROM clause of SELECT statement p. Do not invoke the select ** callback on p, but do invoke it on each FROM clause subquery ** and on any subqueries further down in the tree. Return ** WRC_Abort or WRC_Continue; */ static int sqlite3WalkSelectFrom( Walker pWalker, Select p ) { SrcList pSrc; int i; SrcList_item pItem; pSrc = p.pSrc; if ( ALWAYS( pSrc ) ) { for ( i = pSrc.nSrc; i > 0; i-- )// pItem++ ) { pItem = pSrc.a[pSrc.nSrc - i]; if ( sqlite3WalkSelect( pWalker, pItem.pSelect ) != 0 ) { return WRC_Abort; } } } return WRC_Continue; } /* ** Call sqlite3WalkExpr() for every expression in Select statement p. ** Invoke sqlite3WalkSelect() for subqueries in the FROM clause and ** on the compound select chain, p.pPrior. ** ** Return WRC_Continue under normal conditions. Return WRC_Abort if ** there is an abort request. ** ** If the Walker does not have an xSelectCallback() then this routine ** is a no-op returning WRC_Continue. */ static int sqlite3WalkSelect( Walker pWalker, Select p ) { int rc; if ( p == null || pWalker.xSelectCallback == null ) return WRC_Continue; rc = WRC_Continue; while ( p != null ) { rc = pWalker.xSelectCallback( pWalker, p ); if ( rc != 0 ) break; if ( sqlite3WalkSelectExpr( pWalker, p ) != 0 ) return WRC_Abort; if ( sqlite3WalkSelectFrom( pWalker, p ) != 0 ) return WRC_Abort; p = p.pPrior; } return rc & WRC_Abort; } } }