Skip to content

WIP Fix nullable entity comparison with null #2612

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

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions src/NHibernate.Test/Associations/OneToOneFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,12 @@ public void OneToOneCompositeQueryOverByNotNull()
{
using (var session = OpenSession())
{
var loadedEntity = session.QueryOver<Parent>().Where(p => p.OneToOneComp != null).SingleOrDefault();
var loadedEntity = session.QueryOver<Parent>().Where(p => p.OneToOneComp != null).JoinQueryOver(x => x.OneToOneComp).SingleOrDefault();

Assert.That(loadedEntity, Is.Not.Null);
}
}

[Test]
public void OneToOneCompositeQueryCompareWithJoin()
{
Expand All @@ -92,7 +92,20 @@ public void OneToOneCompositeQueryCompareWithJoin()
Assert.That(loadedEntity, Is.Not.Null);
}
}


[Explicit("Not supported.")]
[Test]
public void OneToOneCompositeQueryCompareWithJoinOrIsNull()
{
using(new SqlLogSpy())
using (var session = OpenSession())
{
var loadedEntities = session.CreateQuery("select p from Parent p, EntityWithCompositeId e where p.OneToOneComp = e or p.OneToOneComp is null").List<Parent>();

Assert.That(loadedEntities.Count, Is.EqualTo(2));
}
}

[Explicit("Expression in Restrictions.Where can't recognize direct alias comparison.")]
[Test]
public void OneToOneCompositeQueryOverCompareWithJoin()
Expand Down Expand Up @@ -134,7 +147,7 @@ public void OneToOneCompositeQuerySelectProjection()
{
using (var session = OpenSession())
{
var loadedProjection = session.Query<Parent>().Select(x => new {x.OneToOneComp, x.Key}).FirstOrDefault();
var loadedProjection = session.Query<Parent>().Where(x => x.OneToOneComp != null).Select(x => new {x.OneToOneComp, x.Key}).FirstOrDefault();

Assert.That(loadedProjection.OneToOneComp, Is.Not.Null);
}
Expand All @@ -147,6 +160,7 @@ public void OneToOneQueryOverSelectProjection()
using (var session = OpenSession())
{
var loadedEntity = session.QueryOver<Parent>()
.JoinQueryOver(x => x.OneToOneComp)
.Select(x => x.OneToOneComp)
.SingleOrDefault<EntityWithCompositeId>();

Expand Down Expand Up @@ -225,6 +239,7 @@ protected override void OnSetUp()

session.Save(oneToOneParent.OneToOneComp);
session.Save(oneToOneParent);
session.Save(new Parent() {Key = new CompositeKey() {Id1 = 1, Id2 = 1}});

session.Flush();
transaction.Commit();
Expand Down
23 changes: 19 additions & 4 deletions src/NHibernate.Test/Async/Associations/OneToOneFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,12 @@ public async Task OneToOneCompositeQueryOverByNotNullAsync()
{
using (var session = OpenSession())
{
var loadedEntity = await (session.QueryOver<Parent>().Where(p => p.OneToOneComp != null).SingleOrDefaultAsync());
var loadedEntity = await (session.QueryOver<Parent>().Where(p => p.OneToOneComp != null).JoinQueryOver(x => x.OneToOneComp).SingleOrDefaultAsync());

Assert.That(loadedEntity, Is.Not.Null);
}
}

[Test]
public async Task OneToOneCompositeQueryCompareWithJoinAsync()
{
Expand All @@ -104,7 +104,20 @@ public async Task OneToOneCompositeQueryCompareWithJoinAsync()
Assert.That(loadedEntity, Is.Not.Null);
}
}


[Explicit("Not supported.")]
[Test]
public async Task OneToOneCompositeQueryCompareWithJoinOrIsNullAsync()
{
using(new SqlLogSpy())
using (var session = OpenSession())
{
var loadedEntities = await (session.CreateQuery("select p from Parent p, EntityWithCompositeId e where p.OneToOneComp = e or p.OneToOneComp is null").ListAsync<Parent>());

Assert.That(loadedEntities.Count, Is.EqualTo(2));
}
}

[Explicit("Expression in Restrictions.Where can't recognize direct alias comparison.")]
[Test]
public async Task OneToOneCompositeQueryOverCompareWithJoinAsync()
Expand Down Expand Up @@ -146,7 +159,7 @@ public async Task OneToOneCompositeQuerySelectProjectionAsync()
{
using (var session = OpenSession())
{
var loadedProjection = await (session.Query<Parent>().Select(x => new {x.OneToOneComp, x.Key}).FirstOrDefaultAsync());
var loadedProjection = await (session.Query<Parent>().Where(x => x.OneToOneComp != null).Select(x => new {x.OneToOneComp, x.Key}).FirstOrDefaultAsync());

Assert.That(loadedProjection.OneToOneComp, Is.Not.Null);
}
Expand All @@ -159,6 +172,7 @@ public async Task OneToOneQueryOverSelectProjectionAsync()
using (var session = OpenSession())
{
var loadedEntity = await (session.QueryOver<Parent>()
.JoinQueryOver(x => x.OneToOneComp)
.Select(x => x.OneToOneComp)
.SingleOrDefaultAsync<EntityWithCompositeId>());

Expand Down Expand Up @@ -237,6 +251,7 @@ protected override void OnSetUp()

session.Save(oneToOneParent.OneToOneComp);
session.Save(oneToOneParent);
session.Save(new Parent() {Key = new CompositeKey() {Id1 = 1, Id2 = 1}});

session.Flush();
transaction.Commit();
Expand Down
109 changes: 90 additions & 19 deletions src/NHibernate.Test/Async/Hql/EntityJoinHqlTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
//------------------------------------------------------------------------------


using System.Linq;
using System.Text.RegularExpressions;
using NHibernate.Cfg.MappingSchema;
using NHibernate.Linq;
using NHibernate.Mapping.ByCode;
using NHibernate.Test.Hql.EntityJoinHqlTestEntities;
using NUnit.Framework;
Expand Down Expand Up @@ -164,12 +166,12 @@ public async Task EntityJoinWithNullableOneToOneEntityComparisonInWithClausShoul
.CreateQuery(
"select ex "
+ "from NullableOwner ex "
+ "left join OneToOneEntity st with st = ex.OneToOne "
).SetMaxResults(1)
+ "inner join OneToOneEntity st with st = ex.OneToOne "
)
.UniqueResultAsync<NullableOwner>());

Assert.That(Regex.Matches(sqlLog.GetWholeLog(), "OneToOneEntity").Count, Is.EqualTo(2));
Assert.That(sqlLog.Appender.GetEvents().Length, Is.EqualTo(1), "Only one SQL select is expected");
Assert.That(entity, Is.Not.Null);
Assert.That(Regex.Matches(sqlLog.Appender.GetEvents()[0].RenderedMessage, "OneToOneEntity").Count, Is.EqualTo(2));
}
}

