Skip to content

Commit 8e283dd

Browse files
committed
Port remaining part of Criteria/CriteriaJoinWalker.cs changes from HHH-3646 to fix regression on Criteria API querying of collection-of-components. NH-3694.
1 parent c1fde7d commit 8e283dd

File tree

2 files changed

+64
-19
lines changed

2 files changed

+64
-19
lines changed

src/NHibernate.Test/NHSpecificTest/CriteriaQueryOnComponentCollection/Fixture.cs

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Generic;
33
using NHibernate.Cfg;
44
using NHibernate.Criterion;
5+
using NHibernate.SqlCommand;
56
using NHibernate.Transform;
67
using NUnit.Framework;
78

@@ -69,7 +70,10 @@ public void CanQueryByCriteriaOnSetOfCompositeElement()
6970
.Add(Restrictions.Eq("Position", "parent"))
7071
.SetResultTransformer(new RootEntityResultTransformer())
7172
.List();
72-
Assert.IsNotEmpty(list);
73+
Assert.That(list, Has.Count.EqualTo(1));
74+
Assert.That(list[0], Is.Not.Null);
75+
Assert.That(list[0], Is.TypeOf<Employee>());
76+
Assert.That(((Employee) list[0]).Id, Is.EqualTo(1));
7377
}
7478
}
7579

@@ -83,10 +87,33 @@ public void CanQueryByCriteriaOnSetOfElement()
8387
.Add(Restrictions.Gt("Amount", 5m))
8488
.SetResultTransformer(new RootEntityResultTransformer())
8589
.List();
86-
Assert.IsNotEmpty(list);
90+
Assert.That(list, Has.Count.EqualTo(1));
91+
Assert.That(list[0], Is.Not.Null);
92+
Assert.That(list[0], Is.TypeOf<Employee>());
93+
Assert.That(((Employee) list[0]).Id, Is.EqualTo(1));
8794
}
8895
}
8996

97+
98+
[TestCase(JoinType.LeftOuterJoin)]
99+
[TestCase(JoinType.InnerJoin)]
100+
public void CanQueryByCriteriaOnSetOfElementByCreateAlias(JoinType joinType)
101+
{
102+
using (var s = sessions.OpenSession())
103+
{
104+
var list = s.CreateCriteria<Employee>("x")
105+
.CreateAlias("x.Amounts", "amount", joinType)
106+
.Add(Restrictions.Gt("amount.Amount", 5m))
107+
.SetResultTransformer(new RootEntityResultTransformer())
108+
.List();
109+
Assert.That(list, Has.Count.EqualTo(1));
110+
Assert.That(list[0], Is.Not.Null);
111+
Assert.That(list[0], Is.TypeOf<Employee>());
112+
Assert.That(((Employee) list[0]).Id, Is.EqualTo(1));
113+
}
114+
}
115+
116+
90117
[Test]
91118
public void CanQueryByCriteriaOnSetOfCompositeElement_UsingDetachedCriteria()
92119
{
@@ -99,7 +126,10 @@ public void CanQueryByCriteriaOnSetOfCompositeElement_UsingDetachedCriteria()
99126
.CreateCriteria("Amounts")
100127
.Add(Restrictions.Gt("Amount", 5m))))
101128
.List();
102-
Assert.IsNotEmpty(list);
129+
Assert.That(list, Has.Count.EqualTo(1));
130+
Assert.That(list[0], Is.Not.Null);
131+
Assert.That(list[0], Is.TypeOf<Employee>());
132+
Assert.That(((Employee) list[0]).Id, Is.EqualTo(1));
103133
}
104134
}
105135

src/NHibernate/Loader/Criteria/CriteriaJoinWalker.cs

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -169,42 +169,57 @@ private static bool IsDefaultFetchMode(FetchMode fetchMode)
169169
return fetchMode == FetchMode.Default;
170170
}
171171

172+
172173
protected override string GenerateTableAlias(int n, string path, IJoinable joinable)
173174
{
174175
// TODO: deal with side-effects (changes to includeInSelectList, userAliasList, resultTypeList)!!!
175-
bool shouldCreateUserAlias = joinable.ConsumesEntityAlias();
176-
if(shouldCreateUserAlias == false && joinable.IsCollection)
176+
177+
// for collection-of-entity, we are called twice for given "path"
178+
// once for the collection Joinable, once for the entity Joinable.
179+
// the second call will/must "consume" the alias + perform side effects according to consumesEntityAlias()
180+
// for collection-of-other, however, there is only one call
181+
// it must "consume" the alias + perform side effects, despite what consumeEntityAlias() return says
182+
//
183+
// note: the logic for adding to the userAliasList is still strictly based on consumesEntityAlias return value
184+
185+
bool shouldCreateUserAlias = joinable.ConsumesEntityAlias();
186+
if (!shouldCreateUserAlias && joinable.IsCollection)
177187
{
178-
var elementType = ((ICollectionPersister)joinable).ElementType;
188+
// is it a collection-of-other (component or value) ?
189+
var elementType = ((ICollectionPersister) joinable).ElementType;
179190
if (elementType != null)
180-
shouldCreateUserAlias = elementType.IsComponentType;
191+
shouldCreateUserAlias = elementType.IsComponentType || !elementType.IsEntityType;
181192
}
193+
194+
string sqlAlias = null;
195+
182196
if (shouldCreateUserAlias)
183197
{
184198
ICriteria subcriteria = translator.GetCriteria(path);
185-
string sqlAlias = subcriteria == null ? null : translator.GetSQLAlias(subcriteria);
186-
if (sqlAlias != null)
199+
sqlAlias = subcriteria == null ? null : translator.GetSQLAlias(subcriteria);
200+
201+
if (joinable.ConsumesEntityAlias() && !translator.HasProjection)
187202
{
188-
if (!translator.HasProjection)
203+
includeInResultRowList.Add(subcriteria != null && subcriteria.Alias != null);
204+
205+
if (sqlAlias != null)
189206
{
190-
includeInResultRowList.Add(subcriteria.Alias != null);
191-
if (subcriteria.Alias!=null)
207+
if (subcriteria.Alias != null)
192208
{
193209
userAliasList.Add(subcriteria.Alias); //alias may be null
194210
resultTypeList.Add(translator.ResultType(subcriteria));
195211
}
196212
}
197-
return sqlAlias; //EARLY EXIT
198-
}
199-
else
200-
{
201-
if (!translator.HasProjection)
202-
includeInResultRowList.Add(false);
203213
}
204214
}
205-
return base.GenerateTableAlias(n + translator.SQLAliasCount, path, joinable);
215+
216+
if (sqlAlias == null)
217+
sqlAlias = base.GenerateTableAlias(n + translator.SQLAliasCount, path, joinable);
218+
219+
return sqlAlias;
206220
}
207221

222+
208223
protected override string GenerateRootAlias(string tableName)
209224
{
210225
return CriteriaQueryTranslator.RootSqlAlias;

0 commit comments

Comments
 (0)