Github user dilipbiswal commented on a diff in the pull request:
https://github.com/apache/spark/pull/17541#discussion_r110212520
--- Diff:
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/plans/QueryPlan.scala
---
@@ -359,9 +359,47 @@ abstract class QueryPlan[PlanType <:
QueryPlan[PlanType]] extends TreeNode[PlanT
override protected def innerChildren: Seq[QueryPlan[_]] = subqueries
/**
- * Canonicalized copy of this query plan.
+ * Returns a plan where a best effort attempt has been made to transform
`this` in a way
+ * that preserves the result but removes cosmetic variations (case
sensitivity, ordering for
+ * commutative operations, expression id, etc.)
+ *
+ * Plans where `this.canonicalized == other.canonicalized` will always
evaluate to the same
+ * result.
+ *
+ * Some leaf nodes should overwrite this to provide proper canonicalize
logic.
*/
- protected lazy val canonicalized: PlanType = this
+ lazy val canonicalized: PlanType = {
+ val canonicalizedChildren = children.map(_.canonicalized)
+ withNewChildren(canonicalizedChildren) mapExpressions {
+ case a: Alias =>
+ // As the root of the expression, Alias will always take an
arbitrary exprId, we need to
+ // erase that for equality testing. The alias name doesn't matter
and should also be erased.
+ Alias(normalizeExprId(a.child), "")(ExprId(-1), a.qualifier,
isGenerated = a.isGenerated)
+
+ case ar: AttributeReference if allAttributes.indexOf(ar.exprId) ==
-1 =>
+ // Top level `AttributeReference` may also be used for output like
`Alias`, we should
+ // erase the epxrId too.
+ ar.withExprId(ExprId(-1))
+
+ case other => normalizeExprId(other)
+ }
+ }
+
+ /**
+ * Normalize the exprIds in the given expression, by updating the exprId
in `AttributeReference`
+ * with its referenced ordinal from input attributes. It's similar to
`BindReferences` but we
+ * do not use `BindReferences` here as the plan may take the expression
as a parameter with type
+ * `Attribute`, and replace it with `BoundReference` will cause error.
+ */
+ private def normalizeExprId(e: Expression): Expression = e.canonicalized
transformUp {
+ case ar: AttributeReference =>
+ val ordinal = allAttributes.indexOf(ar.exprId)
+ if (ordinal == -1) {
+ ar
+ } else {
+ ar.withExprId(ExprId(ordinal))
--- End diff --
@cloud-fan this is very nice idea :-) I was running into the same issue
when you asked me to try normalizing the attributes in my caching pr.
---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at [email protected] or file a JIRA ticket
with INFRA.
---
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]