Skip to content

Commit 4c38acb

Browse files
committed
Merge branch 'oskarb-NH-3363'
2 parents ab86ab8 + 2849641 commit 4c38acb

26 files changed

+874
-111
lines changed

src/NHibernate.Test/CacheTest/QueryKeyFixture.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,13 @@ private void QueryKeyFilterDescLikeToCompare(out QueryKey qk, out QueryKey qk1)
4242
f.SetParameter("pLike", "so%");
4343
var fk = new FilterKey(filterName, f.Parameters, f.FilterDefinition.ParameterTypes, EntityMode.Poco);
4444
ISet<FilterKey> fks = new HashSet<FilterKey> { fk };
45-
qk = new QueryKey(sessions, SqlAll, new QueryParameters(), fks);
45+
qk = new QueryKey(sessions, SqlAll, new QueryParameters(), fks, null);
4646

4747
var f1 = new FilterImpl(sessions.GetFilterDefinition(filterName));
4848
f1.SetParameter("pLike", "%ing");
4949
var fk1 = new FilterKey(filterName, f.Parameters, f.FilterDefinition.ParameterTypes, EntityMode.Poco);
5050
fks = new HashSet<FilterKey> { fk1 };
51-
qk1 = new QueryKey(sessions, SqlAll, new QueryParameters(), fks);
51+
qk1 = new QueryKey(sessions, SqlAll, new QueryParameters(), fks, null);
5252
}
5353

5454
private void QueryKeyFilterDescValueToCompare(out QueryKey qk, out QueryKey qk1)
@@ -59,13 +59,13 @@ private void QueryKeyFilterDescValueToCompare(out QueryKey qk, out QueryKey qk1)
5959
f.SetParameter("pDesc", "something").SetParameter("pValue", 10);
6060
var fk = new FilterKey(filterName, f.Parameters, f.FilterDefinition.ParameterTypes, EntityMode.Poco);
6161
ISet<FilterKey> fks = new HashSet<FilterKey> { fk };
62-
qk = new QueryKey(sessions, SqlAll, new QueryParameters(), fks);
62+
qk = new QueryKey(sessions, SqlAll, new QueryParameters(), fks, null);
6363

6464
var f1 = new FilterImpl(sessions.GetFilterDefinition(filterName));
6565
f1.SetParameter("pDesc", "something").SetParameter("pValue", 11);
6666
var fk1 = new FilterKey(filterName, f.Parameters, f.FilterDefinition.ParameterTypes, EntityMode.Poco);
6767
fks = new HashSet<FilterKey> { fk1 };
68-
qk1 = new QueryKey(sessions, SqlAll, new QueryParameters(), fks);
68+
qk1 = new QueryKey(sessions, SqlAll, new QueryParameters(), fks, null);
6969
}
7070

7171
[Test]
@@ -113,15 +113,15 @@ public void ToStringWithFilters()
113113
f.SetParameter("pLike", "so%");
114114
var fk = new FilterKey(filterName, f.Parameters, f.FilterDefinition.ParameterTypes, EntityMode.Poco);
115115
ISet<FilterKey> fks = new HashSet<FilterKey> { fk };
116-
var qk = new QueryKey(sessions, SqlAll, new QueryParameters(), fks);
116+
var qk = new QueryKey(sessions, SqlAll, new QueryParameters(), fks, null);
117117
Assert.That(qk.ToString(), Is.StringContaining(string.Format("filters: ['{0}']",fk)));
118118

119119
filterName = "DescriptionEqualAndValueGT";
120120
f = new FilterImpl(sessions.GetFilterDefinition(filterName));
121121
f.SetParameter("pDesc", "something").SetParameter("pValue", 10);
122122
fk = new FilterKey(filterName, f.Parameters, f.FilterDefinition.ParameterTypes, EntityMode.Poco);
123123
fks = new HashSet<FilterKey> { fk };
124-
qk = new QueryKey(sessions, SqlAll, new QueryParameters(), fks);
124+
qk = new QueryKey(sessions, SqlAll, new QueryParameters(), fks, null);
125125
Assert.That(qk.ToString(), Is.StringContaining(string.Format("filters: ['{0}']", fk)));
126126
}
127127

