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

Missing Cast to SingleResourceCastNode in BindSingleResourceCastFunctionCall Method in QueryBinder #1304

Closed
WanjohiSammy opened this issue Aug 29, 2024 · 1 comment · Fixed by #1313
Labels
bug Something isn't working feature P2

Comments

@WanjohiSammy
Copy link
Contributor

WanjohiSammy commented Aug 29, 2024

Assemblies affected
ASP.NET Core OData 7.x +

Describe the bug
The BindSingleResourceCastFunctionCall() method links a "SingleResourceFunctionCallNode" to produce a LINQ "Expression" that signifies the meaning of the "SingleResourceFunctionCallNode".

This method takes two arguments: SingleResourceFunctionCallNode and QueryBinderContext.
SingleResourceFunctionCallNode has a Parameters property, which is a list of QueryNodes.

The last QueryNode in this SingleResourceFunctionCallNode.Parameters parameter could be either of type ConstantNode or SingleResourceCastNode.
For instance:

  • /People?$orderby=cast(Location,NS.WorkAddress)/Company: The last query node in the SingleResourceFunctionCallNode.Parameters is of type SingleResourceCastNode. This occurs because NS.WorkAddress is bound as a DottedIdentifier and thus transformed into a SingleResourceCastNode.
  • /People?$orderby=cast(Location,'NS.WorkAddress')/Company: The last query node in the SingleResourceFunctionCallNode.Parameters is of type ConstantNode, as 'NS.WorkAddress' is bound as a Literal and consequently converted to ConstantNode.
  • /People?$filter=cast(Location,'NS.HomeAddress')/IsPrimaryResidence eq true: The last parameter is SingleResourceCastNode.
  • /People?$filter=cast(Location,NS.HomeAddress)/IsPrimaryResidence eq true: The last parameter is ConstantNode.
    etc.

Currently, the implementation only allows for casting to ConstantNode: Microsoft.AspNetCore.OData/Query/Expressions/QueryBinder.cs#L620

We should be able to cast the parameter as either SingleResourceCastNode or ConstantNode in order to enable the solution for this other issue OData/odata.net#1744

Reproduce steps
This issue was identified while fixing another issue OData/odata.net#1744

cast with unquoted type parameter throw an error:
/Airports?$filter=cast(Location,Microsoft.OData.SampleService.Models.TripPin.AirportLocation)/City/Name eq 'Beijing'

cast with quoted type parameter works just fine:
/Airports?$filter=cast(Location,Microsoft.OData.SampleService.Models.TripPin.AirportLocation)/City/Name eq 'Beijing'

The above issue is describe here

EDM (CSDL) Model
https://services.odata.org/V4/(S(4dwtx43m0k0tpfool4gce2di))/TripPinServiceRW/$metadata

Expected behavior
cast with quoted and unquoted type param should return the same data. For example
cast(Location,Microsoft.OData.SampleService.Models.TripPin.AirportLocation)/City/Name eq 'Beijing' should be the same as cast(Location,Microsoft.OData.SampleService.Models.TripPin.AirportLocation)/City/Name eq 'Beijing'

Screenshots
Getting the below after fixing the issue #1744 to SingleResourceCastNode in case of unquoted type parameter:

image

Additional context
Add a condition to try cast QueryNode to SingleResourceCastNode or ConstantNode

public virtual Expression BindSingleResourceCastFunctionCall(SingleResourceFunctionCallNode node, QueryBinderContext context)
{
    ...

    string targetEdmTypeName = null;
    QueryNode queryNode = node.Parameters.Last();
    if (queryNode is SingleResourceCastNode singleResourceCastNode)
    {
        targetEdmTypeName = singleResourceCastNode.TypeReference.FullName();
    }
    else if (queryNode is ConstantNode constantNode)
    {
        targetEdmTypeName = constantNode.Value as string;
    }

    IEdmType targetEdmType = model.FindType(targetEdmTypeName);
    ...
}
@WanjohiSammy WanjohiSammy added bug Something isn't working and removed bug Something isn't working labels Aug 29, 2024
@xuzhg
Copy link
Member

xuzhg commented Sep 3, 2024

I am curious whether the following works?

/Airports?$filter=Location/Microsoft.OData.SampleService.Models.TripPin.AirportLocation/City/Name eq 'Beijing'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working feature P2
Projects
None yet
4 participants