예제 #1
0
        public SqlInsertNode ParseMergeNotMatched(ITokenizer t)
        {
            var insertToken = t.Expect(SqlTokenType.Keyword, "INSERT");
            var insertNode  = new SqlInsertNode
            {
                Location = insertToken.Location,
                Columns  = ParseInsertColumnList(t)
            };

            var next = t.Peek();

            if (next.IsKeyword("VALUES"))
            {
                insertNode.Source = ParseValues(t);
            }
            else if (next.IsKeyword("DEFAULT"))
            {
                t.GetNext();
                t.Expect(SqlTokenType.Keyword, "VALUES");
                insertNode.Source = new SqlKeywordNode("DEFAULT VALUES");
            }
            else
            {
                throw new ParsingException("INSERT statement does not have a source");
            }

            return(insertNode);
        }
예제 #2
0
        private ISqlNode ParseInsertOnConflictClause(ITokenizer t)
        {
            if (!t.Peek().IsKeyword("ON"))
            {
                return(null);
            }

            t.GetNext();
            t.Expect(SqlTokenType.Keyword, "CONFLICT");
            t.Expect(SqlTokenType.Keyword, "DO");

            var next = t.Peek();

            if (next.IsKeyword("NOTHING"))
            {
                return(new SqlKeywordNode(t.GetNext()));
            }
            if (next.IsKeyword("UPDATE"))
            {
                var updateToken = t.Expect(SqlTokenType.Keyword, "UPDATE");
                return(new SqlUpdateNode
                {
                    Location = updateToken.Location,
                    SetClause = ParseUpdateSetClause(t),
                    WhereClause = ParseWhereClause(t)
                });
            }

            throw new ParsingException("Cannot parse INSERT ... ON CONFLICT clause. Unexpected token " + next);
        }
        private ISqlNode ParseFunctionCall(ITokenizer t)
        {
            var name = t.GetNext();

            if (name.Type != SqlTokenType.Keyword && name.Type != SqlTokenType.Identifier)
            {
                throw ParsingException.UnexpectedToken(SqlTokenType.Identifier, name);
            }

            // "COUNT" "(" "*" ")"
            if (name.IsKeyword("COUNT"))
            {
                var openParen = t.Expect(SqlTokenType.Symbol, "(");
                var maybeStar = t.Peek();
                if (maybeStar.IsSymbol("*"))
                {
                    t.GetNext();
                    t.Expect(SqlTokenType.Symbol, ")");
                    return(new SqlFunctionCallNode
                    {
                        Location = name.Location,
                        Name = new SqlKeywordNode(name),
                        Arguments = new SqlListNode <ISqlNode> {
                            new SqlOperatorNode(maybeStar)
                        }
                    });
                }

                // It's not *, so put everything back, fallthrough, and let the rest of the parsing happen
                t.PutBack(openParen);
            }

            // TODO: "CONVERT" "(" <DataType>, <ScalarExpression> ("," <int>)? ")"
            // "CAST" "(" <ScalarExpression> "AS" <DataType> ")"
            if (name.IsKeyword("CAST"))
            {
                t.Expect(SqlTokenType.Symbol, "(");
                var first = ParseScalarExpression(t);
                t.Expect(SqlTokenType.Keyword, "AS");
                var type = ParseDataType(t);
                t.Expect(SqlTokenType.Symbol, ")");
                return(new SqlCastNode
                {
                    Location = name.Location,
                    Expression = first,
                    DataType = type
                });
            }

            // <Name> "(" <ScalarExpressionList> ")"
            return(new SqlFunctionCallNode
            {
                Location = name.Location,
                Name = Facts.IsBuiltInFunctionName(name.Value) ? (ISqlNode) new SqlKeywordNode(name.Value.ToUpperInvariant(), name.Location) : new SqlIdentifierNode(name),
                Arguments = ParseParenthesis(t, x => ParseList(x, ParseScalarExpression)).Expression
            });
        }
