Skip to content

Commit

Permalink
Adding support and tests for virtual property count.
Browse files Browse the repository at this point in the history
  • Loading branch information
shinlges authored and robward-ms committed Feb 14, 2017
1 parent 2ef3fc9 commit c0c6006
Show file tree
Hide file tree
Showing 10 changed files with 125 additions and 3 deletions.
Expand Up @@ -1602,6 +1602,9 @@
<Compile Include="..\UriParser\SemanticAst\CollectionResourceNode.cs">
<Link>Microsoft\OData\Core\UriParser\SemanticAst\CollectionResourceNode.cs</Link>
</Compile>
<Compile Include="..\UriParser\SemanticAst\CountVirtualPropertyNode.cs">
<Link>Microsoft\OData\Core\UriParser\SemanticAst\CountVirtualPropertyNode.cs</Link>
</Compile>
<Compile Include="..\UriParser\SemanticAst\NonResourceRangeVariable.cs">
<Link>Microsoft\OData\Core\UriParser\SemanticAst\NonResourceRangeVariable.cs</Link>
</Compile>
Expand Down
1 change: 1 addition & 0 deletions src/Microsoft.OData.Core/Microsoft.OData.Core.csproj
Expand Up @@ -68,6 +68,7 @@
<Compile Include="BindingPathHelper.cs" />
<Compile Include="UriParser\ODataPathInfo.cs" />
<Compile Include="UriParser\SemanticAst\CollectionComplexNode.cs" />
<Compile Include="UriParser\SemanticAst\CountVirtualPropertyNode.cs" />
<Compile Include="UriParser\SemanticAst\SingleComplexNode.cs" />
<Compile Include="UriParser\SemanticAst\SingleResourceNode.cs" />
<Compile Include="UriParser\TypeFacetsPromotionRules.cs" />
Expand Down
Expand Up @@ -34,6 +34,12 @@ public enum AggregationMethod
/// <summary>
/// The aggregation method CountDistinct.
/// </summary>
CountDistinct
CountDistinct,

/// <summary>
/// The aggregation method Count.
/// Used only internally to represent the virtual property $count.
/// </summary>
VirtualPropertyCount,
}
}
Expand Up @@ -116,6 +116,7 @@ private IEdmTypeReference CreateAggregateExpressionTypeReference(SingleValueNode
expressionPrimitiveKind));
}

case AggregationMethod.VirtualPropertyCount:
case AggregationMethod.CountDistinct:
return EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.Int64, false);
case AggregationMethod.Max:
Expand Down
5 changes: 5 additions & 0 deletions src/Microsoft.OData.Core/UriParser/Binders/EndPathBinder.cs
Expand Up @@ -172,6 +172,11 @@ internal QueryNode BindEndPath(EndPathToken endPathToken)
return GeneratePropertyAccessQueryNode(singleValueParent as SingleResourceNode, property, state);
}

if (endPathToken.Identifier == ExpressionConstants.QueryOptionCount)
{
return new CountVirtualPropertyNode();
}

if (functionCallBinder.TryBindEndPathAsFunctionCall(endPathToken, singleValueParent, state, out boundFunction))
{
return boundFunction;
Expand Down
Expand Up @@ -284,9 +284,19 @@ internal AggregateExpressionToken ParseAggregateExpression()
{
// expression
var expression = this.ParseExpression();
var endPathExpression = expression as EndPathToken;
AggregationMethod verb;

// "with" verb
var verb = this.ParseAggregateWith();
if (endPathExpression != null && endPathExpression.Identifier == ExpressionConstants.QueryOptionCount)
{
expression = new EndPathToken("$count", endPathExpression.NextToken);
verb = AggregationMethod.VirtualPropertyCount;
}
else
{
// "with" verb
verb = this.ParseAggregateWith();
}

// "as" alias
var alias = this.ParseAggregateAs();
Expand Down
@@ -0,0 +1,27 @@
using Microsoft.OData.Edm;

namespace Microsoft.OData.UriParser
{
/// <summary>
/// Dummy class that allows virtual property $count
/// to work like any other aggregation method.
/// </summary>
public sealed class CountVirtualPropertyNode : SingleValueNode
{
public CountVirtualPropertyNode() { }

public override QueryNodeKind Kind
{
get
{
return QueryNodeKind.None;
}
}

public override IEdmTypeReference TypeReference {
get {
return EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.Int64, false);
}
}
}
}
Expand Up @@ -65,6 +65,32 @@ public void BindApplyWithAggregateShouldReturnApplyClause()
statement.Alias.Should().Be("TotalPrice");
}

