From 45ff1cf0a8d9c6523912a442f7c958f4452ed002 Mon Sep 17 00:00:00 2001 From: Gunnar Liljas Date: Fri, 3 Jan 2025 12:04:48 +0100 Subject: [PATCH 1/2] Make previously HQL:ed expressions automatic candidates in SELECT --- src/NHibernate/Linq/Visitors/QueryModelVisitor.cs | 7 +++++-- src/NHibernate/Linq/Visitors/SelectClauseVisitor.cs | 10 ++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs b/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs index 43720cb12fb..3eb720c8710 100644 --- a/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs +++ b/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs @@ -111,6 +111,7 @@ public static ExpressionToHqlTranslationResults GenerateHqlQuery(QueryModel quer } private readonly IntermediateHqlTree _hqlTree; + private readonly HashSet _hqlCandidates; private readonly NhLinqExpressionReturnType? _rootReturnType; private static readonly ResultOperatorMap ResultOperatorMap; private bool _serverSide = true; @@ -165,6 +166,7 @@ private QueryModelVisitor(VisitorParameters visitorParameters, bool root, QueryM _root = root; _rootReturnType = root ? rootReturnType : null; _hqlTree = new IntermediateHqlTree(root, _queryMode); + _hqlCandidates = new HashSet(); } private void Visit() @@ -476,7 +478,7 @@ public override void VisitSelectClause(SelectClause selectClause, QueryModel que private HqlSelect GetSelectClause(Expression selectClause) { - var visitor = new SelectClauseVisitor(typeof(object[]), VisitorParameters); + var visitor = new SelectClauseVisitor(typeof(object[]), VisitorParameters, _hqlCandidates); visitor.VisitSelector(selectClause, !_root); @@ -537,7 +539,7 @@ private void VisitDeleteClause(Expression expression) return; // We only need to check there is no unexpected select, for avoiding silently ignoring them. - var visitor = new SelectClauseVisitor(typeof(object[]), VisitorParameters); + var visitor = new SelectClauseVisitor(typeof(object[]), VisitorParameters, new HashSet()); visitor.VisitSelector(expression); if (visitor.ProjectionExpression != null) @@ -566,6 +568,7 @@ public override void VisitOrderByClause(OrderByClause orderByClause, QueryModel : (HqlDirectionStatement)_hqlTree.TreeBuilder.Descending(); _hqlTree.AddOrderByClause(orderBy, direction); + _hqlCandidates.Add(clause.Expression); } } diff --git a/src/NHibernate/Linq/Visitors/SelectClauseVisitor.cs b/src/NHibernate/Linq/Visitors/SelectClauseVisitor.cs index a5155415dfd..4b55d940e79 100644 --- a/src/NHibernate/Linq/Visitors/SelectClauseVisitor.cs +++ b/src/NHibernate/Linq/Visitors/SelectClauseVisitor.cs @@ -16,14 +16,16 @@ public class SelectClauseVisitor : RelinqExpressionVisitor private HashSet _hqlNodes; private readonly ParameterExpression _inputParameter; private readonly VisitorParameters _parameters; + private readonly HashSet _hqlCandidates; private int _iColumn; private List _hqlTreeNodes = new List(); private readonly HqlGeneratorExpressionVisitor _hqlVisitor; - public SelectClauseVisitor(System.Type inputType, VisitorParameters parameters) + public SelectClauseVisitor(System.Type inputType, VisitorParameters parameters, HashSet hqlCandidates) { _inputParameter = Expression.Parameter(inputType, "input"); _parameters = parameters; + _hqlCandidates = hqlCandidates; _hqlVisitor = new HqlGeneratorExpressionVisitor(_parameters); } @@ -69,9 +71,9 @@ public void VisitSelector(Expression expression, bool isSubQuery) if (distinct != null) { - var treeNodes = new List(_hqlTreeNodes.Count + 1) {_hqlTreeBuilder.Distinct()}; + var treeNodes = new List(_hqlTreeNodes.Count + 1) { _hqlTreeBuilder.Distinct() }; treeNodes.AddRange(_hqlTreeNodes); - _hqlTreeNodes = new List(1) {_hqlTreeBuilder.ExpressionSubTreeHolder(treeNodes)}; + _hqlTreeNodes = new List(1) { _hqlTreeBuilder.ExpressionSubTreeHolder(treeNodes) }; } } @@ -82,7 +84,7 @@ public override Expression Visit(Expression expression) return null; } - if (_hqlNodes.Contains(expression)) + if (_hqlNodes.Contains(expression) || _hqlCandidates.Contains(expression)) { // Pure HQL evaluation _hqlTreeNodes.Add(_hqlVisitor.Visit(expression).AsExpression()); From 1bd096dd30995e237a2d901b65f209e633733388 Mon Sep 17 00:00:00 2001 From: Gunnar Liljas Date: Mon, 6 Jan 2025 13:25:57 +0100 Subject: [PATCH 2/2] Update src/NHibernate/Linq/Visitors/SelectClauseVisitor.cs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Frédéric Delaporte <12201973+fredericDelaporte@users.noreply.github.com> --- src/NHibernate/Linq/Visitors/SelectClauseVisitor.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/NHibernate/Linq/Visitors/SelectClauseVisitor.cs b/src/NHibernate/Linq/Visitors/SelectClauseVisitor.cs index 4b55d940e79..9f73e293e42 100644 --- a/src/NHibernate/Linq/Visitors/SelectClauseVisitor.cs +++ b/src/NHibernate/Linq/Visitors/SelectClauseVisitor.cs @@ -21,6 +21,12 @@ public class SelectClauseVisitor : RelinqExpressionVisitor private List _hqlTreeNodes = new List(); private readonly HqlGeneratorExpressionVisitor _hqlVisitor; + // Since v5.6 + [Obsolete("Use overload providing expressions to be executed with HQL.")] + public SelectClauseVisitor(System.Type inputType, VisitorParameters parameters) : + this(inputType, parameters, new HashSet()) + { } + public SelectClauseVisitor(System.Type inputType, VisitorParameters parameters, HashSet hqlCandidates) { _inputParameter = Expression.Parameter(inputType, "input");