Skip to content

Commit 639c6dc

Browse files
committed
Fix for queries with implicit joins
1 parent 58b6c04 commit 639c6dc

File tree

3 files changed

+34
-12
lines changed

3 files changed

+34
-12
lines changed

src/NHibernate.Test/Async/Hql/EntityJoinHqlTest.cs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@
1111
using System.Linq;
1212
using System.Text.RegularExpressions;
1313
using NHibernate.Cfg.MappingSchema;
14+
using NHibernate.Linq;
1415
using NHibernate.Mapping.ByCode;
1516
using NHibernate.Test.Hql.EntityJoinHqlTestEntities;
1617
using NUnit.Framework;
17-
using NHibernate.Linq;
1818

1919
namespace NHibernate.Test.Hql
2020
{
@@ -298,26 +298,34 @@ public async Task NullableOneIsNullLinqAsync()
298298
{
299299
using (var session = OpenSession())
300300
{
301-
var entity = await (session.Query<NullableOwner>().Where(x => x.OneToOne == null).FirstOrDefaultAsync());
301+
var entity = await (session.Query<NullableOwner>().Where(x => x.OneToOne == null).SingleOrDefaultAsync());
302+
Assert.That(entity, Is.Not.Null);
303+
}
304+
}
305+
306+
[Test(Description = "GH-2611")]
307+
public async Task NullableOneFetchIsNullLinqAsync()
308+
{
309+
using (var session = OpenSession())
310+
{
311+
var entity = await (session.Query<NullableOwner>().Fetch(x => x.OneToOne).Where(x => x.OneToOne == null).SingleOrDefaultAsync());
302312
Assert.That(entity, Is.Not.Null);
303313
}
304314
}
305315

306316
[Test]
307317
public async Task NullableOneToOneFetchQueryIsNotAffected2Async()
308318
{
309-
using (var sqlLog = new SqlLogSpy())
310319
using (var session = OpenSession())
311320
{
312-
var entities =
321+
var entity =
313322
await (session
314323
.CreateQuery(
315324
"select ex "
316325
+ "from NullableOwner ex left join fetch ex.OneToOne o "
317326
+ "where o.Id is null "
318327
)
319-
.ListAsync<NullableOwner>());
320-
var entity = entities[0];
328+
.UniqueResultAsync<NullableOwner>());
321329

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

src/NHibernate.Test/Hql/EntityJoinHqlTest.cs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.Linq;
22
using System.Text.RegularExpressions;
33
using NHibernate.Cfg.MappingSchema;
4+
using NHibernate.Linq;
45
using NHibernate.Mapping.ByCode;
56
using NHibernate.Test.Hql.EntityJoinHqlTestEntities;
67
using NUnit.Framework;
@@ -286,26 +287,34 @@ public void NullableOneIsNullLinq()
286287
{
287288
using (var session = OpenSession())
288289
{
289-
var entity = session.Query<NullableOwner>().Where(x => x.OneToOne == null).FirstOrDefault();
290+
var entity = session.Query<NullableOwner>().Where(x => x.OneToOne == null).SingleOrDefault();
291+
Assert.That(entity, Is.Not.Null);
292+
}
293+
}
294+
295+
[Test(Description = "GH-2611")]
296+
public void NullableOneFetchIsNullLinq()
297+
{
298+
using (var session = OpenSession())
299+
{
300+
var entity = session.Query<NullableOwner>().Fetch(x => x.OneToOne).Where(x => x.OneToOne == null).SingleOrDefault();
290301
Assert.That(entity, Is.Not.Null);
291302
}
292303
}
293304

294305
[Test]
295306
public void NullableOneToOneFetchQueryIsNotAffected2()
296307
{
297-
using (var sqlLog = new SqlLogSpy())
298308
using (var session = OpenSession())
299309
{
300-
var entities =
310+
var entity =
301311
session
302312
.CreateQuery(
303313
"select ex "
304314
+ "from NullableOwner ex left join fetch ex.OneToOne o "
305315
+ "where o.Id is null "
306316
)
307-
.List<NullableOwner>();
308-
var entity = entities[0];
317+
.UniqueResult<NullableOwner>();
309318

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

src/NHibernate/Hql/Ast/ANTLR/Tree/DotNode.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Linq;
23
using Antlr.Runtime;
34

45
using NHibernate.Engine;
@@ -412,7 +413,11 @@ private void DereferenceEntity(EntityType entityType, bool implicitJoin, string
412413
if (Walker.IsComparativeExpressionClause && entityType.IsNullable)
413414
{
414415
joinIsNeeded = comparisonWithNullableEntity = true;
415-
_joinType = JoinType.LeftOuterJoin;
416+
417+
//TODO: Fix this hack. We should always left join here. Skip left join for nullable entity if query contains implicit joins. We currently don't support such queries (see OneToOneCompositeQueryCompareWithJoin)
418+
var fromJoins = ASTUtil.CollectChildren<FromElement>(Walker.CurrentFromClause, x => x is FromElement fe && !fe.IsImplied && fe.Type == HqlSqlWalker.FROM_FRAGMENT);
419+
if(fromJoins.Count == 1)
420+
_joinType = JoinType.LeftOuterJoin;
416421
}
417422
else
418423
{

0 commit comments

Comments
 (0)