Expand All @@ -188,8 +190,28 @@ public async Task NullableOneToOneWhereEntityIsNotNullAsync()
).SetMaxResults(1)
.UniqueResultAsync<NullableOwner>());

Assert.That(Regex.Matches(sqlLog.GetWholeLog(), "OneToOneEntity").Count, Is.EqualTo(1));
Assert.That(sqlLog.Appender.GetEvents().Length, Is.EqualTo(1), "Only one SQL select is expected");
Assert.That(entity, Is.Not.Null);
Assert.That(Regex.Matches(sqlLog.Appender.GetEvents()[0].RenderedMessage, "OneToOneEntity").Count, Is.EqualTo(1));
}
}

[Test]
public async Task NullableOneToOneWhereEntityIsNullAsync()
{
using (var sqlLog = new SqlLogSpy())
using (var session = OpenSession())
{
var entity =
await (session
.CreateQuery(
"select ex "
+ "from NullableOwner ex "
+ "where ex.OneToOne is null "
).SetMaxResults(1)
.UniqueResultAsync<NullableOwner>());

Assert.That(entity, Is.Not.Null);
Assert.That(Regex.Matches(sqlLog.Appender.GetEvents()[0].RenderedMessage, "OneToOneEntity").Count, Is.EqualTo(1));
}
}

Expand All @@ -208,8 +230,8 @@ public async Task NullableOneToOneWhereIdIsNotNullAsync()
).SetMaxResults(1)
.UniqueResultAsync<NullableOwner>());

Assert.That(Regex.Matches(sqlLog.GetWholeLog(), "OneToOneEntity").Count, Is.EqualTo(1));
Assert.That(sqlLog.Appender.GetEvents().Length, Is.EqualTo(1), "Only one SQL select is expected");
Assert.That(entity, Is.Not.Null);
Assert.That(Regex.Matches(sqlLog.Appender.GetEvents()[0].RenderedMessage, "OneToOneEntity").Count, Is.EqualTo(1));
}
}

Expand All @@ -222,14 +244,32 @@ public async Task NullablePropRefWhereIdEntityNotNullShouldAddJoinAsync()
var entity =
await (session
.CreateQuery(
"select ex "
+ "from NullableOwner ex "
"select ex from NullableOwner ex "
+ "where ex.PropRef is not null "
).SetMaxResults(1)
)
.UniqueResultAsync<NullableOwner>());

