@@ -154,16 +154,16 @@ func replaceIdxSortHelper(ctx *sql.Context, scope *plan.Scope, node sql.Node, so
154154 * plan.Project , * plan.Filter , * plan.Limit , * plan.Offset , * plan.Distinct , * plan.TableAlias :
155155 newChildren [i ], same , err = replaceIdxSortHelper (ctx , scope , child , sortNode )
156156 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- }
162157 // It's (probably) not possible to have Sort as child of Join without Subquery/SubqueryAlias,
163158 // and in the case where there is a Subq/SQA it's taken care of through finalizeSubqueries
164159 if sortNode == nil {
165160 continue
166161 }
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+ }
167167 newLeft , sameLeft , errLeft := replaceIdxSortHelper (ctx , scope , c .Left (), sortNode )
168168 if errLeft != nil {
169169 return nil , transform .SameTree , errLeft
@@ -172,35 +172,48 @@ func replaceIdxSortHelper(ctx *sql.Context, scope *plan.Scope, node sql.Node, so
172172 if errRight != nil {
173173 return nil , transform .SameTree , errRight
174174 }
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 {
176178 continue
177179 }
178180 // No need to check all SortField orders because of isValidSortFieldOrder
179181 isReversed := sortNode .SortFields [0 ].Order == sql .Descending
180182 // If both left and right have been replaced, no need to manually reverse any indexes as they both should be
181183 // replaced already
182- if ! sameLeft && ! sameRight {
184+ if leftIsSorted && rightIsSorted {
183185 c .IsReversed = isReversed
184186 continue
185187 }
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
193195 }
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
196214 }
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
203215 }
216+
204217 newChildren [i ], err = c .WithChildren (newLeft , newRight )
205218 if err != nil {
206219 return nil , transform .SameTree , err
0 commit comments