Skip to content

Commit f0386b2

Browse files
authored
Merge branch 'master' into nh3813
2 parents 358522b + 74ff7a1 commit f0386b2

File tree

6 files changed

+108
-7
lines changed

6 files changed

+108
-7
lines changed

src/NHibernate.Test/Async/Linq/WhereSubqueryTests.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,21 @@ public async Task OrdersWithSubquery11Async()
487487
Assert.That(productsNotInLargestOrders.Count, Is.EqualTo(49), nameof(productsNotInLargestOrders));
488488
}
489489

490+
[Test]
491+
public async Task OrdersWithSubquery11AAsync()
492+
{
493+
var ordersQuery = db.Orders
494+
.OrderByDescending(x => x.OrderLines.Count).ThenBy(x => x.OrderId);
495+
496+
var orderLineQuery = ordersQuery.SelectMany(x => x.OrderLines);
497+
var productsNotInLargestOrders = await (db.Products
498+
.Where(x => orderLineQuery.All(p => p.Product != x))
499+
.OrderBy(x => x.ProductId)
500+
.ToListAsync());
501+
502+
Assert.That(productsNotInLargestOrders.Count, Is.EqualTo(0), nameof(productsNotInLargestOrders));
503+
}
504+
490505
[Test(Description = "NH-2654")]
491506
public async Task CategoriesWithDiscountedProductsAsync()
492507
{

src/NHibernate.Test/Linq/WhereSubqueryTests.cs

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,7 @@ public void OrdersWithSubquery9()
519519

520520
var ordersQuery = db.Orders
521521
.Where(x => x.Employee.EmployeeId > 5)
522-
.OrderBy(x => x.OrderId)
522+
.OrderByDescending(x => x.OrderId)
523523
.Take(2);
524524

525525
var orderLinesFuture = db.OrderLines
@@ -531,7 +531,26 @@ public void OrdersWithSubquery9()
531531
var orderLines = orderLinesFuture.ToList();
532532

533533
Assert.That(orders.Count, Is.EqualTo(2), nameof(orders));
534-
Assert.That(orderLines.Count, Is.EqualTo(6), nameof(orderLines));
534+
Assert.That(orderLines.Count, Is.EqualTo(4), nameof(orderLines));
535+
}
536+
537+
[Test]
538+
public void OrdersWithSubquery9A()
539+
{
540+
var ordersQuery = db.Orders
541+
.Where(x => x.Employee.EmployeeId > 5)
542+
.OrderByDescending(x => x.OrderId);
543+
544+
var orderLinesFuture = db.OrderLines
545+
.Where(x => ordersQuery.Any(o => o == x.Order))
546+
.OrderBy(x => x.Id)
547+
.ToFuture();
548+
549+
var orders = ordersQuery.ToFuture().ToList();
550+
var orderLines = orderLinesFuture.ToList();
551+
552+
Assert.That(orders.Count, Is.EqualTo(286), nameof(orders));
553+
Assert.That(orderLines.Count, Is.EqualTo(711), nameof(orderLines));
535554
}
536555

537556
[Test(Description = "GH2479")]
@@ -542,7 +561,7 @@ public void OrdersWithSubquery10()
542561

543562
var ordersQuery = db.Orders
544563
.Where(x => x.Employee.EmployeeId > 5)
545-
.OrderBy(x => x.OrderId)
564+
.OrderByDescending(x => x.OrderId)
546565
.Take(2);
547566

548567
var productsQuery = ordersQuery.SelectMany(x => x.OrderLines).Select(x => x.Product);
@@ -555,7 +574,27 @@ public void OrdersWithSubquery10()
555574
var products = productsFuture.ToList();
556575

557576
Assert.That(orders.Count, Is.EqualTo(2), nameof(orders));
558-
Assert.That(products.Count, Is.EqualTo(6), nameof(products));
577+
Assert.That(products.Count, Is.EqualTo(4), nameof(products));
578+
}
579+
580+
[Test]
581+
public void OrdersWithSubquery10A()
582+
{
583+
var ordersQuery = db.Orders
584+
.Where(x => x.Employee.EmployeeId > 5)
585+
.OrderByDescending(x => x.OrderId);
586+
587+
var productsQuery = ordersQuery.SelectMany(x => x.OrderLines).Select(x => x.Product);
588+
var productsFuture = db.Products
589+
.Where(x => productsQuery.Contains(x))
590+
.OrderBy(x => x.ProductId)
591+
.ToFuture();
592+
593+
var orders = ordersQuery.ToFuture().ToList();
594+
var products = productsFuture.ToList();
595+
596+
Assert.That(orders.Count, Is.EqualTo(286), nameof(orders));
597+
Assert.That(products.Count, Is.EqualTo(77), nameof(products));
559598
}
560599

