Skip to content

Commit 9f8ecd1

Browse files
oskarbhazzik
authored andcommitted
Port result transformer handling from Hibernate (dc00c4dcde1bae399a9350bd4a13f9a2a449f6c3) (NH3363).
1 parent 9c98271 commit 9f8ecd1

16 files changed

+776
-101
lines changed

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: 3 additions & 3 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;
@@ -37,7 +37,7 @@ public class QueryKey
3737
/// <param name="filters">The filters.</param>
3838
/// <param name="customTransformer">The result transformer; should be null if data is not transformed before being cached.</param>
3939
public QueryKey(ISessionFactoryImplementor factory, SqlString queryString, QueryParameters queryParameters,
40-
ISet<FilterKey> filters, IResultTransformer customTransformer)
40+
ISet<FilterKey> filters, CacheableResultTransformer customTransformer)
4141
{
4242
_factory = factory;
4343
_sqlQueryString = queryString;
@@ -61,7 +61,7 @@ public QueryKey(ISessionFactoryImplementor factory, SqlString queryString, Query
6161
_hashCode = ComputeHashCode();
6262
}
6363

64-
public IResultTransformer ResultTransformer
64+
public CacheableResultTransformer ResultTransformer
6565
{
6666
get { return _customTransformer; }
6767
}

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
}

src/NHibernate/Loader/Criteria/CriteriaLoader.cs

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ public class CriteriaLoader : OuterJoinLoader
2828
//the user visible aliases, which are unknown to the superclass,
2929
//these are not the actual "physical" SQL aliases
3030
private readonly string[] userAliases;
31+
private readonly bool[] includeInResultRow;
32+
private readonly int resultRowLength;
3133

3234
public CriteriaLoader(IOuterJoinLoadable persister, ISessionFactoryImplementor factory, CriteriaImpl rootCriteria,
3335
string rootEntityName, IDictionary<string, IFilter> enabledFilters)
@@ -44,6 +46,8 @@ public CriteriaLoader(IOuterJoinLoadable persister, ISessionFactoryImplementor f
4446

4547
userAliases = walker.UserAliases;
4648
resultTypes = walker.ResultTypes;
49+
includeInResultRow = walker.IncludeInResultRow;
50+
resultRowLength = ArrayHelper.CountTrue(IncludeInResultRow);
4751

4852
PostInstantiate();
4953
}
@@ -70,6 +74,16 @@ public IType[] ResultTypes
7074
get { return resultTypes; }
7175
}
7276

77+
protected string[] ResultRowAliases
78+
{
79+
get { return userAliases; }
80+
}
81+
82+
protected override bool[] IncludeInResultRow
83+
{
84+
get { return includeInResultRow; }
85+
}
86+
7387
public IList List(ISessionImplementor session)
7488
{
7589
return List(session, translator.GetQueryParameters(), querySpaces, resultTypes);
@@ -80,18 +94,22 @@ protected override IResultTransformer ResolveResultTransformer(IResultTransforme
8094
return translator.RootCriteria.ResultTransformer;
8195
}
8296

83-
protected override bool AreResultSetRowsTransformedImmediately(IResultTransformer transformer)
97+
protected override bool AreResultSetRowsTransformedImmediately()
8498
{
85-
// comparing to null just in case there is no transformer
86-
// (there should always be a result transformer;
87-
return ResolveResultTransformer(transformer) != null;
99+
return true;
88100
}
89101

90102
protected override object GetResultColumnOrRow(object[] row, IResultTransformer customResultTransformer, IDataReader rs,
91103
ISessionImplementor session)
104+
{
105+
return ResolveResultTransformer(customResultTransformer)
106+
.TransformTuple(GetResultRow(row, rs, session), ResultRowAliases);
107+
}
108+
109+
110+
protected override object[] GetResultRow(object[] row, IDataReader rs, ISessionImplementor session)
92111
{
93112
object[] result;
94-
string[] aliases;
95113

96114
if (translator.HasProjection)
97115
{
@@ -114,15 +132,29 @@ protected override object GetResultColumnOrRow(object[] row, IResultTransformer
114132
}
115133
position += numColumns;
116134
}
117-
aliases = translator.ProjectedAliases;
118135
}
119136
else
120137
{
121-
result = row;
122-
aliases = userAliases;
138+
result = ToResultRow(row);
139+
}
140+
return result;
141+
}
142+
143+
144+
private object[] ToResultRow(object[] row)
145+
{
146+
if (resultRowLength == row.Length)
147+
return row;
148+
149+
var result = new object[resultRowLength];
150+
int j = 0;
151+
for (int i = 0; i < row.Length; i++)
152+
{
153+
if (includeInResultRow[i])
154+
result[j++] = row[i];
123155
}
124156

125-
return ResolveResultTransformer(customResultTransformer).TransformTuple(result, aliases);
157+
return result;
126158
}
127159

