Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
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 @@ -17,6 +17,8 @@

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

import java.util.Locale

import org.apache.spark.sql.catalyst.expressions._
import org.apache.spark.sql.catalyst.trees.{CurrentOrigin, TreeNode}
import org.apache.spark.sql.internal.SQLConf
Expand Down Expand Up @@ -237,7 +239,7 @@ abstract class QueryPlan[PlanType <: QueryPlan[PlanType]] extends TreeNode[PlanT
// Top level `AttributeReference` may also be used for output like `Alias`, we should
// normalize the epxrId too.
id += 1
ar.withExprId(ExprId(id)).canonicalized
ar.withExprId(ExprId(id)).withName(ar.name.toLowerCase(Locale.ROOT)).canonicalized

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.

shall we just erase the attribute name like alias?

@eatoncys eatoncys Jul 20, 2018

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think it is Ok, and it erase the attribute name in spark version 2.0.2


case other => QueryPlan.normalizeExprId(other, allAttributes)
}.withNewChildren(canonicalizedChildren)
Expand Down Expand Up @@ -282,9 +284,9 @@ object QueryPlan extends PredicateHelper {
case ar: AttributeReference =>
val ordinal = input.indexOf(ar.exprId)
if (ordinal == -1) {
ar
ar.withName(ar.name.toLowerCase(Locale.ROOT))
} else {
ar.withExprId(ExprId(ordinal))
ar.withExprId(ExprId(ordinal)).withName(ar.name.toLowerCase(Locale.ROOT))
}
}.canonicalized.asInstanceOf[T]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
package org.apache.spark.sql.catalyst.expressions

import org.apache.spark.SparkFunSuite
import org.apache.spark.sql.catalyst.dsl.expressions._
import org.apache.spark.sql.catalyst.dsl.plans._
import org.apache.spark.sql.catalyst.plans.logical.Range
import org.apache.spark.sql.catalyst.plans.logical.{Aggregate, LocalRelation, Range}
import org.apache.spark.sql.types.LongType

class CanonicalizeSuite extends SparkFunSuite {

Expand Down Expand Up @@ -50,4 +52,30 @@ class CanonicalizeSuite extends SparkFunSuite {
assert(range.where(arrays1).sameResult(range.where(arrays2)))
assert(!range.where(arrays1).sameResult(range.where(arrays3)))
}

test("Canonicalized result is not case-insensitive") {

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.

let's move it to SameResultSuite, also let's pick a simpler test, like using a Project with one columns instead of Aggregate.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ok,modified,thanks.

val u1 = 'A.string.at(0)
val u2 = 'B.string.at(1)
val u3 = 'C.string.at(2)
val caseA = CaseWhen(Seq((u1, u2)), u3)
val otherA = AttributeReference("D", LongType)(exprId = ExprId(3))
val aliases = Alias(sum(caseA), "E")() :: Nil
val planUppercase = Aggregate(
Nil,
aliases,
LocalRelation(otherA))

val l1 = 'a.string.at(0)
val l2 = 'b.string.at(1)
val l3 = 'c.string.at(2)
val caseALower = CaseWhen(Seq((l1, l2)), l3)
val otherALower = AttributeReference("d", LongType)(exprId = ExprId(3))
val aliasesLower = Alias(sum(caseALower), "e")() :: Nil
val planLowercase = Aggregate(
Nil,
aliasesLower,
LocalRelation(otherALower))

assert(planUppercase.canonicalized == planLowercase.canonicalized)
}
}