@@ -154,16 +154,16 @@ func replaceIdxSortHelper(ctx *sql.Context, scope *plan.Scope, node sql.Node, so
154
154
* plan.Project , * plan.Filter , * plan.Limit , * plan.Offset , * plan.Distinct , * plan.TableAlias :
155
155
newChildren [i ], same , err = replaceIdxSortHelper (ctx , scope , child , sortNode )
156
156
case * plan.JoinNode :
157
- // TODO: is this applicable to other types of joins?
158
- // as long as left child is already sorted and SortFields are a prefix, then it's ok?
159
- if ! c .JoinType ().IsMerge () {
160
- continue
161
- }
162
157
// It's (probably) not possible to have Sort as child of Join without Subquery/SubqueryAlias,
163
158
// and in the case where there is a Subq/SQA it's taken care of through finalizeSubqueries
164
159
if sortNode == nil {
165
160
continue
166
161
}
162
+ // Merge Joins assume that left and right are sorted
163
+ // Cross Joins and Inner Joins are valid for sort removal if left child is sorted
164
+ if ! c .JoinType ().IsMerge () && ! c .JoinType ().IsCross () && ! c .JoinType ().IsInner () {
165
+ continue
166
+ }
167
167
newLeft , sameLeft , errLeft := replaceIdxSortHelper (ctx , scope , c .Left (), sortNode )
168
168
if errLeft != nil {
169
169
return nil , transform .SameTree , errLeft
@@ -172,35 +172,48 @@ func replaceIdxSortHelper(ctx *sql.Context, scope *plan.Scope, node sql.Node, so
172
172
if errRight != nil {
173
173
return nil , transform .SameTree , errRight
174
174
}
175
- if sameLeft && sameRight {
175
+ // Neither child was converted to an IndexedTableAccess, so we can't remove the sort node
176
+ leftIsSorted , rightIsSorted := ! sameLeft , ! sameRight
177
+ if ! leftIsSorted && ! rightIsSorted {
176
178
continue
177
179
}
178
180
// No need to check all SortField orders because of isValidSortFieldOrder
179
181
isReversed := sortNode .SortFields [0 ].Order == sql .Descending
180
182
// If both left and right have been replaced, no need to manually reverse any indexes as they both should be
181
183
// replaced already
182
- if ! sameLeft && ! sameRight {
184
+ if leftIsSorted && rightIsSorted {
183
185
c .IsReversed = isReversed
184
186
continue
185
187
}
186
- // If only one side has been replaced, we need to check if the other side can be reversed
187
- if ( sameLeft != sameRight ) && isReversed {
188
- // If descending, then both Indexes must be reversed
189
- if sameLeft {
190
- newLeft , same , err = buildReverseIndexedTable ( ctx , newLeft )
191
- } else if sameRight {
192
- newRight , same , err = buildReverseIndexedTable ( ctx , newRight )
188
+ if c . JoinType (). IsCross () || c . JoinType (). IsInner () {
189
+ // For cross joins and inner joins, if the right child is sorted, we need to swap
190
+ if ! sameRight {
191
+ // Swapping may mess up projections, but
192
+ // eraseProjection will drop any Projections that are now unnecessary and
193
+ // fixExecIndexes will fix any existing Projection GetField indexes.
194
+ newLeft , newRight = newRight , newLeft
193
195
}
194
- if err != nil {
195
- return nil , transform .SameTree , err
196
+ } else {
197
+ // If only one side has been replaced, we need to check if the other side can be reversed
198
+ if (leftIsSorted != rightIsSorted ) && isReversed {
199
+ // If descending, then both Indexes must be reversed
200
+ if rightIsSorted {
201
+ newLeft , same , err = buildReverseIndexedTable (ctx , newLeft )
202
+ } else if leftIsSorted {
203
+ newRight , same , err = buildReverseIndexedTable (ctx , newRight )
204
+ }
205
+ if err != nil {
206
+ return nil , transform .SameTree , err
207
+ }
208
+ // If we could not replace the IndexedTableAccess with a reversed one (due to lack of reversible index)
209
+ // same = true, so just continue
210
+ if same {
211
+ continue
212
+ }
213
+ c .IsReversed = true
196
214
}
197
- // If we could not replace the IndexedTableAccess with a reversed one (due to lack of reversible index)
198
- // same = true, so just continue
199
- if same {
200
- continue
201
- }
202
- c .IsReversed = true
203
215
}
216
+
204
217
newChildren [i ], err = c .WithChildren (newLeft , newRight )
205
218
if err != nil {
206
219
return nil , transform .SameTree , err
0 commit comments