예제 #4
0
        private SqlObjectIdentifierNode ParseObjectIdentifier(ITokenizer t)
        {
            // (((<ServerName> ".")? <DatabaseName> ".")? <Schema> ".")? <Identifier>
            var item1 = t.Expect(SqlTokenType.Identifier);

            if (!t.NextIs(SqlTokenType.Symbol, ".", true))
            {
                return(new SqlObjectIdentifierNode
                {
                    Location = item1.Location,
                    Name = new SqlIdentifierNode(item1)
                });
            }

            var item2 = t.Expect(SqlTokenType.Identifier);

            if (!t.NextIs(SqlTokenType.Symbol, ".", true))
            {
                return(new SqlObjectIdentifierNode
                {
                    Location = item1.Location,
                    Schema = new SqlIdentifierNode(item1),
                    Name = new SqlIdentifierNode(item2)
                });
            }

            var item3 = t.Expect(SqlTokenType.Identifier);

            if (!t.NextIs(SqlTokenType.Symbol, ".", true))
            {
                return(new SqlObjectIdentifierNode
                {
                    Location = item1.Location,
                    Database = new SqlIdentifierNode(item1),
                    Schema = new SqlIdentifierNode(item2),
                    Name = new SqlIdentifierNode(item3)
                });
            }

            var item4 = t.Expect(SqlTokenType.Identifier);

            return(new SqlObjectIdentifierNode
            {
                Location = item1.Location,
                Server = new SqlIdentifierNode(item1),
                Database = new SqlIdentifierNode(item2),
                Schema = new SqlIdentifierNode(item3),
                Name = new SqlIdentifierNode(item4)
            });
        }
예제 #5
0
        private ISqlNode ParseSelectFetchClause(ITokenizer t)
        {
            if (!t.NextIs(SqlTokenType.Keyword, "FETCH"))
            {
                return(null);
            }

            t.GetNext();
            t.Expect(SqlTokenType.Keyword, "FIRST", "NEXT");
            var fetch = ParseNumberOrVariable(t);

            t.Expect(SqlTokenType.Keyword, "ROW", "ROWS");
            t.Expect(SqlTokenType.Keyword, "ONLY");
            return(fetch);
        }
예제 #6
0
        private ISqlNode ParseQuerySpecificiation(ITokenizer t)
        {
            // "SELECT" ...
            var selectToken = t.Expect(SqlTokenType.Keyword, "SELECT");
            var selectNode  = new SqlSelectNode
            {
                Location = selectToken.Location
            };

            var modifier = t.Peek();

            if (modifier.IsKeyword("ALL") || modifier.IsKeyword("DISTINCT"))
            {
                t.GetNext();
                selectNode.Modifier = modifier.Value;
            }

            selectNode.Columns        = ParseList(t, ParseSelectColumn);
            selectNode.FromClause     = ParseSelectFromClause(t);
            selectNode.WhereClause    = ParseWhereClause(t);
            selectNode.GroupByClause  = ParseSelectGroupByClause(t);
            selectNode.HavingClause   = ParseSelectHavingClause(t);
            selectNode.OrderByClause  = ParseSelectOrderByClause(t);
            selectNode.TopLimitClause = ParseSelectLimitClause(t);
            selectNode.OffsetClause   = ParseSelectOffsetClause(t);
            selectNode.FetchClause    = ParseSelectFetchClause(t);

            return(selectNode);
        }
예제 #7
0
        private ISqlNode ParseJoin(ITokenizer t)
        {
            // <TableExpression> (<JoinOperator> <TableExpression> "ON" <JoinCondition>)?
            // TODO: <TableExpression> ("WITH" <Hint>)?
            var tableExpression1 = ParseMaybeAliasedTable(t, ParseTableOrSubexpression);

            var join = ParseJoinOperator(t);

            if (join == null)
            {
                return(tableExpression1);
            }
            var tableExpression2 = ParseMaybeAliasedTable(t, ParseTableOrSubexpression);

            ISqlNode condition = null;

            if (join.Operator != "NATURAL JOIN")
            {
                // "ON" <BooleanExpression>
                t.Expect(SqlTokenType.Keyword, "ON");
                condition = ParseBooleanExpression(t);
            }

            return(new SqlJoinNode
            {
                Location = tableExpression1.Location,
                Left = tableExpression1,
                Operator = join,
                Right = tableExpression2,
                OnCondition = condition
            });
        }
