internal TSQLCharacter( int beginPostion, string text) : base( beginPostion, text) { Character = TSQLCharacters.Parse(text); }
public static bool IsCharacter(this TSQLToken token, TSQLCharacters character) { if (token == null) { return(false); } if (token.Type != TSQLTokenType.Character) { return(false); } if (token.AsCharacter.Character != character) { return(false); } return(true); }
public static void RecurseParens( ITSQLTokenizer tokenizer, TSQLExpression expression, ref int nestedLevel) { if (tokenizer.Current.Type == TSQLTokenType.Character) { expression.Tokens.Add(tokenizer.Current); TSQLCharacters character = tokenizer.Current.AsCharacter.Character; if (character == TSQLCharacters.OpenParentheses) { // should we recurse for correlated subqueries? nestedLevel++; } else if (character == TSQLCharacters.CloseParentheses) { nestedLevel--; } } else if (tokenizer.Current.IsKeyword(TSQLKeywords.CASE)) { // not going to add CASE token directly because it will be contained // within the returned expression and we don't want to double up the // CASE token within the results. // CASE is a special situation because it's stop word (END) is part of // the expression itself and needs to be included in it's token list. // all other clauses stop at the beginning of the next clause and do // not include the stop token within their token list. TSQLCaseExpression caseExpression = new TSQLCaseExpressionParser().Parse(tokenizer); expression.Tokens.AddRange(caseExpression.Tokens); } else { expression.Tokens.Add(tokenizer.Current); } }
public static void RecurseParens( ITSQLTokenizer tokenizer, TSQLElement element, ref int nestedLevel) { if (tokenizer.Current.Type == TSQLTokenType.Character) { element.Tokens.Add(tokenizer.Current); TSQLCharacters character = tokenizer.Current.AsCharacter.Character; if (character == TSQLCharacters.OpenParentheses) { nestedLevel++; } else if (character == TSQLCharacters.CloseParentheses) { nestedLevel--; } } else if (tokenizer.Current.IsKeyword(TSQLKeywords.CASE)) { // have to handle CASE special, so that we always match up // 1 and only 1 END TSQLCaseExpression caseExp = new TSQLCaseExpressionParser().Parse(tokenizer); element.Tokens.AddRange(caseExp.Tokens); if (tokenizer.Current != null) { element.Tokens.Add(tokenizer.Current); } } else { element.Tokens.Add(tokenizer.Current); } }
public TSQLGroupByClause Parse(ITSQLTokenizer tokenizer) { TSQLGroupByClause groupBy = new TSQLGroupByClause(); if (!tokenizer.Current.IsKeyword(TSQLKeywords.GROUP)) { throw new ApplicationException("GROUP expected."); } groupBy.Tokens.Add(tokenizer.Current); // subqueries int nestedLevel = 0; while ( tokenizer.MoveNext() && !tokenizer.Current.IsCharacter(TSQLCharacters.Semicolon) && !( nestedLevel == 0 && tokenizer.Current.IsCharacter(TSQLCharacters.CloseParentheses) ) && ( nestedLevel > 0 || tokenizer.Current.Type != TSQLTokenType.Keyword || ( tokenizer.Current.Type == TSQLTokenType.Keyword && tokenizer.Current.AsKeyword.Keyword.In ( TSQLKeywords.BY, TSQLKeywords.NULL, TSQLKeywords.CASE, TSQLKeywords.WHEN, TSQLKeywords.THEN, TSQLKeywords.ELSE, TSQLKeywords.AND, TSQLKeywords.OR, TSQLKeywords.BETWEEN, TSQLKeywords.EXISTS, TSQLKeywords.END, TSQLKeywords.IN, TSQLKeywords.IS, TSQLKeywords.NOT, TSQLKeywords.OVER, TSQLKeywords.LIKE, TSQLKeywords.ALL, TSQLKeywords.WITH, TSQLKeywords.DISTINCT ) ) )) { groupBy.Tokens.Add(tokenizer.Current); if (tokenizer.Current.Type == TSQLTokenType.Character) { TSQLCharacters character = tokenizer.Current.AsCharacter.Character; if (character == TSQLCharacters.OpenParentheses) { // should we recurse for subqueries? nestedLevel++; if (tokenizer.MoveNext()) { if (tokenizer.Current.IsKeyword(TSQLKeywords.SELECT)) { TSQLSelectStatement selectStatement = new TSQLSelectStatementParser().Parse(tokenizer); groupBy.Tokens.AddRange(selectStatement.Tokens); if (tokenizer.Current.IsCharacter(TSQLCharacters.CloseParentheses)) { nestedLevel--; groupBy.Tokens.Add(tokenizer.Current); } } else { groupBy.Tokens.Add(tokenizer.Current); } } } else if (character == TSQLCharacters.CloseParentheses) { nestedLevel--; } } } return(groupBy); }
public void Characters_ParseNull() { Assert.AreEqual(TSQLCharacters.None, TSQLCharacters.Parse(null)); }
public void Characters_IsNull() { Assert.IsFalse(TSQLCharacters.IsCharacter(null)); }
public void Characters_IsFalse() { Assert.IsFalse(TSQLCharacters.IsCharacter("a")); }
public void Characters_IsTrue() { Assert.IsTrue(TSQLCharacters.IsCharacter(",")); }
public TSQLHavingClause Parse(TSQLTokenizer tokenizer) { TSQLHavingClause having = new TSQLHavingClause(); if ( tokenizer.Current == null || tokenizer.Current.Type != TSQLTokenType.Keyword || tokenizer.Current.AsKeyword.Keyword != TSQLKeywords.HAVING) { throw new ApplicationException("HAVING expected."); } having.Tokens.Add(tokenizer.Current); // subqueries int nestedLevel = 0; while ( tokenizer.Read() && !( tokenizer.Current.Type == TSQLTokenType.Character && tokenizer.Current.AsCharacter.Character == TSQLCharacters.Semicolon ) && !( nestedLevel == 0 && tokenizer.Current.Type == TSQLTokenType.Character && tokenizer.Current.AsCharacter.Character == TSQLCharacters.CloseParentheses ) && ( nestedLevel > 0 || tokenizer.Current.Type != TSQLTokenType.Keyword || ( tokenizer.Current.Type == TSQLTokenType.Keyword && tokenizer.Current.AsKeyword.Keyword.In ( TSQLKeywords.NULL, TSQLKeywords.CASE, TSQLKeywords.WHEN, TSQLKeywords.THEN, TSQLKeywords.ELSE, TSQLKeywords.AND, TSQLKeywords.OR, TSQLKeywords.BETWEEN, TSQLKeywords.EXISTS, TSQLKeywords.END, TSQLKeywords.IN, TSQLKeywords.IS, TSQLKeywords.NOT, TSQLKeywords.LIKE ) ) )) { having.Tokens.Add(tokenizer.Current); if (tokenizer.Current.Type == TSQLTokenType.Character) { TSQLCharacters character = tokenizer.Current.AsCharacter.Character; if (character == TSQLCharacters.OpenParentheses) { // should we recurse for subqueries? nestedLevel++; if (tokenizer.Read()) { if ( tokenizer.Current.Type == TSQLTokenType.Keyword && tokenizer.Current.AsKeyword.Keyword == TSQLKeywords.SELECT) { TSQLSelectStatement selectStatement = new TSQLSelectStatementParser().Parse(tokenizer); having.Tokens.AddRange(selectStatement.Tokens); if ( tokenizer.Current != null && tokenizer.Current.Type == TSQLTokenType.Character && tokenizer.Current.AsCharacter.Character == TSQLCharacters.CloseParentheses) { nestedLevel--; having.Tokens.Add(tokenizer.Current); } } else { having.Tokens.Add(tokenizer.Current); } } } else if (character == TSQLCharacters.CloseParentheses) { nestedLevel--; } } } return(having); }
public TSQLFromClause Parse(ITSQLTokenizer tokenizer) { TSQLFromClause from = new TSQLFromClause(); if (!tokenizer.Current.IsKeyword(TSQLKeywords.FROM)) { throw new InvalidOperationException("FROM expected."); } from.Tokens.Add(tokenizer.Current); // derived tables // TVF int nestedLevel = 0; while ( tokenizer.MoveNext() && !( tokenizer.Current.Type == TSQLTokenType.Character && tokenizer.Current.AsCharacter.Character == TSQLCharacters.Semicolon ) && !( nestedLevel == 0 && tokenizer.Current.Type == TSQLTokenType.Character && tokenizer.Current.AsCharacter.Character == TSQLCharacters.CloseParentheses ) && ( nestedLevel > 0 || tokenizer.Current.Type != TSQLTokenType.Keyword || ( tokenizer.Current.Type == TSQLTokenType.Keyword && tokenizer.Current.AsKeyword.Keyword.In ( TSQLKeywords.JOIN, TSQLKeywords.ON, TSQLKeywords.INNER, TSQLKeywords.LEFT, TSQLKeywords.RIGHT, TSQLKeywords.OUTER, TSQLKeywords.CROSS, TSQLKeywords.FULL, TSQLKeywords.AS, TSQLKeywords.PIVOT, TSQLKeywords.UNPIVOT, TSQLKeywords.WITH, TSQLKeywords.MERGE, TSQLKeywords.TABLESAMPLE, TSQLKeywords.FOR, TSQLKeywords.FROM, // FOR SYSTEM_TIME FROM TSQLKeywords.BETWEEN, TSQLKeywords.AND, TSQLKeywords.IN, TSQLKeywords.REPEATABLE, TSQLKeywords.ALL ) ) )) { from.Tokens.Add(tokenizer.Current); if (tokenizer.Current.Type == TSQLTokenType.Character) { TSQLCharacters character = tokenizer.Current.AsCharacter.Character; if (character == TSQLCharacters.OpenParentheses) { // should we recurse for derived tables? nestedLevel++; if (tokenizer.MoveNext()) { if ( tokenizer.Current.Type == TSQLTokenType.Keyword && tokenizer.Current.AsKeyword.Keyword == TSQLKeywords.SELECT) { TSQLSelectStatement selectStatement = new TSQLSelectStatementParser().Parse(tokenizer); from.Tokens.AddRange(selectStatement.Tokens); if ( tokenizer.Current != null && tokenizer.Current.Type == TSQLTokenType.Character && tokenizer.Current.AsCharacter.Character == TSQLCharacters.CloseParentheses) { nestedLevel--; from.Tokens.Add(tokenizer.Current); } } else if (tokenizer.Current.IsCharacter( TSQLCharacters.CloseParentheses)) { nestedLevel--; from.Tokens.Add(tokenizer.Current); } else { from.Tokens.Add(tokenizer.Current); } } } else if (character == TSQLCharacters.CloseParentheses) { nestedLevel--; } } } return(from); }
public TSQLOrderByClause Parse(ITSQLTokenizer tokenizer) { TSQLOrderByClause orderBy = new TSQLOrderByClause(); if (!tokenizer.Current.IsKeyword(TSQLKeywords.ORDER)) { throw new InvalidOperationException("ORDER expected."); } orderBy.Tokens.Add(tokenizer.Current); // subqueries int nestedLevel = 0; while ( tokenizer.MoveNext() && !tokenizer.Current.IsCharacter(TSQLCharacters.Semicolon) && !( nestedLevel == 0 && tokenizer.Current.IsCharacter(TSQLCharacters.CloseParentheses) ) && ( nestedLevel > 0 || tokenizer.Current.Type != TSQLTokenType.Keyword || ( tokenizer.Current.Type == TSQLTokenType.Keyword && tokenizer.Current.AsKeyword.Keyword.In ( TSQLKeywords.BY, TSQLKeywords.NULL, TSQLKeywords.CASE, TSQLKeywords.WHEN, TSQLKeywords.THEN, TSQLKeywords.ELSE, TSQLKeywords.AND, TSQLKeywords.OR, TSQLKeywords.BETWEEN, TSQLKeywords.EXISTS, TSQLKeywords.END, TSQLKeywords.IN, TSQLKeywords.IS, TSQLKeywords.NOT, TSQLKeywords.OVER, TSQLKeywords.LIKE, TSQLKeywords.ASC, TSQLKeywords.DESC, TSQLKeywords.FETCH, TSQLKeywords.COLLATE ) ) )) { orderBy.Tokens.Add(tokenizer.Current); if (tokenizer.Current.Type == TSQLTokenType.Character) { TSQLCharacters character = tokenizer.Current.AsCharacter.Character; if (character == TSQLCharacters.OpenParentheses) { // should we recurse for subqueries? nestedLevel++; if (tokenizer.MoveNext()) { if (tokenizer.Current.IsKeyword(TSQLKeywords.SELECT)) { TSQLSelectStatement selectStatement = new TSQLSelectStatementParser().Parse(tokenizer); orderBy.Tokens.AddRange(selectStatement.Tokens); if (tokenizer.Current.IsCharacter(TSQLCharacters.CloseParentheses)) { nestedLevel--; orderBy.Tokens.Add(tokenizer.Current); } } else if (tokenizer.Current.IsCharacter( TSQLCharacters.CloseParentheses)) { nestedLevel--; orderBy.Tokens.Add(tokenizer.Current); } else if (tokenizer.Current.IsCharacter( TSQLCharacters.OpenParentheses)) { nestedLevel++; orderBy.Tokens.Add(tokenizer.Current); } else { orderBy.Tokens.Add(tokenizer.Current); } } } else if (character == TSQLCharacters.CloseParentheses) { nestedLevel--; } } } return(orderBy); }
public TSQLSelectClause Parse(TSQLTokenizer tokenizer) { TSQLSelectClause select = new TSQLSelectClause(); if ( tokenizer.Current == null || tokenizer.Current.Type != TSQLTokenType.Keyword || tokenizer.Current.AsKeyword.Keyword != TSQLKeywords.SELECT) { throw new ApplicationException("SELECT expected."); } select.Tokens.Add(tokenizer.Current); // can contain ALL, DISTINCT, TOP, PERCENT, WITH TIES, AS // ends with FROM, semicolon, or keyword other than those listed above, when used outside of parens // recursively walk down and back up parens int nestedLevel = 0; while ( tokenizer.Read() && !( tokenizer.Current.Type == TSQLTokenType.Character && tokenizer.Current.AsCharacter.Character == TSQLCharacters.Semicolon ) && !( nestedLevel == 0 && tokenizer.Current.Type == TSQLTokenType.Character && tokenizer.Current.AsCharacter.Character == TSQLCharacters.CloseParentheses ) && ( nestedLevel > 0 || tokenizer.Current.Type != TSQLTokenType.Keyword || ( tokenizer.Current.Type == TSQLTokenType.Keyword && tokenizer.Current.AsKeyword.Keyword.In ( TSQLKeywords.ALL, TSQLKeywords.AS, TSQLKeywords.DISTINCT, TSQLKeywords.PERCENT, TSQLKeywords.TOP, TSQLKeywords.WITH, TSQLKeywords.NULL, TSQLKeywords.CASE, TSQLKeywords.WHEN, TSQLKeywords.THEN, TSQLKeywords.ELSE, TSQLKeywords.AND, TSQLKeywords.OR, TSQLKeywords.BETWEEN, TSQLKeywords.EXISTS, TSQLKeywords.END, TSQLKeywords.IN, TSQLKeywords.IS, TSQLKeywords.NOT, TSQLKeywords.OVER, TSQLKeywords.IDENTITY, TSQLKeywords.LIKE ) ) )) { select.Tokens.Add(tokenizer.Current); if (tokenizer.Current.Type == TSQLTokenType.Character) { TSQLCharacters character = tokenizer.Current.AsCharacter.Character; if (character == TSQLCharacters.OpenParentheses) { // should we recurse for correlated subqueries? nestedLevel++; if (tokenizer.Read()) { if ( tokenizer.Current.Type == TSQLTokenType.Keyword && tokenizer.Current.AsKeyword.Keyword == TSQLKeywords.SELECT) { TSQLSelectStatement selectStatement = new TSQLSelectStatementParser().Parse(tokenizer); select.Tokens.AddRange(selectStatement.Tokens); if ( tokenizer.Current != null && tokenizer.Current.Type == TSQLTokenType.Character && tokenizer.Current.AsCharacter.Character == TSQLCharacters.CloseParentheses) { nestedLevel--; select.Tokens.Add(tokenizer.Current); } } else { select.Tokens.Add(tokenizer.Current); } } } else if (character == TSQLCharacters.CloseParentheses) { nestedLevel--; } } } return(select); }
public TSQLUnknownStatement Parse() { Statement.Tokens.Add(Tokenizer.Current); int nestedLevel = 0; while ( Tokenizer.MoveNext() && !Tokenizer.Current.IsCharacter(TSQLCharacters.Semicolon) && !( nestedLevel == 0 && Tokenizer.Current.IsCharacter(TSQLCharacters.CloseParentheses) ) && ( nestedLevel > 0 || Tokenizer.Current.Type != TSQLTokenType.Keyword || ( Tokenizer.Current.Type == TSQLTokenType.Keyword && !Tokenizer.Current.AsKeyword.Keyword.IsStatementStart() ) )) { Statement.Tokens.Add(Tokenizer.Current); if (Tokenizer.Current.Type == TSQLTokenType.Character) { TSQLCharacters character = Tokenizer.Current.AsCharacter.Character; if (character == TSQLCharacters.OpenParentheses) { // should we recurse for correlated subqueries? nestedLevel++; if (Tokenizer.MoveNext()) { if (Tokenizer.Current.IsCharacter( TSQLCharacters.CloseParentheses)) { nestedLevel--; Statement.Tokens.Add(Tokenizer.Current); } else if (Tokenizer.Current.IsCharacter( TSQLCharacters.OpenParentheses)) { nestedLevel++; Statement.Tokens.Add(Tokenizer.Current); } else { Statement.Tokens.Add(Tokenizer.Current); } } } else if (character == TSQLCharacters.CloseParentheses) { nestedLevel--; } } } return(Statement); }
public TSQLToken Parse( string tokenValue, int startPosition, int endPosition, bool useQuotedIdentifiers) { if ( char.IsWhiteSpace(tokenValue[0])) { return (new TSQLWhitespace( startPosition, tokenValue)); } else if ( tokenValue[0] == '@') { if (TSQLVariables.IsVariable(tokenValue)) { return (new TSQLSystemVariable( startPosition, tokenValue)); } else { return (new TSQLVariable( startPosition, tokenValue)); } } else if (tokenValue.StartsWith("--")) { return (new TSQLSingleLineComment( startPosition, tokenValue)); } else if (tokenValue.StartsWith("/*")) { if (tokenValue.EndsWith("*/")) { return (new TSQLMultilineComment( startPosition, tokenValue)); } else { return (new TSQLIncompleteCommentToken( startPosition, tokenValue)); } } else if ( tokenValue.StartsWith("'") || tokenValue.StartsWith("N'")) { // make sure there's an even number of quotes so that it's closed properly if ((tokenValue.Split('\'').Length - 1) % 2 == 0) { return (new TSQLStringLiteral( startPosition, tokenValue)); } else { return (new TSQLIncompleteStringToken( startPosition, tokenValue)); } } else if ( !useQuotedIdentifiers && tokenValue.StartsWith("\"")) { // make sure there's an even number of quotes so that it's closed properly if ((tokenValue.Split('\"').Length - 1) % 2 == 0) { return (new TSQLStringLiteral( startPosition, tokenValue)); } else { return (new TSQLIncompleteStringToken( startPosition, tokenValue)); } } else if ( tokenValue[0] == '$') { // $IDENTITY if ( tokenValue.Length > 1 && char.IsLetter(tokenValue[1])) { return (new TSQLSystemColumnIdentifier( startPosition, tokenValue)); } // $45.56 else { return (new TSQLMoneyLiteral( startPosition, tokenValue)); } } else if (CharUnicodeInfo.GetUnicodeCategory(tokenValue[0]) == UnicodeCategory.CurrencySymbol) { return (new TSQLMoneyLiteral( startPosition, tokenValue)); } else if (tokenValue.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) { return (new TSQLBinaryLiteral( startPosition, tokenValue)); } else if ( char.IsDigit(tokenValue[0]) || ( tokenValue[0] == '.' && tokenValue.Length > 1 && char.IsDigit(tokenValue[1]) )) { return (new TSQLNumericLiteral( startPosition, tokenValue)); } else if ( tokenValue[0] == '=' || tokenValue[0] == '~' || tokenValue[0] == '-' || tokenValue[0] == '+' || tokenValue[0] == '*' || tokenValue[0] == '/' || tokenValue[0] == '<' || tokenValue[0] == '>' || tokenValue[0] == '!' || tokenValue[0] == '&' || tokenValue[0] == '|' || tokenValue[0] == '^' || tokenValue[0] == '%' || tokenValue[0] == ':') { return (new TSQLOperator( startPosition, tokenValue)); } else if (TSQLCharacters.IsCharacter(tokenValue)) { return (new TSQLCharacter( startPosition, tokenValue)); } else if (TSQLKeywords.IsKeyword(tokenValue)) { return (new TSQLKeyword( startPosition, tokenValue)); } else if (TSQLIdentifiers.IsIdentifier(tokenValue)) { return (new TSQLSystemIdentifier( startPosition, tokenValue)); } else { if ( ( tokenValue.StartsWith("[") && !tokenValue.EndsWith("]") ) || ( useQuotedIdentifiers && tokenValue.StartsWith("\"") && // see if there's an odd number of quotes (tokenValue.Split('\"').Length - 1) % 2 == 1 )) { return (new TSQLIncompleteIdentifierToken( startPosition, tokenValue)); } else { return (new TSQLIdentifier( startPosition, tokenValue)); } } }
public static bool IsCharacter(this TSQLToken token, TSQLCharacters character) { if (token == null) { return false; } if (token.Type != TSQLTokenType.Character) { return false; } if (token.AsCharacter.Character != character) { return false; } return true; }
public static void RecurseParens( ITSQLTokenizer tokenizer, TSQLExpression expression, ref int nestedLevel) { expression.Tokens.Add(tokenizer.Current); if (tokenizer.Current.Type == TSQLTokenType.Character) { TSQLCharacters character = tokenizer.Current.AsCharacter.Character; if (character == TSQLCharacters.OpenParentheses) { // should we recurse for correlated subqueries? nestedLevel++; if (tokenizer.MoveNext()) { if (tokenizer.Current.IsKeyword( TSQLKeywords.SELECT)) { TSQLSelectStatement selectStatement = new TSQLSelectStatementParser(tokenizer).Parse(); expression.Tokens.AddRange(selectStatement.Tokens); if (tokenizer.Current.IsCharacter( TSQLCharacters.CloseParentheses)) { nestedLevel--; expression.Tokens.Add(tokenizer.Current); } } else if (tokenizer.Current.IsCharacter( TSQLCharacters.CloseParentheses)) { nestedLevel--; expression.Tokens.Add(tokenizer.Current); } else if (tokenizer.Current.IsCharacter( TSQLCharacters.OpenParentheses)) { nestedLevel++; expression.Tokens.Add(tokenizer.Current); } else { expression.Tokens.Add(tokenizer.Current); } } } else if (character == TSQLCharacters.CloseParentheses) { nestedLevel--; } } else if (tokenizer.Current.IsKeyword(TSQLKeywords.CASE)) { TSQLCaseExpression caseExpression = new TSQLCaseExpressionParser().Parse(tokenizer); expression.Tokens.AddRange(caseExpression.Tokens); } }
public TSQLWhereClause Parse(IEnumerator <TSQLToken> tokenizer) { TSQLWhereClause where = new TSQLWhereClause(); TSQLKeyword keyword = tokenizer.Current.AsKeyword; if (keyword == null || keyword.Keyword != TSQLKeywords.WHERE) { throw new ApplicationException("WHERE expected."); } where.Tokens.Add(keyword); // subqueries int nestedLevel = 0; while ( tokenizer.MoveNext() && !( tokenizer.Current.Type == TSQLTokenType.Character && tokenizer.Current.AsCharacter.Character == TSQLCharacters.Semicolon ) && !( nestedLevel == 0 && tokenizer.Current.Type == TSQLTokenType.Character && tokenizer.Current.AsCharacter.Character == TSQLCharacters.CloseParentheses ) && ( nestedLevel > 0 || tokenizer.Current.Type != TSQLTokenType.Keyword || ( tokenizer.Current.Type == TSQLTokenType.Keyword && tokenizer.Current.AsKeyword.Keyword.In ( TSQLKeywords.NULL, TSQLKeywords.CASE, TSQLKeywords.WHEN, TSQLKeywords.THEN, TSQLKeywords.ELSE, TSQLKeywords.AND, TSQLKeywords.OR, TSQLKeywords.BETWEEN, TSQLKeywords.EXISTS, TSQLKeywords.END, TSQLKeywords.IN, TSQLKeywords.IS, TSQLKeywords.NOT, TSQLKeywords.LIKE ) ) )) { where.Tokens.Add(tokenizer.Current); if (tokenizer.Current.Type == TSQLTokenType.Character) { TSQLCharacters character = tokenizer.Current.AsCharacter.Character; if (character == TSQLCharacters.OpenParentheses) { // should we recurse for subqueries? nestedLevel++; if (tokenizer.MoveNext()) { if ( tokenizer.Current.Type == TSQLTokenType.Keyword && tokenizer.Current.AsKeyword.Keyword == TSQLKeywords.SELECT) { TSQLSelectStatement selectStatement = new TSQLSelectStatementParser().Parse(tokenizer); where.Tokens.AddRange(selectStatement.Tokens); if ( tokenizer.Current != null && tokenizer.Current.Type == TSQLTokenType.Character && tokenizer.Current.AsCharacter.Character == TSQLCharacters.CloseParentheses) { nestedLevel--; where.Tokens.Add(tokenizer.Current); } } else { where.Tokens.Add(tokenizer.Current); } } } else if (character == TSQLCharacters.CloseParentheses) { nestedLevel--; } } } return(where); }