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

Fix to #19499 - Query: null semantics not applied on subquery.Contains(null) #19744

Merged
merged 1 commit into from
Mar 4, 2020

Conversation

maumar
Copy link
Contributor

@maumar maumar commented Jan 30, 2020

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 and IN expressions as never nullable for purpose of null semantics,
  • optimized EXISITS (subquery) with predicate that resolves to false, directly into false, since empty subquery never exisits,
  • improves expression printer output for IN expression in the subquery scenario.

@maumar maumar requested a review from roji January 30, 2020 00:37
@maumar maumar force-pushed the fix19499 branch 2 times, most recently from af8fa81 to 509e08a Compare January 30, 2020 01:50
@maumar maumar requested a review from smitpatel January 30, 2020 18:53
@maumar
Copy link
Contributor Author

maumar commented Feb 4, 2020

ping

&& 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())
Copy link
Member

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
Copy link
Member

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.

@smitpatel
Copy link
Member

rebase.

@maumar maumar force-pushed the fix19499 branch 2 times, most recently from 48bb523 to 3d23171 Compare February 28, 2020 00:18
@maumar
Copy link
Contributor Author

maumar commented Feb 28, 2020

@smitpatel new version up

@maumar
Copy link
Contributor Author

maumar commented Mar 3, 2020

@smitpatel ping

…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.
@maumar maumar merged commit b84eec1 into master Mar 4, 2020
@maumar maumar deleted the fix19499 branch March 4, 2020 02:19
@maumar maumar linked an issue Mar 4, 2020 that may be closed by this pull request
if (methodCallExpression.Method.IsGenericMethod
&& methodCallExpression.Method.GetGenericMethodDefinition() is MethodInfo containsMethodInfo
&& containsMethodInfo.Equals(QueryableMethods.Contains)
&& !(methodCallExpression.Arguments[0] is ParameterExpression)
Copy link
Member

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.

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.

Query: null semantics not applied on subquery.Contains(null)
2 participants