예제 #8
0
        private SqlTopLimitNode ParseSelectTopClause(ITokenizer t)
        {
            // "TOP" "(" <Number> | <Variable> ")" "PERCENT"? "WITH TIES"?
            // "TOP" <Number> | <Variable> "PERCENT"? "WITH TIES"?
            if (!t.NextIs(SqlTokenType.Keyword, "TOP"))
            {
                return(null);
            }

            var topToken = t.GetNext();

            var numberOrVariable = ParseMaybeParenthesis(t, ParseNumberOrVariable);

            bool percent  = t.NextIs(SqlTokenType.Keyword, "PERCENT", true);
            bool withTies = false;

            if (t.NextIs(SqlTokenType.Keyword, "WITH", true))
            {
                t.Expect(SqlTokenType.Keyword, "TIES");
                withTies = true;
            }

            return(new SqlTopLimitNode {
                Location = topToken.Location,
                Value = numberOrVariable,
                Percent = percent,
                WithTies = withTies
            });
        }
예제 #9
0
        private SqlInfixOperationNode ParseUpdateColumnAssignExpression(ITokenizer t)
        {
            // (<Column> | <Variable>) <CompareOp> ("DEFAULT" | <Expression>)
            var columnName = ParseVariableOrQualifiedIdentifier(t);
            // TODO: Other assignment operators
            var      opToken = t.Expect(SqlTokenType.Symbol, "=", "+=", "-=", "*=", "/=", "%=", "&=", "^=", "|=");
            ISqlNode rvalue;
            var      lookahead = t.Peek();

            if (lookahead.Is(SqlTokenType.Keyword, "DEFAULT"))
            {
                t.GetNext();
                rvalue = new SqlKeywordNode(lookahead);
            }
            else
            {
                rvalue = ParseScalarExpression(t);
            }
            return(new SqlInfixOperationNode
            {
                Left = columnName,
                Location = columnName.Location,
                Operator = new SqlOperatorNode(opToken),
                Right = rvalue
            });
        }
예제 #10
0
        private ISqlNode ParseMaybeAliasedScalar(ITokenizer t, Func <ITokenizer, ISqlNode> parse)
        {
            var node = parse(t);

            var next = t.Peek();

            if (next.IsKeyword("AS"))
            {
                var asToken = t.GetNext();
                var alias   = t.Expect(SqlTokenType.Identifier);
                return(new SqlAliasNode
                {
                    Location = asToken.Location,
                    Source = node,
                    Alias = new SqlIdentifierNode(alias)
                });
            }
            if (next.IsType(SqlTokenType.Identifier))
            {
                t.GetNext();
                return(new SqlAliasNode
                {
                    Location = node.Location,
                    Source = node,
                    Alias = new SqlIdentifierNode(next)
                });
            }

            return(node);
        }
예제 #11
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);
        }
예제 #12
0
        private SqlSetNode ParseSet(ITokenizer t)
        {
            // "SET" <variable> <assignOp> <Expression>
            var setToken = t.Expect(SqlTokenType.Keyword, "SET");
            var v        = t.Expect(SqlTokenType.Variable);
            var op       = t.Expect(SqlTokenType.Symbol, "=", "+=", "-=", "*=", "/=", "%=", "&=", "^=", "|=");
            var expr     = ParseScalarExpression(t);

            return(new SqlSetNode
            {
                Location = setToken.Location,
                Variable = new SqlVariableNode(v),
                Operator = new SqlOperatorNode(op),
                Right = expr
            });
        }
예제 #13
0
        private SqlListNode <SqlInfixOperationNode> ParseUpdateSetClause(ITokenizer t)
        {
            t.Expect(SqlTokenType.Keyword, "SET");
            var setList = ParseList(t, ParseUpdateColumnAssignExpression);

            return(setList);
        }
