Skip to content

Commit 22ef4f7

Browse files
gmalyshevMalishev Georgy
authored and
Malishev Georgy
committed
Implementation (fix) NH-3427
Joining to association twice using criteria.
1 parent 8f5d3c2 commit 22ef4f7

File tree

7 files changed

+329
-85
lines changed

7 files changed

+329
-85
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: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using NHibernate.Criterion;
4+
using NHibernate.SqlCommand;
5+
using NUnit.Framework;
6+
7+
namespace NHibernate.Test.NHSpecificTest.NH3472
8+
{
9+
[TestFixture]
10+
public class Fixture : BugTestCase
11+
{
12+
public override string BugNumber
13+
{
14+
get { return "NH3472"; }
15+
}
16+
17+
18+
[Test]
19+
public void CriteriaQueryWithMultipleJoinsToSameAssociation()
20+
{
21+
int catId;
22+
23+
using (ISession sess = OpenSession())
24+
{
25+
Cat c = new Cat();
26+
c.Age = 0;
27+
c.Children = new List<Cat>
28+
{
29+
new Cat {Color = "Ginger", Age = 1},
30+
new Cat {Color = "Black", Age = 3}
31+
};
32+
sess.Save(c);
33+
sess.Flush();
34+
}
35+
36+
using (ISession sess = OpenSession())
37+
{
38+
try
39+
{
40+
var list = sess.CreateCriteria<Cat>("cat")
41+
.CreateAlias("cat.Children", "gingerCat", JoinType.LeftOuterJoin, Restrictions.Eq("Color", "Ginger"))
42+
43+
.CreateAlias("cat.Children", "blackCat", JoinType.LeftOuterJoin,
44+
Restrictions.Eq("Color", "Black"))
45+
.SetProjection(
46+
Projections.Alias(Projections.Property("gingerCat.Age"), "gingerCatAge"),
47+
Projections.Alias(Projections.Property("blackCat.Age"), "blackCatAge")
48+
).AddOrder(new Order(Projections.Property("Age"), true)).List<object[]>();
49+
Assert.AreEqual(list.Count, 3);
50+
Assert.AreEqual(list[0][0], 1);
51+
Assert.AreEqual(list[0][1], 3);
52+
53+
Assert.IsNull(list[1][0]);
54+
Assert.IsNull(list[1][1]);
55+
56+
Assert.IsNull(list[2][0]);
57+
Assert.IsNull(list[2][1]);
58+
}
59+
finally
60+
{
61+
sess.Delete("from Cat");
62+
sess.Flush();
63+
}
64+
}
65+
}
66+
}
67+
}
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.Test/NHibernate.Test.csproj

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,8 @@
687687
<Compile Include="NHSpecificTest\BagWithLazyExtraAndFilter\Fixture.cs" />
688688
<Compile Include="Linq\ByMethod\DistinctTests.cs" />
689689
<Compile Include="Component\Basic\ComponentWithUniqueConstraintTests.cs" />
690+
<Compile Include="NHSpecificTest\NH3472\Fixture.cs" />
691+
<Compile Include="NHSpecificTest\NH3472\Domain.cs" />
690692
<Compile Include="NHSpecificTest\NH3620\Fixture.cs" />
691693
<Compile Include="NHSpecificTest\NH3620\TwoBlobs.cs" />
692694
<Compile Include="NHSpecificTest\NH3455\Address.cs" />
@@ -3047,6 +3049,9 @@
30473049
<EmbeddedResource Include="NHSpecificTest\NH1291AnonExample\Mappings.hbm.xml" />
30483050
</ItemGroup>
30493051
<ItemGroup>
3052+
<EmbeddedResource Include="NHSpecificTest\NH3472\Mappings.hbm.xml">
3053+
<SubType>Designer</SubType>
3054+
</EmbeddedResource>
30503055
<EmbeddedResource Include="NHSpecificTest\NH3455\Mappings.hbm.xml" />
30513056
<EmbeddedResource Include="NHSpecificTest\NH3590\Mappings.hbm.xml" />
30523057
<EmbeddedResource Include="NHSpecificTest\NH3377\Mappings.hbm.xml" />
@@ -3630,4 +3635,4 @@ if exist hibernate.cfg.xml (del hibernate.cfg.xml)
36303635
if exist "$(ProjectDir)hibernate.cfg.xml" (copy "$(ProjectDir)hibernate.cfg.xml" "hibernate.cfg.xml")
36313636
copy /y "..\..\..\NHibernate.DomainModel\ABC.hbm.xml" "ABC.hbm.xml"</PostBuildEvent>
36323637
</PropertyGroup>
3633-
</Project>
3638+
</Project>

