From 3409888b2589d7445a25e5be9dc5469bb430fd47 Mon Sep 17 00:00:00 2001 From: Roman Artiukhin Date: Sat, 25 Mar 2023 15:34:11 +0200 Subject: [PATCH 1/4] Test case --- src/NHibernate.Test/Linq/WhereTests.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/NHibernate.Test/Linq/WhereTests.cs b/src/NHibernate.Test/Linq/WhereTests.cs index 02dc58b34b7..99daeb795c5 100644 --- a/src/NHibernate.Test/Linq/WhereTests.cs +++ b/src/NHibernate.Test/Linq/WhereTests.cs @@ -645,6 +645,18 @@ where sheet.Users.Contains(user) Assert.That(query.Count, Is.EqualTo(2)); } + [Test] + public void TimesheetsWithEnumerableContainsOnSelect() + { + using var log = new SqlLogSpy(); + var value = (EnumStoredAsInt32) 1000; + var query = (from sheet in db.Timesheets + where sheet.Users.Select(x => x.NullableEnum2 ?? value).Contains(value) + select sheet).ToList(); + + Assert.That(query.Count, Is.EqualTo(1)); + } + [Test] public void SearchOnObjectTypeWithExtensionMethod() { From 725d9274679fe6497260bf88bb30d5df3414eef3 Mon Sep 17 00:00:00 2001 From: Roman Artiukhin Date: Sat, 25 Mar 2023 15:49:15 +0200 Subject: [PATCH 2/4] Skip SelectClauseVisitor for sub-queries --- .../Linq/Visitors/QueryModelVisitor.cs | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs b/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs index 3c95d90c9ab..c9f2a054bb1 100644 --- a/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs +++ b/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs @@ -114,6 +114,7 @@ public static ExpressionToHqlTranslationResults GenerateHqlQuery(QueryModel quer private readonly NhLinqExpressionReturnType? _rootReturnType; private static readonly ResultOperatorMap ResultOperatorMap; private bool _serverSide = true; + private readonly bool _root; public VisitorParameters VisitorParameters { get; } @@ -161,6 +162,7 @@ private QueryModelVisitor(VisitorParameters visitorParameters, bool root, QueryM _queryMode = root ? visitorParameters.RootQueryMode : QueryMode.Select; VisitorParameters = visitorParameters; Model = queryModel; + _root = root; _rootReturnType = root ? rootReturnType : null; _hqlTree = new IntermediateHqlTree(root, _queryMode); } @@ -467,19 +469,27 @@ public override void VisitSelectClause(SelectClause selectClause, QueryModel que } //This is a standard select query + _hqlTree.AddSelectClause(GetSelectClause(selectClause.Selector)); + + base.VisitSelectClause(selectClause, queryModel); + } + + 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.Selector); + visitor.VisitSelector(selectClause); if (visitor.ProjectionExpression != null) { _hqlTree.AddItemTransformer(visitor.ProjectionExpression); } - _hqlTree.AddSelectClause(_hqlTree.TreeBuilder.Select(visitor.GetHqlNodes())); - - base.VisitSelectClause(selectClause, queryModel); + return _hqlTree.TreeBuilder.Select(visitor.GetHqlNodes()); } private void VisitInsertClause(Expression expression) @@ -527,6 +537,9 @@ private void VisitUpdateClause(Expression expression) private void VisitDeleteClause(Expression expression) { + if (!_root) + return; + // We only need to check there is no unexpected select, for avoiding silently ignoring them. var visitor = new SelectClauseVisitor(typeof(object[]), VisitorParameters); visitor.VisitSelector(expression); From 8299fc9223c5a9c54d9308043bb89626c1273901 Mon Sep 17 00:00:00 2001 From: Roman Artiukhin Date: Sat, 25 Mar 2023 15:51:14 +0200 Subject: [PATCH 3/4] test cleanup --- src/NHibernate.Test/Linq/WhereTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/NHibernate.Test/Linq/WhereTests.cs b/src/NHibernate.Test/Linq/WhereTests.cs index 99daeb795c5..0b4b5da6575 100644 --- a/src/NHibernate.Test/Linq/WhereTests.cs +++ b/src/NHibernate.Test/Linq/WhereTests.cs @@ -648,7 +648,6 @@ where sheet.Users.Contains(user) [Test] public void TimesheetsWithEnumerableContainsOnSelect() { - using var log = new SqlLogSpy(); var value = (EnumStoredAsInt32) 1000; var query = (from sheet in db.Timesheets where sheet.Users.Select(x => x.NullableEnum2 ?? value).Contains(value) From b1236dd8c569e2e4d95c3aafe5b845557e7e3430 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 25 Mar 2023 13:53:54 +0000 Subject: [PATCH 4/4] Generate async files --- src/NHibernate.Test/Async/Linq/WhereTests.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/NHibernate.Test/Async/Linq/WhereTests.cs b/src/NHibernate.Test/Async/Linq/WhereTests.cs index 56d183e49c9..5d8a936b342 100644 --- a/src/NHibernate.Test/Async/Linq/WhereTests.cs +++ b/src/NHibernate.Test/Async/Linq/WhereTests.cs @@ -644,6 +644,17 @@ where sheet.Users.Contains(user) Assert.That(query.Count, Is.EqualTo(2)); } + [Test] + public async Task TimesheetsWithEnumerableContainsOnSelectAsync() + { + var value = (EnumStoredAsInt32) 1000; + var query = await ((from sheet in db.Timesheets + where sheet.Users.Select(x => x.NullableEnum2 ?? value).Contains(value) + select sheet).ToListAsync()); + + Assert.That(query.Count, Is.EqualTo(1)); + } + [Test] public async Task SearchOnObjectTypeWithExtensionMethodAsync() {