187 lines
No EOL
5.4 KiB
C#
187 lines
No EOL
5.4 KiB
C#
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 <stdlib.h>
|
|
//#include <string.h>
|
|
|
|
/*
|
|
** 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.
|
|
*/
|
|
|
|
private 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.
|
|
*/
|
|
|
|
private 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.
|
|
*/
|
|
|
|
private 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;
|
|
*/
|
|
|
|
private 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.
|
|
*/
|
|
|
|
private 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;
|
|
}
|
|
}
|
|
} |