Skip to content

Commit 6b0e9e4

Browse files
committed
NH-3727 - Fix re-using Criteria with SubqueryProjection
1 parent f16e9b5 commit 6b0e9e4

File tree

2 files changed

+18
-36
lines changed

2 files changed

+18
-36
lines changed

src/NHibernate/Criterion/SubqueryExpression.cs

Lines changed: 15 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,8 @@ public abstract class SubqueryExpression : AbstractCriterion
2020
private QueryParameters parameters;
2121
private IType[] types;
2222

23-
[NonSerialized] private CriteriaQueryTranslator innerQuery;
24-
2523
protected SubqueryExpression(String op, String quantifier, DetachedCriteria dc)
26-
:this(op, quantifier, dc, true)
24+
: this(op, quantifier, dc, true)
2725
{
2826
}
2927

@@ -44,16 +42,23 @@ public IType[] GetTypes()
4442

4543
public override SqlString ToSqlString(ICriteria criteria, ICriteriaQuery criteriaQuery, IDictionary<string, IFilter> enabledFilters)
4644
{
47-
InitializeInnerQueryAndParameters(criteriaQuery);
45+
ISessionFactoryImplementor factory = criteriaQuery.Factory;
46+
47+
var innerQuery = new CriteriaQueryTranslator(
48+
factory,
49+
criteriaImpl, //implicit polymorphism not supported (would need a union)
50+
criteriaImpl.EntityOrClassName,
51+
criteriaQuery.GenerateSQLAlias(),
52+
criteriaQuery);
53+
54+
types = innerQuery.HasProjection ? innerQuery.ProjectedTypes : null;
4855

4956
if (innerQuery.HasProjection == false)
5057
{
5158
throw new QueryException("Cannot use subqueries on a criteria without a projection.");
5259
}
5360

54-
ISessionFactoryImplementor factory = criteriaQuery.Factory;
55-
56-
IOuterJoinLoadable persister = (IOuterJoinLoadable)factory.GetEntityPersister(criteriaImpl.EntityOrClassName);
61+
IOuterJoinLoadable persister = (IOuterJoinLoadable) factory.GetEntityPersister(criteriaImpl.EntityOrClassName);
5762

5863
//patch to generate joins on subqueries
5964
//stolen from CriteriaLoader
@@ -73,11 +78,6 @@ public override SqlString ToSqlString(ICriteria criteria, ICriteriaQuery criteri
7378
sql = factory.Dialect.GetLimitString(sql, offset, limit, offsetParameter, limitParameter);
7479
}
7580

76-
// during CriteriaImpl.Clone we are doing a shallow copy of each criterion.
77-
// this is not a problem for common criterion but not for SubqueryExpression because here we are holding the state of inner CriteriaTraslator (ICriteriaQuery).
78-
// After execution (ToSqlString) we have to clean the internal state because the next execution may be performed in a different tree reusing the same istance of SubqueryExpression.
79-
innerQuery = null;
80-
8181
SqlStringBuilder buf = new SqlStringBuilder().Add(ToLeftSqlString(criteria, criteriaQuery));
8282
if (op != null)
8383
{
@@ -88,7 +88,7 @@ public override SqlString ToSqlString(ICriteria criteria, ICriteriaQuery criteri
8888
{
8989
buf.Add(quantifier).Add(" ");
9090
}
91-
91+
9292
buf.Add("(").Add(sql).Add(")");
9393

9494
if (quantifier != null && prefixOp == false)
@@ -101,9 +101,9 @@ public override SqlString ToSqlString(ICriteria criteria, ICriteriaQuery criteri
101101

102102
public override string ToString()
103103
{
104-
if(prefixOp)
104+
if (prefixOp)
105105
return string.Format("{0} {1} ({2})", op, quantifier, criteriaImpl);
106-
106+
107107
return string.Format("{0} ({1}) {2}", op, criteriaImpl, quantifier);
108108
}
109109

@@ -117,23 +117,6 @@ public override IProjection[] GetProjections()
117117
return null;
118118
}
119119

120-
public void InitializeInnerQueryAndParameters(ICriteriaQuery criteriaQuery)
121-
{
122-
if (innerQuery == null)
123-
{
124-
ISessionFactoryImplementor factory = criteriaQuery.Factory;
125-
126-
innerQuery = new CriteriaQueryTranslator(
127-
factory,
128-
criteriaImpl, //implicit polymorphism not supported (would need a union)
129-
criteriaImpl.EntityOrClassName,
130-
criteriaQuery.GenerateSQLAlias(),
131-
criteriaQuery);
132-
133-
types = innerQuery.HasProjection ? innerQuery.ProjectedTypes : null;
134-
}
135-
}
136-
137120
public ICriteria Criteria
138121
{
139122
// NH-1146

src/NHibernate/Criterion/SubqueryProjection.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace NHibernate.Criterion
1313
[Serializable]
1414
public class SubqueryProjection : SimpleProjection
1515
{
16-
private SelectSubqueryExpression _subQuery;
16+
private readonly SelectSubqueryExpression _subQuery;
1717

1818
protected internal SubqueryProjection(SelectSubqueryExpression subquery)
1919
{
@@ -37,14 +37,13 @@ public override bool IsAggregate
3737

3838
public override IType[] GetTypes(ICriteria criteria, ICriteriaQuery criteriaQuery)
3939
{
40-
_subQuery.InitializeInnerQueryAndParameters(criteriaQuery);
4140
return _subQuery.GetTypes();
4241
}
4342

4443
public override SqlString ToSqlString(ICriteria criteria, int loc, ICriteriaQuery criteriaQuery, IDictionary<string, IFilter> enabledFilters)
4544
{
46-
SqlString sqlStringSubquery = _subQuery.ToSqlString(criteria, criteriaQuery, enabledFilters);
47-
return sqlStringSubquery.Append(new SqlString(new object[] { " as y", loc.ToString(), "_" } ));
45+
return _subQuery.ToSqlString(criteria, criteriaQuery, enabledFilters)
46+
.Append(new SqlString(" as y", loc.ToString(), "_"));
4847
}
4948

5049
public override SqlString ToGroupSqlString(ICriteria criteria, ICriteriaQuery criteriaQuery, IDictionary<string, IFilter> enabledFilters)

0 commit comments

Comments
 (0)