예제 #14
0
        public ISqlNode ParseExecute(ITokenizer t)
        {
            // ("EXEC"|"EXECUTE") ( <stringExpression> | <objectIdentifier> <ListOfArgument> )
            // TODO: @return_status = ...
            // TODO: WITH <execute_option>
            var execToken = t.Expect(SqlTokenType.Keyword, "EXEC", "EXECUTE");
            var execNode  = new SqlExecuteNode()
            {
                Location = execToken.Location,
            };

            if (t.Peek().IsType(SqlTokenType.Identifier))
            {
                execNode.Name      = ParseObjectIdentifier(t);
                execNode.Arguments = ParseList(t, ParseExecArgument);
                return(execNode);
            }

            bool isParenthesis    = t.Peek().IsSymbol("(");
            var  stringExpression = ParseScalarTerm(t);

            if (isParenthesis)
            {
                stringExpression = new SqlParenthesisNode <ISqlNode>(stringExpression);
            }
            execNode.Name = stringExpression;
            return(execNode);
        }
예제 #15
0
        private ISqlNode ParseInsertStatement(ITokenizer t)
        {
            // "INSERT" "INTO" <ObjectIdOrVariable> "(" <ColumnList> ")" <ValuesOrSelect>
            var insertToken = t.Expect(SqlTokenType.Keyword, "INSERT");

            t.Expect(SqlTokenType.Keyword, "INTO");

            var insertNode = new SqlInsertNode
            {
                Location = insertToken.Location,
                Table    = ParseObjectIdentifier(t),
                Columns  = ParseInsertColumnList(t)
            };

            // TODO: OUTPUT Clause

            var next = t.Peek();

            if (next.IsKeyword("VALUES"))
            {
                insertNode.Source = ParseValues(t);
            }
            else if (next.IsKeyword("SELECT"))
            {
                insertNode.Source = ParseQueryExpression(t);
            }
            else if (next.IsKeyword("EXEC", "EXECUTE"))
            {
                insertNode.Source = ParseExecute(t);
            }
            else if (next.IsKeyword("DEFAULT"))
            {
                t.GetNext();
                t.Expect(SqlTokenType.Keyword, "VALUES");
                insertNode.Source = new SqlKeywordNode("DEFAULT VALUES");
            }
            else
            {
                throw new ParsingException("INSERT INTO statement does not have a source");
            }

            insertNode.OnConflict = ParseInsertOnConflictClause(t);

            // TODO: RETURNING clause

            return(insertNode);
        }
        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);
            }
        }
예제 #17
0
        public SqlMergeNode ParseMergeStatement(ITokenizer t)
        {
            var mergeToken = t.Expect(SqlTokenType.Keyword, "MERGE");
            var mergeNode  = new SqlMergeNode
            {
                Location = mergeToken.Location
            };

            // TODO: "TOP" <maybeParenVariableOrNumericExpression> "PERCENT"?

            t.NextIs(SqlTokenType.Keyword, "INTO", true);
            mergeNode.Target = ParseMaybeAliasedTable(t, ParseObjectIdentifier);
            t.Expect(SqlTokenType.Keyword, "USING");
            mergeNode.Source = ParseMaybeAliasedTable(t, ParseObjectIdentifier);
            t.Expect(SqlTokenType.Keyword, "ON");
            mergeNode.MergeCondition = ParseBooleanExpression(t);
            while (true)
            {
                var whenClauseToken = t.MaybeGetKeywordSequence("WHEN", "NOT", "MATCHED", "BY", "SOURCE", "TARGET");
                if (whenClauseToken == null)
                {
                    break;
                }
                // TODO: "AND" <clauseSearchCondition>
                t.Expect(SqlTokenType.Keyword, "THEN");
                if (whenClauseToken.Value == "WHEN MATCHED")
                {
                    // TODO: Allow multiple
                    mergeNode.Matched = ParseMergeMatched(t);
                }
                else if (whenClauseToken.Value == "WHEN NOT MATCHED" || whenClauseToken.Value == "WHEN NOT MATCHED BY TARGET")
                {
                    mergeNode.NotMatchedByTarget = ParseMergeNotMatched(t);
                }
                else if (whenClauseToken.Value == "WHEN NOT MATCHED BY SOURCE")
                {
                    // TODO: Allow multiple
                    mergeNode.NotMatchedBySource = ParseMergeMatched(t);
                }
            }
            // TODO: Output clause
            // TODO: OPTION clause
            return(mergeNode);
        }