561600
[Test(Description = "GH2479")]
@@ -579,6 +618,21 @@ public void OrdersWithSubquery11()
579618
Assert.That(productsNotInLargestOrders.Count, Is.EqualTo(49), nameof(productsNotInLargestOrders));
580619
}
581620

621+
[Test]
622+
public void OrdersWithSubquery11A()
623+
{
624+
var ordersQuery = db.Orders
625+
.OrderByDescending(x => x.OrderLines.Count).ThenBy(x => x.OrderId);
626+
627+
var orderLineQuery = ordersQuery.SelectMany(x => x.OrderLines);
628+
var productsNotInLargestOrders = db.Products
629+
.Where(x => orderLineQuery.All(p => p.Product != x))
630+
.OrderBy(x => x.ProductId)
631+
.ToList();
632+
633+
Assert.That(productsNotInLargestOrders.Count, Is.EqualTo(0), nameof(productsNotInLargestOrders));
634+
}
635+
582636
[Test(Description = "NH-2654")]
583637
public void CategoriesWithDiscountedProducts()
584638
{

src/NHibernate.Test/Settings.StyleCop

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<StyleCopSettings Version="105">
2+
<Analyzers>
3+
<Analyzer AnalyzerId="StyleCop.CSharp.MaintainabilityRules">
4+
<Rules>
5+
<Rule Name="FileMayOnlyContainASingleClass">
6+
<RuleSettings>
7+
<BooleanProperty Name="Enabled">False</BooleanProperty>
8+
</RuleSettings>
9+
</Rule>
10+
</Rules>
11+
<AnalyzerSettings />
12+
</Analyzer>
13+
</Analyzers>
14+
</StyleCopSettings>

src/NHibernate/Linq/GroupBy/PagingRewriter.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ private static void FlattenSubQuery(SubQueryExpression subQueryExpression, Query
5353
var where = new WhereClause(new SubQueryExpression(newSubQueryModel));
5454
queryModel.BodyClauses.Add(where);
5555

56-
if (!queryModel.BodyClauses.OfType<OrderByClause>().Any() &&
57-
!(queryModel.ResultOperators.Count == 1 && queryModel.ResultOperators.All(x => x is AnyResultOperator || x is ContainsResultOperator || x is AllResultOperator)))
56+
if (!queryModel.BodyClauses.OfType<OrderByClause>().Any())
5857
{
5958
var orderByClauses = subQueryModel.BodyClauses.OfType<OrderByClause>();
6059
foreach (var orderByClause in orderByClauses)

src/NHibernate/Linq/ReWriters/RemoveUnnecessaryBodyOperators.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,27 @@ public static void ReWrite(QueryModel queryModel)
1919
rewriter.VisitQueryModel(queryModel);
2020
}
2121

22+
internal static void RemoveUnnecessaryOrderByClauses(QueryModel queryModel)
23+
{
24+
if (queryModel.ResultOperators.Count == 1 &&
25+
queryModel.ResultOperators.All(
26+
r => r is ContainsResultOperator || r is AnyResultOperator || r is AllResultOperator))
27+
{
28+
// For these operators, we can remove any order-by clause
29+
var bodyClauses = queryModel.BodyClauses;
30+
for (int i = bodyClauses.Count - 1; i >= 0; i--)
31+
{
32+
if (bodyClauses[i] is OrderByClause)
33+
bodyClauses.RemoveAt(i);
34+
}
35+
}
36+
}
37+
2238
public override void VisitResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, int index)
2339
{
2440
if (resultOperator is CountResultOperator || resultOperator is LongCountResultOperator)
2541
{
26-
// For count operators, we can remove any order-by result operators
42+
// For count operators, we can remove any order-by clause
2743
var bodyClauses = queryModel.BodyClauses.OfType<OrderByClause>().ToList();
2844
foreach (var orderby in bodyClauses)
2945
{

src/NHibernate/Linq/Visitors/QueryModelVisitor.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ public static ExpressionToHqlTranslationResults GenerateHqlQuery(QueryModel quer
6565
// Rewrite paging
6666
PagingRewriter.ReWrite(queryModel);
6767

68+
//Remove unnecessary order-by clauses
69+
RemoveUnnecessaryBodyOperators.RemoveUnnecessaryOrderByClauses(queryModel);
70+
6871
// Flatten pointless subqueries
6972
QueryReferenceExpressionFlattener.ReWrite(queryModel);
7073

0 commit comments

Comments
 (0)