Skip to content

Table group joins support in hql #2361

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 14, 2020
Merged
Show file tree
Hide file tree
Changes from all 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
39 changes: 9 additions & 30 deletions src/NHibernate.Test/Async/Hql/Ast/WithClauseFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@
//------------------------------------------------------------------------------


using System;
using System.Collections;
using NHibernate.Exceptions;
using NHibernate.Hql.Ast.ANTLR;
using NUnit.Framework;

Expand Down Expand Up @@ -54,40 +52,21 @@ public async Task WithClauseFailsWithFetchAsync()
}

[Test]
public async Task ValidWithSemanticsAsync()
public async Task WithClauseOnSubclassesAsync()
{
using (var s = OpenSession())
{
await (s.CreateQuery(
"from Animal a inner join a.offspring o inner join o.mother as m inner join m.father as f with o.bodyWeight > 1").ListAsync());
}
}

[Test]
public async Task InvalidWithSemanticsAsync()
{
using (ISession s = OpenSession())
{
// PROBLEM : f.bodyWeight is a reference to a column on the Animal table; however, the 'f'
// alias relates to the Human.friends collection which the aonther Human entity. The issue
// here is the way JoinSequence and Joinable (the persister) interact to generate the
// joins relating to the sublcass/superclass tables
Assert.ThrowsAsync<InvalidWithClauseException>(
() =>
s.CreateQuery("from Human h inner join h.friends as f with f.bodyWeight < :someLimit").SetDouble("someLimit", 1).ListAsync());

//The query below is no longer throw InvalidWithClauseException but generates "invalid" SQL to better support complex with join clauses.
//Invalid SQL means that additional joins for "o.mother.father" are currently added after "offspring" join. Some DBs can process such query and some can't.
try
{
await (s.CreateQuery("from Human h inner join h.offspring o with o.mother.father = :cousin")
.SetInt32("cousin", 123)
.ListAsync());
}
catch (GenericADOException)
{
//Apparently SQLite can process queries with wrong join orders
}
// f.bodyWeight is a reference to a column on the Animal table; however, the 'f'
// alias relates to the Human.friends collection which the aonther Human entity.
// Group join allows us to use such constructs
await (s.CreateQuery("from Human h inner join h.friends as f with f.bodyWeight < :someLimit").SetDouble("someLimit", 1).ListAsync());

await (s.CreateQuery("from Human h inner join h.offspring o with o.mother.father = :cousin")
.SetInt32("cousin", 123)
.ListAsync());
}
}

Expand Down
24 changes: 24 additions & 0 deletions src/NHibernate.Test/Async/Hql/EntityJoinHqlTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,30 @@ public async Task EntityJoinWithFetchesAsync()
}
}

[Test]
public async Task WithImpliedJoinOnAssociationAsync()
{
using (var session = OpenSession())
{
var result = await (session.CreateQuery(
"SELECT s " +
"FROM EntityComplex s left join s.SameTypeChild q on q.SameTypeChild.SameTypeChild.Name = s.Name"
).ListAsync());
}
}

[Test]
public async Task WithImpliedEntityJoinAsync()
{
using (var session = OpenSession())
{
var result = await (session.CreateQuery(
"SELECT s " +
"FROM EntityComplex s left join EntityComplex q on q.SameTypeChild.SameTypeChild.Name = s.Name"
).ListAsync());
}
}

[Test]
public async Task CrossJoinAndWhereClauseAsync()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,13 @@ public async Task CanCriteriaQueryWithFilterOnJoinClassBaseClassPropertyAsync()
}