예제 #18
0
 private ISqlNode ParseOverOrderBy(ITokenizer t)
 {
     // "ORDER" "BY" <OrderByTerm> ("," <OrderByTerm>)*
     if (!t.NextIs(SqlTokenType.Keyword, "ORDER", true))
     {
         return(null);
     }
     t.Expect(SqlTokenType.Keyword, "BY");
     return(ParseList(t, ParseOrderTerm));
 }
예제 #19
0
 private ISqlNode ParseOverPartitionBy(ITokenizer t)
 {
     // "PARTITION" "BY" <Expr> ("," <Expr>)*
     if (!t.NextIs(SqlTokenType.Keyword, "PARTITION", true))
     {
         return(null);
     }
     t.Expect(SqlTokenType.Keyword, "BY");
     return(ParseList(t, ParseScalarExpression));
 }
예제 #20
0
        private ISqlNode ParseValues(ITokenizer t)
        {
            // "VALUES" "(" <ValueList> ")" ("," "(" <ValueList> ")")*
            var valuesToken = t.Expect(SqlTokenType.Keyword, "VALUES");

            return(new SqlValuesNode
            {
                Location = valuesToken.Location,
                Values = ParseList(t, a => ParseParenthesis(a, b => ParseList(b, ParseVariableOrConstant)).Expression)
            });
        }
예제 #21
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());
        }
예제 #22
0
        private ISqlNode ParseSelectOffsetClause(ITokenizer t)
        {
            if (!t.NextIs(SqlTokenType.Keyword, "OFFSET"))
            {
                return(null);
            }
            t.GetNext();
            var offset = ParseNumberOrVariable(t);

            t.Expect(SqlTokenType.Keyword, "ROW", "ROWS");
            return(offset);
        }
예제 #23
0
        private ISqlNode ParseWithStatement(ITokenizer t)
        {
            // "WITH" <Cte> ("," <Cte>)* <WithChildStatement>
            var with = new SqlWithNode();

            t.Expect(SqlTokenType.Keyword, "WITH");
            with.Ctes = ParseList(t, ParseCte);
            var statement = ParseWithChildStatement(t);

            with.Statement = statement;
            return(with);
        }
예제 #24
0
        private ISqlNode ParseSelectGroupByClause(ITokenizer t)
        {
            // "GROUP" "BY" <IdentifierList>
            if (!t.NextIs(SqlTokenType.Keyword, "GROUP"))
            {
                return(null);
            }
            t.GetNext();
            t.Expect(SqlTokenType.Keyword, "BY");

            return(ParseList(t, ParseQualifiedIdentifier));
        }
예제 #25
0
        private SqlDeclareNode ParseDeclare(ITokenizer t)
        {
            // "DECLARE" <identifier> <DataType> (":=" <Expression>)?
            // TODO: "DECLARE" <identifier> <DataType> (":=" <Expression>)? ("," <identifier> <DataType> (":=" <Expression>)?)*
            var declare = t.Expect(SqlTokenType.Keyword, "DECLARE");
            var v       = t.Expect(SqlTokenType.Identifier);
            // TODO: Improve data type parsing
            var dataType    = ParseDataType(t);
            var declareNode = new SqlDeclareNode
            {
                Location = declare.Location,
                DataType = dataType,
                Variable = new SqlIdentifierNode(v)
            };

            if (t.NextIs(SqlTokenType.Symbol, ":=", true))
            {
                declareNode.Initializer = ParseScalarExpression(t);
            }
            return(declareNode);
        }
