Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
4 changes: 4 additions & 0 deletions src/NHibernate.Test/Async/Hql/EntityJoinHqlTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -342,8 +342,12 @@ public async Task NullableEntityProjectionAsync()

var fullList = await (session.Query<NullableOwner>().Select(x => new {x.Name, ManyToOneId = (Guid?) x.ManyToOne.Id}).ToListAsync());
var withValidManyToOneList = await (session.Query<NullableOwner>().Where(x => x.ManyToOne != null).Select(x => new {x.Name, ManyToOneId = (Guid?) x.ManyToOne.Id}).ToListAsync());
var withValidManyToOneList2 = await (session.CreateQuery("from NullableOwner ex where not ex.ManyToOne is null").ListAsync<NullableOwner>());
var withNullManyToOneList = await (session.Query<NullableOwner>().Where(x => x.ManyToOne == null).ToListAsync());
Assert.That(fullList.Count, Is.EqualTo(2));
Assert.That(withValidManyToOneList.Count, Is.EqualTo(0));
Assert.That(withValidManyToOneList2.Count, Is.EqualTo(0));
Assert.That(withNullManyToOneList.Count, Is.EqualTo(2));
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/NHibernate.Test/Hql/EntityJoinHqlTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -330,8 +330,12 @@ public void NullableEntityProjection()

var fullList = session.Query<NullableOwner>().Select(x => new {x.Name, ManyToOneId = (Guid?) x.ManyToOne.Id}).ToList();
var withValidManyToOneList = session.Query<NullableOwner>().Where(x => x.ManyToOne != null).Select(x => new {x.Name, ManyToOneId = (Guid?) x.ManyToOne.Id}).ToList();
var withValidManyToOneList2 = session.CreateQuery("from NullableOwner ex where not ex.ManyToOne is null").List<NullableOwner>();
var withNullManyToOneList = session.Query<NullableOwner>().Where(x => x.ManyToOne == null).ToList();
Assert.That(fullList.Count, Is.EqualTo(2));
Assert.That(withValidManyToOneList.Count, Is.EqualTo(0));
Assert.That(withValidManyToOneList2.Count, Is.EqualTo(0));
Assert.That(withNullManyToOneList.Count, Is.EqualTo(2));
}
}

Expand Down
3 changes: 3 additions & 0 deletions src/NHibernate/Hql/Ast/ANTLR/HqlSqlWalker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public partial class HqlSqlWalker
private SelectClause _selectClause;
private readonly AliasGenerator _aliasGenerator = new AliasGenerator();
private readonly ASTPrinter _printer = new ASTPrinter();
private bool _isNullComparison;

//
//Maps each top-level result variable to its SelectExpression;
Expand Down Expand Up @@ -1203,6 +1204,8 @@ public IASTFactory ASTFactory
}
}

internal bool IsNullComparison => _isNullComparison;

public void AddQuerySpaces(string[] spaces)
{
for (int i = 0; i < spaces.Length; i++)
Expand Down
2 changes: 1 addition & 1 deletion src/NHibernate/Hql/Ast/ANTLR/HqlSqlWalker.g
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ comparisonExpr
| ^(NOT_BETWEEN exprOrSubquery exprOrSubquery exprOrSubquery)
| ^(IN exprOrSubquery inRhs )
| ^(NOT_IN exprOrSubquery inRhs )
| ^(IS_NULL exprOrSubquery)
| ^(IS_NULL { _isNullComparison = true; } exprOrSubquery { _isNullComparison = false; })
| ^(IS_NOT_NULL exprOrSubquery)
// | ^(IS_TRUE expr)
// | ^(IS_FALSE expr)
Expand Down
13 changes: 9 additions & 4 deletions src/NHibernate/Hql/Ast/ANTLR/Tree/DotNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -389,8 +389,6 @@ private void DereferenceEntity(EntityType entityType, bool implicitJoin, string
bool joinIsNeeded;

//For nullable entity comparisons we always need to add join (like not constrained one-to-one or not-found ignore associations)
//NOTE: This fix is not fully correct. It doesn't work for comparisons with null (where e.OneToOneProp is null)
// as by default implicit join is generated and to work propelry left join is required (see GH-2611)
bool comparisonWithNullableEntity = entityType.IsNullable && Walker.IsComparativeExpressionClause;

if ( IsDotNode( parent ) )
Expand All @@ -417,8 +415,15 @@ private void DereferenceEntity(EntityType entityType, bool implicitJoin, string
|| comparisonWithNullableEntity;
}

if ( joinIsNeeded )
if ( joinIsNeeded )
{
//TODO: Find correct place for this if.
if (Walker.IsNullComparison)
{
implicitJoin = false;
_joinType = JoinType.LeftOuterJoin;
}

DereferenceEntityJoin( classAlias, entityType, implicitJoin, parent );
if (comparisonWithNullableEntity)
{
Expand Down Expand Up @@ -472,7 +477,7 @@ private void DereferenceEntityJoin(string classAlias, EntityType propertyType, b
string[] joinColumns = GetColumns();
string joinPath = Path;

if ( impliedJoin && Walker.IsInFrom )
if ( impliedJoin && Walker.IsInFrom )
{
_joinType = Walker.ImpliedJoinType;
}
Expand Down