[Test]
[KnownBug("Known bug NH-2049.", "NHibernate.Exceptions.GenericADOException")]
public async Task CanHqlQueryWithFilterOnJoinClassBaseClassPropertyAsync()
{
using (ISession session = OpenSession())
{
session.EnableFilter("DeletedCustomer").SetParameter("deleted", false);
var persons = await (session.CreateQuery("from Person as person left join person.IndividualCustomer as indCustomer")
.ListAsync<Person>());
var persons = await (session.CreateQuery("from Person as person inner join fetch person.IndividualCustomer as indCustomer")
.ListAsync<Person>());

Assert.That(persons, Has.Count.EqualTo(1));
Assert.That(persons[0].Id, Is.EqualTo(1));
Expand Down
29 changes: 29 additions & 0 deletions src/NHibernate.Test/Async/NHSpecificTest/NH2208/Filter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by AsyncGenerator.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------


using NUnit.Framework;

namespace NHibernate.Test.NHSpecificTest.NH2208
{
using System.Threading.Tasks;
[TestFixture]
public class FilterAsync : BugTestCase
{
[Test]
public async Task TestAsync()
{
using (ISession session = OpenSession())
{
session.EnableFilter("myfilter");
await (session.CreateQuery("from E1 e join fetch e.BO").ListAsync());
}
}
}
}
39 changes: 9 additions & 30 deletions src/NHibernate.Test/Hql/Ast/WithClauseFixture.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System;
using System.Collections;
using NHibernate.Exceptions;
using NHibernate.Hql.Ast.ANTLR;
using NUnit.Framework;

Expand Down Expand Up @@ -42,40 +40,21 @@ public void WithClauseFailsWithFetch()
}

[Test]
public void ValidWithSemantics()
public void WithClauseOnSubclasses()
{
using (var s = OpenSession())
{
s.CreateQuery(
"from Animal a inner join a.offspring o inner join o.mother as m inner join m.father as f with o.bodyWeight > 1").List();
}
}

[Test]
public void InvalidWithSemantics()
{
using (ISession s = OpenSession())
{
// PROBLEM : f.bodyWeight is a reference to a column on the Animal table; however, the 'f'
// alias relates to the Human.friends collection which the aonther Human entity. The issue
// here is the way JoinSequence and Joinable (the persister) interact to generate the
// joins relating to the sublcass/superclass tables
Assert.Throws<InvalidWithClauseException>(
() =>
s.CreateQuery("from Human h inner join h.friends as f with f.bodyWeight < :someLimit").SetDouble("someLimit", 1).List());

//The query below is no longer throw InvalidWithClauseException but generates "invalid" SQL to better support complex with join clauses.
//Invalid SQL means that additional joins for "o.mother.father" are currently added after "offspring" join. Some DBs can process such query and some can't.
try
{
s.CreateQuery("from Human h inner join h.offspring o with o.mother.father = :cousin")
.SetInt32("cousin", 123)
.List();
}
catch (GenericADOException)
{
//Apparently SQLite can process queries with wrong join orders
}
// f.bodyWeight is a reference to a column on the Animal table; however, the 'f'
// alias relates to the Human.friends collection which the aonther Human entity.
// Group join allows us to use such constructs
s.CreateQuery("from Human h inner join h.friends as f with f.bodyWeight < :someLimit").SetDouble("someLimit", 1).List();

s.CreateQuery("from Human h inner join h.offspring o with o.mother.father = :cousin")
.SetInt32("cousin", 123)
.List();
}
}

Expand Down
28 changes: 26 additions & 2 deletions src/NHibernate.Test/Hql/EntityJoinHqlTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ public void EntityJoinWithFetches()
}

[Test, Ignore("Failing for unrelated reasons")]
public void ImplicitJoinAndWithClause()
public void CrossJoinAndWithClause()
{
//This is about complex theta style join fix that was implemented in hibernate along with entity join functionality
//https://hibernate.atlassian.net/browse/HHH-7321
Expand All @@ -391,12 +391,36 @@ public void ImplicitJoinAndWithClause()
{
session.CreateQuery(
"SELECT s " +
"FROM EntityComplex s, EntityComplex q " +
"FROM EntityComplex s CROSS JOIN EntityComplex q " +
"LEFT JOIN s.SameTypeChild AS sa WITH sa.SameTypeChild.Id = q.SameTypeChild.Id"
).List();
}
}

[Test]
public void WithImpliedJoinOnAssociation()
{
using (var session = OpenSession())
{
var result = session.CreateQuery(
"SELECT s " +
"FROM EntityComplex s left join s.SameTypeChild q on q.SameTypeChild.SameTypeChild.Name = s.Name"
).List();
}
}

[Test]
public void WithImpliedEntityJoin()
{
using (var session = OpenSession())
{
var result = session.CreateQuery(
"SELECT s " +
"FROM EntityComplex s left join EntityComplex q on q.SameTypeChild.SameTypeChild.Name = s.Name"
).List();
}
}

[Test]
public void CrossJoinAndWhereClause()
{
Expand Down
5 changes: 2 additions & 3 deletions src/NHibernate.Test/NHSpecificTest/NH2049/Fixture2049.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,13 @@ public void CanCriteriaQueryWithFilterOnJoinClassBaseClassProperty()
}

[Test]
[KnownBug("Known bug NH-2049.", "NHibernate.Exceptions.GenericADOException")]
public void CanHqlQueryWithFilterOnJoinClassBaseClassProperty()
{
using (ISession session = OpenSession())
{
session.EnableFilter("DeletedCustomer").SetParameter("deleted", false);
var persons = session.CreateQuery("from Person as person left join person.IndividualCustomer as indCustomer")
.List<Person>();
var persons = session.CreateQuery("from Person as person inner join fetch person.IndividualCustomer as indCustomer")
.List<Person>();

Assert.That(persons, Has.Count.EqualTo(1));
Assert.That(persons[0].Id, Is.EqualTo(1));
Expand Down
2 changes: 1 addition & 1 deletion src/NHibernate.Test/NHSpecificTest/NH2208/Filter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace NHibernate.Test.NHSpecificTest.NH2208
[TestFixture]
public class Filter : BugTestCase
{
[Test, Ignore("Not fixed yet")]
[Test]
public void Test()
{
using (ISession session = OpenSession())
Expand Down
Loading