From cf5973352d7e07cc5aa587d1a1f6b2d1f3659ebb Mon Sep 17 00:00:00 2001 From: Nathan Brown Date: Thu, 13 Aug 2020 02:42:52 -0700 Subject: [PATCH 1/5] Add test for #2479 --- .../Async/Linq/WhereSubqueryTests.cs | 2 +- .../Linq/WhereSubqueryTests.cs | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/NHibernate.Test/Async/Linq/WhereSubqueryTests.cs b/src/NHibernate.Test/Async/Linq/WhereSubqueryTests.cs index 2e67bea1c82..8c9a67f4306 100644 --- a/src/NHibernate.Test/Async/Linq/WhereSubqueryTests.cs +++ b/src/NHibernate.Test/Async/Linq/WhereSubqueryTests.cs @@ -12,8 +12,8 @@ using System.Linq; using System.Linq.Expressions; using NHibernate.DomainModel.Northwind.Entities; -using NUnit.Framework; using NHibernate.Linq; +using NUnit.Framework; namespace NHibernate.Test.Linq { diff --git a/src/NHibernate.Test/Linq/WhereSubqueryTests.cs b/src/NHibernate.Test/Linq/WhereSubqueryTests.cs index f272d438707..c6e8bef91f6 100644 --- a/src/NHibernate.Test/Linq/WhereSubqueryTests.cs +++ b/src/NHibernate.Test/Linq/WhereSubqueryTests.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Linq.Expressions; using NHibernate.DomainModel.Northwind.Entities; +using NHibernate.Linq; using NUnit.Framework; namespace NHibernate.Test.Linq @@ -509,6 +510,26 @@ where subquery.Any(x => x.OrderId == order.OrderId) Assert.That(query.Count, Is.EqualTo(61)); } + [Test(Description = "GH2479")] + public void OrdersWithSubquery9() + { + var ordersQuery = db.Orders + .Where(x => x.Employee.EmployeeId > 5) + .OrderBy(x => x.OrderId) + .Take(2); + + var orderLinesFuture = db.OrderLines + .Where(x => ordersQuery.Any(o => o == x.Order)) + .OrderBy(x => x.Id) + .ToFuture(); + + var orders = ordersQuery.ToFuture().ToList(); + var orderLines = orderLinesFuture.ToList(); + + Assert.That(orders.Count, Is.EqualTo(2), nameof(orders)); + Assert.That(orderLines.Count, Is.EqualTo(6), nameof(orderLines)); + } + [Test(Description = "NH-2654")] public void CategoriesWithDiscountedProducts() { From de3dcd3d05f4d3f797f8831810664e969f2bff27 Mon Sep 17 00:00:00 2001 From: Nathan Brown Date: Sat, 15 Aug 2020 11:17:47 -0700 Subject: [PATCH 2/5] Fix spelling typo --- src/NHibernate/Linq/GroupBy/PagingRewriter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NHibernate/Linq/GroupBy/PagingRewriter.cs b/src/NHibernate/Linq/GroupBy/PagingRewriter.cs index 922f1790a10..4ba3b05d5f4 100644 --- a/src/NHibernate/Linq/GroupBy/PagingRewriter.cs +++ b/src/NHibernate/Linq/GroupBy/PagingRewriter.cs @@ -28,7 +28,7 @@ public static void ReWrite(QueryModel queryModel) private static void FlattenSubQuery(SubQueryExpression subQueryExpression, QueryModel queryModel) { - // we can not flattern subquery if outer query has body clauses. + // we can not flatten subquery if outer query has body clauses. var subQueryModel = subQueryExpression.QueryModel; var subQueryMainFromClause = subQueryModel.MainFromClause; if (queryModel.BodyClauses.Count == 0) From 7a3daaec9bdf2cf53a1f5ecfb3d65c443c6754a8 Mon Sep 17 00:00:00 2001 From: Nathan Brown Date: Sat, 15 Aug 2020 14:35:56 -0700 Subject: [PATCH 3/5] More tests for Contains and Any --- .../Async/Linq/WhereSubqueryTests.cs | 16 ++++++++ .../Linq/WhereSubqueryTests.cs | 37 +++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/src/NHibernate.Test/Async/Linq/WhereSubqueryTests.cs b/src/NHibernate.Test/Async/Linq/WhereSubqueryTests.cs index 8c9a67f4306..8a4492ca7ea 100644 --- a/src/NHibernate.Test/Async/Linq/WhereSubqueryTests.cs +++ b/src/NHibernate.Test/Async/Linq/WhereSubqueryTests.cs @@ -465,6 +465,22 @@ where subquery.Any(x => x.OrderId == order.OrderId) Assert.That(query.Count, Is.EqualTo(61)); } + [Test(Description = "GH2479")] + public async Task OrdersWithSubquery11Async() + { + var ordersQuery = db.Orders + .OrderByDescending(x => x.OrderLines.Count).ThenBy(x => x.OrderId) + .Take(2); + + var orderLineQuery = ordersQuery.SelectMany(x => x.OrderLines); + var productsNotInLargestOrders = await (db.Products + .Where(x => orderLineQuery.All(p => p.Product != x)) + .OrderBy(x => x.ProductId) + .ToListAsync()); + + Assert.That(productsNotInLargestOrders.Count, Is.EqualTo(49), nameof(productsNotInLargestOrders)); + } + [Test(Description = "NH-2654")] public async Task CategoriesWithDiscountedProductsAsync() { diff --git a/src/NHibernate.Test/Linq/WhereSubqueryTests.cs b/src/NHibernate.Test/Linq/WhereSubqueryTests.cs index c6e8bef91f6..329eb9928f3 100644 --- a/src/NHibernate.Test/Linq/WhereSubqueryTests.cs +++ b/src/NHibernate.Test/Linq/WhereSubqueryTests.cs @@ -530,6 +530,43 @@ public void OrdersWithSubquery9() Assert.That(orderLines.Count, Is.EqualTo(6), nameof(orderLines)); } + [Test(Description = "GH2479")] + public void OrdersWithSubquery10() + { + var ordersQuery = db.Orders + .Where(x => x.Employee.EmployeeId > 5) + .OrderBy(x => x.OrderId) + .Take(2); + + var productsQuery = ordersQuery.SelectMany(x => x.OrderLines).Select(x => x.Product); + var productsFuture = db.Products + .Where(x => productsQuery.Contains(x)) + .OrderBy(x => x.ProductId) + .ToFuture(); + + var orders = ordersQuery.ToFuture().ToList(); + var products = productsFuture.ToList(); + + Assert.That(orders.Count, Is.EqualTo(2), nameof(orders)); + Assert.That(products.Count, Is.EqualTo(6), nameof(products)); + } + + [Test(Description = "GH2479")] + public void OrdersWithSubquery11() + { + var ordersQuery = db.Orders + .OrderByDescending(x => x.OrderLines.Count).ThenBy(x => x.OrderId) + .Take(2); + + var orderLineQuery = ordersQuery.SelectMany(x => x.OrderLines); + var productsNotInLargestOrders = db.Products + .Where(x => orderLineQuery.All(p => p.Product != x)) + .OrderBy(x => x.ProductId) + .ToList(); + + Assert.That(productsNotInLargestOrders.Count, Is.EqualTo(49), nameof(productsNotInLargestOrders)); + } + [Test(Description = "NH-2654")] public void CategoriesWithDiscountedProducts() { From 9e4f20f59f9f295203a308363fb8acd6a9175b80 Mon Sep 17 00:00:00 2001 From: Nathan Brown Date: Sat, 15 Aug 2020 14:36:16 -0700 Subject: [PATCH 4/5] Fix for #2479 --- src/NHibernate/Linq/GroupBy/PagingRewriter.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/NHibernate/Linq/GroupBy/PagingRewriter.cs b/src/NHibernate/Linq/GroupBy/PagingRewriter.cs index 4ba3b05d5f4..690330eade0 100644 --- a/src/NHibernate/Linq/GroupBy/PagingRewriter.cs +++ b/src/NHibernate/Linq/GroupBy/PagingRewriter.cs @@ -53,7 +53,8 @@ private static void FlattenSubQuery(SubQueryExpression subQueryExpression, Query var where = new WhereClause(new SubQueryExpression(newSubQueryModel)); queryModel.BodyClauses.Add(where); - if (!queryModel.BodyClauses.OfType().Any()) + if (!queryModel.BodyClauses.OfType().Any() && + !(queryModel.ResultOperators.Count == 1 && queryModel.ResultOperators.All(x => x is AnyResultOperator || x is ContainsResultOperator || x is AllResultOperator))) { var orderByClauses = subQueryModel.BodyClauses.OfType(); foreach (var orderByClause in orderByClauses) From e9361940ee2b6ed6c1965f6fff2147c267b45de0 Mon Sep 17 00:00:00 2001 From: Nathan Brown Date: Sat, 15 Aug 2020 21:07:04 -0700 Subject: [PATCH 5/5] Add exclusions for database that don't support features of new tests. --- src/NHibernate.Test/Async/Linq/WhereSubqueryTests.cs | 6 ++++++ src/NHibernate.Test/Linq/WhereSubqueryTests.cs | 12 ++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/NHibernate.Test/Async/Linq/WhereSubqueryTests.cs b/src/NHibernate.Test/Async/Linq/WhereSubqueryTests.cs index 8a4492ca7ea..fcd730b4314 100644 --- a/src/NHibernate.Test/Async/Linq/WhereSubqueryTests.cs +++ b/src/NHibernate.Test/Async/Linq/WhereSubqueryTests.cs @@ -11,6 +11,7 @@ using System; using System.Linq; using System.Linq.Expressions; +using NHibernate.Dialect; using NHibernate.DomainModel.Northwind.Entities; using NHibernate.Linq; using NUnit.Framework; @@ -468,6 +469,11 @@ where subquery.Any(x => x.OrderId == order.OrderId) [Test(Description = "GH2479")] public async Task OrdersWithSubquery11Async() { + if (Dialect is MySQLDialect) + Assert.Ignore("MySQL does not support LIMIT in subqueries."); + if (Dialect is MsSqlCeDialect) + Assert.Ignore("MS SQL CE does not support sorting on a subquery."); + var ordersQuery = db.Orders .OrderByDescending(x => x.OrderLines.Count).ThenBy(x => x.OrderId) .Take(2); diff --git a/src/NHibernate.Test/Linq/WhereSubqueryTests.cs b/src/NHibernate.Test/Linq/WhereSubqueryTests.cs index 329eb9928f3..9f951546406 100644 --- a/src/NHibernate.Test/Linq/WhereSubqueryTests.cs +++ b/src/NHibernate.Test/Linq/WhereSubqueryTests.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Linq.Expressions; +using NHibernate.Dialect; using NHibernate.DomainModel.Northwind.Entities; using NHibernate.Linq; using NUnit.Framework; @@ -513,6 +514,9 @@ where subquery.Any(x => x.OrderId == order.OrderId) [Test(Description = "GH2479")] public void OrdersWithSubquery9() { + if (Dialect is MySQLDialect) + Assert.Ignore("MySQL does not support LIMIT in subqueries."); + var ordersQuery = db.Orders .Where(x => x.Employee.EmployeeId > 5) .OrderBy(x => x.OrderId) @@ -533,6 +537,9 @@ public void OrdersWithSubquery9() [Test(Description = "GH2479")] public void OrdersWithSubquery10() { + if (Dialect is MySQLDialect) + Assert.Ignore("MySQL does not support LIMIT in subqueries."); + var ordersQuery = db.Orders .Where(x => x.Employee.EmployeeId > 5) .OrderBy(x => x.OrderId) @@ -554,6 +561,11 @@ public void OrdersWithSubquery10() [Test(Description = "GH2479")] public void OrdersWithSubquery11() { + if (Dialect is MySQLDialect) + Assert.Ignore("MySQL does not support LIMIT in subqueries."); + if (Dialect is MsSqlCeDialect) + Assert.Ignore("MS SQL CE does not support sorting on a subquery."); + var ordersQuery = db.Orders .OrderByDescending(x => x.OrderLines.Count).ThenBy(x => x.OrderId) .Take(2);