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); }
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); }
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); }
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); } }
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); }
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()); }
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 }); }
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); }
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); }
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); }
// 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); }
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); }