public TSQLForClause Parse(ITSQLTokenizer tokenizer) { // FOR XML AUTO TSQLForClause forClause = new TSQLForClause(); if (!tokenizer.Current.IsKeyword(TSQLKeywords.FOR)) { throw new InvalidOperationException("FOR expected."); } forClause.Tokens.Add(tokenizer.Current); while ( tokenizer.MoveNext() && !tokenizer.Current.IsCharacter(TSQLCharacters.Semicolon) && ( tokenizer.Current.Type != TSQLTokenType.Keyword || ( tokenizer.Current.Type == TSQLTokenType.Keyword && !tokenizer.Current.AsKeyword.Keyword.In ( TSQLKeywords.OPTION ) && !tokenizer.Current.AsKeyword.Keyword.IsStatementStart() ) )) { forClause.Tokens.Add(tokenizer.Current); } return(forClause); }
public TSQLIntoClause Parse(ITSQLTokenizer tokenizer) { TSQLIntoClause into = new TSQLIntoClause(); if (!tokenizer.Current.IsKeyword(TSQLKeywords.INTO)) { throw new InvalidOperationException("INTO expected."); } into.Tokens.Add(tokenizer.Current); while ( tokenizer.MoveNext() && ( tokenizer.Current.Type == TSQLTokenType.Identifier || tokenizer.Current.IsCharacter(TSQLCharacters.Period) || tokenizer.Current.Type == TSQLTokenType.Whitespace || tokenizer.Current.Type == TSQLTokenType.SingleLineComment || tokenizer.Current.Type == TSQLTokenType.MultilineComment || tokenizer.Current.IsKeyword(TSQLKeywords.AS) ) && // since USING is a stop word but it's also a TSQLTokenType.Identifier // we need to check for it explicitly !tokenizer.Current.IsFutureKeyword(TSQLFutureKeywords.USING) ) { into.Tokens.Add(tokenizer.Current); } return(into); }
public TSQLUnknownStatement Parse(ITSQLTokenizer tokenizer) { TSQLUnknownStatement statement = new TSQLUnknownStatement(); statement.Tokens.Add(tokenizer.Current); while ( tokenizer.MoveNext() && !( tokenizer.Current is TSQLCharacter && tokenizer.Current.AsCharacter.Character == TSQLCharacters.Semicolon )) { statement.Tokens.Add(tokenizer.Current); } if ( tokenizer.Current != null && tokenizer.Current is TSQLCharacter && tokenizer.Current.AsCharacter.Character == TSQLCharacters.Semicolon) { statement.Tokens.Add(tokenizer.Current); } return(statement); }
public TSQLCaseExpression Parse(ITSQLTokenizer tokenizer) { TSQLCaseExpression caseExpression = new TSQLCaseExpression(); if (!tokenizer.Current.IsKeyword(TSQLKeywords.CASE)) { throw new InvalidOperationException("CASE expected."); } caseExpression.Tokens.Add(tokenizer.Current); TSQLTokenParserHelper.ReadUntilStop( tokenizer, caseExpression, new List <TSQLFutureKeywords>() { }, new List <TSQLKeywords>() { TSQLKeywords.END }, lookForStatementStarts: false); // this is different than the other clauses because the // stop word is still part of the expression instead of // being part of the next expression or clause like in // the other parsers caseExpression.Tokens.Add(tokenizer.Current); tokenizer.MoveNext(); return(caseExpression); }
public TSQLIntoClause Parse(ITSQLTokenizer tokenizer) { TSQLIntoClause into = new TSQLIntoClause(); if (!tokenizer.Current.IsKeyword(TSQLKeywords.INTO)) { throw new ApplicationException("INTO expected."); } into.Tokens.Add(tokenizer.Current); while ( tokenizer.MoveNext() && ( tokenizer.Current.Type == TSQLTokenType.Identifier || tokenizer.Current.IsCharacter(TSQLCharacters.Period) || tokenizer.Current.Type == TSQLTokenType.Whitespace || tokenizer.Current.Type == TSQLTokenType.SingleLineComment || tokenizer.Current.Type == TSQLTokenType.MultilineComment )) { into.Tokens.Add(tokenizer.Current); } return(into); }
public TSQLUsingClause Parse(ITSQLTokenizer tokenizer) { TSQLUsingClause usingClause = new TSQLUsingClause(); if (!tokenizer.Current.IsFutureKeyword(TSQLFutureKeywords.USING)) { throw new InvalidOperationException("USING expected."); } usingClause.Tokens.Add(tokenizer.Current); /* can contain: * * <table_source> ::= * { * table_or_view_name [ [ AS ] table_alias ] [ <tablesample_clause> ] * [ WITH ( table_hint [ [ , ]...n ] ) ] * | rowset_function [ [ AS ] table_alias ] * [ ( bulk_column_alias [ ,...n ] ) ] * | user_defined_function [ [ AS ] table_alias ] * | OPENXML <openxml_clause> * | derived_table [ AS ] table_alias [ ( column_alias [ ,...n ] ) ] * | <joined_table> * | <pivoted_table> * | <unpivoted_table> * } * https://docs.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql?view=sql-server-ver15#syntax */ 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 ( // ON is required in MERGE statement after USING TSQLKeywords.ON ) ) )) { TSQLTokenParserHelper.RecurseParens( tokenizer, usingClause, ref nestedLevel); } return(usingClause); }
public TSQLSelectClause Parse(ITSQLTokenizer tokenizer) { TSQLSelectClause select = new TSQLSelectClause(); if (!tokenizer.Current.IsKeyword(TSQLKeywords.SELECT)) { throw new InvalidOperationException("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.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.INTO, TSQLKeywords.FROM, TSQLKeywords.WHERE, TSQLKeywords.GROUP, TSQLKeywords.HAVING, TSQLKeywords.ORDER, TSQLKeywords.UNION, TSQLKeywords.EXCEPT, TSQLKeywords.INTERSECT, TSQLKeywords.FOR, TSQLKeywords.OPTION ) && !tokenizer.Current.AsKeyword.Keyword.IsStatementStart() ) )) { TSQLSubqueryHelper.RecurseParens( tokenizer, select, ref nestedLevel); } return(select); }
public TSQLWithStatement Parse(ITSQLTokenizer tokenizer) { TSQLWithStatement statement = new TSQLWithStatement(); if (!tokenizer.Current.IsKeyword(TSQLKeywords.WITH)) { throw new ApplicationException("WITH expected."); } statement.Tokens.Add(tokenizer.Current); while ( tokenizer.MoveNext() && tokenizer.Current.Type != TSQLTokenType.Identifier) { statement.Tokens.Add(tokenizer.Current); } while ( tokenizer.Current != null && tokenizer.Current.Type == TSQLTokenType.Identifier) { TSQLCommonTableExpressionClause cte = new TSQLCommonTableExpressionClauseParser().Parse(tokenizer); statement.Tokens.AddRange(cte.Tokens); if ( tokenizer.Current != null && tokenizer.Current.Type != TSQLTokenType.Identifier) { statement.Tokens.Add(tokenizer.Current); while ( tokenizer.MoveNext() && tokenizer.Current.Type != TSQLTokenType.Keyword) { statement.Tokens.Add(tokenizer.Current); } } } return(statement); }
public TSQLSetOperatorClause Parse(ITSQLTokenizer tokenizer) { TSQLSetOperatorClause set = null; if (tokenizer.Current.IsKeyword(TSQLKeywords.UNION)) { set = new TSQLUnionClause(); set.Tokens.Add(tokenizer.Current); if (tokenizer.MoveNext() && tokenizer.Current.IsKeyword(TSQLKeywords.ALL)) { set.Tokens.Add(tokenizer.Current); tokenizer.MoveNext(); } } else if (tokenizer.Current.IsKeyword(TSQLKeywords.EXCEPT)) { set = new TSQLExceptClause(); set.Tokens.Add(tokenizer.Current); tokenizer.MoveNext(); } else if (tokenizer.Current.IsKeyword(TSQLKeywords.INTERSECT)) { set = new TSQLIntersectClause(); set.Tokens.Add(tokenizer.Current); tokenizer.MoveNext(); } TSQLSelectStatement select = new TSQLLimitedSelectStatementParser(tokenizer).Parse(); set.Select = select; set.Tokens.AddRange(select.Tokens); return(set); }
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.WHERE, TSQLKeywords.GROUP, TSQLKeywords.HAVING, TSQLKeywords.ORDER, TSQLKeywords.UNION, TSQLKeywords.EXCEPT, TSQLKeywords.INTERSECT, TSQLKeywords.FOR, TSQLKeywords.OPTION ) && !tokenizer.Current.AsKeyword.Keyword.IsStatementStart() ) )) { TSQLSubqueryHelper.RecurseParens( tokenizer, from, ref nestedLevel); } return(from); }
public TSQLDefaultValues Parse(ITSQLTokenizer tokenizer) { TSQLDefaultValues defaultValues = new TSQLDefaultValues(); if (!tokenizer.Current.IsKeyword(TSQLKeywords.DEFAULT)) { throw new InvalidOperationException("DEFAULT expected."); } defaultValues.Tokens.Add(tokenizer.Current); if (tokenizer.MoveNext() && tokenizer.Current.IsKeyword(TSQLKeywords.VALUES)) { defaultValues.Tokens.Add(tokenizer.Current); tokenizer.MoveNext(); } return(defaultValues); }
public static void ReadCommentsAndWhitespace( ITSQLTokenizer tokenizer, List <TSQLToken> savedTokens) { while (tokenizer.Current.IsWhitespace() || tokenizer.Current.IsComment()) { savedTokens.Add(tokenizer.Current); tokenizer.MoveNext(); } }
public TSQLSetClause Parse(ITSQLTokenizer tokenizer) { TSQLSetClause set = new TSQLSetClause(); if (!tokenizer.Current.IsKeyword(TSQLKeywords.SET)) { throw new InvalidOperationException("SET expected."); } set.Tokens.Add(tokenizer.Current); // TODO: // parse this rare but valid horror scenario // update output // set output.output = 1 // output deleted.* // maybe create assignment expression parser? 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.IsFutureKeyword(TSQLFutureKeywords.OUTPUT) ) || ( tokenizer.Current.Type == TSQLTokenType.Keyword && !tokenizer.Current.AsKeyword.Keyword.In ( TSQLKeywords.FROM, TSQLKeywords.WHERE, TSQLKeywords.OPTION ) && !tokenizer.Current.AsKeyword.Keyword.IsStatementStart() ) )) { TSQLSubqueryHelper.RecurseParens( tokenizer, set, ref nestedLevel); } return(set); }
public TSQLOptionClause Parse(ITSQLTokenizer tokenizer) { TSQLOptionClause option = new TSQLOptionClause(); if (!tokenizer.Current.IsKeyword(TSQLKeywords.OPTION)) { throw new InvalidOperationException("OPTION expected."); } option.Tokens.Add(tokenizer.Current); while ( tokenizer.MoveNext() && !tokenizer.Current.IsCharacter(TSQLCharacters.OpenParentheses)) { option.Tokens.Add(tokenizer.Current); } do { if (tokenizer.Current != null) { option.Tokens.Add(tokenizer.Current); } } while ( tokenizer.MoveNext() && !tokenizer.Current.IsCharacter(TSQLCharacters.CloseParentheses)); if (tokenizer.Current != null) { option.Tokens.Add(tokenizer.Current); tokenizer.MoveNext(); } TSQLTokenParserHelper.ReadCommentsAndWhitespace( tokenizer, option); return(option); }
public static void ReadThroughAnyCommentsOrWhitespace( ITSQLTokenizer tokenizer, List <TSQLToken> savedTokens) { while ( tokenizer.MoveNext() && ( tokenizer.Current.IsWhitespace() || tokenizer.Current.IsComment()) ) { savedTokens.Add(tokenizer.Current); } }
public TSQLWhereClause Parse(ITSQLTokenizer tokenizer) { TSQLWhereClause where = new TSQLWhereClause(); if (!tokenizer.Current.IsKeyword(TSQLKeywords.WHERE)) { throw new InvalidOperationException("WHERE expected."); } where.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.GROUP, TSQLKeywords.HAVING, TSQLKeywords.UNION, TSQLKeywords.EXCEPT, TSQLKeywords.INTERSECT, TSQLKeywords.ORDER, TSQLKeywords.FOR, TSQLKeywords.OPTION ) && !tokenizer.Current.AsKeyword.Keyword.IsStatementStart() ) )) { TSQLSubqueryHelper.RecurseParens( tokenizer, where, ref nestedLevel); } return(where); }
public TSQLOptionClause Parse(ITSQLTokenizer tokenizer) { TSQLOptionClause option = new TSQLOptionClause(); if (!tokenizer.Current.IsKeyword(TSQLKeywords.OPTION)) { throw new ApplicationException("OPTION expected."); } option.Tokens.Add(tokenizer.Current); while ( tokenizer.MoveNext() && !tokenizer.Current.IsCharacter(TSQLCharacters.OpenParentheses)) { option.Tokens.Add(tokenizer.Current); } do { if (tokenizer.Current != null) { option.Tokens.Add(tokenizer.Current); } } while ( tokenizer.MoveNext() && !tokenizer.Current.IsCharacter(TSQLCharacters.CloseParentheses)); if (tokenizer.Current != null) { option.Tokens.Add(tokenizer.Current); tokenizer.MoveNext(); } return(option); }
public TSQLCommonTableExpressionClause Parse(ITSQLTokenizer tokenizer) { TSQLCommonTableExpressionClause cte = new TSQLCommonTableExpressionClause(); if (tokenizer.Current.Type != Tokens.TSQLTokenType.Identifier) { throw new ApplicationException("Identifier expected."); } cte.Name = tokenizer.Current.AsIdentifier.Name; tokenizer.MoveNext(); return(cte); }
public TSQLArgumentList Parse(ITSQLTokenizer tokenizer) { List <TSQLExpression> arguments = new List <TSQLExpression>(); TSQLValueExpressionParser factory = new TSQLValueExpressionParser(); List <TSQLToken> tokens = new List <TSQLToken>(); // need to do this before starting the argument loop // so we can handle an empty argument list of just whitespace // and comments TSQLTokenParserHelper.ReadCommentsAndWhitespace( tokenizer, tokens); while ( tokenizer.Current != null && !tokenizer.Current.IsCharacter(TSQLCharacters.CloseParentheses)) { TSQLTokenParserHelper.ReadCommentsAndWhitespace( tokenizer, tokens); TSQLExpression argument = factory.Parse(tokenizer); tokens.AddRange(argument.Tokens); arguments.Add(argument); if (tokenizer.Current.IsCharacter(TSQLCharacters.Comma)) { tokens.Add(tokenizer.Current); tokenizer.MoveNext(); TSQLTokenParserHelper.ReadCommentsAndWhitespace( tokenizer, tokens); } } TSQLArgumentList argList = new TSQLArgumentList( arguments); argList.Tokens.AddRange(tokens); return(argList); }
public TSQLOperatorExpression Parse( ITSQLTokenizer tokenizer, TSQLExpression leftSide) { TSQLOperatorExpression opExpression = new TSQLOperatorExpression(); opExpression.LeftSide = leftSide; opExpression.Operator = tokenizer.Current.AsOperator; if (leftSide != null) { opExpression.Tokens.AddRange(leftSide.Tokens); } opExpression.Tokens.Add(tokenizer.Current); while ( tokenizer.MoveNext() && ( tokenizer.Current.IsWhitespace() || tokenizer.Current.IsComment() )) { opExpression.Tokens.Add(tokenizer.Current); } TSQLExpression rightSide = new TSQLValueExpressionParser().Parse( tokenizer); // a + (b + (c + d)) if ( tokenizer.Current != null && tokenizer.Current.Type.In( TSQLTokenType.Operator)) { rightSide = Parse( tokenizer, rightSide); } opExpression.RightSide = rightSide; opExpression.Tokens.AddRange(rightSide.Tokens); return(opExpression); }
public TSQLWithClause Parse(ITSQLTokenizer tokenizer) { TSQLWithClause with = new TSQLWithClause(); if (!tokenizer.Current.IsKeyword(TSQLKeywords.WITH)) { throw new InvalidOperationException("WITH expected."); } with.Tokens.Add(tokenizer.Current); // subqueries int nestedLevel = 0; while ( tokenizer.MoveNext() && !( 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.SELECT, TSQLKeywords.INSERT, TSQLKeywords.UPDATE, TSQLKeywords.DELETE, TSQLKeywords.MERGE ) ) )) { TSQLSubqueryHelper.RecurseParens( tokenizer, with, ref nestedLevel); } return(with); }
public TSQLVariableAssignmentExpression Parse( ITSQLTokenizer tokenizer, TSQLVariableExpression variable) { TSQLVariableAssignmentExpression opExpression = new TSQLVariableAssignmentExpression(); opExpression.Variable = variable.Variable; opExpression.Operator = tokenizer.Current.AsOperator; opExpression.Tokens.AddRange(variable.Tokens); opExpression.Tokens.Add(tokenizer.Current); while ( tokenizer.MoveNext() && ( tokenizer.Current.IsWhitespace() || tokenizer.Current.IsComment() )) { opExpression.Tokens.Add(tokenizer.Current); } TSQLExpression rightSide = new TSQLValueExpressionParser().Parse( tokenizer); // TODO: add test for nested operators like below // a + (b + (c + d)) if ( tokenizer.Current != null && tokenizer.Current.Type.In( TSQLTokenType.Operator)) { rightSide = new TSQLOperatorExpressionParser().Parse( tokenizer, rightSide); } opExpression.ValueExpression = rightSide; opExpression.Tokens.AddRange(rightSide.Tokens); return(opExpression); }
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.FOR, TSQLKeywords.OPTION ) && !tokenizer.Current.AsKeyword.Keyword.IsStatementStart() ) )) { TSQLSubqueryHelper.RecurseParens( tokenizer, orderBy, ref nestedLevel); } return(orderBy); }
public TSQLCaseExpression Parse(ITSQLTokenizer tokenizer) { TSQLCaseExpression caseExpression = new TSQLCaseExpression(); if (!tokenizer.Current.IsKeyword(TSQLKeywords.CASE)) { throw new InvalidOperationException("CASE expected."); } caseExpression.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.In ( TSQLKeywords.END ) ) )) { TSQLSubqueryHelper.RecurseParens( tokenizer, caseExpression, ref nestedLevel); } return(caseExpression); }
public TSQLOutputClause Parse(ITSQLTokenizer tokenizer) { TSQLOutputClause output = new TSQLOutputClause(); if (!tokenizer.Current.IsFutureKeyword(TSQLFutureKeywords.OUTPUT)) { throw new InvalidOperationException("OUTPUT expected."); } output.Tokens.Add(tokenizer.Current); while ( tokenizer.MoveNext() && !tokenizer.Current.IsCharacter(TSQLCharacters.Semicolon) && ( tokenizer.Current.IsKeyword(TSQLKeywords.AS) || tokenizer.Current.Type == TSQLTokenType.Identifier || tokenizer.Current.Type == TSQLTokenType.SystemColumnIdentifier || tokenizer.Current.IsCharacter(TSQLCharacters.Period) || tokenizer.Current.IsCharacter(TSQLCharacters.Comma) || tokenizer.Current.Text == "*" || tokenizer.Current.Type == TSQLTokenType.Whitespace || tokenizer.Current.Type == TSQLTokenType.SingleLineComment || tokenizer.Current.Type == TSQLTokenType.MultilineComment )) { output.Tokens.Add(tokenizer.Current); } if (tokenizer.Current.IsKeyword(TSQLKeywords.INTO)) { TSQLIntoClause intoClause = new TSQLIntoClauseParser().Parse(tokenizer); output.Into = intoClause; output.Tokens.AddRange(intoClause.Tokens); } return(output); }
public TSQLIntoClause Parse(ITSQLTokenizer tokenizer) { TSQLIntoClause into = new TSQLIntoClause(); if (!tokenizer.Current.IsKeyword(TSQLKeywords.INTO)) { throw new InvalidOperationException("INTO expected."); } into.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.Identifier || tokenizer.Current.IsCharacter(TSQLCharacters.Period) || tokenizer.Current.IsCharacter(TSQLCharacters.OpenParentheses) || tokenizer.Current.Type == TSQLTokenType.Whitespace || tokenizer.Current.Type == TSQLTokenType.SingleLineComment || tokenizer.Current.Type == TSQLTokenType.MultilineComment )) { TSQLTokenParserHelper.RecurseParens( tokenizer, into, ref nestedLevel); } return(into); }
/// <summary> /// This reads recursively through parenthesis and returns when it hits /// one of the stop words outside of any nested parenthesis. /// </summary> public static void ReadUntilStop( ITSQLTokenizer tokenizer, TSQLElement element, List <TSQLFutureKeywords> futureKeywords, List <TSQLKeywords> keywords, bool lookForStatementStarts) { 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 && !futureKeywords.Any(fk => tokenizer.Current.IsFutureKeyword(fk)) ) || ( tokenizer.Current.Type == TSQLTokenType.Keyword && !keywords.Any(k => tokenizer.Current.AsKeyword.Keyword == k) && !( lookForStatementStarts && tokenizer.Current.AsKeyword.Keyword.IsStatementStart() ) ) )) { RecurseParens( tokenizer, element, ref nestedLevel); } }
public TSQLSelectColumn Parse(ITSQLTokenizer tokenizer) { TSQLSelectColumn column = new TSQLSelectColumn(); TSQLExpression columnExpression = new TSQLSelectExpressionParser().Parse(tokenizer); column.Expression = columnExpression; column.Tokens.AddRange(columnExpression.Tokens); TSQLTokenParserHelper.ReadCommentsAndWhitespace( tokenizer, column); // check for operator =, when expression type is column, and return new column expression with alias // e.g. IsFinishedGoods = p.FinishedGoodsFlag if ( tokenizer.Current != null && tokenizer.Current.Type == TSQLTokenType.Operator && tokenizer.Current.Text == "=" && columnExpression.Type == TSQLExpressionType.Column ) { column.Tokens.Add(tokenizer.Current); tokenizer.MoveNext(); TSQLExpression actualColumn = new TSQLValueExpressionParser().Parse(tokenizer); column.Expression = actualColumn; column.ColumnAlias = columnExpression.AsColumn.Column; column.Tokens.AddRange(actualColumn.Tokens); } else { if (tokenizer.Current.IsKeyword(TSQLKeywords.AS)) { column.Tokens.Add(tokenizer.Current); tokenizer.MoveNext(); TSQLTokenParserHelper.ReadCommentsAndWhitespace( tokenizer, column); } if (tokenizer.Current != null && tokenizer.Current.Type.In( TSQLTokenType.Identifier, TSQLTokenType.SystemIdentifier, TSQLTokenType.IncompleteIdentifier)) { column.Tokens.Add(tokenizer.Current); if (tokenizer.Current.Type.In( TSQLTokenType.Identifier, TSQLTokenType.SystemIdentifier)) { column.ColumnAlias = tokenizer.Current.AsIdentifier; } tokenizer.MoveNext(); } } return(column); }
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 TSQLWithClause Parse(ITSQLTokenizer tokenizer) { TSQLWithClause with = new TSQLWithClause(); if (!tokenizer.Current.IsKeyword(TSQLKeywords.WITH)) { throw new InvalidOperationException("WITH expected."); } with.Tokens.Add(tokenizer.Current); // subqueries int nestedLevel = 0; int parenCount = 0; int identifierCount = 0; bool afterAs = false; while ( tokenizer.MoveNext() && !tokenizer.Current.IsCharacter(TSQLCharacters.Semicolon) && !( nestedLevel == 0 && tokenizer.Current.IsCharacter(TSQLCharacters.CloseParentheses) ) && !( // only allow a set of parens at root level // if it's following an AS // or if it's the column list between the CTE name and the AS nestedLevel == 0 && tokenizer.Current.IsCharacter(TSQLCharacters.OpenParentheses) && afterAs && parenCount >= identifierCount ) && ( nestedLevel > 0 || tokenizer.Current.Type != TSQLTokenType.Keyword || ( tokenizer.Current.Type == TSQLTokenType.Keyword && !tokenizer.Current.AsKeyword.Keyword.In ( TSQLKeywords.SELECT, TSQLKeywords.INSERT, TSQLKeywords.UPDATE, TSQLKeywords.DELETE, TSQLKeywords.MERGE ) ) )) { if (nestedLevel == 0) { if (afterAs && tokenizer.Current.IsCharacter(TSQLCharacters.OpenParentheses)) { parenCount++; } else if (tokenizer.Current.Type == TSQLTokenType.Identifier) { identifierCount++; afterAs = false; } else if (tokenizer.Current.IsKeyword(TSQLKeywords.AS)) { afterAs = true; } } TSQLTokenParserHelper.RecurseParens( tokenizer, with, ref nestedLevel); } return(with); }