Skip to content

Commit

Permalink
Fixed "SELECT COUNT(DISTINCT ...)" and "SELECT NULL..." by adding new…
Browse files Browse the repository at this point in the history
… expression types. #101 #104
  • Loading branch information
bruce-dunwiddie committed Jul 15, 2022
1 parent 430e4cb commit 3e648b5
Show file tree
Hide file tree
Showing 14 changed files with 196 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@

namespace TSQL.Expressions.Parsers
{
internal class TSQLOperatorExpressionParser
internal class TSQLOperationExpressionParser
{
public TSQLOperatorExpression Parse(
public TSQLOperationExpression Parse(
ITSQLTokenizer tokenizer,
TSQLExpression leftSide)
{
TSQLOperatorExpression opExpression = new TSQLOperatorExpression();
TSQLOperationExpression opExpression = new TSQLOperationExpression();

opExpression.LeftSide = leftSide;
opExpression.Operator = tokenizer.Current.AsOperator;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public TSQLExpression Parse(ITSQLTokenizer tokenizer)
}
else
{
return new TSQLOperatorExpressionParser().Parse(
return new TSQLOperationExpressionParser().Parse(
tokenizer,
expression);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public TSQLExpression Parse(ITSQLTokenizer tokenizer)
tokenizer.Current.Type.In(
TSQLTokenType.Operator))
{
return new TSQLOperatorExpressionParser().Parse(
return new TSQLOperationExpressionParser().Parse(
tokenizer,
expression);
}
Expand Down Expand Up @@ -125,6 +125,39 @@ public TSQLExpression ParseNext(
#endregion
}
}
else if (
tokenizer.Current.IsKeyword(TSQLKeywords.DISTINCT) ||
tokenizer.Current.IsKeyword(TSQLKeywords.ALL))
{
#region parse rest of expression contained inside parenthesis

TSQLDuplicateSpecificationExpression distinct = new TSQLDuplicateSpecificationExpression();

distinct.Tokens.Add(tokenizer.Current);

if (tokenizer.Current.IsKeyword(TSQLKeywords.ALL))
{
distinct.DuplicateSpecificationType = TSQLDuplicateSpecificationExpression.TSQLDuplicateSpecificationType.All;
}
else
{
distinct.DuplicateSpecificationType = TSQLDuplicateSpecificationExpression.TSQLDuplicateSpecificationType.Distinct;
}

TSQLTokenParserHelper.ReadThroughAnyCommentsOrWhitespace(
tokenizer,
distinct.Tokens);

distinct.InnerExpression =
new TSQLValueExpressionParser().Parse(
tokenizer);

distinct.Tokens.AddRange(distinct.InnerExpression.Tokens);

return distinct;

#endregion
}
else if (tokenizer.Current.Type.In(
TSQLTokenType.Variable,
TSQLTokenType.SystemVariable))
Expand Down Expand Up @@ -158,6 +191,18 @@ public TSQLExpression ParseNext(

return constant;
}
else if (tokenizer.Current.IsKeyword(TSQLKeywords.NULL))
{
TSQLNullExpression nullExp = new TSQLNullExpression();

nullExp.Tokens.Add(tokenizer.Current);

TSQLTokenParserHelper.ReadThroughAnyCommentsOrWhitespace(
tokenizer,
nullExp.Tokens);

return nullExp;
}
else if (tokenizer.Current.IsKeyword(TSQLKeywords.CASE))
{
return new TSQLCaseExpressionParser().Parse(tokenizer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public TSQLVariableAssignmentExpression Parse(
tokenizer.Current.Type.In(
TSQLTokenType.Operator))
{
rightSide = new TSQLOperatorExpressionParser().Parse(
rightSide = new TSQLOperationExpressionParser().Parse(
tokenizer,
rightSide);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using TSQL.Tokens;

namespace TSQL.Expressions
{
public class TSQLDuplicateSpecificationExpression : TSQLExpression
{
public override TSQLExpressionType Type
{
get
{
return TSQLExpressionType.DuplicateSpecification;
}
}

public TSQLDuplicateSpecificationType DuplicateSpecificationType { get; internal set; }

public TSQLExpression InnerExpression { get; internal set; }

public enum TSQLDuplicateSpecificationType
{
Distinct,
All
}
}
}
20 changes: 18 additions & 2 deletions TSQL_Parser/TSQL_Parser/Expressions/TSQLExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,11 @@ public TSQLMulticolumnExpression AsMulticolumn
}
}

public TSQLOperatorExpression AsOperator
public TSQLOperationExpression AsOperation
{
get
{
return this as TSQLOperatorExpression;
return this as TSQLOperationExpression;
}
}

Expand Down Expand Up @@ -119,5 +119,21 @@ public TSQLValueAsTypeExpression AsValueAsType
return this as TSQLValueAsTypeExpression;
}
}

public TSQLNullExpression AsNull
{
get
{
return this as TSQLNullExpression;
}
}

public TSQLDuplicateSpecificationExpression AsDuplicateSpecification
{
get
{
return this as TSQLDuplicateSpecificationExpression;
}
}
}
}
14 changes: 12 additions & 2 deletions TSQL_Parser/TSQL_Parser/Expressions/TSQLExpressionType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public enum TSQLExpressionType
/// </summary>
Multicolumn,

Operator,
Operation,

/// <summary>
/// i.e. an expression surrounded by parenthesis, but not containing a subquery
Expand All @@ -54,6 +54,16 @@ public enum TSQLExpressionType
/// <summary>
/// e.g. 123.45 AS INT (only used as an argument to CAST function)
/// </summary>
ValueAsType
ValueAsType,

/// <summary>
/// e.g. NULL
/// </summary>
Null,

/// <summary>
/// e.g. DISTINCT or ALL
/// </summary>
DuplicateSpecification
}
}
21 changes: 21 additions & 0 deletions TSQL_Parser/TSQL_Parser/Expressions/TSQLNullExpression.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using TSQL.Tokens;

