Skip to content

Commit 50defd3

Browse files
committed
Table group joins support in hql
1 parent 1fa50d9 commit 50defd3

19 files changed

+467
-243
lines changed

src/NHibernate.Test/Async/Hql/Ast/WithClauseFixture.cs

Lines changed: 9 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@
88
//------------------------------------------------------------------------------
99

1010

11-
using System;
1211
using System.Collections;
13-
using NHibernate.Exceptions;
1412
using NHibernate.Hql.Ast.ANTLR;
1513
using NUnit.Framework;
1614

@@ -54,40 +52,21 @@ public async Task WithClauseFailsWithFetchAsync()
5452
}
5553

5654
[Test]
57-
public async Task ValidWithSemanticsAsync()
55+
public async Task WithClauseOnSubclassesAsync()
5856
{
5957
using (var s = OpenSession())
6058
{
6159
await (s.CreateQuery(
6260
"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());
63-
}
64-
}
6561

66-
[Test]
67-
public async Task InvalidWithSemanticsAsync()
68-
{
69-
using (ISession s = OpenSession())
70-
{
71-
// PROBLEM : f.bodyWeight is a reference to a column on the Animal table; however, the 'f'
72-
// alias relates to the Human.friends collection which the aonther Human entity. The issue
73-
// here is the way JoinSequence and Joinable (the persister) interact to generate the
74-
// joins relating to the sublcass/superclass tables
75-
Assert.ThrowsAsync<InvalidWithClauseException>(
76-
() =>
77-
s.CreateQuery("from Human h inner join h.friends as f with f.bodyWeight < :someLimit").SetDouble("someLimit", 1).ListAsync());
78-
79-
//The query below is no longer throw InvalidWithClauseException but generates "invalid" SQL to better support complex with join clauses.
80-
//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.
81-
try
82-
{
83-
await (s.CreateQuery("from Human h inner join h.offspring o with o.mother.father = :cousin")
84-
.SetInt32("cousin", 123)
85-
.ListAsync());
86-
}
87-
catch (GenericADOException)
88-
{
89-
//Apparently SQLite can process queries with wrong join orders
90-
}
62+
// f.bodyWeight is a reference to a column on the Animal table; however, the 'f'
63+
// alias relates to the Human.friends collection which the aonther Human entity.
64+
// Group join allows us to use such constructs
65+
await (s.CreateQuery("from Human h inner join h.friends as f with f.bodyWeight < :someLimit").SetDouble("someLimit", 1).ListAsync());
66+
67+
await (s.CreateQuery("from Human h inner join h.offspring o with o.mother.father = :cousin")
68+
.SetInt32("cousin", 123)
69+
.ListAsync());
9170
}
9271
}
9372

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,30 @@ public async Task EntityJoinWithFetchesAsync()
392392
}
393393
}
394394

395+
[Test]
396+
public async Task WithImpliedJoinOnAssociationAsync()
397+
{
398+
using (var session = OpenSession())
399+
{
400+
var result = await (session.CreateQuery(
401+
"SELECT s " +
402+
"FROM EntityComplex s left join s.SameTypeChild q on q.SameTypeChild.SameTypeChild.Name = s.Name"
403+
).ListAsync());
404+
}
405+
}
406+
407+
[Test]
408+
public async Task WithImpliedEntityJoinAsync()
409+
{
410+
using (var session = OpenSession())
411+
{
412+
var result = await (session.CreateQuery(
413+
"SELECT s " +
414+
"FROM EntityComplex s left join EntityComplex q on q.SameTypeChild.SameTypeChild.Name = s.Name"
415+
).ListAsync());
416+
}
417+
}
418+
395419
[Test]
396420
public async Task CrossJoinAndWhereClauseAsync()
397421
{

src/NHibernate.Test/Async/NHSpecificTest/NH2049/Fixture2049.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,13 @@ public async Task CanCriteriaQueryWithFilterOnJoinClassBaseClassPropertyAsync()
6565
}
6666

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

7776
Assert.That(persons, Has.Count.EqualTo(1));
7877
Assert.That(persons[0].Id, Is.EqualTo(1));
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//------------------------------------------------------------------------------
2+
// <auto-generated>
3+
// This code was generated by AsyncGenerator.
4+
//
5+
// Changes to this file may cause incorrect behavior and will be lost if
6+
// the code is regenerated.
7+
// </auto-generated>
8+
//------------------------------------------------------------------------------
9+
10+
11+
using NUnit.Framework;
12+
13+
namespace NHibernate.Test.NHSpecificTest.NH2208
14+
{
15+
using System.Threading.Tasks;
16+
[TestFixture]
17+
public class FilterAsync : BugTestCase
18+
{
19+
[Test]
20+
public async Task TestAsync()
21+
{
22+
using (ISession session = OpenSession())
23+
{
24+
session.EnableFilter("myfilter");
25+
await (session.CreateQuery("from E1 e join fetch e.BO").ListAsync());
26+
}
27+
}
28+
}
29+
}