Assert.That(Regex.Matches(sqlLog.GetWholeLog(), "PropRefEntity").Count, Is.EqualTo(1));
Assert.That(sqlLog.Appender.GetEvents().Length, Is.EqualTo(1), "Only one SQL select is expected");
Assert.That(entity, Is.Not.Null);
Assert.That(Regex.Matches(sqlLog.Appender.GetEvents()[0].RenderedMessage, "PropRefEntity").Count, Is.EqualTo(1));
}
}

[Test]
public async Task NullablePropRefWhereIdEntityNullShouldAddJoinAsync()
{
using (var sqlLog = new SqlLogSpy())
using (var session = OpenSession())
{
var entity =
await (session
.CreateQuery(
"select ex from NullableOwner ex "
+ "where ex.PropRef is null "
)
.UniqueResultAsync<NullableOwner>());

Assert.That(entity, Is.Not.Null);
Assert.That(Regex.Matches(sqlLog.Appender.GetEvents()[0].RenderedMessage, "PropRefEntity").Count, Is.EqualTo(1));
}
}

Expand All @@ -245,13 +285,34 @@ public async Task NullableOneToOneFetchQueryIsNotAffectedAsync()
"select ex "
+ "from NullableOwner ex left join fetch ex.OneToOne o "
+ "where o is null "
).SetMaxResults(1)
)
.UniqueResultAsync<NullableOwner>());

Assert.That(entity, Is.Not.Null);
Assert.That(Regex.Matches(sqlLog.GetWholeLog(), "OneToOneEntity").Count, Is.EqualTo(1));
}
}


[Test(Description = "GH-2611")]
public async Task NullableOneIsNullLinqAsync()
{
using (var session = OpenSession())
{
var entity = await (session.Query<NullableOwner>().Where(x => x.OneToOne == null).SingleOrDefaultAsync());
Assert.That(entity, Is.Not.Null);
}
}

[Test(Description = "GH-2611")]
public async Task NullableOneFetchIsNullLinqAsync()
{
using (var session = OpenSession())
{
var entity = await (session.Query<NullableOwner>().Fetch(x => x.OneToOne).Where(x => x.OneToOne == null).SingleOrDefaultAsync());
Assert.That(entity, Is.Not.Null);
}
}

[Test]
public async Task NullableOneToOneFetchQueryIsNotAffected2Async()
{
Expand All @@ -264,9 +325,10 @@ public async Task NullableOneToOneFetchQueryIsNotAffected2Async()
"select ex "
+ "from NullableOwner ex left join fetch ex.OneToOne o "
+ "where o.Id is null "
).SetMaxResults(1)
)
.UniqueResultAsync<NullableOwner>());

Assert.That(entity, Is.Not.Null);
Assert.That(Regex.Matches(sqlLog.GetWholeLog(), "OneToOneEntity").Count, Is.EqualTo(1));
}
}
Expand Down Expand Up @@ -488,8 +550,9 @@ protected override HbmMapping GetMappings()
mapper.Class<OneToOneEntity>(
rc =>
{
rc.Id(e => e.Id, m => m.Generator(Generators.GuidComb));
rc.Id(e => e.Id, m => m.Generator(Generators.Foreign<OneToOneEntity>(x => x.Parent)));
rc.Property(e => e.Name);
rc.OneToOne(x => x.Parent, x => x.Constrained(true));
});

mapper.Class<PropRefEntity>(
Expand All @@ -505,7 +568,11 @@ protected override HbmMapping GetMappings()
{
rc.Id(e => e.Id, m => m.Generator(Generators.GuidComb));
rc.Property(e => e.Name);
rc.OneToOne(e => e.OneToOne, m => m.Constrained(false));
rc.OneToOne(e => e.OneToOne, m =>
{
m.Constrained(false);
m.Cascade(Mapping.ByCode.Cascade.All);
});
rc.ManyToOne(
e => e.PropRef,
m =>
Expand All @@ -514,6 +581,7 @@ protected override HbmMapping GetMappings()
m.PropertyRef(nameof(PropRefEntity.PropertyRef));
m.ForeignKey("none");
m.NotFound(NotFoundMode.Ignore);
m.Cascade(Mapping.ByCode.Cascade.All);
});
});

Expand Down Expand Up @@ -584,7 +652,10 @@ protected override void OnSetUp()
};
session.Save(_noAssociation);

session.Flush();
session.Save(new NullableOwner() {Name = "NoAssociation"});
var nullableOwner = new NullableOwner() {Name = "Association", PropRef = new PropRefEntity() {Name = "x", PropertyRef = "xx"}, OneToOne = new OneToOneEntity() {Name = "x"},};
nullableOwner.OneToOne.Parent = nullableOwner;
session.Save(nullableOwner);
transaction.Commit();
}
}
Expand Down
Loading