-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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 comparison of nullable result of functions #13642
Comments
I found the point, where the "IS NULL"statement is builded: I added to this method: if(extensionExpression.Type.IsNullableType())
{
AddToResult(new IsNullExpression(extensionExpression));
return extensionExpression;
} And now my copy of EFCore generates expected condition for second example:
Could anybody verify this change with own tests of EFCore? |
Additional changes for IsNullExpressionBuildingVisitor::VisitBinary if (binaryExpression.Type.IsNullableType())
{
AddToResult(new IsNullExpression(binaryExpression));
return binaryExpression;
}//if Need for correct translation of comparisons like
Expected condition:
|
The way I was thinking about this is that function is null if any of its arguments is null (doesn't apply to all functions like COALESCE but it does to most). So we don't need to test the entire function for NULL, just its arguments: So it would look something like this: WHERE ((DATEADD(YEAR,1,"r"."COL_TIMESTAMP") = DATEADD(YEAR,1,"r"."COL_TIMESTAMP")) OR ("r"."COL_TIMESTAMP" IS NULL AND "r"."COL_TIMESTAMP" IS NULL)) AND ("r"."TEST_ID" = :__testID_0) further optimized to: WHERE ((DATEADD(YEAR,1,"r"."COL_TIMESTAMP") = DATEADD(YEAR,1,"r"."COL_TIMESTAMP")) OR "r"."COL_TIMESTAMP" IS NULL ) AND ("r"."TEST_ID" = :__testID_0) This would also work for functions that return non-nullable values, e.g. |
Hello @maumar, I think, in common case (at first stage) need generate expression:
Optimization of this expression - it is optional / additional / second stage. Personally I not want to mix this stages - it is way for bad designe. This issue is critical for me, I hope you will find the decision. For example, you may offer the way for replacing of IsNullExpressionBuildingVisitor at data provider level. |
I not sure, but seem optimization of "DATEADD(YEAR,1,"r"."COL_TIMESTAMP") IS NULL))" may be implemented at PredicateReductionExpressionOptimizer level. |
…blem, which described in dotnet#13642. Optimization of generated code is linked with dotnet#13654 and will be second task :)
Problem was that we were not applying clr null semantics when comparing result of functions, i.e. if the function results in null and we compared it to another null value, we would treat them as non-equal. According to clr null semantics they should be treated as the same. Fix is to expand IsNullExpression builder to handle functions with nullable arguments. f(a, b) == null <=> a == null || b == null, unless function is COALESCE (in that case both arguments have to be null), so we can just test arguments not the entire function expression. Also added small optimization in PredicateReductionExpressionOptimizer that removes redundant IS NULL terms.
Problem was that we were not applying clr null semantics when comparing result of functions, i.e. if the function results in null and we compared it to another null value, we would treat them as non-equal. According to clr null semantics they should be treated as the same. Fix is to expand IsNullExpression builder to handle functions with nullable arguments. f(a, b) == null <=> a == null || b == null, unless function is COALESCE (in that case both arguments have to be null), so we can just test arguments not the entire function expression. Also added small optimization in PredicateReductionExpressionOptimizer that removes redundant IS NULL terms.
Problem was that we were not applying clr null semantics when comparing result of functions, i.e. if the function results in null and we compared it to another null value, we would treat them as non-equal. According to clr null semantics they should be treated as the same. Fix is to expand IsNullExpression builder to handle functions with nullable arguments. f(a, b) == null <=> a == null || b == null, unless function is COALESCE (in that case both arguments have to be null), so we can just test arguments not the entire function expression. Also added small optimization in PredicateReductionExpressionOptimizer that removes redundant IS NULL terms.
Problem was that we were not applying clr null semantics when comparing result of functions, i.e. if the function results in null and we compared it to another null value, we would treat them as non-equal. According to clr null semantics they should be treated as the same. Fix is to expand IsNullExpression builder to handle functions with nullable arguments. f(a, b) == null <=> a == null || b == null, unless function is COALESCE (in that case both arguments have to be null), so we can just test arguments not the entire function expression. Also added small optimization in PredicateReductionExpressionOptimizer that removes redundant IS NULL terms.
fixed in fd842ed |
…blem, which described in dotnet#13642.
EF Core - master source
First example:
EFCore generates SQL:
It is OK,
Second example:
Where used extension method:
EFCore generates SQL:
From my point of view - it is problem. In second case EFCore must generate SQL like SQL from first example:
The text was updated successfully, but these errors were encountered: