Skip to content

Commit

Permalink
SPARK-49618. Fixed a bug in equality code and added bug test
Browse files Browse the repository at this point in the history
  • Loading branch information
ashahid committed Sep 14, 2024
1 parent 1ee1b1c commit 5c02cb3
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

package org.apache.spark.sql.catalyst.plans

import scala.collection.mutable

import org.apache.spark.sql.catalyst.expressions.{Attribute, ExprId}

trait UnionEquality [PlanType <: QueryPlan[PlanType]] {
Expand All @@ -28,9 +30,22 @@ trait UnionEquality [PlanType <: QueryPlan[PlanType]] {
def positionAgnosticEquals(that: PlanType): Boolean = {
val thisChildren = this.children
val thatChildren = that.children
thisChildren.length == thatChildren.length &&
normalizeOutputAttributes(this.asInstanceOf[PlanType]) == normalizeOutputAttributes(that) &&
thisChildren.toSet == thatChildren.toSet
if (thisChildren.length == thatChildren.length &&
normalizeOutputAttributes(this.asInstanceOf[PlanType]) == normalizeOutputAttributes(that)) {
// check for elements equality disregarding order
val buff = mutable.ArrayBuffer[PlanType](thatChildren: _*)
thisChildren.forall(p => {
val i = buff.indexOf(p)
if (i == -1) {
false
} else {
buff.remove(i)
true
}
} )
} else {
false
}
}

def positionAgnosticHashCode: Int = this.positionAgnosticHash
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -585,4 +585,29 @@ class CanonicalizeSuite extends SparkFunSuite {
// but canonicalized form should be same even though respective ordering is different
assert(u1.canonicalized == u2.canonicalized)
}

test("SPARK-49618: equality check for repeated legs") {
val table1 = LocalRelation(
AttributeReference("i", IntegerType)(),
AttributeReference("u", DecimalType.SYSTEM_DEFAULT)(),
AttributeReference("b", ByteType)(),
AttributeReference("d", DoubleType)()).select($"u", $"i").analyze

val table2 = LocalRelation(
AttributeReference("i", IntegerType)(),
AttributeReference("u", DecimalType.SYSTEM_DEFAULT)(),
AttributeReference("b", ByteType)(),
AttributeReference("d", DoubleType)()).select($"u" as "a", $"i" as "b").analyze

val table3 = LocalRelation(
AttributeReference("u", DecimalType.SYSTEM_DEFAULT)(),
AttributeReference("d", DoubleType)(),
AttributeReference("i", IntegerType)()).select($"u", $"i").analyze

// These unions are not equal because the head output attributes name are differing
val u1 = Union(Seq(table1, table2, table2, table3))
val u2 = Union(Seq(table1, table2, table3, table3))
assert(u1 != u2)
assert(u1.canonicalized != u2.canonicalized)
}
}

0 comments on commit 5c02cb3

Please sign in to comment.