Skip to content

Commit c963aa4

Browse files
authored
Improve the de duplication in the ORDER BY clause (#211)
1 parent 5913805 commit c963aa4

13 files changed

+460
-361
lines changed

src/EFCore.Jet/Query/Internal/JetLiftOrderByPostprocessor.cs

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using System.Collections.Generic;
23
using System.Diagnostics.CodeAnalysis;
34
using System.Linq;
@@ -55,15 +56,26 @@ public virtual Expression Process(Expression expression)
5556
switch (expression)
5657
{
5758
case ShapedQueryExpression shapedQueryExpression:
58-
return shapedQueryExpression.UpdateQueryExpression(Visit(shapedQueryExpression.QueryExpression));
59+
shapedQueryExpression = shapedQueryExpression.UpdateQueryExpression(Visit(shapedQueryExpression.QueryExpression));
60+
shapedQueryExpression = shapedQueryExpression.UpdateShaperExpression(Visit(shapedQueryExpression.ShaperExpression));
61+
return shapedQueryExpression;
62+
case RelationalSplitCollectionShaperExpression relationalSplitCollectionShaperExpression:
63+
var newSelect = Visit(relationalSplitCollectionShaperExpression.SelectExpression);
64+
var newInner = Visit(relationalSplitCollectionShaperExpression.InnerShaper);
65+
relationalSplitCollectionShaperExpression = relationalSplitCollectionShaperExpression.Update(
66+
relationalSplitCollectionShaperExpression.ParentIdentifier,
67+
relationalSplitCollectionShaperExpression.ChildIdentifier, (SelectExpression)newSelect, newInner);
68+
return relationalSplitCollectionShaperExpression;
69+
case NonQueryExpression nonQueryExpression:
70+
return nonQueryExpression;
5971
case SelectExpression selectExpression:
6072
{
6173
Dictionary<int, (int? indexcol, OrderingExpression? orderexp, bool ascend, bool rewrite, bool referstocurouter)> columnsToRewrite = new();
6274
bool isscalarselect = selectExpression is { Limit: SqlConstantExpression { Value: 1 }, Projection.Count: 1 };
6375
for (int i = 0; i < selectExpression.Orderings.Count; i++)
6476
{
6577
var sqlExpression = selectExpression.Orderings[i].Expression;
66-
if (sqlExpression is not ColumnExpression)
78+
if (sqlExpression is not ColumnExpression && sqlExpression is not SqlConstantExpression && sqlExpression is not SqlParameterExpression)
6779
{
6880
var locate = new JetLocateScalarSubqueryVisitor(_typeMappingSource, _sqlExpressionFactory);
6981
var locatedExpression = locate.Visit(sqlExpression);
@@ -72,24 +84,26 @@ public virtual Expression Process(Expression expression)
7284
{
7385
int index = selectExpression.AddToProjection(sqlExpression);
7486
columnsToRewrite.Add(i, (index, null, selectExpression.Orderings[i].IsAscending, true, false));
87+
continue;
88+
}
89+
90+
var existingIndex = selectExpression.Projection.ToList().FindIndex(pe => pe.Expression.Equals(sqlExpression));
91+
if (existingIndex != -1)
92+
{
93+
columnsToRewrite.Add(i, (existingIndex, null, selectExpression.Orderings[i].IsAscending, true, false));
7594
}
7695
}
7796
else
7897
{
79-
var foundproj = selectExpression.Projection.FirstOrDefault(p =>
80-
p.Expression.Equals(sqlExpression));
81-
if (foundproj == null && sqlExpression is ColumnExpression colexp && !selectExpression.Tables.Contains(colexp.Table))
82-
{
83-
var ix = selectExpression.AddToProjection(sqlExpression);
84-
columnsToRewrite.Add(i, (ix, null, selectExpression.Orderings[i].IsAscending, false, false));
85-
}
86-
else
98+
var existingIndex = selectExpression.Projection.ToList().FindIndex(pe => pe.Expression.Equals(sqlExpression));
99+
if (existingIndex != -1)
87100
{
88101
bool referouter = sqlExpression is ColumnExpression colexp1 &&
89-
selectExpression.Tables.Contains(colexp1.Table);
102+
selectExpression.Tables.Contains(colexp1.Table);
90103
columnsToRewrite.Add(i,
91-
(null, selectExpression.Orderings[i], selectExpression.Orderings[i].IsAscending, false, referouter));
104+
(existingIndex, selectExpression.Orderings[i], selectExpression.Orderings[i].IsAscending, false, referouter));
92105
}
106+
93107
}
94108
}
95109

@@ -98,20 +112,21 @@ public virtual Expression Process(Expression expression)
98112
return base.Visit(expression);
99113
}
100114

101-
for (int A = 0; A < columnsToRewrite.Count; A++)
115+
selectExpression.ClearOrdering();
116+
//Keep the limit in parent expression
117+
if (selectExpression.Limit != null)
102118
{
103-
if (!columnsToRewrite[A].referstocurouter)
104-
{
105-
continue;
106-
}
107-
var col = columnsToRewrite[A].orderexp!.Expression as ColumnExpression;
108-
var colitem = columnsToRewrite[A];
109-
colitem.indexcol = selectExpression.AddToProjection(col!);
110-
columnsToRewrite[A] = colitem;
119+
var limit = selectExpression.Limit;
120+
selectExpression = selectExpression.Update(selectExpression.Projection, selectExpression.Tables,
121+
selectExpression.Predicate, selectExpression.GroupBy, selectExpression.Having,
122+
selectExpression.Orderings, null, null);
123+
selectExpression.PushdownIntoSubquery();
124+
selectExpression.ApplyLimit(limit);
125+
}
126+
else
127+
{
128+
selectExpression.PushdownIntoSubquery();
111129
}
112-
113-
selectExpression.ClearOrdering();
114-
selectExpression.PushdownIntoSubquery();
115130

116131
for (int j = 0; j < columnsToRewrite.Count; j++)
117132
{

0 commit comments

Comments
 (0)