-
Notifications
You must be signed in to change notification settings - Fork 349
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
Fix for Error occurs when you check whether a string or integer literal is in an enum collection #3023
Fix for Error occurs when you check whether a string or integer literal is in an enum collection #3023
Conversation
…ber integral values
…d is Invalid integral values
...ctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/UriParser/EnumFilterFunctionalTests.cs
Outdated
Show resolved
Hide resolved
...ctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/UriParser/EnumFilterFunctionalTests.cs
Outdated
Show resolved
Hide resolved
… exists as enum member name
…ode is required to private method
// left operand with fully qualified namespace // left operand without fully qualified namespace // left operand with integral value in single quotes // left operand with integral value without single quotes From the issue description, the first and last scenarios are currently supported..is that true? What this PR is supporting is the second and third scenario? |
...ctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/UriParser/EnumFilterFunctionalTests.cs
Show resolved
Hide resolved
@ElizabethOkerio Currently, we are supporting only the 1st scenario. This PR is to support |
...ctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/UriParser/EnumFilterFunctionalTests.cs
Outdated
Show resolved
Hide resolved
...ctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/UriParser/EnumFilterFunctionalTests.cs
Outdated
Show resolved
Hide resolved
...ctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/UriParser/EnumFilterFunctionalTests.cs
Outdated
Show resolved
Hide resolved
...ctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/UriParser/EnumFilterFunctionalTests.cs
Outdated
Show resolved
Hide resolved
...ctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/UriParser/EnumFilterFunctionalTests.cs
Outdated
Show resolved
Hide resolved
...ctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/UriParser/EnumFilterFunctionalTests.cs
Outdated
Show resolved
Hide resolved
Action action = () => ParseFilter(filterQuery, this.userModel, this.entityType, this.entitySet); | ||
|
||
// Assert | ||
action.Throws<NullReferenceException>(erroMessage); |
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.
Is the cause of the exception the fact that Red
in the filterQuery
is not in single quotes? If so, why does it throw a null reference exception? Is that by design or a bug? Should it throw a friendlier error message that states what the error is? (e.g. Red
is not a known property or is not of the correct type or whatever the appropriate error should be)?
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.
@habbes Thanks for bringing this up. This was happening because the EdmEntityType
for testing was set to be open. In case where isOpen is false, the exception thrown is: "Could not find a property named '{1}' on type '{0}'.
"
internal SingleValueOpenPropertyAccessNode GeneratePropertyAccessQueryForOpenType(
EndPathToken endPathToken, SingleValueNode parentNode)
{
if (parentNode.TypeReference == null ||
parentNode.TypeReference.Definition.IsOpen() ||
IsAggregatedProperty(endPathToken))
{
return new SingleValueOpenPropertyAccessNode(parentNode, endPathToken.Identifier);
}
else
{
throw new ODataException(ODataErrorStrings.MetadataBinder_PropertyNotDeclared(
parentNode.TypeReference.FullName(),
endPathToken.Identifier));
}
}
I have modified the isOpen
to false
this.entityType = new EdmEntityType("NS", "MyEntityType", isAbstract: false, isOpen: false, baseType: null);
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.
Okay that makes sense. But it seems like there are two issues. This has not addressed the issue when we have an open type, which I assume would still throw a null-reference exception. I'd still be curious about that, because it's possible that customers are using open types. I guess the challenge is that we may not know the type. But regardless, if it's an error, it should throw a meaningful error, not a null-reference exception.
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.
@habbes That seems like an existing issue. Even if we remove this fix, we will still get the same error. If you pass Red
without single quotes, it will be treated like a property and hence the error when trying to check if left node
can be assignableFrom right node
. This is happening because the left node does not exist as a property and therefore has a null
EdmTypeReference
:
This image shows where the error is thrown:
I found that this is where the issue is in the case of In Operator
:
if (!this.left.GetEdmTypeReference().IsAssignableFrom(this.right.ItemType) &&
!this.right.ItemType.IsAssignableFrom(this.left.GetEdmTypeReference()))
In the above code, this.left.GetEdmTypeReference()
is always null for this example: ?$filter=Red in Colors
.
public InNode(SingleValueNode left, CollectionNode right)
{
ExceptionUtils.CheckArgumentNotNull(left, "left");
ExceptionUtils.CheckArgumentNotNull(right, "right");
this.left = left;
this.right = right;
if (!right.GetEdmTypeReference().IsUntyped())
{
if (!this.left.GetEdmTypeReference().IsAssignableFrom(this.right.ItemType) &&
!this.right.ItemType.IsAssignableFrom(this.left.GetEdmTypeReference()))
{
throw new ArgumentException(ODataErrorStrings.Nodes_InNode_CollectionItemTypeMustBeSameAsSingleItemType(
this.right.ItemType.FullName(), this.left.GetEdmTypeReference().FullName()));
}
}
}
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.
@habbes Unless the spec permit, we can try to convert the left operand Red
to the same enum type if possible. Hence, to support the following. But this will only work if the EdmEntityType
is open
.
/Employees?$filter=Red in Colors
The left node will be converted to ConvertNode()
since the left.TypeReference == null
internal static SingleValueNode ConvertToTypeIfNeeded(SingleValueNode source, IEdmTypeReference targetTypeReference)
{
Debug.Assert(source != null, "source != null");
if (targetTypeReference == null)
{
return source;
}
if (source.TypeReference != null)
{
...
}
else
{
// If the source doesn't have a type (possibly an open property), then it's possible to convert it
// cause we don't know for sure.
return new ConvertNode(source, targetTypeReference);
}
}
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.
Since this PR was specific about the literals, may no need to add support for type coercions of non-literals. I was just concerned about the error message.
...ctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/UriParser/EnumFilterFunctionalTests.cs
Show resolved
Hide resolved
...ctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/UriParser/EnumFilterFunctionalTests.cs
Show resolved
Hide resolved
...ctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/UriParser/EnumFilterFunctionalTests.cs
Show resolved
Hide resolved
…' of https://github.com/OData/odata.net into fix/2371-allow-filter-stringliterals-in-enum-collection
...ctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/UriParser/EnumFilterFunctionalTests.cs
Outdated
Show resolved
Hide resolved
...ctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/UriParser/EnumFilterFunctionalTests.cs
Outdated
Show resolved
Hide resolved
...ctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/UriParser/EnumFilterFunctionalTests.cs
Outdated
Show resolved
Hide resolved
...lTests/Microsoft.OData.Core.Tests/ScenarioTests/UriParser/FilterAndOrderByFunctionalTests.cs
Outdated
Show resolved
Hide resolved
...lTests/Microsoft.OData.Core.Tests/ScenarioTests/UriParser/FilterAndOrderByFunctionalTests.cs
Outdated
Show resolved
Hide resolved
...lTests/Microsoft.OData.Core.Tests/ScenarioTests/UriParser/FilterAndOrderByFunctionalTests.cs
Outdated
Show resolved
Hide resolved
…al is in an enum collection (#3023) * Refactor InBinder to convert left operand to enum type if necessary * Add tests for filter with In Operator with enums member names and member integral values * Add more functional tests for parseFilter with 'In' Operation with Enums * Add a failed tests when Float are used as enum integral value with In Operator * Add parse filter test with 'In' operator with enums where left operand is Invalid integral values * Adding tests for errors thrown when using string literal that doesn't exists as enum member name * Refactor to reuse methods and move logic that check if convert left node is required to private method * Remove unnecessary ShouldConvertLeftOperand() method and put the logic inside BindInOperator() * Make the new tests to only use generic methods introduced * Resolve comments * Reuse GetIEdmProperty() and GetIEdmType() methods in the other existing tests * Merge related tests using [Theory] * use string instead of object
Issues
This pull request fixes #2371.
Description
This change is to fix the issue raised where the
in
operator does not allow using astring
orinteger
literal as left operand when comparing against a collection of enums.The change involves:
left operand
is either anintegral
or astring
type and theright operand
is a collection of enums.MetadataBindingUtils.ConvertToTypeIfNeeded()
method to try convert the left operand to the same enum type if possible.Assume you have the following entity:
This change enables support of the following scenarios for
$filter
withIn
Operator:Checklist (Uncheck if it is not completed)
Additional work necessary
If documentation update is needed, please add "Docs Needed" label to the issue and provide details about the required document change in the issue.