Skip to content

Commit 174d788

Browse files
gmalyshevfredericDelaporte
authored andcommitted
Implementation (fix) NH-3427
Joining to association twice using criteria.
1 parent a09830f commit 174d788

File tree

6 files changed

+309
-81
lines changed

6 files changed

+309
-81
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System.Collections;
2+
using System.Collections.Generic;
3+
4+
namespace NHibernate.Test.NHSpecificTest.NH3472
5+
{
6+
7+
public class Cat
8+
{
9+
private int id;
10+
private IList<Cat> children = new List<Cat>();
11+
12+
public virtual string Color { get; set; }
13+
public int Age { get; set; }
14+
15+
public int Id
16+
{
17+
get { return id; }
18+
set { id = value; }
19+
}
20+
21+
public IList<Cat> Children
22+
{
23+
get { return children; }
24+
set { children = value; }
25+
}
26+
}
27+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using System.Collections.Generic;
2+
using NHibernate.Criterion;
3+
using NHibernate.SqlCommand;
4+
using NUnit.Framework;
5+
6+
namespace NHibernate.Test.NHSpecificTest.NH3472
7+
{
8+
[TestFixture]
9+
public class Fixture : BugTestCase
10+
{
11+
[Test]
12+
public void CriteriaQueryWithMultipleJoinsToSameAssociation()
13+
{
14+
using (ISession sess = OpenSession())
15+
{
16+
Cat c = new Cat();
17+
c.Age = 0;
18+
c.Children = new List<Cat>
19+
{
20+
new Cat {Color = "Ginger", Age = 1},
21+
new Cat {Color = "Black", Age = 3}
22+
};
23+
sess.Save(c);
24+
sess.Flush();
25+
}
26+
27+
using (ISession sess = OpenSession())
28+
{
29+
try
30+
{
31+
var list = sess.CreateCriteria<Cat>("cat")
32+
.CreateAlias("cat.Children", "gingerCat", JoinType.LeftOuterJoin, Restrictions.Eq("Color", "Ginger"))
33+
34+
.CreateAlias("cat.Children", "blackCat", JoinType.LeftOuterJoin,
35+
Restrictions.Eq("Color", "Black"))
36+
.SetProjection(
37+
Projections.Alias(Projections.Property("gingerCat.Age"), "gingerCatAge"),
38+
Projections.Alias(Projections.Property("blackCat.Age"), "blackCatAge")
39+
).AddOrder(new Order(Projections.Property("Age"), true)).List<object[]>();
40+
Assert.AreEqual(list.Count, 3);
41+
Assert.AreEqual(list[0][0], 1);
42+
Assert.AreEqual(list[0][1], 3);
43+
44+
Assert.IsNull(list[1][0]);
45+
Assert.IsNull(list[1][1]);
46+
47+
Assert.IsNull(list[2][0]);
48+
Assert.IsNull(list[2][1]);
49+
}
50+
finally
51+
{
52+
sess.Delete("from Cat");
53+
sess.Flush();
54+
}
55+
}
56+
}
57+
}
58+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
3+
assembly="NHibernate.Test"
4+
namespace="NHibernate.Test.NHSpecificTest.NH3472"
5+
default-lazy="false">
6+
7+
<class name="Cat">
8+
<id name="Id" type="Int32" unsaved-value="0" >
9+
<generator class="native" />
10+
</id>
11+
12+
<property name="Color" type="string"/>
13+
<property name="Age" type="int"/>
14+
15+
<bag name="Children" cascade="all" lazy="true">
16+
<key column="parentId" />
17+
<one-to-many class="Cat" />
18+
</bag>
19+
</class>
20+
21+
22+
23+
</hibernate-mapping>

src/NHibernate/Loader/Criteria/CriteriaJoinWalker.cs

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ protected override void AddAssociations()
8080
foreach (var entityJoinInfo in translator.GetEntityJoins().Values)
8181
{
8282
var tableAlias = translator.GetSQLAlias(entityJoinInfo.Criteria);
83-
var criteriaPath = entityJoinInfo.Criteria.Alias; //path for entity join is equal to alias
83+
var criteriaPath = entityJoinInfo.Criteria.Alias;
8484
var persister = entityJoinInfo.Persister as IOuterJoinLoadable;
8585
AddExplicitEntityJoinAssociation(persister, tableAlias, translator.GetJoinType(criteriaPath), criteriaPath);
8686
IncludeInResultIfNeeded(persister, entityJoinInfo.Criteria, tableAlias, criteriaPath);
@@ -166,13 +166,20 @@ public override string Comment
166166
get { return "criteria query"; }
167167
}
168168

169-
protected override JoinType GetJoinType(IAssociationType type, FetchMode config, string path, string lhsTable,
170-
string[] lhsColumns, bool nullable, int currentDepth,
171-
CascadeStyle cascadeStyle)
169+
protected override IList<string> AliasByPath(string path, string sqlAlias)
172170
{
173-
if (translator.IsJoin(path))
171+
var alias = translator.AliasByPath(path, sqlAlias);
172+
if (alias.Count == 0)
173+
return base.AliasByPath(path, sqlAlias);
174+
return alias;
175+
}
176+
177+
protected override JoinType GetJoinType(IAssociationType type, FetchMode config, string path, string pathAlias,
178+
string lhsTable, string[] lhsColumns, bool nullable, int currentDepth, CascadeStyle cascadeStyle)
179+
{
180+
if (translator.IsJoin(path, pathAlias))
174181
{
175-
return translator.GetJoinType(path);
182+
return translator.GetJoinType(path, pathAlias);
176183
}
177184

178185
if (translator.HasProjection)
@@ -184,7 +191,7 @@ protected override JoinType GetJoinType(IAssociationType type, FetchMode config,
184191
switch (selectMode)
185192
{
186193
case SelectMode.Undefined:
187-
return base.GetJoinType(type, config, path, lhsTable, lhsColumns, nullable, currentDepth, cascadeStyle);
194+
return base.GetJoinType(type, config, path, pathAlias, lhsTable, lhsColumns, nullable, currentDepth, cascadeStyle);
188195

189196
case SelectMode.Fetch:
190197
case SelectMode.FetchLazyProperties:
@@ -200,7 +207,7 @@ protected override JoinType GetJoinType(IAssociationType type, FetchMode config,
200207
}
201208
}
202209

203-
protected override string GenerateTableAlias(int n, string path, IJoinable joinable)
210+
protected override string GenerateTableAlias(int n, string path, string pathAlias, IJoinable joinable)
204211
{
205212
// TODO: deal with side-effects (changes to includeInSelectList, userAliasList, resultTypeList)!!!
206213

@@ -225,14 +232,14 @@ protected override string GenerateTableAlias(int n, string path, IJoinable joina
225232

226233
if (shouldCreateUserAlias)
227234
{
228-
ICriteria subcriteria = translator.GetCriteria(path);
235+
ICriteria subcriteria = translator.GetCriteria(path, pathAlias);
229236
sqlAlias = subcriteria == null ? null : translator.GetSQLAlias(subcriteria);
230237

231238
IncludeInResultIfNeeded(joinable, subcriteria, sqlAlias, path);
232239
}
233240

234241
if (sqlAlias == null)
235-
sqlAlias = base.GenerateTableAlias(n + translator.SQLAliasCount, path, joinable);
242+
sqlAlias = base.GenerateTableAlias(n + translator.SQLAliasCount, path, pathAlias, joinable);
236243

237244
return sqlAlias;
238245
}
@@ -261,9 +268,9 @@ protected override string GenerateRootAlias(string tableName)
261268
// NH: really not used (we are using a different ctor to support SubQueryCriteria)
262269
}
263270

264-
protected override SqlString GetWithClause(string path)
271+
protected override SqlString GetWithClause(string path, string pathAlias)
265272
{
266-
return translator.GetWithClause(path);
273+
return translator.GetWithClause(path, pathAlias);
267274
}
268275
}
269276
}

0 commit comments

Comments
 (0)