diff --git a/releasenotes.txt b/releasenotes.txt index a612526094e..2f999a17b66 100644 --- a/releasenotes.txt +++ b/releasenotes.txt @@ -1,4 +1,20 @@ -Build 5.4.5 +Build 5.4.6 +============================= + +Release notes - NHibernate - Version 5.4.6 + +2 issues were resolved in this release. + +** Bug + + * #3414 Reenable use of SelectClauseVisitor for subqueries + +** Task + + * #3419 Release 5.4.6 + + +Build 5.4.5 ============================= Release notes - NHibernate - Version 5.4.5 @@ -7,8 +23,8 @@ Release notes - NHibernate - Version 5.4.5 ** Task - * #3408 Release 5.4.4 - * #3407 Release Merge 5.3.19 in 5.4.x + * #3408 Release 5.4.5 + * #3407 Merge 5.3.19 in 5.4.x Build 5.4.4 diff --git a/src/NHibernate.Test/Async/Linq/WhereTests.cs b/src/NHibernate.Test/Async/Linq/WhereTests.cs index 71b9a76cc99..47809de4738 100644 --- a/src/NHibernate.Test/Async/Linq/WhereTests.cs +++ b/src/NHibernate.Test/Async/Linq/WhereTests.cs @@ -685,6 +685,19 @@ where sheet.Users.Select(x => x.NullableEnum2 ?? value).Contains(value) Assert.That(query.Count, Is.EqualTo(1)); } + [Test] + public async Task TimesheetsWithProjectionInSubqueryAsync() + { + if (Dialect is MsSqlCeDialect) + Assert.Ignore("Dialect is not supported"); + + var query = await ((from sheet in db.Timesheets + where sheet.Users.Select(x => new { Id = x.Id, Name = x.Name }).Any(x => x.Id == 1) + select sheet).ToListAsync()); + + Assert.That(query.Count, Is.EqualTo(2)); + } + [Test] public async Task ContainsSubqueryWithCoalesceStringEnumSelectAsync() { diff --git a/src/NHibernate.Test/Linq/WhereTests.cs b/src/NHibernate.Test/Linq/WhereTests.cs index 99edd450d62..9297d1e684d 100644 --- a/src/NHibernate.Test/Linq/WhereTests.cs +++ b/src/NHibernate.Test/Linq/WhereTests.cs @@ -686,6 +686,19 @@ where sheet.Users.Select(x => x.NullableEnum2 ?? value).Contains(value) Assert.That(query.Count, Is.EqualTo(1)); } + [Test] + public void TimesheetsWithProjectionInSubquery() + { + if (Dialect is MsSqlCeDialect) + Assert.Ignore("Dialect is not supported"); + + var query = (from sheet in db.Timesheets + where sheet.Users.Select(x => new { Id = x.Id, Name = x.Name }).Any(x => x.Id == 1) + select sheet).ToList(); + + Assert.That(query.Count, Is.EqualTo(2)); + } + [Test] public void ContainsSubqueryWithCoalesceStringEnumSelect() { diff --git a/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs b/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs index c9f2a054bb1..43720cb12fb 100644 --- a/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs +++ b/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs @@ -476,13 +476,9 @@ public override void VisitSelectClause(SelectClause selectClause, QueryModel que private HqlSelect GetSelectClause(Expression selectClause) { - if (!_root) - return _hqlTree.TreeBuilder.Select( - HqlGeneratorExpressionVisitor.Visit(selectClause, VisitorParameters).AsExpression()); - var visitor = new SelectClauseVisitor(typeof(object[]), VisitorParameters); - visitor.VisitSelector(selectClause); + visitor.VisitSelector(selectClause, !_root); if (visitor.ProjectionExpression != null) { diff --git a/src/NHibernate/Linq/Visitors/SelectClauseNominator.cs b/src/NHibernate/Linq/Visitors/SelectClauseNominator.cs index 52bf954101d..0ab0dc25e4d 100644 --- a/src/NHibernate/Linq/Visitors/SelectClauseNominator.cs +++ b/src/NHibernate/Linq/Visitors/SelectClauseNominator.cs @@ -43,13 +43,13 @@ public SelectClauseHqlNominator(VisitorParameters parameters) _parameters = parameters; } - internal Expression Nominate(Expression expression) + internal Expression Nominate(Expression expression, bool isSubQuery = false) { HqlCandidates = new HashSet(); ContainsUntranslatedMethodCalls = false; _canBeCandidate = true; _stateStack = new Stack(); - _stateStack.Push(false); + _stateStack.Push(isSubQuery); return Visit(expression); } diff --git a/src/NHibernate/Linq/Visitors/SelectClauseVisitor.cs b/src/NHibernate/Linq/Visitors/SelectClauseVisitor.cs index df1cdfb3daa..a5155415dfd 100644 --- a/src/NHibernate/Linq/Visitors/SelectClauseVisitor.cs +++ b/src/NHibernate/Linq/Visitors/SelectClauseVisitor.cs @@ -34,7 +34,9 @@ public IEnumerable GetHqlNodes() return _hqlTreeNodes; } - public void VisitSelector(Expression expression) + public void VisitSelector(Expression expression) => VisitSelector(expression, false); + + public void VisitSelector(Expression expression, bool isSubQuery) { var distinct = expression as NhDistinctExpression; if (distinct != null) @@ -44,7 +46,7 @@ public void VisitSelector(Expression expression) // Find the sub trees that can be expressed purely in HQL var nominator = new SelectClauseHqlNominator(_parameters); - expression = nominator.Nominate(expression); + expression = nominator.Nominate(expression, isSubQuery); _hqlNodes = nominator.HqlCandidates; // Linq2SQL ignores calls to local methods. Linq2EF seems to not support