예제 #26
0
        private SqlParenthesisNode <TNode> ParseParenthesis <TNode>(ITokenizer t, Func <ITokenizer, TNode> parse)
            where TNode : class, ISqlNode
        {
            var openingParen = t.Expect(SqlTokenType.Symbol, "(");

            if (t.Peek().IsSymbol(")"))
            {
                t.GetNext();
                return(new SqlParenthesisNode <TNode>
                {
                    Location = openingParen.Location
                });
            }
            var value = parse(t);

            t.Expect(SqlTokenType.Symbol, ")");
            return(new SqlParenthesisNode <TNode>
            {
                Location = openingParen.Location,
                Expression = value
            });
        }
예제 #27
0
        private SqlWithCteNode ParseCte(ITokenizer t)
        {
            // <identifier> ("(" <columnList> ")")? "AS" "(" <QueryExpression> ")"
            var name    = t.Expect(SqlTokenType.Identifier);
            var cteNode = new SqlWithCteNode
            {
                Location  = name.Location,
                Name      = new SqlIdentifierNode(name),
                Recursive = false
            };

            var lookahead = t.Peek();

            if (lookahead.IsSymbol("("))
            {
                cteNode.ColumnNames = ParseParenthesis(t, x => ParseList(x, ParseIdentifier)).Expression;
            }

            t.Expect(SqlTokenType.Keyword, "AS");
            cteNode.Select = ParseParenthesis(t, ParseQueryExpression).Expression;
            cteNode.DetectRecursion();
            return(cteNode);
        }
예제 #28
0
        private ISqlNode ParseSelectColumnExpression(ITokenizer t)
        {
            var expr      = ParseScalarExpression(t);
            var lookahead = t.Peek();

            if (lookahead.IsKeyword("OVER"))
            {
                // "OVER" "(" <OverPartitionBy>? <OverOrderBy>? <OverRows>? ")"
                var overToken = t.GetNext();
                t.Expect(SqlTokenType.Symbol, "(");
                var overNode = new SqlOverNode
                {
                    Location    = overToken.Location,
                    Expression  = expr,
                    PartitionBy = ParseOverPartitionBy(t),
                    OrderBy     = ParseOverOrderBy(t),
                    RowsRange   = ParseOverRows(t)
                };
                t.Expect(SqlTokenType.Symbol, ")");
                return(overNode);
            }

            return(expr);
        }
예제 #29
0
        private SqlWithCteNode ParseCte(ITokenizer t)
        {
            // "RECURSIVE"? <identifier> ("(" <columnList> ")")? "AS" "(" <QueryExpression> ")"
            bool isRecursive = t.NextIs(SqlTokenType.Keyword, "RECURSIVE", true);
            var  name        = t.Expect(SqlTokenType.Identifier);
            var  cteNode     = new SqlWithCteNode
            {
                Location  = name.Location,
                Name      = new SqlIdentifierNode(name),
                Recursive = isRecursive
            };

            var lookahead = t.Peek();

            if (lookahead.IsSymbol("("))
            {
                cteNode.ColumnNames = ParseParenthesis(t, x => ParseList(x, ParseIdentifier)).Expression;
            }

            t.Expect(SqlTokenType.Keyword, "AS");
            // TODO: The CTE can contain INSERT, UPDATE and DELETE statements as well (usually with the RETURNING clause)
            cteNode.Select = ParseParenthesis(t, ParseQueryExpression).Expression;
            return(cteNode);
        }
예제 #30
0
        private ISqlNode ParseBooleanExpression3(ITokenizer t)
        {
            // "(" <BooleanExpression> ")
            // <BooleanExpression2>
            var lookahead = t.Peek();

            if (lookahead.IsSymbol("("))
            {
                t.GetNext();
                var value = ParseBooleanExpression(t);
                t.Expect(SqlTokenType.Symbol, ")");
                return(value);
            }

            return(ParseBooleanExpression2(t));
        }