diff --git a/src/NHibernate.Test/Async/Hql/EntityJoinHqlTest.cs b/src/NHibernate.Test/Async/Hql/EntityJoinHqlTest.cs index 0632a01771a..adfd4d7ed49 100644 --- a/src/NHibernate.Test/Async/Hql/EntityJoinHqlTest.cs +++ b/src/NHibernate.Test/Async/Hql/EntityJoinHqlTest.cs @@ -8,6 +8,7 @@ //------------------------------------------------------------------------------ +using System; using System.Text.RegularExpressions; using NHibernate.Cfg.MappingSchema; using NHibernate.Mapping.ByCode; @@ -233,6 +234,21 @@ public async Task NullablePropRefWhereIdEntityNotNullShouldAddJoinAsync() } } + [Test(Description = "GH-2688")] + public async Task NullableManyToOneDeleteQueryAsync() + { + using (var session = OpenSession()) + { + await (session + .CreateQuery( + "delete " + + "from NullableOwner ex " + + "where ex.ManyToOne.id = :id" + ).SetParameter("id", Guid.Empty) + .ExecuteUpdateAsync()); + } + } + [Test] public async Task NullableOneToOneFetchQueryIsNotAffectedAsync() { @@ -515,6 +531,7 @@ protected override HbmMapping GetMappings() m.ForeignKey("none"); m.NotFound(NotFoundMode.Ignore); }); + rc.ManyToOne(e => e.ManyToOne, m => m.NotFound(NotFoundMode.Ignore)); }); diff --git a/src/NHibernate.Test/Hql/EntityJoinHqlTest.cs b/src/NHibernate.Test/Hql/EntityJoinHqlTest.cs index f01b6303d30..cc2cc1da4a9 100644 --- a/src/NHibernate.Test/Hql/EntityJoinHqlTest.cs +++ b/src/NHibernate.Test/Hql/EntityJoinHqlTest.cs @@ -1,4 +1,5 @@ -using System.Text.RegularExpressions; +using System; +using System.Text.RegularExpressions; using NHibernate.Cfg.MappingSchema; using NHibernate.Mapping.ByCode; using NHibernate.Test.Hql.EntityJoinHqlTestEntities; @@ -222,6 +223,21 @@ public void NullablePropRefWhereIdEntityNotNullShouldAddJoin() } } + [Test(Description = "GH-2688")] + public void NullableManyToOneDeleteQuery() + { + using (var session = OpenSession()) + { + session + .CreateQuery( + "delete " + + "from NullableOwner ex " + + "where ex.ManyToOne.id = :id" + ).SetParameter("id", Guid.Empty) + .ExecuteUpdate(); + } + } + [Test] public void NullableOneToOneFetchQueryIsNotAffected() { @@ -520,6 +536,7 @@ protected override HbmMapping GetMappings() m.ForeignKey("none"); m.NotFound(NotFoundMode.Ignore); }); + rc.ManyToOne(e => e.ManyToOne, m => m.NotFound(NotFoundMode.Ignore)); }); diff --git a/src/NHibernate.Test/Hql/EntityJoinHqlTestEntities.cs b/src/NHibernate.Test/Hql/EntityJoinHqlTestEntities.cs index 277b0ea706b..4535bd27886 100644 --- a/src/NHibernate.Test/Hql/EntityJoinHqlTestEntities.cs +++ b/src/NHibernate.Test/Hql/EntityJoinHqlTestEntities.cs @@ -31,6 +31,7 @@ public class NullableOwner public virtual string Name { get; set; } public virtual OneToOneEntity OneToOne { get; set; } public virtual PropRefEntity PropRef { get; set; } + public virtual OneToOneEntity ManyToOne { get; set; } } public class EntityWithCompositeId diff --git a/src/NHibernate/Hql/Ast/ANTLR/Tree/DotNode.cs b/src/NHibernate/Hql/Ast/ANTLR/Tree/DotNode.cs index bbe0a91b740..0a2d2a1ad61 100644 --- a/src/NHibernate/Hql/Ast/ANTLR/Tree/DotNode.cs +++ b/src/NHibernate/Hql/Ast/ANTLR/Tree/DotNode.cs @@ -386,7 +386,9 @@ private void DereferenceEntity(EntityType entityType, bool implicitJoin, string string property = _propertyName; bool joinIsNeeded; - //For nullable entity comparisons we always need to add join (like not constrained one-to-one or not-found ignore associations) + //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 = false; if ( IsDotNode( parent ) ) @@ -396,7 +398,7 @@ private void DereferenceEntity(EntityType entityType, bool implicitJoin, string // entity's PK (because 'our' table would know the FK). parentAsDotNode = ( DotNode ) parent; property = parentAsDotNode._propertyName; - joinIsNeeded = generateJoin && (entityType.IsNullable || !IsReferenceToPrimaryKey( parentAsDotNode._propertyName, entityType )); + joinIsNeeded = generateJoin && ((Walker.IsSelectStatement && entityType.IsNullable) || !IsReferenceToPrimaryKey( parentAsDotNode._propertyName, entityType )); } else if ( ! Walker.IsSelectStatement ) {