Skip to content
Closed
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,25 @@ object UnionPushdown extends Rule[LogicalPlan] {
*/
object ColumnPruning extends Rule[LogicalPlan] {
def apply(plan: LogicalPlan): LogicalPlan = plan transform {
// Eliminate unneeded attributes from Expand that is used in GroupingSets
case a @ Aggregate(groupByExprs, aggregations, e @ Expand(projections, output, child))
if (e.outputSet -- a.references).nonEmpty =>

val substitution = projections.map { groupExpr =>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: substitution is usually the word we use for a map that contains replacements. Perhaps prunedProjections?.

It would also be good to comment why it is safe to remove certain projections, but others must be kept around. In particular I don't understand why you are collecting literals. If understand the logic here correctly you are going to do transformations like the following:

GroupExpression(a + 1) => GroupExpression(a, 1)
GroupExpression(a + b) => GroupExpression(a, b)

Is a collect really the right thing to be using here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Analyzer.ResolveGroupingAnalytics, the projections of Expand node contain some Literals that are constant null. Also the groupingId will be replaced with concrete value (the bit mask). We need to keep these Literals.

Because it performs collect on the groupExpr: Seq[Expression], it just keeps all Literals and the NamedExpressions which are refered in a: Aggregate.

So we do:

GroupExpression(a + 1, b, 1) => GroupExpression(a + 1, 1)  # suppose that b is not referred in above Aggregate

val newExprs = groupExpr.collect {
case x: NamedExpression if a.references.contains(x) => x
case l: Literal => l

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need special handling here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because there are some constant null values and bitmasks we need to keep them.

}
GroupExpression(newExprs)
}

val newOutput = output.collect {
case x: NamedExpression if a.references.contains(x) => x
case x: AttributeReference if x.name == VirtualColumn.groupingIdName => x
}

Aggregate(groupByExprs, aggregations, Expand(substitution, newOutput, child))

// Eliminate attributes that are not needed to calculate the specified aggregates.
case a @ Aggregate(_, _, child) if (child.outputSet -- a.references).nonEmpty =>
a.copy(child = Project(a.references.toSeq, child))
Expand Down