src/NHibernate.Test/Hql/Ast/WithClauseFixture.cs

Lines changed: 9 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
using System;
21
using System.Collections;
3-
using NHibernate.Exceptions;
42
using NHibernate.Hql.Ast.ANTLR;
53
using NUnit.Framework;
64

@@ -42,40 +40,21 @@ public void WithClauseFailsWithFetch()
4240
}
4341

4442
[Test]
45-
public void ValidWithSemantics()
43+
public void WithClauseOnSubclasses()
4644
{
4745
using (var s = OpenSession())
4846
{
4947
s.CreateQuery(
5048
"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();
51-
}
52-
}
5349

54-
[Test]
55-
public void InvalidWithSemantics()
56-
{
57-
using (ISession s = OpenSession())
58-
{
59-
// PROBLEM : f.bodyWeight is a reference to a column on the Animal table; however, the 'f'
60-
// alias relates to the Human.friends collection which the aonther Human entity. The issue
61-
// here is the way JoinSequence and Joinable (the persister) interact to generate the
62-
// joins relating to the sublcass/superclass tables
63-
Assert.Throws<InvalidWithClauseException>(
64-
() =>
65-
s.CreateQuery("from Human h inner join h.friends as f with f.bodyWeight < :someLimit").SetDouble("someLimit", 1).List());
66-
67-
//The query below is no longer throw InvalidWithClauseException but generates "invalid" SQL to better support complex with join clauses.
68-
//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.
69-
try
70-
{
71-
s.CreateQuery("from Human h inner join h.offspring o with o.mother.father = :cousin")
72-
.SetInt32("cousin", 123)
73-
.List();
74-
}
75-
catch (GenericADOException)
76-
{
77-
//Apparently SQLite can process queries with wrong join orders
78-
}
50+
// f.bodyWeight is a reference to a column on the Animal table; however, the 'f'
51+
// alias relates to the Human.friends collection which the aonther Human entity.
52+
// Group join allows us to use such constructs
53+
s.CreateQuery("from Human h inner join h.friends as f with f.bodyWeight < :someLimit").SetDouble("someLimit", 1).List();
54+
55+
s.CreateQuery("from Human h inner join h.offspring o with o.mother.father = :cousin")
56+
.SetInt32("cousin", 123)
57+
.List();
7958
}
8059
}
8160

src/NHibernate.Test/Hql/EntityJoinHqlTest.cs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ public void EntityJoinWithFetches()
382382
}
383383

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

400+
[Test]
401+
public void WithImpliedJoinOnAssociation()
402+
{
403+
using (var session = OpenSession())
404+
{
405+
var result = session.CreateQuery(
406+
"SELECT s " +
407+
"FROM EntityComplex s left join s.SameTypeChild q on q.SameTypeChild.SameTypeChild.Name = s.Name"
408+
).List();
409+
}
410+
}
411+
412+
[Test]
413+
public void WithImpliedEntityJoin()
414+
{
415+
using (var session = OpenSession())
416+
{
417+
var result = session.CreateQuery(
418+
"SELECT s " +
419+
"FROM EntityComplex s left join EntityComplex q on q.SameTypeChild.SameTypeChild.Name = s.Name"
420+
).List();
421+
}
422+
}
423+
400424
[Test]
401425
public void CrossJoinAndWhereClause()
402426
{

src/NHibernate.Test/NHSpecificTest/NH2049/Fixture2049.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,13 @@ public void CanCriteriaQueryWithFilterOnJoinClassBaseClassProperty()
5454
}
5555

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

6665
Assert.That(persons, Has.Count.EqualTo(1));
6766
Assert.That(persons[0].Id, Is.EqualTo(1));

src/NHibernate.Test/NHSpecificTest/NH2208/Filter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace NHibernate.Test.NHSpecificTest.NH2208
55
[TestFixture]
66
public class Filter : BugTestCase
77
{
8-
[Test, Ignore("Not fixed yet")]
8+
[Test]
99
public void Test()
1010
{
1111
using (ISession session = OpenSession())

0 commit comments

Comments
 (0)