示例#1
0
        private SqlStatementListNode ParseBeginEndStatementList(ITokenizer t)
        {
            t.Expect(SqlTokenType.Keyword, "BEGIN");
            var statements = new SqlStatementListNode {
                UseBeginEnd = true
            };

            while (true)
            {
                var lookahead = t.Peek();
                if (lookahead.IsType(SqlTokenType.EndOfInput))
                {
                    throw ParsingException.CouldNotParseRule(nameof(ParseBeginEndStatementList), lookahead);
                }
                if (lookahead.Is(SqlTokenType.Keyword, "END"))
                {
                    t.GetNext();
                    break;
                }

                var statement = ParseStatement(t);
                if (statement == null)
                {
                    throw ParsingException.CouldNotParseRule(nameof(ParseBeginEndStatementList), t.Peek());
                }

                statements.Statements.Add(statement);
            }

            return(statements);
        }
示例#2
0
        private SqlOrderByEntryNode ParseOrderTerm(ITokenizer t)
        {
            // ( <QualifiedIdentifier> | <Number> ) ("ASC" | "DESC")?
            var identifier = ParseQualifiedIdentifier(t);

            if (identifier == null)
            {
                if (t.Peek().IsType(SqlTokenType.Number))
                {
                    var number = t.GetNext();
                    identifier = new SqlNumberNode(number);
                }
            }

            if (identifier == null)
            {
                throw ParsingException.CouldNotParseRule(nameof(ParseOrderTerm), t.Peek());
            }
            var entry = new SqlOrderByEntryNode
            {
                Location = identifier.Location,
                Source   = identifier
            };
            var next = t.Peek();

            if (next.IsKeyword("ASC") || next.IsKeyword("DESC"))
            {
                t.GetNext();
                entry.Direction = next.Value;
            }

            return(entry);
        }
示例#3
0
        private ISqlNode ParseTableOrSubexpression(ITokenizer t)
        {
            // <ObjectIdentifier> | <tableVariable> | "(" <QueryExpression> ")" | "(" <ValuesExpression> ")"
            var lookahead = t.Peek();

            // <ObjectIdentifier>
            if (lookahead.IsType(SqlTokenType.Identifier))
            {
                return(ParseObjectIdentifier(t));
            }

            // <tableVariable>
            if (lookahead.IsType(SqlTokenType.Variable))
            {
                return(new SqlVariableNode(t.GetNext()));
            }

            // "(" <Subexpression> ")"
            if (lookahead.Is(SqlTokenType.Symbol, "("))
            {
                return(ParseParenthesis(t, ParseSubexpression));
            }

            throw ParsingException.CouldNotParseRule(nameof(ParseTableOrSubexpression), lookahead);
        }
示例#4
0
        private ISqlNode ParseNumberOrVariable(ITokenizer t)
        {
            var next = t.GetNext();

            if (next.IsType(SqlTokenType.Variable))
            {
                return(new SqlVariableNode(next));
            }
            if (next.IsType(SqlTokenType.Number))
            {
                return(new SqlNumberNode(next));
            }

            throw ParsingException.CouldNotParseRule(nameof(ParseNumberOrVariable), next);
        }
        private ISqlNode ParseCaseExpression(ITokenizer t)
        {
            // "CASE" <Expression>? <When>+ <Else>? "END"
            var caseToken = t.Expect(SqlTokenType.Keyword, "CASE");
            var caseNode  = new SqlCaseNode
            {
                Location = caseToken.Location
            };

            if (!t.Peek().IsKeyword("WHEN"))
            {
                caseNode.InputExpression = ParseScalarExpression(t);
            }
            while (true)
            {
                var lookahead = t.Peek();
                if (lookahead.IsKeyword("END"))
                {
                    t.GetNext();
                    return(caseNode);
                }
                if (lookahead.IsKeyword("ELSE"))
                {
                    t.GetNext();
                    caseNode.ElseExpression = ParseScalarExpression(t);
                    t.Expect(SqlTokenType.Keyword, "END");
                    return(caseNode);
                }
                if (lookahead.IsKeyword("WHEN"))
                {
                    var whenNode  = t.GetNext();
                    var condition = ParseBooleanExpression(t);
                    t.Expect(SqlTokenType.Keyword, "THEN");
                    var result = ParseScalarExpression(t);
                    caseNode.WhenExpressions.Add(new SqlCaseWhenNode
                    {
                        Location  = whenNode.Location,
                        Condition = condition,
                        Result    = result
                    });
                    continue;
                }

                throw ParsingException.CouldNotParseRule(nameof(ParseCaseExpression), lookahead);
            }
        }
