public void SelectClause_Comments()
        {
            using (StringReader reader = new StringReader(
                       @"select top 1
					oh.TaxAmt / oh.SubTotal /* tax percent */
				from
					Sales.SalesOrderHeader oh;"                    ))
                using (ITSQLTokenizer tokenizer = new TSQLTokenizer(reader))
                {
                    Assert.IsTrue(tokenizer.MoveNext());

                    TSQLSelectClause select = new TSQLSelectClauseParser().Parse(tokenizer);
                    Assert.AreEqual(11, select.Tokens.Count);
                    Assert.AreEqual(TSQLKeywords.FROM, tokenizer.Current.AsKeyword.Keyword);

                    Assert.AreEqual(1, select.Columns.Count);
                    Assert.IsNull(select.Columns[0].ColumnAlias);
                    Assert.AreEqual(TSQLExpressionType.Operator, select.Columns[0].Expression.Type);

                    TSQLOperatorExpression operatorExpression = select.Columns[0].Expression.AsOperator;
                    Assert.AreEqual("/", operatorExpression.Operator.Text);
                    Assert.AreEqual(TSQLExpressionType.Column, operatorExpression.LeftSide.Type);

                    TSQLColumnExpression leftSide = operatorExpression.LeftSide.AsColumn;
                    Assert.AreEqual("oh", leftSide.TableReference.Single().AsIdentifier.Name);
                    Assert.AreEqual("TaxAmt", leftSide.Column.Name);
                    Assert.AreEqual(TSQLExpressionType.Column, operatorExpression.RightSide.Type);

                    TSQLColumnExpression rightSide = operatorExpression.RightSide.AsColumn;
                    Assert.AreEqual("oh", rightSide.TableReference.Single().AsIdentifier.Name);
                    Assert.AreEqual("SubTotal", rightSide.Column.Name);
                    Assert.AreEqual(" tax percent ", select.Columns.Last().Tokens.Last().AsMultilineComment.Comment);
                }
        }
        public void SelectClause_UnaryOperator()
        {
            using (StringReader reader = new StringReader(
                       @"SELECT
					+1;"                    ))
                using (ITSQLTokenizer tokenizer = new TSQLTokenizer(reader))
                {
                    Assert.IsTrue(tokenizer.MoveNext());

                    TSQLSelectClause select = new TSQLSelectClauseParser().Parse(tokenizer);
                    Assert.AreEqual(3, select.Tokens.Count);
                    Assert.IsTrue(tokenizer.Current.IsCharacter(TSQLCharacters.Semicolon));

                    Assert.AreEqual(1, select.Columns.Count);

                    TSQLSelectColumn column = select.Columns[0];

                    Assert.IsNull(column.ColumnAlias);
                    Assert.AreEqual(TSQLExpressionType.Operator, column.Expression.Type);

                    TSQLOperatorExpression tsqlOperator = column.Expression.AsOperator;

                    Assert.AreEqual("+", tsqlOperator.Operator.Text);
                    Assert.IsNull(tsqlOperator.LeftSide);

                    Assert.AreEqual(TSQLExpressionType.Constant, tsqlOperator.RightSide.Type);
                    Assert.AreEqual(1, tsqlOperator.RightSide.AsConstant.Literal.AsNumericLiteral.Value);
                }
        }
        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);
        }
        public void OperatorExpression_Simple()
        {
            TSQLTokenizer tokenizer = new TSQLTokenizer(
                "+ 2 - 3")
            {
                IncludeWhitespace = true
            };

            TSQLConstantExpression leftSide = new TSQLConstantExpression()
            {
                Literal = new TSQLNumericLiteral(
                    0,
                    "1")
            };

            leftSide.Tokens.Add(leftSide.Literal);

            Assert.IsTrue(tokenizer.MoveNext());

            TSQLOperatorExpression op = new TSQLOperatorExpressionParser().Parse(
                tokenizer,
                leftSide);

            Assert.AreSame(leftSide, op.LeftSide);
            TokenComparisons.CompareTokenLists(
                new List <TSQLToken>()
            {
                // bogus begin position because we made it up
                new TSQLNumericLiteral(0, "1"),

                new TSQLOperator(0, "+"),
                new TSQLWhitespace(1, " "),
                new TSQLNumericLiteral(2, "2"),
                new TSQLWhitespace(3, " "),
                new TSQLOperator(4, "-"),
                new TSQLWhitespace(5, " "),
                new TSQLNumericLiteral(6, "3")
            },
                op.Tokens);

            Assert.AreEqual("+", op.Operator.Text);

            Assert.AreEqual(TSQLExpressionType.Operator, op.RightSide.Type);
            TSQLOperatorExpression rightSide = op.RightSide.AsOperator;

            TokenComparisons.CompareTokenLists(
                new List <TSQLToken>()
            {
                new TSQLNumericLiteral(2, "2"),
                new TSQLWhitespace(3, " "),
                new TSQLOperator(4, "-"),
                new TSQLWhitespace(5, " "),
                new TSQLNumericLiteral(6, "3")
            },
                rightSide.Tokens);

            Assert.AreEqual("-", rightSide.Operator.Text);

            Assert.AreEqual(TSQLExpressionType.Constant, rightSide.LeftSide.Type);
            TSQLConstantExpression leftNumber = rightSide.LeftSide.AsConstant;

            TokenComparisons.CompareTokenLists(
                new List <TSQLToken>()
            {
                new TSQLNumericLiteral(2, "2"),
                new TSQLWhitespace(3, " ")
            },
                leftNumber.Tokens);
            Assert.AreEqual(TSQLTokenType.NumericLiteral, leftNumber.Literal.Type);
            Assert.AreEqual(2, leftNumber.Literal.AsNumericLiteral.Value);

            Assert.AreEqual(TSQLExpressionType.Constant, rightSide.RightSide.Type);
            TSQLConstantExpression rightNumber = rightSide.RightSide.AsConstant;

            TokenComparisons.CompareTokenLists(
                new List <TSQLToken>()
            {
                new TSQLNumericLiteral(6, "3")
            },
                rightNumber.Tokens);
            Assert.AreEqual(TSQLTokenType.NumericLiteral, rightNumber.Literal.Type);
            Assert.AreEqual(3, rightNumber.Literal.AsNumericLiteral.Value);
        }