-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Fix to #19499 - Query: null semantics not applied on subquery.Contains(null) #19744
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Conversation
af8fa81
to
509e08a
Compare
ping |
src/EFCore.Relational/Query/NullabilityBasedSqlProcessingExpressionVisitor.cs
Outdated
Show resolved
Hide resolved
&& methodCallExpression.Method.GetGenericMethodDefinition() is MethodInfo containsMethodInfo | ||
&& containsMethodInfo.Equals(QueryableMethods.Contains) | ||
&& methodCallExpression.Arguments[0].NodeType is ExpressionType containsFirstArgumentNodeType | ||
&& (containsFirstArgumentNodeType != ExpressionType.Constant || ((ConstantExpression)methodCallExpression.Arguments[0]).IsEntityQueryable()) |
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 ConstantExpression would remove the explicit cast.
&& containsMethodInfo.Equals(QueryableMethods.Contains) | ||
&& methodCallExpression.Arguments[0].NodeType is ExpressionType containsFirstArgumentNodeType | ||
&& (containsFirstArgumentNodeType != ExpressionType.Constant || ((ConstantExpression)methodCallExpression.Arguments[0]).IsEntityQueryable()) | ||
&& containsFirstArgumentNodeType != ExpressionType.Parameter |
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.
use Expression directly rather than ET type enum. It is mixed here.
rebase. |
48bb523
to
3d23171
Compare
@smitpatel new version up |
@smitpatel ping |
src/EFCore.Relational/Query/NullabilityBasedSqlProcessingExpressionVisitor.cs
Outdated
Show resolved
Hide resolved
src/EFCore.Relational/Query/NullabilityBasedSqlProcessingExpressionVisitor.cs
Outdated
Show resolved
Hide resolved
…s(null) We used to translate this into `NULL IN subquery` pattern, but this doesn't work because it doesn't match if the subquery also contains null. Fix is to convert this into subquery.Any(e => e == NULL), which translates to EXISTS with predicate and we can correctly apply null semantics. Also it allows us to translate contains on entities with composite keys. Also made several small fixes: - marked EXISTS as never nullable for purpose of null semantics, - marked IN as never nullable for purpose of null semantics when both the subquery projection element and the item expression are not nullable, - optimized EXISITS (subquery) and IN (subquery) with predicate that resolves to false, directly into false, since empty subquery never exisits and doesn't contain any results, - improves expression printer output for IN expression in the subquery scenario.
if (methodCallExpression.Method.IsGenericMethod | ||
&& methodCallExpression.Method.GetGenericMethodDefinition() is MethodInfo containsMethodInfo | ||
&& containsMethodInfo.Equals(QueryableMethods.Contains) | ||
&& !(methodCallExpression.Arguments[0] is ParameterExpression) |
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.
What are these conditions on parameter/constant doing here? I removed them an no test failed.
We used to translate this into
NULL IN subquery
pattern, but this doesn't work because it doesn't match if the subquery also contains null.Fix is to convert this into subquery.Any(e => e == NULL), which translates to EXISTS with predicate and we can correctly apply null semantics.
Also it allows us to translate contains on entities with composite keys.
Also made several small fixes: