Inheritance: ITSQLStatementParser
Example #1
0
        public TSQLInsertStatement Parse()
        {
            TSQLInsertClause insertClause = new TSQLInsertClauseParser().Parse(Tokenizer);

            Statement.Insert = insertClause;

            Statement.Tokens.AddRange(insertClause.Tokens);

            if (Tokenizer.Current.IsFutureKeyword(TSQLFutureKeywords.OUTPUT))
            {
                TSQLOutputClause outputClause = new TSQLOutputClauseParser().Parse(Tokenizer);

                Statement.Output = outputClause;

                Statement.Tokens.AddRange(outputClause.Tokens);
            }

            if (Tokenizer.Current.IsKeyword(TSQLKeywords.VALUES))
            {
                TSQLValuesExpression values = new TSQLValuesExpressionParser().Parse(Tokenizer);

                Statement.Values = values;

                Statement.Tokens.AddRange(values.Tokens);
            }
            else if (Tokenizer.Current.IsKeyword(TSQLKeywords.SELECT))
            {
                TSQLSelectStatement select = new TSQLSelectStatementParser(Tokenizer).Parse();

                Statement.Select = select;

                Statement.Tokens.AddRange(select.Tokens);
            }
            else if (Tokenizer.Current.IsKeyword(TSQLKeywords.DEFAULT))
            {
                TSQLDefaultValuesExpression defaultValues = new TSQLDefaultValuesExpressionParser().Parse(Tokenizer);

                Statement.Default = defaultValues;

                Statement.Tokens.AddRange(defaultValues.Tokens);
            }
            else if (Tokenizer.Current.IsKeyword(TSQLKeywords.EXECUTE))
            {
                TSQLExecuteStatement exec = new TSQLExecuteStatementParser(Tokenizer).Parse();

                Statement.Execute = exec;

                Statement.Tokens.AddRange(exec.Tokens);
            }

            if (
                Tokenizer.Current?.AsKeyword != null &&
                Tokenizer.Current.AsKeyword.Keyword.IsStatementStart())
            {
                Tokenizer.Putback();
            }

            return(Statement);
        }
        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 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 TSQLFromClause Parse(TSQLTokenizer tokenizer)
        {
            TSQLFromClause from = new TSQLFromClause();

            if (
                tokenizer.Current == null ||
                tokenizer.Current.Type != TSQLTokenType.Keyword ||
                tokenizer.Current.AsKeyword.Keyword != TSQLKeywords.FROM)
            {
                throw new ApplicationException("FROM expected.");
            }

            from.Tokens.Add(tokenizer.Current);

            // derived tables
            // TVF
            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.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.Read())
                        {
                            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
                            {
                                from.Tokens.Add(tokenizer.Current);
                            }
                        }
                    }
                    else if (character == TSQLCharacters.CloseParentheses)
                    {
                        nestedLevel--;
                    }
                }
            }

            return from;
        }
        public TSQLOrderByClause Parse(TSQLTokenizer tokenizer)
        {
            TSQLOrderByClause orderBy = new TSQLOrderByClause();

            TSQLKeyword keyword = tokenizer.Current.AsKeyword;

            if (keyword == null ||
                keyword.Keyword != TSQLKeywords.ORDER)
            {
                throw new ApplicationException("ORDER expected.");
            }

            orderBy.Tokens.Add(keyword);

            // 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.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.Read())
                        {
                            if (
                                tokenizer.Current.Type == TSQLTokenType.Keyword &&
                                tokenizer.Current.AsKeyword.Keyword == TSQLKeywords.SELECT)
                            {
                                TSQLSelectStatement selectStatement = new TSQLSelectStatementParser().Parse(tokenizer);

                                orderBy.Tokens.AddRange(selectStatement.Tokens);

                                if (
                                    tokenizer.Current != null &&
                                    tokenizer.Current.Type == TSQLTokenType.Character &&
                                    tokenizer.Current.AsCharacter.Character == TSQLCharacters.CloseParentheses)
                                {
                                    nestedLevel--;
                                    orderBy.Tokens.Add(tokenizer.Current);
                                }
                            }
                            else
                            {
                                orderBy.Tokens.Add(tokenizer.Current);
                            }
                        }
                    }
                    else if (character == TSQLCharacters.CloseParentheses)
                    {
                        nestedLevel--;
                    }
                }
            }

            return orderBy;
        }