-
Notifications
You must be signed in to change notification settings - Fork 352
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implementing virtual property $count #738
Conversation
Hi @athoscouto, I'm your friendly neighborhood Microsoft Pull Request Bot (You can call me MSBOT). Thanks for your contribution!
TTYL, MSBOT; |
Hi @athoscouto, I'm your friendly neighborhood Microsoft Pull Request Bot (You can call me MSBOT). Thanks for your contribution!
TTYL, MSBOT; |
Hi @LaylaLiu, I couldn't build ODL via |
/// The aggregation method Count. | ||
/// Used only internally to represent the virtual property $count. | ||
/// </summary> | ||
VirtualPropertyCount, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you take a look at the aggregation doc, you will find that VirtualPropertyCount actually is not a method.
So I think it shouldn't be added here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The doc says it's a virtual property. If I'm not mistaken, ODL does not have any other virtual property implemented. Since I didn't find any guideline to follow about implementing these properties, I created a internal aggregation method count and mapped each call of the virtual property to it. This internal method is not visible to the end user, unlike the other aggregation methods.
I'd be happy to know about better approaches to implement it.
@@ -116,6 +129,7 @@ private IEdmTypeReference CreateAggregateExpressionTypeReference(SingleValueNode | |||
expressionPrimitiveKind)); | |||
} | |||
|
|||
case AggregationMethod.VirtualPropertyCount: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to above code, it seems that this line will never be touched, right? If the token is a virtualPropertyCount, the code will always go to line 82 instead of line 87.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your observation is correct. I added this line to be able to use CreateAggregateExpressionTypeReference for both cases, but ended up not using it in the $count one. I'll correct it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved the logic to handle $count to EndPathBinder. It made the logic simpler and now this line is used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The change looks good. However, it looks like both CountDistinct and VirtualPropertyCount should return Decimal not Int64. I don't think you should change CountDistinct as part of your change, could you simply add a TODO comment that these should be Decimal instead of Int64? Something like:
// TODO: CountDistinct and $Count should return type Edm.Decimal with Scale="0" and sufficient Precision.
return EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.Int64, false);
3.1.3.5 Standard Aggregation Method countdistinct
The result property MUST have type Edm.Decimal with Scale="0" and sufficient Precision.
3.1.5 Virtual Property $count
The result property will have type Edm.Decimal with Scale="0" and sufficient Precision.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Created issue #758 to address problem and will reference it on code.
var verb = this.ParseAggregateWith(); | ||
if (endPathExpression != null && endPathExpression.Identifier == ExpressionConstants.QueryOptionCount) | ||
{ | ||
expression = new EndPathToken("$count virtual property", endPathExpression.NextToken); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the identifier should be the $count
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right. Done.
var verb = this.ParseAggregateWith(); | ||
if (endPathExpression != null && endPathExpression.Identifier == ExpressionConstants.QueryOptionCount) | ||
{ | ||
expression = new EndPathToken("$count", endPathExpression.NextToken); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't new EndPathToken() redundant? Why does expression not already == EndPathToken("$count", endPathExpression.NextToken)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you also add a few comment in here for examples you are trying to parse, such as:
(.e.g. aggregate($count as SalesCount)
(.e.g. aggregate(UnitPrice with sum as TotalUnitPrice)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it is redundant. We can't really use the ==, because it would compare the object reference. So I just removed the assignment to the new object and added the comments you asked for.
@@ -116,6 +129,7 @@ private IEdmTypeReference CreateAggregateExpressionTypeReference(SingleValueNode | |||
expressionPrimitiveKind)); | |||
} | |||
|
|||
case AggregationMethod.VirtualPropertyCount: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The change looks good. However, it looks like both CountDistinct and VirtualPropertyCount should return Decimal not Int64. I don't think you should change CountDistinct as part of your change, could you simply add a TODO comment that these should be Decimal instead of Int64? Something like:
// TODO: CountDistinct and $Count should return type Edm.Decimal with Scale="0" and sufficient Precision.
return EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.Int64, false);
3.1.3.5 Standard Aggregation Method countdistinct
The result property MUST have type Edm.Decimal with Scale="0" and sufficient Precision.
3.1.5 Virtual Property $count
The result property will have type Edm.Decimal with Scale="0" and sufficient Precision.
} | ||
|
||
public override IEdmTypeReference TypeReference { | ||
get { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: put { on its own line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
||
VerifyAggregateExpressionToken("$count", AggregationMethod.VirtualPropertyCount, "Count", aggregate.Expressions.First()); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A negative test would be nice, something like "aggregate(#count with sum as Count)" and possible "aggregate(#count).
From the spec:
"It MUST always specify an alias and MUST NOT specify an aggregation method."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea. Done.
…dant code and adding comments referencing issue OData#758.
Merged. |
Issues
This pull request creates infrastructure to solve issue #773 of WebAPI project. It also addresses issue #562 of this repo.
Description
In this change I add support to parse into lexical and semantical trees aggregation queries that uses the virtual property $count.
Checklist (Uncheck if it is not completed)