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]

Reply via email to