예제 #1
0
        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);
        }
예제 #5
0
        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);
        }
예제 #6
0
        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);
        }
예제 #7
0
        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);
        }
예제 #9
0
        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);
        }
예제 #10
0
        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();
            }
        }
예제 #13
0
        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);
        }
예제 #14
0
        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);
     }
 }
예제 #16
0
        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);
        }
예제 #17
0
        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);
        }
예제 #19
0
        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);
        }
예제 #21
0
        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);
        }
예제 #23
0
        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);
        }
예제 #24
0
        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);
        }
예제 #25
0
        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);
        }
예제 #26
0
        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);
            }
        }
예제 #28
0
        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);
        }
예제 #29
0
        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);
        }
예제 #30
0
        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);
        }