128160
protected override SqlString ApplyLocks(SqlString sqlSelectString, IDictionary<string, LockMode> lockModes,

src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,14 @@ public SqlString GetSelect(IDictionary<string, IFilter> enabledFilters)
164164
return rootCriteria.Projection.ToSqlString(rootCriteria.ProjectionCriteria, 0, this, enabledFilters);
165165
}
166166

167+
168+
internal IType ResultType(ICriteria criteria)
169+
{
170+
return TypeFactory.ManyToOne(GetEntityName(criteria));
171+
//return Factory.getTypeResolver().getTypeFactory().manyToOne(getEntityName(criteria));
172+
}
173+
174+
167175
public IType[] ProjectedTypes
168176
{
169177
get { return rootCriteria.Projection.GetTypes(rootCriteria, this); }

src/NHibernate/Loader/Hql/QueryLoader.cs

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -327,36 +327,34 @@ protected override IResultTransformer ResolveResultTransformer(IResultTransforme
327327
protected override object GetResultColumnOrRow(object[] row, IResultTransformer resultTransformer, IDataReader rs,
328328
ISessionImplementor session)
329329
{
330-
row = ToResultRow(row);
330+
Object[] resultRow = GetResultRow(row, rs, session);
331331
bool hasTransform = HasSelectNew || resultTransformer != null;
332+
return (!hasTransform && resultRow.Length == 1
333+
? resultRow[0]
334+
: resultRow
335+
);
336+
}
337+
338+
protected override object[] GetResultRow(object[] row, IDataReader rs, ISessionImplementor session)
339+
{
340+
object[] resultRow;
332341

333342
if (_hasScalars)
334343
{
335344
string[][] scalarColumns = _scalarColumnNames;
336345
int queryCols = _queryReturnTypes.Length;
337-
338-
if (!hasTransform && queryCols == 1)
339-
{
340-
return _queryReturnTypes[0].NullSafeGet(rs, scalarColumns[0], session, null);
341-
}
342-
else
346+
resultRow = new object[queryCols];
347+
for (int i = 0; i < queryCols; i++)
343348
{
344-
row = new object[queryCols];
345-
for (int i = 0; i < queryCols; i++)
346-
{
347-
row[i] = _queryReturnTypes[i].NullSafeGet(rs, scalarColumns[i], session, null);
348-
}
349-
return row;
349+
resultRow[i] = _queryReturnTypes[i].NullSafeGet(rs, scalarColumns[i], session, null);
350350
}
351351
}
352-
else if (!hasTransform)
353-
{
354-
return row.Length == 1 ? row[0] : row;
355-
}
356352
else
357353
{
358-
return row;
354+
resultRow = ToResultRow(row);
359355
}
356+
357+
return resultRow;
360358
}
361359

362360
private object[] ToResultRow(object[] row)
@@ -391,6 +389,25 @@ private bool HasSelectNew
391389
get { return _selectNewTransformer != null; }
392390
}
393391

392+
protected override string[] ResultRowAliases
393+
{
394+
get { return _queryReturnAliases; }
395+
}
396+
397+
protected override bool[] IncludeInResultRow
398+
{
399+
get
400+
{
401+
bool[] includeInResultTuple = _includeInSelect;
402+
if (_hasScalars)
403+
{
404+
includeInResultTuple = new bool[_queryReturnTypes.Length];
405+
ArrayHelper.Fill(includeInResultTuple, true);
406+
}
407+
return includeInResultTuple;
408+
}
409+
}
410+
394411
public IType[] ReturnTypes
395412
{
396413
get { return _queryReturnTypes; }

0 commit comments

Comments
 (0)