src/NHibernate/Loader/Criteria/CriteriaJoinWalker.cs

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -127,13 +127,20 @@ public override string Comment
127127
get { return "criteria query"; }
128128
}
129129

130-
protected override JoinType GetJoinType(IAssociationType type, FetchMode config, string path, string lhsTable,
131-
string[] lhsColumns, bool nullable, int currentDepth,
132-
CascadeStyle cascadeStyle)
130+
protected override IList<string> AliasByPath(string path, string sqlAlias)
133131
{
134-
if (translator.IsJoin(path))
132+
var alias = translator.AliasByPath(path, sqlAlias);
133+
if (alias.Count == 0)
134+
return base.AliasByPath(path, sqlAlias);
135+
return alias;
136+
}
137+
138+
protected override JoinType GetJoinType(IAssociationType type, FetchMode config, string path, string pathAlias,
139+
string lhsTable, string[] lhsColumns, bool nullable, int currentDepth, CascadeStyle cascadeStyle)
140+
{
141+
if (translator.IsJoin(path, pathAlias))
135142
{
136-
return translator.GetJoinType(path);
143+
return translator.GetJoinType(path, pathAlias);
137144
}
138145
else
139146
{
@@ -146,7 +153,7 @@ protected override JoinType GetJoinType(IAssociationType type, FetchMode config,
146153
FetchMode fetchMode = translator.RootCriteria.GetFetchMode(path);
147154
if (IsDefaultFetchMode(fetchMode))
148155
{
149-
return base.GetJoinType(type, config, path, lhsTable, lhsColumns, nullable, currentDepth, cascadeStyle);
156+
return base.GetJoinType(type, config, path, pathAlias, lhsTable, lhsColumns, nullable, currentDepth, cascadeStyle);
150157
}
151158
else
152159
{
@@ -169,26 +176,26 @@ private static bool IsDefaultFetchMode(FetchMode fetchMode)
169176
return fetchMode == FetchMode.Default;
170177
}
171178

172-
protected override string GenerateTableAlias(int n, string path, IJoinable joinable)
179+
protected override string GenerateTableAlias(int n, string path, string pathAlias, IJoinable joinable)
173180
{
174181
// TODO: deal with side-effects (changes to includeInSelectList, userAliasList, resultTypeList)!!!
175-
bool shouldCreateUserAlias = joinable.ConsumesEntityAlias();
176-
if(shouldCreateUserAlias == false && joinable.IsCollection)
182+
bool shouldCreateUserAlias = joinable.ConsumesEntityAlias();
183+
if (shouldCreateUserAlias == false && joinable.IsCollection)
177184
{
178185
var elementType = ((ICollectionPersister)joinable).ElementType;
179186
if (elementType != null)
180187
shouldCreateUserAlias = elementType.IsComponentType;
181188
}
182189
if (shouldCreateUserAlias)
183190
{
184-
ICriteria subcriteria = translator.GetCriteria(path);
191+
ICriteria subcriteria = translator.GetCriteria(path, pathAlias);
185192
string sqlAlias = subcriteria == null ? null : translator.GetSQLAlias(subcriteria);
186193
if (sqlAlias != null)
187194
{
188195
if (!translator.HasProjection)
189196
{
190197
includeInResultRowList.Add(subcriteria.Alias != null);
191-
if (subcriteria.Alias!=null)
198+
if (subcriteria.Alias != null)
192199
{
193200
userAliasList.Add(subcriteria.Alias); //alias may be null
194201
resultTypeList.Add(translator.ResultType(subcriteria));
@@ -202,7 +209,7 @@ protected override string GenerateTableAlias(int n, string path, IJoinable joina
202209
includeInResultRowList.Add(false);
203210
}
204211
}
205-
return base.GenerateTableAlias(n + translator.SQLAliasCount, path, joinable);
212+
return base.GenerateTableAlias(n + translator.SQLAliasCount, path, pathAlias, joinable);
206213
}
207214

208215
protected override string GenerateRootAlias(string tableName)
@@ -211,9 +218,9 @@ protected override string GenerateRootAlias(string tableName)
211218
// NH: really not used (we are using a different ctor to support SubQueryCriteria)
212219
}
213220

214-
protected override SqlString GetWithClause(string path)
221+
protected override SqlString GetWithClause(string path, string pathAlias)
215222
{
216-
return translator.GetWithClause(path, EnabledFilters);
223+
return translator.GetWithClause(path, pathAlias, EnabledFilters);
217224
}
218225
}
219226
}

0 commit comments

Comments
 (0)