Skip to content
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

Closed
wants to merge 3 commits into from

Conversation

athoscouto
Copy link
Contributor

@athoscouto athoscouto commented Dec 30, 2016

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)

  • Test cases added
  • Build and test script passing

@msftclas
Copy link

Hi @athoscouto, I'm your friendly neighborhood Microsoft Pull Request Bot (You can call me MSBOT). Thanks for your contribution!


It looks like you're a Microsoft contributor (Athos Couto). If you're full-time, we DON'T require a Contribution License Agreement. If you are a vendor, please DO sign the electronic Contribution License Agreement. It will take 2 minutes and there's no faxing! https://cla.microsoft.com.

TTYL, MSBOT;

@msftclas
Copy link

Hi @athoscouto, I'm your friendly neighborhood Microsoft Pull Request Bot (You can call me MSBOT). Thanks for your contribution!


It looks like you're a Microsoft contributor (Athos Couto). If you're full-time, we DON'T require a Contribution License Agreement. If you are a vendor, please DO sign the electronic Contribution License Agreement. It will take 2 minutes and there's no faxing! https://cla.microsoft.com.

TTYL, MSBOT;

@athoscouto athoscouto changed the title Implementing virtual property . Implementing virtual property $count Jan 19, 2017
@athoscouto
Copy link
Contributor Author

Hi @LaylaLiu, I couldn't build ODL via build.cmd in any branches. Since all the tests are passing in VS, I think I'm done. Do you want me to address any issues in the code?

/// The aggregation method Count.
/// Used only internally to represent the virtual property $count.
/// </summary>
VirtualPropertyCount,
Copy link
Contributor

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

Copy link
Contributor Author

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:
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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.

Copy link
Contributor Author

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);
Copy link
Contributor

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

Copy link
Contributor Author

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);
Copy link
Contributor

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)?

Copy link
Contributor

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)

Copy link
Contributor Author

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:
Copy link
Contributor

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 {
Copy link
Contributor

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.

Copy link
Contributor Author

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());
}

Copy link
Contributor

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."

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. Done.

@robward-ms
Copy link
Contributor

Merged.

@robward-ms robward-ms closed this Feb 14, 2017
@robward-ms robward-ms mentioned this pull request Feb 14, 2017
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants