Skip to content

Commit 3f535af

Browse files
authored
Merge branch '5.4.x' into cacheLog
2 parents ac5abac + 3088367 commit 3f535af

File tree

7 files changed

+232
-1
lines changed

7 files changed

+232
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
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 System.Linq;
12+
using NHibernate.Linq;
13+
using NUnit.Framework;
14+
15+
namespace NHibernate.Test.NHSpecificTest.GH3263
16+
{
17+
using System.Threading.Tasks;
18+
[TestFixture]
19+
public class ReuseFetchJoinFixtureAsync : BugTestCase
20+
{
21+
protected override void OnSetUp()
22+
{
23+
using var s = OpenSession();
24+
using var t = s.BeginTransaction();
25+
var em = new Employee() { Name = "x", OptionalInfo = new OptionalInfo() };
26+
em.OptionalInfo.Employee = em;
27+
s.Save(em);
28+
t.Commit();
29+
}
30+
protected override void OnTearDown()
31+
{
32+
using var session = OpenSession();
33+
using var transaction = session.BeginTransaction();
34+
session.CreateQuery("delete from System.Object").ExecuteUpdate();
35+
36+
transaction.Commit();
37+
}
38+
39+
[Test]
40+
public async Task ReuseJoinScalarSelectAsync()
41+
{
42+
using var session = OpenSession();
43+
await (session.Query<Employee>()
44+
.Fetch(x => x.OptionalInfo)
45+
.Where(x => x.OptionalInfo != null)
46+
.Select(x => new { x.OptionalInfo.Age })
47+
.ToListAsync());
48+
}
49+
50+
[Test]
51+
public async Task ReuseJoinScalarSelectHqlAsync()
52+
{
53+
using var session = OpenSession();
54+
await (session.CreateQuery(
55+
"select x.OptionalInfo.Age " +
56+
"from Employee x " +
57+
"fetch x.OptionalInfo " +
58+
"where x.OptionalInfo != null ").ListAsync());
59+
60+
}
61+
62+
[Test]
63+
public async Task ReuseJoinScalarSelectHql2Async()
64+
{
65+
using var session = OpenSession();
66+
await (session.CreateQuery(
67+
"select x.OptionalInfo.Age " +
68+
"from Employee x " +
69+
"join fetch x.OptionalInfo o " +
70+
"where o != null ").ListAsync());
71+
}
72+
73+
[Test]
74+
public async Task ReuseJoinScalarSelectHql3Async()
75+
{
76+
using var session = OpenSession();
77+
await (session.CreateQuery(
78+
"select x.OptionalInfo.Age from Employee x " +
79+
"join fetch x.OptionalInfo " +
80+
"where x.OptionalInfo != null ").ListAsync());
81+
}
82+
83+
[Test]
84+
public async Task ReuseJoinEntityAndScalarSelectAsync()
85+
{
86+
using var session = OpenSession();
87+
using var sqlLog = new SqlLogSpy();
88+
89+
var x = await (session.Query<Employee>()
90+
.Fetch(x => x.OptionalInfo)
91+
.Where(x => x.OptionalInfo != null)
92+
.Select(x => new { x, x.OptionalInfo.Age })
93+
.FirstAsync());
94+
95+
Assert.That(sqlLog.Appender.GetEvents().Length, Is.EqualTo(1));
96+
Assert.That(NHibernateUtil.IsInitialized(x.x.OptionalInfo), Is.True);
97+
}
98+
}
99+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
namespace NHibernate.Test.NHSpecificTest.GH3263
2+
{
3+
public class Employee
4+
{
5+
public virtual int EmployeeId { get; set; }
6+
public virtual string Name { get; set; }
7+
public virtual OptionalInfo OptionalInfo { get; set; }
8+
}
9+
10+
public class OptionalInfo
11+
{
12+
public virtual int EmployeeId { get; set; }
13+
public virtual int Age { get; set; }
14+
public virtual Employee Employee { get; set; }
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernate.Test"
2+
namespace="NHibernate.Test.NHSpecificTest.GH3263">
3+
<class name="Employee" table="Employee">
4+
<id name="EmployeeId">
5+
<column name="EmployeeId" />
6+
<generator class="identity" />
7+
</id>
8+
<property name="Name" >
9+
<column name="Name" not-null="true" />
10+
</property>
11+
<one-to-one cascade="save-update" name="OptionalInfo" foreign-key="none"/>
12+
</class>
13+
<class name="OptionalInfo" table="OptionalInfo">
14+
<id name="EmployeeId" >
15+
<column name="EmployeeId" />
16+
<generator class="foreign">
17+
<param name="property">Employee</param>
18+
</generator>
19+
</id>
20+
<property name="Age">
21+
<column name="Age" not-null="true" />
22+
</property>
23+
<one-to-one cascade="none" name="Employee" foreign-key="none" />
24+
</class>
25+
</hibernate-mapping>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
using System.Linq;
2+
using NHibernate.Linq;
3+
using NUnit.Framework;
4+
5+
namespace NHibernate.Test.NHSpecificTest.GH3263
6+
{
7+
[TestFixture]
8+
public class ReuseFetchJoinFixture : BugTestCase
9+
{
10+
protected override void OnSetUp()
11+
{
12+
using var s = OpenSession();
13+
using var t = s.BeginTransaction();
14+
var em = new Employee() { Name = "x", OptionalInfo = new OptionalInfo() };
15+
em.OptionalInfo.Employee = em;
16+
s.Save(em);
17+
t.Commit();
18+
}
19+
protected override void OnTearDown()
20+
{
21+
using var session = OpenSession();
22+
using var transaction = session.BeginTransaction();
23+
session.CreateQuery("delete from System.Object").ExecuteUpdate();
24+
25+
transaction.Commit();
26+
}
27+
28+
[Test]
29+
public void ReuseJoinScalarSelect()
30+
{
31+
using var session = OpenSession();
32+
session.Query<Employee>()
33+
.Fetch(x => x.OptionalInfo)
34+
.Where(x => x.OptionalInfo != null)
35+
.Select(x => new { x.OptionalInfo.Age })
36+
.ToList();
37+
}
38+
39+
[Test]
40+
public void ReuseJoinScalarSelectHql()
41+
{
42+
using var session = OpenSession();
43+
session.CreateQuery(
44+
"select x.OptionalInfo.Age " +
45+
"from Employee x " +
46+
"fetch x.OptionalInfo " +
47+
"where x.OptionalInfo != null ").List();
48+
49+
}
50+
51+
[Test]
52+
public void ReuseJoinScalarSelectHql2()
53+
{
54+
using var session = OpenSession();
55+
session.CreateQuery(
56+
"select x.OptionalInfo.Age " +
57+
"from Employee x " +
58+
"join fetch x.OptionalInfo o " +
59+
"where o != null ").List();
60+
}
61+
62+
[Test]
63+
public void ReuseJoinScalarSelectHql3()
64+
{
65+
using var session = OpenSession();
66+
session.CreateQuery(
67+
"select x.OptionalInfo.Age from Employee x " +
68+
"join fetch x.OptionalInfo " +
69+
"where x.OptionalInfo != null ").List();
70+
}
71+
72+
[Test]
73+
public void ReuseJoinEntityAndScalarSelect()
74+
{
75+
using var session = OpenSession();
76+
using var sqlLog = new SqlLogSpy();
77+
78+
var x = session.Query<Employee>()
79+
.Fetch(x => x.OptionalInfo)
80+
.Where(x => x.OptionalInfo != null)
81+
.Select(x => new { x, x.OptionalInfo.Age })
82+
.First();
83+
84+
Assert.That(sqlLog.Appender.GetEvents().Length, Is.EqualTo(1));
85+
Assert.That(NHibernateUtil.IsInitialized(x.x.OptionalInfo), Is.True);
86+
}
87+
}
88+
}

src/NHibernate/Hql/Ast/ANTLR/Tree/DotNode.cs

+2
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,8 @@ private void DereferenceEntityJoin(string classAlias, EntityType propertyType, b
558558
{
559559
elem.JoinSequence.SetJoinType(_joinType);
560560
}
561+
562+
elem.ReusedJoin = true;
561563
currentFromClause.AddDuplicateAlias(classAlias, elem);
562564
}
563565

src/NHibernate/Hql/Ast/ANTLR/Tree/FromElement.cs

+1
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,7 @@ internal virtual string[] GetIdentityColumns(string alias)
631631
}
632632

633633
internal bool UseTableAliases => Walker.StatementType == HqlSqlWalker.SELECT || Walker.IsSubQuery;
634+
internal bool ReusedJoin { get; set; }
634635

635636
public void HandlePropertyBeingDereferenced(IType propertySource, string propertyName)
636637
{

src/NHibernate/Hql/Ast/ANTLR/Tree/SelectClause.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ private List<FromElement> GetFetchedFromElements(FromClause fromClause)
245245
// throw new QueryException(string.Format(JoinFetchWithoutOwnerExceptionMsg, fromElement.GetDisplayText()));
246246

247247
//throw away the fromElement. It's clearly redundant.
248-
if (fromElement.FromClause == fromClause)
248+
if (fromElement.FromClause == fromClause && !fromElement.ReusedJoin)
249249
{
250250
fromElement.Parent.RemoveChild(fromElement);
251251
}

0 commit comments

Comments
 (0)