示例#6
0
        private ISqlNode ParseVariableOrQualifiedIdentifier(ITokenizer t)
        {
            var next = t.GetNext();

            // <Variable>
            if (next.IsType(SqlTokenType.Variable))
            {
                return(new SqlVariableNode(next));
            }
            t.PutBack(next);
            var identifier = ParseQualifiedIdentifier(t);

            if (identifier != null)
            {
                return(identifier);
            }

            throw ParsingException.CouldNotParseRule(nameof(ParseVariableOrQualifiedIdentifier), next);
        }
示例#7
0
        public ISqlNode ParseMergeMatched(ITokenizer t)
        {
            if (t.NextIs(SqlTokenType.Keyword, "UPDATE"))
            {
                var updateToken = t.Expect(SqlTokenType.Keyword, "UPDATE");
                var setList     = ParseUpdateSetClause(t);
                return(new SqlUpdateNode
                {
                    Location = updateToken.Location,
                    SetClause = setList
                });
            }
            if (t.NextIs(SqlTokenType.Keyword, "DELETE"))
            {
                var deleteToken = t.Expect(SqlTokenType.Keyword, "DELETE");
                return(new SqlKeywordNode(deleteToken));
            }

            throw ParsingException.CouldNotParseRule(nameof(ParseMergeMatched), t.Peek());
        }
示例#8
0
        private SqlSetNode ParseSet(ITokenizer t)
        {
            // <variable> ":=" <Expression>
            var v = t.GetNext();

            if (v.Type != SqlTokenType.Identifier && v.Type != SqlTokenType.Variable)
            {
                throw ParsingException.CouldNotParseRule(nameof(ParseSet), v);
            }
            var op   = t.Expect(SqlTokenType.Symbol, ":=");
            var expr = ParseScalarExpression(t);

            return(new SqlSetNode
            {
                Location = v.Location,
                Variable = new SqlIdentifierNode(v),
                Operator = new SqlOperatorNode(op),
                Right = expr
            });
        }
示例#9
0
        private ISqlNode ParseVariableOrConstant(ITokenizer t)
        {
            var next = t.GetNext();

            if (next.IsType(SqlTokenType.Variable))
            {
                return(new SqlVariableNode(next));
            }
            if (next.IsType(SqlTokenType.QuotedString))
            {
                return(new SqlStringNode(next));
            }
            t.PutBack(next);
            var number = ParseNumber(t);

            if (number != null)
            {
                return(number);
            }
            throw ParsingException.CouldNotParseRule(nameof(ParseVariableOrConstant), next);
        }
示例#10
0
        private ISqlNode ParseSubexpression(ITokenizer t)
        {
            // <QueryExpresion> | <Values>
            var      lookahead = t.Peek();
            ISqlNode expr      = null;

            if (lookahead.IsKeyword("SELECT"))
            {
                expr = ParseQueryExpression(t);
            }
            else if (lookahead.IsKeyword("VALUES"))
            {
                expr = ParseValues(t);
            }
            if (expr != null)
            {
                return(expr);
            }

            throw ParsingException.CouldNotParseRule(nameof(ParseSubexpression), lookahead);
        }
示例#11
0
        private SqlDataTypeNode ParseDataType(ITokenizer t)
        {
            // <Keyword> ("(" ("MAX" | <SizeList>)? ")")?
            var next = t.GetNext();

            // TODO: Array types
            // TODO: Should we add TABLE declaration parsing?
            if (next.IsKeyword("TABLE"))
            {
                return(null);
            }

            var dataType = new SqlDataTypeNode
            {
                Location = next.Location,
                DataType = new SqlKeywordNode(next),
            };

            if (t.Peek().IsSymbol("("))
            {
                t.GetNext();
                var lookahead = t.Peek();
                if (lookahead.IsKeyword("MAX"))
                {
                    dataType.Size = new SqlKeywordNode(t.GetNext());
                }
                else if (lookahead.IsType(SqlTokenType.Number))
                {
                    dataType.Size = ParseList(t, ParseNumber);
                }
                else
                {
                    throw ParsingException.CouldNotParseRule(nameof(ParseDataType), lookahead);
                }
                t.Expect(SqlTokenType.Symbol, ")");
            }
            return(dataType);
        }
