public TSQLExpression Parse(ITSQLTokenizer tokenizer)
        {
            TSQLExpression expression = ParseNext(tokenizer);

            if (
                tokenizer.Current != null &&
                tokenizer.Current.Text != "*" &&
                tokenizer.Current.Type.In(
                    TSQLTokenType.Operator) &&

                // check for operator =, when expression type is column, and don't parse operator if found
                // e.g. IsFinishedGoods = p.FinishedGoodsFlag

                (
                    tokenizer.Current.Text != "=" ||
                    expression?.Type != TSQLExpressionType.Column
                ))
            {
                if (
                    expression?.Type == TSQLExpressionType.Variable &&

                    // https://docs.microsoft.com/en-us/sql/t-sql/language-elements/compound-operators-transact-sql

                    new string[] {
                    "=",
                    "+=",
                    "-=",
                    "*=",
                    "/=",
                    "%=",
                    "&=",
                    "|="
                }.Contains(tokenizer.Current.AsOperator.Text))
                {
                    return(new TSQLVariableAssignmentExpressionParser().Parse(
                               tokenizer,
                               expression.AsVariable));
                }
                else
                {
                    return(new TSQLOperatorExpressionParser().Parse(
                               tokenizer,
                               expression));
                }
            }
            else
            {
                return(expression);
            }
        }
Exemplo n.º 2
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 void SelectStatement_MultiLevelParens()
        {
            string query = "SELECT ((A/B)-1) FROM SomeTable";
            List <TSQLStatement> statements = TSQLStatementReader.ParseStatements(query);

            Assert.AreEqual(1, statements.Count);
            Assert.AreEqual(TSQLStatementType.Select, statements[0].Type);
            TSQLSelectStatement selectStatement = statements[0].AsSelect;

            Assert.AreEqual(12, selectStatement.Tokens.Count);
            TSQLSelectClause selectClause = selectStatement.Select;

            Assert.AreEqual(1, selectClause.Columns.Count);
            // outer parens
            TSQLExpression lvl1Expression = selectClause.Columns[0].Expression;

            Assert.AreEqual(TSQLExpressionType.Grouped, lvl1Expression.Type);
            // contents of outer parens
            TSQLExpression lvl2Expression = lvl1Expression.AsGrouped.InnerExpression;

            Assert.AreEqual(TSQLExpressionType.Operator, lvl2Expression.Type);
            Assert.AreEqual("-", lvl2Expression.AsOperator.Operator.Text);
            // (A/B)
            TSQLExpression lvl2aExpression = lvl2Expression.AsOperator.LeftSide;
            // 1
            TSQLExpression lvl2bExpression = lvl2Expression.AsOperator.RightSide;

            Assert.AreEqual(TSQLExpressionType.Grouped, lvl2aExpression.Type);
            Assert.AreEqual(TSQLExpressionType.Constant, lvl2bExpression.Type);
            Assert.AreEqual(1, lvl2bExpression.AsConstant.Literal.AsNumericLiteral.Value);
            // A/B
            TSQLExpression lvl3Expression = lvl2aExpression.AsGrouped.InnerExpression;

            Assert.AreEqual(TSQLExpressionType.Operator, lvl3Expression.Type);
            Assert.AreEqual("/", lvl3Expression.AsOperator.Operator.Text);
            // A
            TSQLExpression lvl3aExpression = lvl3Expression.AsOperator.LeftSide;
            // B
            TSQLExpression lvl3bExpression = lvl3Expression.AsOperator.RightSide;

            Assert.AreEqual(TSQLExpressionType.Column, lvl3aExpression.Type);
            Assert.AreEqual("A", lvl3aExpression.AsColumn.Column.Name);
            Assert.IsNull(lvl3aExpression.AsColumn.TableReference);
            Assert.AreEqual(TSQLExpressionType.Column, lvl3bExpression.Type);
            Assert.AreEqual("B", lvl3bExpression.AsColumn.Column.Name);
            Assert.IsNull(lvl3bExpression.AsColumn.TableReference);
        }
        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);
        }