@@ -139,7 +139,7 @@ public void ToStringWithMoreFilters()
139139
var fvk = new FilterKey(filterName, f.Parameters, f.FilterDefinition.ParameterTypes, EntityMode.Poco);
140140

141141
ISet<FilterKey> fks = new HashSet<FilterKey> { fk, fvk };
142-
var qk = new QueryKey(sessions, SqlAll, new QueryParameters(), fks);
142+
var qk = new QueryKey(sessions, SqlAll, new QueryParameters(), fks, null);
143143
Assert.That(qk.ToString(), Is.StringContaining(string.Format("filters: ['{0}', '{1}']", fk, fvk)));
144144
}
145145
}

src/NHibernate.Test/NHSpecificTest/NH2673/CachingWithTransformerTests.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,6 @@ public void WhenEagerLoadingWithHqlThenNotThrows()
210210

211211

212212
[Test(Description = "NH2961/3311")]
213-
[Ignore("Not fixed yet.")]
214213
public void CanCacheCriteriaWithLeftJoinAndResultTransformer()
215214
{
216215
Post posts = null;
@@ -229,7 +228,6 @@ public void CanCacheCriteriaWithLeftJoinAndResultTransformer()
229228

230229

231230
[Test(Description = "NH2961/3311")]
232-
[Ignore("Not fixed yet.")]
233231
public void CanCacheCriteriaWithEagerLoadAndResultTransformer()
234232
{
235233
using (new Scenario(Sfi))

src/NHibernate.Test/SecondLevelCacheTest/QueryCacheFixture.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ public void SimpleProjections()
257257
tx.Commit();
258258
}
259259

260-
Assert.That(qs.CacheHitCount, Is.EqualTo(1), "hit count should not go up since we are adding a resulttransformer");
260+
Assert.That(qs.CacheHitCount, Is.EqualTo(2), "hit count should go up since the cache contains the result before the possible application of a resulttransformer");
261261

262262
using (ISession s = OpenSession())
263263
using (ITransaction tx = s.BeginTransaction())
@@ -266,7 +266,7 @@ public void SimpleProjections()
266266
tx.Commit();
267267
}
268268

269-
Assert.That(qs.CacheHitCount, Is.EqualTo(2), "hit count should go up since we are using the same resulttransformer");
269+
Assert.That(qs.CacheHitCount, Is.EqualTo(3), "hit count should go up since we are using the same resulttransformer");
270270
using (ISession s = OpenSession())
271271
using (ITransaction tx = s.BeginTransaction())
272272
{
@@ -277,8 +277,8 @@ public void SimpleProjections()
277277
tx.Commit();
278278
}
279279

280-
Assert.That(qs.CacheHitCount, Is.EqualTo(3));
281-
Assert.That(qs.CacheMissCount, Is.EqualTo(3));
280+
Assert.That(qs.CacheHitCount, Is.EqualTo(4));
281+
Assert.That(qs.CacheMissCount, Is.EqualTo(2));
282282

283283
Thread.Sleep(200);
284284

@@ -294,10 +294,10 @@ public void SimpleProjections()
294294
tx.Commit();
295295
}
296296

297-
Assert.That(qs.CacheHitCount, Is.EqualTo(3));
298-
Assert.That(qs.CacheMissCount, Is.EqualTo(4));
299-
Assert.That(qs.CachePutCount, Is.EqualTo(4));
300-
Assert.That(qs.ExecutionCount, Is.EqualTo(4));
297+
Assert.That(qs.CacheHitCount, Is.EqualTo(4));
298+
Assert.That(qs.CacheMissCount, Is.EqualTo(3));
299+
Assert.That(qs.CachePutCount, Is.EqualTo(3));
300+
Assert.That(qs.ExecutionCount, Is.EqualTo(3));
301301
Assert.That(es.FetchCount, Is.EqualTo(0)); //check that it was being cached
302302
}
303303

