@@ -97,20 +97,27 @@ class EliminateSortsSuite extends PlanTest {
9797 comparePlans(optimized, correctAnswer)
9898 }
9999
100- test(" remove redundant local sort " ) {
100+ test(" SPARK-33183: remove redundant sortBy " ) {
101101 val orderedPlan = testRelation.select(' a , ' b ).orderBy(' a .asc, ' b .desc_nullsFirst)
102102 val unnecessaryReordered = orderedPlan.limit(2 ).select(' a ).sortBy(' a .asc, ' b .desc_nullsFirst)
103103 val optimized = Optimize .execute(unnecessaryReordered.analyze)
104104 val correctAnswer = orderedPlan.limit(2 ).select(' a ).analyze
105- comparePlans(Optimize .execute(optimized), correctAnswer)
105+ comparePlans(optimized, correctAnswer)
106+ }
107+
108+ test(" SPARK-33183: remove all redundant local sorts" ) {
109+ val orderedPlan = testRelation.sortBy(' a .asc).orderBy(' a .asc).sortBy(' a .asc)
110+ val optimized = Optimize .execute(orderedPlan.analyze)
111+ val correctAnswer = testRelation.orderBy(' a .asc).analyze
112+ comparePlans(optimized, correctAnswer)
106113 }
107114
108- test(" should not remove global sort" ) {
115+ test(" SPARK-33183: should not remove global sort" ) {
109116 val orderedPlan = testRelation.select(' a , ' b ).orderBy(' a .asc, ' b .desc_nullsFirst)
110117 val reordered = orderedPlan.limit(2 ).select(' a ).orderBy(' a .asc, ' b .desc_nullsFirst)
111118 val optimized = Optimize .execute(reordered.analyze)
112119 val correctAnswer = reordered.analyze
113- comparePlans(Optimize .execute( optimized) , correctAnswer)
120+ comparePlans(optimized, correctAnswer)
114121 }
115122
116123 test(" do not remove sort if the order is different" ) {
@@ -121,15 +128,15 @@ class EliminateSortsSuite extends PlanTest {
121128 comparePlans(optimized, correctAnswer)
122129 }
123130
124- test(" filters don't affect order for local sort" ) {
131+ test(" SPARK-33183: filters should not affect order for local sort" ) {
125132 val orderedPlan = testRelation.select(' a , ' b ).orderBy(' a .asc, ' b .desc)
126133 val filteredAndReordered = orderedPlan.where(' a > Literal (10 )).sortBy(' a .asc, ' b .desc)
127134 val optimized = Optimize .execute(filteredAndReordered.analyze)
128135 val correctAnswer = orderedPlan.where(' a > Literal (10 )).analyze
129136 comparePlans(optimized, correctAnswer)
130137 }
131138
132- test(" should keep global sort when child is a filter operator with the same ordering " ) {
139+ test(" SPARK-33183: should not remove global sort with filter operators " ) {
133140 val projectPlan = testRelation.select(' a , ' b )
134141 val orderedPlan = projectPlan.orderBy(' a .asc, ' b .desc)
135142 val filteredAndReordered = orderedPlan.where(' a > Literal (10 )).orderBy(' a .asc, ' b .desc)
@@ -138,15 +145,15 @@ class EliminateSortsSuite extends PlanTest {
138145 comparePlans(optimized, correctAnswer)
139146 }
140147
141- test(" limits don't affect order for local sort" ) {
148+ test(" SPARK-33183: limits should not affect order for local sort" ) {
142149 val orderedPlan = testRelation.select(' a , ' b ).orderBy(' a .asc, ' b .desc)
143150 val filteredAndReordered = orderedPlan.limit(Literal (10 )).sortBy(' a .asc, ' b .desc)
144151 val optimized = Optimize .execute(filteredAndReordered.analyze)
145152 val correctAnswer = orderedPlan.limit(Literal (10 )).analyze
146153 comparePlans(optimized, correctAnswer)
147154 }
148155
149- test(" should keep global sort when child is a limit operator with the same ordering " ) {
156+ test(" SPARK-33183: should not remove global sort with limit operators " ) {
150157 val orderedPlan = testRelation.select(' a , ' b ).orderBy(' a .asc, ' b .desc)
151158 val filteredAndReordered = orderedPlan.limit(Literal (10 )).orderBy(' a .asc, ' b .desc)
152159 val optimized = Optimize .execute(filteredAndReordered.analyze)
@@ -162,11 +169,11 @@ class EliminateSortsSuite extends PlanTest {
162169 comparePlans(optimized, correctAnswer)
163170 }
164171
165- test(" range is already sorted " ) {
172+ test(" SPARK-33183: should not remove global sort with range operator " ) {
166173 val inputPlan = Range (1L , 1000L , 1 , 10 )
167174 val orderedPlan = inputPlan.orderBy(' id .asc)
168175 val optimized = Optimize .execute(orderedPlan.analyze)
169- val correctAnswer = inputPlan .analyze
176+ val correctAnswer = orderedPlan .analyze
170177 comparePlans(optimized, correctAnswer)
171178
172179 val reversedPlan = inputPlan.orderBy(' id .desc)
@@ -177,10 +184,18 @@ class EliminateSortsSuite extends PlanTest {
177184 val negativeStepInputPlan = Range (10L , 1L , - 1 , 10 )
178185 val negativeStepOrderedPlan = negativeStepInputPlan.orderBy(' id .desc)
179186 val negativeStepOptimized = Optimize .execute(negativeStepOrderedPlan.analyze)
180- val negativeStepCorrectAnswer = negativeStepInputPlan .analyze
187+ val negativeStepCorrectAnswer = negativeStepOrderedPlan .analyze
181188 comparePlans(negativeStepOptimized, negativeStepCorrectAnswer)
182189 }
183190
191+ test(" SPARK-33183: remove local sort with range operator" ) {
192+ val inputPlan = Range (1L , 1000L , 1 , 10 )
193+ val orderedPlan = inputPlan.sortBy(' id .asc)
194+ val optimized = Optimize .execute(orderedPlan.analyze)
195+ val correctAnswer = inputPlan.analyze
196+ comparePlans(optimized, correctAnswer)
197+ }
198+
184199 test(" sort should not be removed when there is a node which doesn't guarantee any order" ) {
185200 val orderedPlan = testRelation.select(' a , ' b )
186201 val groupedAndResorted = orderedPlan.groupBy(' a )(sum(' a )).orderBy(' a .asc)
@@ -357,18 +372,31 @@ class EliminateSortsSuite extends PlanTest {
357372 comparePlans(optimized, correctAnswer)
358373 }
359374
360- test(" remove two consecutive global sorts with same ordering" ) {
375+ test(" SPARK-33183: remove consecutive global sorts with the same ordering" ) {
361376 Seq (
362377 (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))
378+ (testRelation.orderBy(' a .asc, ' b .desc).orderBy(' a .asc), testRelation.orderBy(' a .asc))
365379 ).foreach { case (ordered, answer) =>
366380 val optimized = Optimize .execute(ordered.analyze)
367381 comparePlans(optimized, answer.analyze)
368382 }
369383 }
370384
371- test(" should keep global sort when child is a local sort with the same ordering" ) {
385+ test(" SPARK-33183: remove consecutive local sorts with the same ordering" ) {
386+ val orderedPlan = testRelation.sortBy(' a .asc).sortBy(' a .asc).sortBy(' a .asc)
387+ val optimized = Optimize .execute(orderedPlan.analyze)
388+ val correctAnswer = testRelation.sortBy(' a .asc).analyze
389+ comparePlans(optimized, correctAnswer)
390+ }
391+
392+ test(" SPARK-33183: remove consecutive local sorts with different ordering" ) {
393+ val orderedPlan = testRelation.sortBy(' b .asc).sortBy(' a .desc).sortBy(' a .asc)
394+ val optimized = Optimize .execute(orderedPlan.analyze)
395+ val correctAnswer = testRelation.sortBy(' a .asc).analyze
396+ comparePlans(optimized, correctAnswer)
397+ }
398+
399+ test(" SPARK-33183: should keep global sort when child is a local sort with the same ordering" ) {
372400 val correctAnswer = testRelation.orderBy(' a .asc).analyze
373401 Seq (
374402 testRelation.sortBy(' a .asc).orderBy(' a .asc),
0 commit comments