Exemplo n.º 5
0
        public TSQLExpression Parse(ITSQLTokenizer tokenizer)
        {
            TSQLExpression expression = ParseNext(tokenizer);

            if (
                tokenizer.Current != null &&
                tokenizer.Current.Text != "*" &&
                tokenizer.Current.Type.In(
                    TSQLTokenType.Operator))
            {
                return(new TSQLOperatorExpressionParser().Parse(
                           tokenizer,
                           expression));
            }
            else
            {
                return(expression);
            }
        }
Exemplo n.º 6
0
        public static void RecurseParens(
            ITSQLTokenizer tokenizer,
            TSQLExpression expression,
            ref int nestedLevel)
        {
            if (tokenizer.Current.Type == TSQLTokenType.Character)
            {
                expression.Tokens.Add(tokenizer.Current);

                TSQLCharacters character = tokenizer.Current.AsCharacter.Character;

                if (character == TSQLCharacters.OpenParentheses)
                {
                    // should we recurse for correlated subqueries?
                    nestedLevel++;
                }
                else if (character == TSQLCharacters.CloseParentheses)
                {
                    nestedLevel--;
                }
            }
            else if (tokenizer.Current.IsKeyword(TSQLKeywords.CASE))
            {
                // not going to add CASE token directly because it will be contained
                // within the returned expression and we don't want to double up the
                // CASE token within the results.

                // CASE is a special situation because it's stop word (END) is part of
                // the expression itself and needs to be included in it's token list.
                // all other clauses stop at the beginning of the next clause and do
                // not include the stop token within their token list.
                TSQLCaseExpression caseExpression = new TSQLCaseExpressionParser().Parse(tokenizer);

                expression.Tokens.AddRange(caseExpression.Tokens);
            }
            else
            {
                expression.Tokens.Add(tokenizer.Current);
            }
        }
Exemplo n.º 7
0
        /// <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,
            TSQLExpression expression,
            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()
                            )
                    )
                ))
            {
                TSQLSubqueryHelper.RecurseParens(
                    tokenizer,
                    expression,
                    ref nestedLevel);
            }
        }
Exemplo n.º 8
0
        public static void RecurseParens(
            ITSQLTokenizer tokenizer,
            TSQLExpression expression,
            ref int nestedLevel)
        {
            expression.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.MoveNext())
                    {
                        if (tokenizer.Current.IsKeyword(
                                TSQLKeywords.SELECT))
                        {
                            TSQLSelectStatement selectStatement = new TSQLSelectStatementParser(tokenizer).Parse();

                            expression.Tokens.AddRange(selectStatement.Tokens);

                            if (tokenizer.Current.IsCharacter(
                                    TSQLCharacters.CloseParentheses))
                            {
                                nestedLevel--;
                                expression.Tokens.Add(tokenizer.Current);
                            }
                        }
                        else if (tokenizer.Current.IsCharacter(
                                     TSQLCharacters.CloseParentheses))
                        {
                            nestedLevel--;
                            expression.Tokens.Add(tokenizer.Current);
                        }
                        else if (tokenizer.Current.IsCharacter(
                                     TSQLCharacters.OpenParentheses))
                        {
                            nestedLevel++;
                            expression.Tokens.Add(tokenizer.Current);
                        }
                        else
                        {
                            expression.Tokens.Add(tokenizer.Current);
                        }
                    }
                }
                else if (character == TSQLCharacters.CloseParentheses)
                {
                    nestedLevel--;
                }
            }
            else if (tokenizer.Current.IsKeyword(TSQLKeywords.CASE))
            {
                TSQLCaseExpression caseExpression = new TSQLCaseExpressionParser().Parse(tokenizer);

                expression.Tokens.AddRange(caseExpression.Tokens);
            }
        }