[Fact]
public void BindApplyWithCountInAggregateShouldReturnApplyClause()
{
var tokens = _parser.ParseApply("aggregate($count as TotalCount)");

var binder = new ApplyBinder(FakeBindMethods.BindSingleComplexProperty, _bindingState);
var actual = binder.BindApply(tokens);

actual.Should().NotBeNull();
actual.Transformations.Should().HaveCount(1);

var transformations = actual.Transformations.ToList();
var aggregate = transformations[0] as AggregateTransformationNode;

aggregate.Should().NotBeNull();
aggregate.Kind.Should().Be(TransformationNodeKind.Aggregate);
aggregate.Expressions.Should().NotBeNull();
aggregate.Expressions.Should().HaveCount(1);

var statements = aggregate.Expressions.ToList();
var statement = statements[0];

statement.Method.Should().Be(AggregationMethod.VirtualPropertyCount);
statement.Alias.Should().Be("TotalCount");
}

[Fact]
public void BindApplyWithAggregateAndFilterShouldReturnApplyClause()
{
Expand Down
Expand Up @@ -164,6 +164,41 @@ public void ParseApplyWithMultipleAggregateExpressionsShouldReturnAggregateToken
VerifyAggregateExpressionToken("SharePrice", AggregationMethod.CountDistinct, "SharePriceDistinctCount", statements[1]);
}

[Fact]
public void ParseApplyWithSingleCountExpressionShouldReturnAggregateToken()
{
var apply = "aggregate($count as Count)";

var actual = this.testSubject.ParseApply(apply);
actual.Should().NotBeNull();
actual.Should().HaveCount(1);

var aggregate = actual.First() as AggregateToken;
aggregate.Should().NotBeNull();
aggregate.Expressions.Should().HaveCount(1);

VerifyAggregateExpressionToken("$count", AggregationMethod.VirtualPropertyCount, "Count", aggregate.Expressions.First());
}

[Fact]
public void ParseApplyWithCountAndOtherAggregationExpressionShouldReturnAggregateToken()
{
var apply = "aggregate($count as Count, SharePrice with countdistinct as SharePriceDistinctCount)";

var actual = this.testSubject.ParseApply(apply);
actual.Should().NotBeNull();
actual.Should().HaveCount(1);

var aggregate = actual.First() as AggregateToken;
aggregate.Should().NotBeNull();
aggregate.Expressions.Should().HaveCount(2);

var statements = aggregate.Expressions.ToList();

VerifyAggregateExpressionToken("$count", AggregationMethod.VirtualPropertyCount, "Count", aggregate.Expressions.First());
VerifyAggregateExpressionToken("SharePrice", AggregationMethod.CountDistinct, "SharePriceDistinctCount", statements[1]);
}

[Fact]
public void ParseApplyWithAggregateMissingOpenParenShouldThrow()
{
Expand Down
Expand Up @@ -5683,6 +5683,13 @@ public sealed class Microsoft.OData.UriParser.CountSegment : Microsoft.OData.Uri
public virtual T TranslateWith (PathSegmentTranslator`1 translator)
}

public sealed class Microsoft.OData.UriParser.CountVirtualPropertyNode : Microsoft.OData.UriParser.SingleValueNode {
public CountVirtualPropertyNode ()

Microsoft.OData.UriParser.QueryNodeKind Kind { public virtual get; }
Microsoft.OData.Edm.IEdmTypeReference TypeReference { public virtual get; }
}

public sealed class Microsoft.OData.UriParser.CustomUriLiteralParsers : IUriLiteralParser {
public static void AddCustomUriLiteralParser (Microsoft.OData.UriParser.IUriLiteralParser customUriLiteralParser)
public static void AddCustomUriLiteralParser (Microsoft.OData.Edm.IEdmTypeReference edmTypeReference, Microsoft.OData.UriParser.IUriLiteralParser customUriLiteralParser)
Expand Down Expand Up @@ -6154,6 +6161,7 @@ public enum Microsoft.OData.UriParser.Aggregation.AggregationMethod : int {
Max = 2
Min = 1
Sum = 0
VirtualPropertyCount = 5
}

public enum Microsoft.OData.UriParser.Aggregation.TransformationNodeKind : int {
Expand Down

0 comments on commit c0c6006

Please sign in to comment.