diff --git a/src/NHibernate.Test/Async/NHSpecificTest/GH3306NullableEntityCorrelatedSubquery/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/GH3306NullableEntityCorrelatedSubquery/Fixture.cs new file mode 100644 index 00000000000..ba446d194f9 --- /dev/null +++ b/src/NHibernate.Test/Async/NHSpecificTest/GH3306NullableEntityCorrelatedSubquery/Fixture.cs @@ -0,0 +1,69 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by AsyncGenerator. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + + +using System.Linq; +using NUnit.Framework; +using NHibernate.Linq; + +namespace NHibernate.Test.NHSpecificTest.GH3306NullableEntityCorrelatedSubquery +{ + using System.Threading.Tasks; + [TestFixture] + public class FixtureAsync : BugTestCase + { + private const string NAME_JOE = "Joe"; + private const string NAME_ALLEN = "Allen"; + + protected override void OnSetUp() + { + using (var session = OpenSession()) + using (var tx = session.BeginTransaction()) + { + var joe = new Customer { Name = NAME_JOE }; + session.Save(joe); + + var allen = new Customer { Name = NAME_ALLEN }; + session.Save(allen); + + var joeInvoice0 = new Invoice { Customer = joe, Number = 0 }; + session.Save(joeInvoice0); + + var allenInvoice1 = new Invoice { Customer = allen, Number = 1 }; + session.Save(allenInvoice1); + + tx.Commit(); + } + } + + protected override void OnTearDown() + { + using (var session = OpenSession()) + using (var tx = session.BeginTransaction()) + { + session.Delete("from Invoice"); + session.Delete("from Customer"); + tx.Commit(); + } + } + + [Test] + public async Task NullableEntityInCorrelatedSubqueryAsync() + { + using (var s = OpenSession()) + { + var customers = s.Query().Where(c => c.Name == NAME_JOE); + var results = await (s.Query() + .Where(i => customers.Any(c => c.Invoices.Any(ci => ci.Customer == i.Customer))).ToListAsync()); + + Assert.That(results.Count, Is.EqualTo(1)); + } + } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH3306NullableEntityCorrelatedSubquery/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/GH3306NullableEntityCorrelatedSubquery/Fixture.cs new file mode 100644 index 00000000000..d1d511eca59 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH3306NullableEntityCorrelatedSubquery/Fixture.cs @@ -0,0 +1,57 @@ +using System.Linq; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.GH3306NullableEntityCorrelatedSubquery +{ + [TestFixture] + public class Fixture : BugTestCase + { + private const string NAME_JOE = "Joe"; + private const string NAME_ALLEN = "Allen"; + + protected override void OnSetUp() + { + using (var session = OpenSession()) + using (var tx = session.BeginTransaction()) + { + var joe = new Customer { Name = NAME_JOE }; + session.Save(joe); + + var allen = new Customer { Name = NAME_ALLEN }; + session.Save(allen); + + var joeInvoice0 = new Invoice { Customer = joe, Number = 0 }; + session.Save(joeInvoice0); + + var allenInvoice1 = new Invoice { Customer = allen, Number = 1 }; + session.Save(allenInvoice1); + + tx.Commit(); + } + } + + protected override void OnTearDown() + { + using (var session = OpenSession()) + using (var tx = session.BeginTransaction()) + { + session.Delete("from Invoice"); + session.Delete("from Customer"); + tx.Commit(); + } + } + + [Test] + public void NullableEntityInCorrelatedSubquery() + { + using (var s = OpenSession()) + { + var customers = s.Query().Where(c => c.Name == NAME_JOE); + var results = s.Query() + .Where(i => customers.Any(c => c.Invoices.Any(ci => ci.Customer == i.Customer))).ToList(); + + Assert.That(results.Count, Is.EqualTo(1)); + } + } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH3306NullableEntityCorrelatedSubquery/Mappings.hbm.xml b/src/NHibernate.Test/NHSpecificTest/GH3306NullableEntityCorrelatedSubquery/Mappings.hbm.xml new file mode 100644 index 00000000000..515584fe116 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH3306NullableEntityCorrelatedSubquery/Mappings.hbm.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/NHibernate.Test/NHSpecificTest/GH3306NullableEntityCorrelatedSubquery/Model.cs b/src/NHibernate.Test/NHSpecificTest/GH3306NullableEntityCorrelatedSubquery/Model.cs new file mode 100644 index 00000000000..2c472579b00 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH3306NullableEntityCorrelatedSubquery/Model.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; + +namespace NHibernate.Test.NHSpecificTest.GH3306NullableEntityCorrelatedSubquery +{ + public class Customer + { + public virtual int ID { get; protected set; } + public virtual ISet Invoices { get; set; } + public virtual string Name { get; set; } + } + + public class Invoice + { + public virtual int ID { get; protected set; } + public virtual Customer Customer { get; set; } + public virtual int Number { get; set; } + } +} diff --git a/src/NHibernate/Hql/Ast/ANTLR/Tree/DotNode.cs b/src/NHibernate/Hql/Ast/ANTLR/Tree/DotNode.cs index f7743426826..2049edefb6e 100644 --- a/src/NHibernate/Hql/Ast/ANTLR/Tree/DotNode.cs +++ b/src/NHibernate/Hql/Ast/ANTLR/Tree/DotNode.cs @@ -389,7 +389,7 @@ 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) - bool comparisonWithNullableEntity = entityType.IsNullable && Walker.IsComparativeExpressionClause; + bool comparisonWithNullableEntity = entityType.IsNullable && Walker.IsComparativeExpressionClause && !IsCorrelatedSubselect; if ( IsDotNode( parent ) ) {