namespace TSQL.Expressions
{
public class TSQLNullExpression : TSQLExpression
{
public override TSQLExpressionType Type
{
get
{
return TSQLExpressionType.Null;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@

namespace TSQL.Expressions
{
public class TSQLOperatorExpression : TSQLExpression
public class TSQLOperationExpression : TSQLExpression
{
public override TSQLExpressionType Type
{
get
{
return TSQLExpressionType.Operator;
return TSQLExpressionType.Operation;
}
}

Expand Down
6 changes: 4 additions & 2 deletions TSQL_Parser/TSQL_Parser/TSQL_Parser.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -118,18 +118,19 @@
<Compile Include="Expressions\Parsers\TSQLValueExpressionParser.cs" />
<Compile Include="Expressions\Parsers\TSQLSelectExpressionParser.cs" />
<Compile Include="Elements\Parsers\TSQLValuesParser.cs" />
<Compile Include="Expressions\Parsers\TSQLOperatorExpressionParser.cs" />
<Compile Include="Expressions\Parsers\TSQLOperationExpressionParser.cs" />
<Compile Include="Expressions\TSQLArgumentList.cs" />
<Compile Include="Expressions\TSQLArgumentList.IEnumerable.cs">
<DependentUpon>TSQLArgumentList.cs</DependentUpon>
</Compile>
<Compile Include="Expressions\TSQLColumnExpression.cs" />
<Compile Include="Elements\TSQLDefaultValues.cs" />
<Compile Include="Expressions\TSQLConstantExpression.cs" />
<Compile Include="Expressions\TSQLDuplicateSpecificationExpression.cs" />
<Compile Include="Expressions\TSQLValueAsTypeExpression.cs" />
<Compile Include="Expressions\TSQLVariableAssignmentExpression.cs" />
<Compile Include="Expressions\TSQLLogicalExpression.cs" />
<Compile Include="Expressions\TSQLOperatorExpression.cs" />
<Compile Include="Expressions\TSQLOperationExpression.cs" />
<Compile Include="Expressions\TSQLExpressionType.cs" />
<Compile Include="Expressions\TSQLFunctionExpression.cs" />
<Compile Include="Expressions\TSQLGroupedExpression.cs" />
Expand All @@ -140,6 +141,7 @@
<Compile Include="Expressions\TSQLCaseExpression.cs" />
<Compile Include="Expressions\Parsers\TSQLCaseExpressionParser.cs" />
<Compile Include="Expressions\TSQLExpression.cs" />
<Compile Include="Expressions\TSQLNullExpression.cs" />
<Compile Include="Expressions\TSQLVariableExpression.cs" />
<Compile Include="IO\BufferedTextReader.cs" />
<Compile Include="IO\BufferedTextReader.IDisposable.cs">
Expand Down
18 changes: 9 additions & 9 deletions TSQL_Parser/Tests/Clauses/SelectClauseTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,18 @@ public void SelectClause_Comments()

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

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

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

TSQLColumnExpression rightSide = operatorExpression.RightSide.AsColumn;
TSQLColumnExpression rightSide = operationExpression.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);
Expand Down Expand Up @@ -327,9 +327,9 @@ public void SelectClause_UnaryOperator()
TSQLSelectColumn column = select.Columns[0];

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

TSQLOperatorExpression tsqlOperator = column.Expression.AsOperator;
TSQLOperationExpression tsqlOperator = column.Expression.AsOperation;

Assert.AreEqual("+", tsqlOperator.Operator.Text);
Assert.IsNull(tsqlOperator.LeftSide);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
namespace Tests.Expressions
{
[TestFixture(Category = "Expression Parsing")]
public class OperatorExpressionTests
public class OperationExpressionTests
{
[Test]
public void OperatorExpression_Simple()
public void OperationExpression_Simple()
{
TSQLTokenizer tokenizer = new TSQLTokenizer(
"+ 2 - 3")
Expand All @@ -38,7 +38,7 @@ public void OperatorExpression_Simple()

Assert.IsTrue(tokenizer.MoveNext());

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

Expand All @@ -61,8 +61,8 @@ public void OperatorExpression_Simple()

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

Assert.AreEqual(TSQLExpressionType.Operator, op.RightSide.Type);
TSQLOperatorExpression rightSide = op.RightSide.AsOperator;
Assert.AreEqual(TSQLExpressionType.Operation, op.RightSide.Type);
TSQLOperationExpression rightSide = op.RightSide.AsOperation;
TokenComparisons.CompareTokenLists(
new List<TSQLToken>()
{
Expand Down
Loading

0 comments on commit 3e648b5

Please sign in to comment.