示例#12
0
        // TODO: "GO" which starts a new logical block and also sets scope limits for variables

        private SqlStatementListNode ParseStatementList(ITokenizer t)
        {
            var statements = new SqlStatementListNode();

            while (true)
            {
                while (t.NextIs(SqlTokenType.Symbol, ";", true))
                {
                    ;
                }
                if (t.Peek().IsType(SqlTokenType.EndOfInput))
                {
                    break;
                }
                var statement = ParseStatement(t);
                if (statement == null)
                {
                    throw ParsingException.CouldNotParseRule(nameof(ParseStatement), t.Peek());
                }
                statements.Statements.Add(statement);
            }

            return(statements);
        }
        private ISqlNode ParseScalarExpression0(ITokenizer t)
        {
            // Terminal expression
            // <MethodCall> | <Identifier> | <Variable> | <String> | <Number> | "(" <Expression> ")"
            var next = t.Peek();

            if (next.IsKeyword("TARGET", "SOURCE"))
            {
                return(ParseQualifiedIdentifier(t));
            }

            if (next.IsKeyword("CAST", "CONVERT", "COUNT"))

            {
                var name = t.GetNext();
                if (t.Peek().IsSymbol("("))
                {
                    t.PutBack(name);
                    return(ParseFunctionCall(t));
                }

                throw ParsingException.CouldNotParseRule(nameof(ParseScalarExpression0), next);
            }

            if (next.IsType(SqlTokenType.Identifier))
            {
                var name = t.GetNext();
                if (t.Peek().IsSymbol("("))
                {
                    t.PutBack(name);
                    return(ParseFunctionCall(t));
                }

                t.PutBack(name);
                return(ParseQualifiedIdentifier(t));
            }

            if (next.IsType(SqlTokenType.Variable))
            {
                return(new SqlVariableNode(t.GetNext()));
            }
            if (next.IsType(SqlTokenType.QuotedString))
            {
                return(new SqlStringNode(t.GetNext()));
            }
            if (next.IsType(SqlTokenType.Number))
            {
                return(new SqlNumberNode(t.GetNext()));
            }

            if (next.IsSymbol("("))
            {
                // "(" (<QueryExpression> | <ScalarExpression>) ")"
                // e.g. SET @x = (select 5) or INSERT INTO x(num) VALUES (1, 2, (select 3))
                var value = ParseParenthesis(t, x =>
                {
                    if (x.Peek().IsKeyword("SELECT"))
                    {
                        return(ParseQueryExpression(t));
                    }
                    return(ParseScalarExpression(t));
                });
                if (value.Expression is SqlSelectNode)
                {
                    return(value);
                }
                return(value.Expression);
            }

            throw ParsingException.CouldNotParseRule(nameof(ParseScalarExpression0), next);
        }
示例#14
0
        private SqlOperatorNode ParseJoinOperator(ITokenizer t)
        {
            // "CROSS" ("APPLY" | "JOIN")
            // "NATURAL" "JOIN"
            // "INNER" "JOIN"
            // ("LEFT" | "RIGHT")?  "OUTER"?  "JOIN"

            var k = t.GetNext();

            if (!k.IsKeyword())
            {
                t.PutBack(k);
                return(null);
            }
            if (k.Value == "CROSS")
            {
                if (t.NextIs(SqlTokenType.Keyword, "APPLY", true))
                {
                    return(new SqlOperatorNode("CROSS APPLY", k.Location));
                }
                if (t.NextIs(SqlTokenType.Keyword, "JOIN", true))
                {
                    return(new SqlOperatorNode("CROSS JOIN", k.Location));
                }
                throw ParsingException.CouldNotParseRule(nameof(ParseJoinOperator), k);
            }
            if (k.Value == "NATURAL")
            {
                t.Expect(SqlTokenType.Keyword, "JOIN");
                return(new SqlOperatorNode("NATURAL JOIN", k.Location));
            }
            if (k.Value == "INNER")
            {
                t.Expect(SqlTokenType.Keyword, "JOIN");
                return(new SqlOperatorNode("INNER JOIN", k.Location));
            }

            var joinOperator = new List <SqlToken>();
            var location     = k.Location;

            if (k.Value == "FULL" || k.Value == "LEFT" || k.Value == "RIGHT")
            {
                joinOperator.Add(k);
                k = t.GetNext();
            }

            if (k.Value == "OUTER")
            {
                joinOperator.Add(k);
                k = t.GetNext();
                if (k.Value == "APPLY")
                {
                    return(new SqlOperatorNode("OUTER APPLY"));
                }
            }

            // TODO: hints: "MERGE" | "HASH" | "REDISTRIBUTE" | "REPLICATE" | "REDUCE"

            if (k.Value == "JOIN")
            {
                joinOperator.Add(k);
                var op = string.Join(" ", joinOperator.Select(j => j.Value));
                return(new SqlOperatorNode(op, location));
            }

            if (joinOperator.Count > 0)
            {
                throw ParsingException.CouldNotParseRule(nameof(ParseJoinOperator), k);
            }

            t.PutBack(k);
            return(null);
        }