-
Notifications
You must be signed in to change notification settings - Fork 928
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
Enhance nullability check for "==" and "!=" operators for LINQ provider #1996
Conversation
@@ -260,13 +265,7 @@ public async Task NullEqualityWithNotNullAsync() | |||
q = session.Query<AnotherEntityRequired>().Where(o => (o.NullableOutput + o.Output) == o.Output); | |||
await (ExpectAsync(q, Does.Not.Contain("is null").IgnoreCase)); | |||
|
|||
q = session.Query<AnotherEntityRequired>().Where(o => (o.Input + o.Output) == o.Output); |
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.
Changed to o.Output + o.Output
as otherwise it fails in oracle as in oracle concatenating null
with a non empty string will not result in a null
value like in the other databases. I think that we should add an additional logic when concatenating strings in order to have a consistent behaviour across various databases and possible align with Linq-to-Object so that null + "test"
will not result in a null
value.
q = session.Query<AnotherEntityRequired>().Where(o => o.RelatedItems.Max(r => r.Id) != 0); | ||
await (ExpectAllAsync(q, Does.Contain("is null").IgnoreCase)); | ||
|
||
q = session.Query<AnotherEntityRequired>().Where(o => o.RelatedItems.Take(10).All(r => r.Output != null) != o.NullableBool); |
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.
Removed the Take
call as it produces an invalid sql statement for Oracle.
</id> | ||
<property name="Output" not-null="true" /> | ||
<property name="Input" not-null="true" /> | ||
<property name="NullableOutput" formula="Output" lazy="true" /> |
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.
I've had to use lazy as otherwise an invalid query is generated due to the missing table alias for the column used in the formula.
MapPropertyToIndex(null, prop, i); | ||
} | ||
|
||
private void MapPropertyToIndex(string path, Mapping.Property prop, int i) |
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.
Copied from #2079. It is a fix for including nested components.
<property name="InvalidLoginAttempts" type="Int32" /> | ||
<property name="RegisteredAt" type="DateTime" /> | ||
<property name="LastLoginDate" type="DateTime" /> | ||
|
||
<many-to-one name="CreatedBy" class="User" not-null="true" lazy="false"> |
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.
I had to add lazy="false"
, otherwise some tests in QueryReuseTests
(CanReuseAfterFirst
, CanReuseAfterFirstOrDefault
, CanReuseAfterSingle
, CanReuseAfterSingleOfDefault
) would fail.
0f8c46b
to
d067e8c
Compare
Rebased and fixed |
I will agree with CodeFactor that this method is too complex (and too hard for me to understand). |
Ok, I will try to make the method more readable by adding documentation, split into multiple methods, try to simplify the logic and add isolated tests. |
I tried my best to make the method more readable and to reduce its complexity in #2036. I've added several isolated tests in order to cover all kind of mappings. I think that the method is now more readable but the complexity didn't dropped, it even increased so I am not sure what to do about it. Should I split it into more smaller methods or replace the method with a method object? EDIT: |
2e892c8
to
29d2052
Compare
Rebased and updated code to use |
This PR adds a slightly complex logic that determines if it should add a
OR <Property> IS NULL
check for==
and!=
operators, fixes #1860. The logic will not add the additional null check for the following scenarios:Example:
s.Query<Order>().Where(o => o.Number != 5)
Example:
s.Query<Order>().Where(o => o.Status != "NEW")
!=
operator.Example:
s.Query<Order>().Where(o => o.Status != null && o.Status != "NEW")
HasValue
check before or after the!=
operator.Example:
s.Query<Order>().Where(o => o.Number.HasValue && o.Number != 3)
!=
operator is not null.Example:
s.Query<Order>().Where(o => (o.NotNullProperty + o.NotNullProperty2) != "TEST")
==
operator and one of them or both have a not null check.Example:
s.Query<Order>().Where(o => o.NullProperty != null && o.NullProperty == o.NullProperty2)
There are some scenarios where the logic will add a null check where currently it is not added:
Example:
s.Query<Order>().Where(o => o.Rows.Max(r => r.Number) != 0)
Example:
s.Query<Order>().Where(o => o.Status.Length != 3)
In addition, the
Equals
method was modified to use the same logic as the==
operator.