Skip to content

Commit 7deea30

Browse files
authored
Force left join for comparisons with nullable entities (nhibernate#3270)
Fixes nhibernate#3269
1 parent e14704f commit 7deea30

File tree

5 files changed

+20
-6
lines changed

5 files changed

+20
-6
lines changed

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

+9
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,15 @@ from x2 in session.Query<NullableOwner>()
358358
//GH-2988
359359
var withNullOrValidList = await (session.Query<NullableOwner>().Where(x => x.ManyToOne.Id == validManyToOne.Id || x.ManyToOne == null).ToListAsync());
360360
var withNullOrValidList2 = await (session.Query<NullableOwner>().Where(x => x.ManyToOne == null || x.ManyToOne.Id == validManyToOne.Id).ToListAsync());
361+
//GH-3269
362+
var invalidId = Guid.NewGuid();
363+
var withInvalidOrValid = await (session.Query<NullableOwner>().Where(x => x.OneToOne.Id == invalidId || x.ManyToOne.Id == validManyToOne.Id).ToListAsync());
364+
var withInvalidOrNull = await (session.Query<NullableOwner>().Where(x => x.ManyToOne.Id == invalidId || x.OneToOne == null).ToListAsync());
365+
var withInvalidOrNotNull = await (session.Query<NullableOwner>().Where(x => x.ManyToOne.Id == invalidId || x.OneToOne != null).ToListAsync());
366+
367+
Assert.That(withInvalidOrValid.Count, Is.EqualTo(1));
368+
Assert.That(withInvalidOrNull.Count, Is.EqualTo(2));
369+
Assert.That(withInvalidOrNotNull.Count, Is.EqualTo(0));
361370

362371
//GH-3185
363372
var mixImplicitAndLeftJoinList = await (session.Query<NullableOwner>().Where(x => x.ManyToOne.Id == validManyToOne.Id && x.OneToOne == null).ToListAsync());

src/NHibernate.Test/Hql/EntityJoinHqlTest.cs

+9
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,15 @@ from x2 in session.Query<NullableOwner>()
346346
//GH-2988
347347
var withNullOrValidList = session.Query<NullableOwner>().Where(x => x.ManyToOne.Id == validManyToOne.Id || x.ManyToOne == null).ToList();
348348
var withNullOrValidList2 = session.Query<NullableOwner>().Where(x => x.ManyToOne == null || x.ManyToOne.Id == validManyToOne.Id).ToList();
349+
//GH-3269
350+
var invalidId = Guid.NewGuid();
351+
var withInvalidOrValid = session.Query<NullableOwner>().Where(x => x.OneToOne.Id == invalidId || x.ManyToOne.Id == validManyToOne.Id).ToList();
352+
var withInvalidOrNull = session.Query<NullableOwner>().Where(x => x.ManyToOne.Id == invalidId || x.OneToOne == null).ToList();
353+
var withInvalidOrNotNull = session.Query<NullableOwner>().Where(x => x.ManyToOne.Id == invalidId || x.OneToOne != null).ToList();
354+
355+
Assert.That(withInvalidOrValid.Count, Is.EqualTo(1));
356+
Assert.That(withInvalidOrNull.Count, Is.EqualTo(2));
357+
Assert.That(withInvalidOrNotNull.Count, Is.EqualTo(0));
349358

350359
//GH-3185
351360
var mixImplicitAndLeftJoinList = session.Query<NullableOwner>().Where(x => x.ManyToOne.Id == validManyToOne.Id && x.OneToOne == null).ToList();

src/NHibernate/Hql/Ast/ANTLR/HqlSqlWalker.cs

-3
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ public partial class HqlSqlWalker
4242
private SelectClause _selectClause;
4343
private readonly AliasGenerator _aliasGenerator = new AliasGenerator();
4444
private readonly ASTPrinter _printer = new ASTPrinter();
45-
private bool _isNullComparison;
4645

4746
//
4847
//Maps each top-level result variable to its SelectExpression;
@@ -1209,8 +1208,6 @@ public IASTFactory ASTFactory
12091208
}
12101209
}
12111210

1212-
internal bool IsNullComparison => _isNullComparison;
1213-
12141211
public void AddQuerySpaces(string[] spaces)
12151212
{
12161213
for (int i = 0; i < spaces.Length; i++)

src/NHibernate/Hql/Ast/ANTLR/HqlSqlWalker.g

+1-1
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ comparisonExpr
380380
| ^(NOT_BETWEEN exprOrSubquery exprOrSubquery exprOrSubquery)
381381
| ^(IN exprOrSubquery inRhs )
382382
| ^(NOT_IN exprOrSubquery inRhs )
383-
| ^(IS_NULL { _isNullComparison = true; } exprOrSubquery { _isNullComparison = false; })
383+
| ^(IS_NULL exprOrSubquery)
384384
| ^(IS_NOT_NULL exprOrSubquery)
385385
// | ^(IS_TRUE expr)
386386
// | ^(IS_FALSE expr)

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

+1-2
Original file line numberDiff line numberDiff line change
@@ -417,8 +417,7 @@ private void DereferenceEntity(EntityType entityType, bool implicitJoin, string
417417

418418
if ( joinIsNeeded )
419419
{
420-
var forceLeftJoin = comparisonWithNullableEntity && Walker.IsNullComparison;
421-
DereferenceEntityJoin(classAlias, entityType, implicitJoin, parent, forceLeftJoin);
420+
DereferenceEntityJoin(classAlias, entityType, implicitJoin, parent, comparisonWithNullableEntity);
422421
if (comparisonWithNullableEntity)
423422
{
424423
_columns = FromElement.GetIdentityColumns();

0 commit comments

Comments
 (0)