@@ -71,7 +71,6 @@ abstract class Optimizer extends RuleExecutor[LogicalPlan] {
7171 PushPredicateThroughAggregate ,
7272 LimitPushDown ,
7373 ColumnPruning ,
74- EliminateOperators ,
7574 InferFiltersFromConstraints ,
7675 // Operator combine
7776 CollapseRepartition ,
@@ -316,7 +315,11 @@ object SetOperationPushDown extends Rule[LogicalPlan] with PredicateHelper {
316315 * - LeftSemiJoin
317316 */
318317object ColumnPruning extends Rule [LogicalPlan ] {
319- def apply (plan : LogicalPlan ): LogicalPlan = plan transformUp {
318+ private def sameOutput (output1 : Seq [Attribute ], output2 : Seq [Attribute ]): Boolean =
319+ output1.size == output2.size &&
320+ output1.zip(output2).forall(pair => pair._1.semanticEquals(pair._2))
321+
322+ def apply (plan : LogicalPlan ): LogicalPlan = plan transform {
320323 // Prunes the unused columns from project list of Project/Aggregate/Expand
321324 case p @ Project (_, p2 : Project ) if (p2.outputSet -- p.references).nonEmpty =>
322325 p.copy(child = p2.copy(projectList = p2.projectList.filter(p.references.contains)))
@@ -377,6 +380,12 @@ object ColumnPruning extends Rule[LogicalPlan] {
377380 p.copy(child = w.copy(
378381 windowExpressions = w.windowExpressions.filter(p.references.contains)))
379382
383+ // Eliminate no-op Window
384+ case w : Window if w.windowExpressions.isEmpty => w.child
385+
386+ // Eliminate no-op Projects
387+ case p @ Project (projectList, child) if sameOutput(child.output, p.output) => child
388+
380389 // Can't prune the columns on LeafNode
381390 case p @ Project (_, l : LeafNode ) => p
382391
@@ -400,24 +409,6 @@ object ColumnPruning extends Rule[LogicalPlan] {
400409 }
401410}
402411
403- /**
404- * Eliminate no-op Project and Window.
405- *
406- * Note: this rule should be executed just after ColumnPruning.
407- */
408- object EliminateOperators extends Rule [LogicalPlan ] {
409- def apply (plan : LogicalPlan ): LogicalPlan = plan transformUp {
410- // Eliminate no-op Projects
411- case p @ Project (projectList, child) if sameOutput(child.output, p.output) => child
412- // Eliminate no-op Window
413- case w : Window if w.windowExpressions.isEmpty => w.child
414- }
415-
416- private def sameOutput (output1 : Seq [Attribute ], output2 : Seq [Attribute ]): Boolean =
417- output1.size == output2.size &&
418- output1.zip(output2).forall(pair => pair._1.semanticEquals(pair._2))
419- }
420-
421412/**
422413 * Combines two adjacent [[Project ]] operators into one and perform alias substitution,
423414 * merging the expressions into one single expression.
0 commit comments