@@ -97,14 +97,22 @@ class EliminateSortsSuite extends PlanTest {
97
97
comparePlans(optimized, correctAnswer)
98
98
}
99
99
100
- test(" remove redundant order by " ) {
100
+ test(" remove redundant local sort " ) {
101
101
val orderedPlan = testRelation.select(' a , ' b ).orderBy(' a .asc, ' b .desc_nullsFirst)
102
- val unnecessaryReordered = orderedPlan.limit(2 ).select(' a ).orderBy (' a .asc, ' b .desc_nullsFirst)
102
+ val unnecessaryReordered = orderedPlan.limit(2 ).select(' a ).sortBy (' a .asc, ' b .desc_nullsFirst)
103
103
val optimized = Optimize .execute(unnecessaryReordered.analyze)
104
104
val correctAnswer = orderedPlan.limit(2 ).select(' a ).analyze
105
105
comparePlans(Optimize .execute(optimized), correctAnswer)
106
106
}
107
107
108
+ test(" should not remove global sort" ) {
109
+ val orderedPlan = testRelation.select(' a , ' b ).orderBy(' a .asc, ' b .desc_nullsFirst)
110
+ val reordered = orderedPlan.limit(2 ).select(' a ).orderBy(' a .asc, ' b .desc_nullsFirst)
111
+ val optimized = Optimize .execute(reordered.analyze)
112
+ val correctAnswer = reordered.analyze
113
+ comparePlans(Optimize .execute(optimized), correctAnswer)
114
+ }
115
+
108
116
test(" do not remove sort if the order is different" ) {
109
117
val orderedPlan = testRelation.select(' a , ' b ).orderBy(' a .asc, ' b .desc_nullsFirst)
110
118
val reorderedDifferently = orderedPlan.limit(2 ).select(' a ).orderBy(' a .asc, ' b .desc)
@@ -113,22 +121,39 @@ class EliminateSortsSuite extends PlanTest {
113
121
comparePlans(optimized, correctAnswer)
114
122
}
115
123
116
- test(" filters don't affect order" ) {
124
+ test(" filters don't affect order for local sort " ) {
117
125
val orderedPlan = testRelation.select(' a , ' b ).orderBy(' a .asc, ' b .desc)
118
- val filteredAndReordered = orderedPlan.where(' a > Literal (10 )).orderBy (' a .asc, ' b .desc)
126
+ val filteredAndReordered = orderedPlan.where(' a > Literal (10 )).sortBy (' a .asc, ' b .desc)
119
127
val optimized = Optimize .execute(filteredAndReordered.analyze)
120
128
val correctAnswer = orderedPlan.where(' a > Literal (10 )).analyze
121
129
comparePlans(optimized, correctAnswer)
122
130
}
123
131
124
- test(" limits don't affect order" ) {
132
+ test(" should keep global sort when child is a filter operator with the same ordering" ) {
133
+ val projectPlan = testRelation.select(' a , ' b )
134
+ val orderedPlan = projectPlan.orderBy(' a .asc, ' b .desc)
135
+ val filteredAndReordered = orderedPlan.where(' a > Literal (10 )).orderBy(' a .asc, ' b .desc)
136
+ val optimized = Optimize .execute(filteredAndReordered.analyze)
137
+ val correctAnswer = projectPlan.where(' a > Literal (10 )).orderBy(' a .asc, ' b .desc).analyze
138
+ comparePlans(optimized, correctAnswer)
139
+ }
140
+
141
+ test(" limits don't affect order for local sort" ) {
125
142
val orderedPlan = testRelation.select(' a , ' b ).orderBy(' a .asc, ' b .desc)
126
- val filteredAndReordered = orderedPlan.limit(Literal (10 )).orderBy (' a .asc, ' b .desc)
143
+ val filteredAndReordered = orderedPlan.limit(Literal (10 )).sortBy (' a .asc, ' b .desc)
127
144
val optimized = Optimize .execute(filteredAndReordered.analyze)
128
145
val correctAnswer = orderedPlan.limit(Literal (10 )).analyze
129
146
comparePlans(optimized, correctAnswer)
130
147
}
131
148
149
+ test(" should keep global sort when child is a limit operator with the same ordering" ) {
150
+ val orderedPlan = testRelation.select(' a , ' b ).orderBy(' a .asc, ' b .desc)
151
+ val filteredAndReordered = orderedPlan.limit(Literal (10 )).orderBy(' a .asc, ' b .desc)
152
+ val optimized = Optimize .execute(filteredAndReordered.analyze)
153
+ val correctAnswer = filteredAndReordered.analyze
154
+ comparePlans(optimized, correctAnswer)
155
+ }
156
+
132
157
test(" different sorts are not simplified if limit is in between" ) {
133
158
val orderedPlan = testRelation.select(' a , ' b ).orderBy(' b .desc).limit(Literal (10 ))
134
159
.orderBy(' a .asc)
@@ -331,4 +356,26 @@ class EliminateSortsSuite extends PlanTest {
331
356
val correctAnswer = PushDownOptimizer .execute(noOrderByPlan.analyze)
332
357
comparePlans(optimized, correctAnswer)
333
358
}
359
+
360
+ test(" remove two consecutive global sorts with same ordering" ) {
361
+ Seq (
362
+ (testRelation.orderBy(' a .asc).orderBy(' a .asc), testRelation.orderBy(' a .asc)),
363
+ (testRelation.orderBy(' a .asc, ' b .desc).orderBy(' a .asc),
364
+ testRelation.orderBy(' a .asc, ' b .desc))
365
+ ).foreach { case (ordered, answer) =>
366
+ val optimized = Optimize .execute(ordered.analyze)
367
+ comparePlans(optimized, answer.analyze)
368
+ }
369
+ }
370
+
371
+ test(" should keep global sort when child is a local sort with the same ordering" ) {
372
+ val correctAnswer = testRelation.orderBy(' a .asc).analyze
373
+ Seq (
374
+ testRelation.sortBy(' a .asc).orderBy(' a .asc),
375
+ testRelation.orderBy(' a .asc).sortBy(' a .asc).orderBy(' a .asc)
376
+ ).foreach { ordered =>
377
+ val optimized = Optimize .execute(ordered.analyze)
378
+ comparePlans(optimized, correctAnswer)
379
+ }
380
+ }
334
381
}
0 commit comments