src/NHibernate.Test/TransformTests/ImplementationOfEqualityTests.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ namespace NHibernate.Test.TransformTests
1111
{
1212
public class ImplementationOfEqualityTests
1313
{
14-
private readonly IEnumerable<System.Type> transformerTypes = typeof(IResultTransformer).Assembly.GetTypes().Where(t => typeof(IResultTransformer).IsAssignableFrom(t) && t.IsClass).ToList();
14+
private readonly IEnumerable<System.Type> transformerTypes =
15+
typeof (IResultTransformer).Assembly.GetTypes()
16+
.Where(t => typeof (IResultTransformer).IsAssignableFrom(t) && t.IsClass && !t.IsAbstract)
17+
.ToList();
1518

1619
[Test]
1720
public void AllEmbeddedTransformersOverridesEqualsAndGetHashCode()

src/NHibernate/Cache/QueryKey.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public class QueryKey
2121
private readonly int _maxRows = RowSelection.NoValue;
2222
private readonly IDictionary<string, TypedValue> _namedParameters;
2323
private readonly ISet<FilterKey> _filters;
24-
private readonly IResultTransformer _customTransformer;
24+
private readonly CacheableResultTransformer _customTransformer;
2525
private readonly int _hashCode;
2626

2727
private int[] _multiQueriesFirstRows;
@@ -35,8 +35,9 @@ public class QueryKey
3535
/// <param name="queryString">The query string.</param>
3636
/// <param name="queryParameters">The query parameters.</param>
3737
/// <param name="filters">The filters.</param>
38+
/// <param name="customTransformer">The result transformer; should be null if data is not transformed before being cached.</param>
3839
public QueryKey(ISessionFactoryImplementor factory, SqlString queryString, QueryParameters queryParameters,
39-
ISet<FilterKey> filters)
40+
ISet<FilterKey> filters, CacheableResultTransformer customTransformer)
4041
{
4142
_factory = factory;
4243
_sqlQueryString = queryString;
@@ -56,13 +57,13 @@ public QueryKey(ISessionFactoryImplementor factory, SqlString queryString, Query
5657
}
5758
_namedParameters = queryParameters.NamedParameters;
5859
_filters = filters;
59-
_customTransformer = queryParameters.ResultTransformer;
60+
_customTransformer = customTransformer;
6061
_hashCode = ComputeHashCode();
6162
}
6263

63-
public bool HasResultTransformer
64+
public CacheableResultTransformer ResultTransformer
6465
{
65-
get { return _customTransformer != null; }
66+
get { return _customTransformer; }
6667
}
6768

6869
public QueryKey SetFirstRows(int[] firstRows)

src/NHibernate/Cache/StandardQueryCache.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public bool Put(QueryKey key, ICacheAssembler[] returnTypes, IList result, bool
6868
IList cacheable = new List<object>(result.Count + 1) {ts};
6969
for (int i = 0; i < result.Count; i++)
7070
{
71-
if (returnTypes.Length == 1 && !key.HasResultTransformer)
71+
if (returnTypes.Length == 1)
7272
{
7373
cacheable.Add(returnTypes[0].Disassemble(result[i], session, null));
7474
}
@@ -109,7 +109,7 @@ public IList Get(QueryKey key, ICacheAssembler[] returnTypes, bool isNaturalKeyL
109109
Log.DebugFormat("returning cached query results for: {0}", key);
110110
for (int i = 1; i < cacheable.Count; i++)
111111
{
112-
if (returnTypes.Length == 1 && !key.HasResultTransformer)
112+
if (returnTypes.Length == 1)
113113
{
114114
returnTypes[0].BeforeAssemble(cacheable[i], session);
115115
}
@@ -124,7 +124,7 @@ public IList Get(QueryKey key, ICacheAssembler[] returnTypes, bool isNaturalKeyL
124124
{
125125
try
126126
{
127-
if (returnTypes.Length == 1 && !key.HasResultTransformer)
127+
if (returnTypes.Length == 1)
128128
{
129129
result.Add(returnTypes[0].Assemble(cacheable[i], session, null));
130130
}

src/NHibernate/Hql/HolderInstantiator.cs

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,16 @@ public static HolderInstantiator GetHolderInstantiator(IResultTransformer select
1414
IResultTransformer customTransformer,
1515
string[] queryReturnAliases)
1616
{
17-
if (selectNewTransformer != null)
18-
{
19-
return new HolderInstantiator(selectNewTransformer, queryReturnAliases);
20-
}
21-
else
22-
{
23-
return new HolderInstantiator(customTransformer, queryReturnAliases);
24-
}
17+
return new HolderInstantiator(ResolveResultTransformer(selectNewTransformer, customTransformer),
18+
queryReturnAliases);
2519
}
2620

21+
22+
public static IResultTransformer ResolveResultTransformer(IResultTransformer selectNewTransformer, IResultTransformer customTransformer)
23+
{
24+
return selectNewTransformer ?? customTransformer;
25+
}
26+
2727
public static IResultTransformer CreateSelectNewTransformer(ConstructorInfo constructor, bool returnMaps,
2828
bool returnLists)
2929
{
@@ -48,14 +48,13 @@ public static IResultTransformer CreateSelectNewTransformer(ConstructorInfo cons
4848
public static HolderInstantiator CreateClassicHolderInstantiator(ConstructorInfo constructor,
4949
IResultTransformer transformer)
5050
{
51-
if (constructor != null)
52-
{
53-
return new HolderInstantiator(new AliasToBeanConstructorResultTransformer(constructor), null);
54-
}
55-
else
56-
{
57-
return new HolderInstantiator(transformer, null);
58-
}
51+
return new HolderInstantiator(ResolveClassicResultTransformer(constructor, transformer), null);
52+
}
53+
54+
public static IResultTransformer ResolveClassicResultTransformer(ConstructorInfo constructor,
55+
IResultTransformer transformer)
56+
{
57+
return constructor != null ? new AliasToBeanConstructorResultTransformer(constructor) : transformer;
5958
}
6059

6160
public HolderInstantiator(IResultTransformer transformer, string[] queryReturnAliases)

src/NHibernate/Impl/CriteriaImpl.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public class CriteriaImpl : ICriteria
2626
private int timeout = RowSelection.NoValue;
2727
private int fetchSize = RowSelection.NoValue;
2828
private ISessionImplementor session;
29-
private IResultTransformer resultTransformer;
29+
private IResultTransformer resultTransformer = CriteriaSpecification.RootEntity;
3030
private bool cacheable;
3131
private string cacheRegion;
3232
private CacheMode? cacheMode;

src/NHibernate/Impl/MultiCriteriaImpl.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ private IList ListUsingQueryCache()
109109

110110
MultipleQueriesCacheAssembler assembler = new MultipleQueriesCacheAssembler(resultTypesList);
111111
QueryParameters combinedParameters = CreateCombinedQueryParameters();
112-
QueryKey key = new QueryKey(session.Factory, SqlString, combinedParameters, filterKeys)
112+
QueryKey key = new QueryKey(session.Factory, SqlString, combinedParameters, filterKeys, null)
113113
.SetFirstRows(firstRows)
114114
.SetMaxRows(maxRows);
115115

src/NHibernate/Impl/MultiQueryImpl.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,7 @@ private IList ListUsingQueryCache()
697697

698698
MultipleQueriesCacheAssembler assembler = new MultipleQueriesCacheAssembler(resultTypesList);
699699

700-
QueryKey key = new QueryKey(session.Factory, SqlString, combinedParameters, filterKeys)
700+
QueryKey key = new QueryKey(session.Factory, SqlString, combinedParameters, filterKeys, null)
701701
.SetFirstRows(firstRows)
702702
.SetMaxRows(maxRows);
703703

src/NHibernate/Loader/Criteria/CriteriaJoinWalker.cs

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,14 @@ public class CriteriaJoinWalker : AbstractEntityJoinWalker
2323
private readonly CriteriaQueryTranslator translator;
2424
private readonly ISet<string> querySpaces;
2525
private readonly IType[] resultTypes;
26+
private readonly bool[] includeInResultRow;
27+
2628
//the user visible aliases, which are unknown to the superclass,
2729
//these are not the actual "physical" SQL aliases
2830
private readonly string[] userAliases;
2931
private readonly IList<string> userAliasList = new List<string>();
32+
private readonly IList<IType> resultTypeList = new List<IType>();
33+
private readonly IList<bool> includeInResultRowList = new List<bool>();
3034

3135
private static readonly IInternalLogger logger = LoggerProvider.LoggerFor(typeof(CriteriaJoinWalker));
3236

@@ -41,8 +45,6 @@ public CriteriaJoinWalker(IOuterJoinLoadable persister, CriteriaQueryTranslator
4145

4246
if (translator.HasProjection)
4347
{
44-
resultTypes = translator.ProjectedTypes;
45-
4648
InitProjection(
4749
translator.GetSelect(enabledFilters),
4850
translator.GetWhereCondition(enabledFilters),
@@ -51,16 +53,26 @@ public CriteriaJoinWalker(IOuterJoinLoadable persister, CriteriaQueryTranslator
5153
translator.GetHavingCondition(enabledFilters),
5254
enabledFilters,
5355
LockMode.None);
56+
57+
resultTypes = translator.ProjectedTypes;
58+
userAliases = translator.ProjectedAliases;
59+
includeInResultRow = new bool[resultTypes.Length];
60+
ArrayHelper.Fill(IncludeInResultRow, true);
5461
}
5562
else
5663
{
57-
resultTypes = new IType[] {TypeFactory.ManyToOne(persister.EntityName)};
58-
5964
InitAll(translator.GetWhereCondition(enabledFilters), translator.GetOrderBy(), LockMode.None);
60-
}
6165

62-
userAliasList.Add(criteria.Alias); //root entity comes *last*
63-
userAliases = userAliasList.ToArray();
66+
resultTypes = new IType[] { TypeFactory.ManyToOne(persister.EntityName) };
67+
68+
// root entity comes last
69+
userAliasList.Add(criteria.Alias); //root entity comes *last*
70+
resultTypeList.Add(translator.ResultType(criteria));
71+
includeInResultRowList.Add(true);
72+
userAliases = userAliasList.ToArray();
73+
resultTypes = resultTypeList.ToArray();
74+
includeInResultRow = includeInResultRowList.ToArray();
75+
}
6476
}
6577

6678
protected override void WalkEntityTree(IOuterJoinLoadable persister, string alias, string path, int currentDepth)
@@ -91,6 +103,11 @@ public string[] UserAliases
91103
get { return userAliases; }
92104
}
93105

106+
public bool[] IncludeInResultRow
107+
{
108+
get { return includeInResultRow; }
109+
}
110+
94111
/// <summary>
95112
/// Use the discriminator, to narrow the select to instances
96113
/// of the queried subclass, also applying any filters.
@@ -154,6 +171,7 @@ private static bool IsDefaultFetchMode(FetchMode fetchMode)
154171

155172
protected override string GenerateTableAlias(int n, string path, IJoinable joinable)
156173
{
174+
// TODO: deal with side-effects (changes to includeInSelectList, userAliasList, resultTypeList)!!!
157175
bool shouldCreateUserAlias = joinable.ConsumesEntityAlias();
158176
if(shouldCreateUserAlias == false && joinable.IsCollection)
159177
{
@@ -167,11 +185,22 @@ protected override string GenerateTableAlias(int n, string path, IJoinable joina
167185
string sqlAlias = subcriteria == null ? null : translator.GetSQLAlias(subcriteria);
168186
if (sqlAlias != null)
169187
{
170-
userAliasList.Add(subcriteria.Alias); //alias may be null
188+
if (!translator.HasProjection)
189+
{
190+
includeInResultRowList.Add(subcriteria.Alias != null);
191+
if (subcriteria.Alias!=null)
192+
{
193+
userAliasList.Add(subcriteria.Alias); //alias may be null
194+
resultTypeList.Add(translator.ResultType(subcriteria));
195+
}
196+
}
171197
return sqlAlias; //EARLY EXIT
172198
}
173-
174-
userAliasList.Add(null);
199+
else
200+
{
201+
if (!translator.HasProjection)
202+
includeInResultRowList.Add(false);
203+
}
175204
}
176205
return base.GenerateTableAlias(n + translator.SQLAliasCount, path, joinable);
177206
}

0 commit comments

Comments
 (0)