From 92989aff066f655250b60c174093c0e5bb56d947 Mon Sep 17 00:00:00 2001 From: Roman Artiukhin Date: Fri, 31 Mar 2023 19:29:18 +0300 Subject: [PATCH 1/6] Test case --- src/NHibernate.Test/Linq/WhereTests.cs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/NHibernate.Test/Linq/WhereTests.cs b/src/NHibernate.Test/Linq/WhereTests.cs index 0b4b5da6575..fc8cb10731e 100644 --- a/src/NHibernate.Test/Linq/WhereTests.cs +++ b/src/NHibernate.Test/Linq/WhereTests.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Linq.Expressions; using log4net.Core; +using NHibernate.Dialect; using NHibernate.Engine.Query; using NHibernate.Linq; using NHibernate.DomainModel.Northwind.Entities; @@ -648,6 +649,9 @@ where sheet.Users.Contains(user) [Test] public void TimesheetsWithEnumerableContainsOnSelect() { + if (Dialect is MsSqlCeDialect) + Assert.Ignore("Dialect is not supported"); + var value = (EnumStoredAsInt32) 1000; var query = (from sheet in db.Timesheets where sheet.Users.Select(x => x.NullableEnum2 ?? value).Contains(value) @@ -656,6 +660,24 @@ where sheet.Users.Select(x => x.NullableEnum2 ?? value).Contains(value) Assert.That(query.Count, Is.EqualTo(1)); } + [Test] + public void ContainsSubqueryWithCoalesceStringEnumSelect() + { + if (Dialect is MsSqlCeDialect) + Assert.Ignore("Dialect is not supported"); + + var results = + db.Timesheets.Where( + o => + o.Users + .Where(u => u.Id != 0.MappedAs(NHibernateUtil.Int32)) + .Select(u => u.Name == u.Name ? u.Enum1 : u.NullableEnum1.Value) + .Contains(EnumStoredAsString.Small)) + .ToList(); + + Assert.That(results.Count, Is.EqualTo(1)); + } + [Test] public void SearchOnObjectTypeWithExtensionMethod() { From 77aed0d045fad09777733b7e0ac8ffc073806d42 Mon Sep 17 00:00:00 2001 From: Roman Artiukhin Date: Fri, 31 Mar 2023 19:33:29 +0300 Subject: [PATCH 2/6] Fix --- .../Linq/Visitors/ParameterTypeLocator.cs | 24 +++++-------------- 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/src/NHibernate/Linq/Visitors/ParameterTypeLocator.cs b/src/NHibernate/Linq/Visitors/ParameterTypeLocator.cs index eeb458568d0..22f372b1fed 100644 --- a/src/NHibernate/Linq/Visitors/ParameterTypeLocator.cs +++ b/src/NHibernate/Linq/Visitors/ParameterTypeLocator.cs @@ -288,42 +288,30 @@ protected override Expression VisitConstant(ConstantExpression node) protected override Expression VisitSubQuery(SubQueryExpression node) { - if (!TryLinkContainsMethod(node.QueryModel)) - { - node.QueryModel.TransformExpressions(Visit); - } + TryLinkContainsMethod(node.QueryModel); + node.QueryModel.TransformExpressions(Visit); return node; } - private bool TryLinkContainsMethod(QueryModel queryModel) + private void TryLinkContainsMethod(QueryModel queryModel) { // ReLinq wraps all ResultOperatorExpressionNodeBase into a SubQueryExpression. In case of // ContainsResultOperator where the constant expression is dislocated from the related expression, // we have to manually link the related expressions. if (queryModel.ResultOperators.Count != 1 || - !(queryModel.ResultOperators[0] is ContainsResultOperator containsOperator) || - !(queryModel.SelectClause.Selector is QuerySourceReferenceExpression querySourceReference) || - !(querySourceReference.ReferencedQuerySource is MainFromClause mainFromClause)) + !(queryModel.ResultOperators[0] is ContainsResultOperator containsOperator)) { - return false; + return; } - var left = UnwrapUnary(Visit(mainFromClause.FromExpression)); + var left = UnwrapUnary(Visit(queryModel.SelectClause.Selector)); var right = UnwrapUnary(Visit(containsOperator.Item)); - // The constant is on the left side (e.g. db.Users.Where(o => users.Contains(o))) - // The constant is on the right side (e.g. db.Customers.Where(o => o.Orders.Contains(item))) - if (left.NodeType != ExpressionType.Constant && right.NodeType != ExpressionType.Constant) - { - return false; - } // Copy all found MemberExpressions to the constant expression // (e.g. values.Contains(o.Name != o.Name2 ? o.Enum1 : o.Enum2) -> copy o.Enum1 and o.Enum2) AddRelatedExpression(null, left, right); AddRelatedExpression(null, right, left); - - return true; } private void VisitAssign(Expression leftNode, Expression rightNode) From 5337be7a904c8d6f32a04c338f93cd52bde78474 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 31 Mar 2023 16:37:21 +0000 Subject: [PATCH 3/6] Generate async files --- src/NHibernate.Test/Async/Linq/WhereTests.cs | 22 ++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/NHibernate.Test/Async/Linq/WhereTests.cs b/src/NHibernate.Test/Async/Linq/WhereTests.cs index 5d8a936b342..2abddb9bdcb 100644 --- a/src/NHibernate.Test/Async/Linq/WhereTests.cs +++ b/src/NHibernate.Test/Async/Linq/WhereTests.cs @@ -15,6 +15,7 @@ using System.Linq; using System.Linq.Expressions; using log4net.Core; +using NHibernate.Dialect; using NHibernate.Engine.Query; using NHibernate.Linq; using NHibernate.DomainModel.Northwind.Entities; @@ -647,6 +648,9 @@ where sheet.Users.Contains(user) [Test] public async Task TimesheetsWithEnumerableContainsOnSelectAsync() { + if (Dialect is MsSqlCeDialect) + Assert.Ignore("Dialect is not supported"); + var value = (EnumStoredAsInt32) 1000; var query = await ((from sheet in db.Timesheets where sheet.Users.Select(x => x.NullableEnum2 ?? value).Contains(value) @@ -655,6 +659,24 @@ where sheet.Users.Select(x => x.NullableEnum2 ?? value).Contains(value) Assert.That(query.Count, Is.EqualTo(1)); } + [Test] + public async Task ContainsSubqueryWithCoalesceStringEnumSelectAsync() + { + if (Dialect is MsSqlCeDialect) + Assert.Ignore("Dialect is not supported"); + + var results = + await (db.Timesheets.Where( + o => + o.Users + .Where(u => u.Id != 0.MappedAs(NHibernateUtil.Int32)) + .Select(u => u.Name == u.Name ? u.Enum1 : u.NullableEnum1.Value) + .Contains(EnumStoredAsString.Small)) + .ToListAsync()); + + Assert.That(results.Count, Is.EqualTo(1)); + } + [Test] public async Task SearchOnObjectTypeWithExtensionMethodAsync() { From 21b4f4a50ac27ec4302747e7bd59b2535a2b2a71 Mon Sep 17 00:00:00 2001 From: Roman Artiukhin Date: Fri, 31 Mar 2023 20:37:16 +0300 Subject: [PATCH 4/6] Restore lost logic --- src/NHibernate/Linq/Visitors/ParameterTypeLocator.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/NHibernate/Linq/Visitors/ParameterTypeLocator.cs b/src/NHibernate/Linq/Visitors/ParameterTypeLocator.cs index 22f372b1fed..3f5b37eab03 100644 --- a/src/NHibernate/Linq/Visitors/ParameterTypeLocator.cs +++ b/src/NHibernate/Linq/Visitors/ParameterTypeLocator.cs @@ -305,7 +305,12 @@ private void TryLinkContainsMethod(QueryModel queryModel) return; } - var left = UnwrapUnary(Visit(queryModel.SelectClause.Selector)); + Expression selector = + queryModel.SelectClause.Selector is QuerySourceReferenceExpression { ReferencedQuerySource: MainFromClause mainFromClause } + ? mainFromClause.FromExpression + : queryModel.SelectClause.Selector; + + var left = UnwrapUnary(Visit(selector)); var right = UnwrapUnary(Visit(containsOperator.Item)); // Copy all found MemberExpressions to the constant expression From 87adcbab269f1de4634093ff6b15a8f5966fd422 Mon Sep 17 00:00:00 2001 From: Roman Artiukhin Date: Fri, 31 Mar 2023 20:55:33 +0300 Subject: [PATCH 5/6] Fix SQLite --- src/NHibernate.Test/Linq/WhereTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NHibernate.Test/Linq/WhereTests.cs b/src/NHibernate.Test/Linq/WhereTests.cs index fc8cb10731e..5fffc56c052 100644 --- a/src/NHibernate.Test/Linq/WhereTests.cs +++ b/src/NHibernate.Test/Linq/WhereTests.cs @@ -663,7 +663,7 @@ where sheet.Users.Select(x => x.NullableEnum2 ?? value).Contains(value) [Test] public void ContainsSubqueryWithCoalesceStringEnumSelect() { - if (Dialect is MsSqlCeDialect) + if (Dialect is MsSqlCeDialect || Dialect is SQLiteDialect) Assert.Ignore("Dialect is not supported"); var results = From 92c53e18b6cd000d1c1674aeec2908ec73c98bbe Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 31 Mar 2023 17:59:14 +0000 Subject: [PATCH 6/6] Generate async files --- src/NHibernate.Test/Async/Linq/WhereTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NHibernate.Test/Async/Linq/WhereTests.cs b/src/NHibernate.Test/Async/Linq/WhereTests.cs index 2abddb9bdcb..aceda381352 100644 --- a/src/NHibernate.Test/Async/Linq/WhereTests.cs +++ b/src/NHibernate.Test/Async/Linq/WhereTests.cs @@ -662,7 +662,7 @@ where sheet.Users.Select(x => x.NullableEnum2 ?? value).Contains(value) [Test] public async Task ContainsSubqueryWithCoalesceStringEnumSelectAsync() { - if (Dialect is MsSqlCeDialect) + if (Dialect is MsSqlCeDialect || Dialect is SQLiteDialect) Assert.Ignore("Dialect is not supported"); var results =