Github user JoshRosen commented on a diff in the pull request:
https://github.com/apache/spark/pull/6479#discussion_r31687465
--- Diff:
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/codegen/GenerateOrdering.scala
---
@@ -38,73 +44,89 @@ object GenerateOrdering extends
CodeGenerator[Seq[SortOrder], Ordering[Row]] wit
protected def create(ordering: Seq[SortOrder]): Ordering[Row] = {
val a = newTermName("a")
val b = newTermName("b")
- val comparisons = ordering.zipWithIndex.map { case (order, i) =>
- val evalA = expressionEvaluator(order.child)
- val evalB = expressionEvaluator(order.child)
+ val ctx = newCodeGenContext()
+ val comparisons = ordering.zipWithIndex.map { case (order, i) =>
+ val evalA = expressionEvaluator(order.child, ctx)
+ val evalB = expressionEvaluator(order.child, ctx)
+ val asc = order.direction == Ascending
val compare = order.child.dataType match {
case BinaryType =>
- q"""
- val x = ${if (order.direction == Ascending) evalA.primitiveTerm
else evalB.primitiveTerm}
- val y = ${if (order.direction != Ascending) evalB.primitiveTerm
else evalA.primitiveTerm}
- var i = 0
- while (i < x.length && i < y.length) {
- val res = x(i).compareTo(y(i))
- if (res != 0) return res
- i = i+1
- }
- return x.length - y.length
- """
+ s"""
+ {
+ byte[] x = ${if (asc) evalA.primitiveTerm else
evalB.primitiveTerm};
+ byte[] y = ${if (!asc) evalB.primitiveTerm else
evalA.primitiveTerm};
+ int j = 0;
+ while (j < x.length && j < y.length) {
+ if (x[j] != y[j]) return x[j] - y[j];
+ j = j + 1;
+ }
+ int d = x.length - y.length;
+ if (d != 0) {
+ return d;
+ }
+ }"""
case _: NumericType =>
- q"""
- val comp = ${evalA.primitiveTerm} - ${evalB.primitiveTerm}
- if(comp != 0) {
- return ${if (order.direction == Ascending) q"comp.toInt" else
q"-comp.toInt"}
- }
- """
- case StringType =>
- if (order.direction == Ascending) {
- q"""return
${evalA.primitiveTerm}.compare(${evalB.primitiveTerm})"""
+ s"""
+ if (${evalA.primitiveTerm} != ${evalB.primitiveTerm}) {
+ if (${evalA.primitiveTerm} > ${evalB.primitiveTerm}) {
+ return ${if (asc) "1" else "-1"};
+ } else {
+ return ${if (asc) "-1" else "1"};
+ }
+ }"""
+ case _ =>
+ s"""
+ int comp =
${evalA.primitiveTerm}.compare(${evalB.primitiveTerm});
+ if (comp != 0) {
+ return ${if (asc) "comp" else "-comp"};
+ }"""
+ }
+
+ s"""
+ i = $a;
+ ${evalA.code}
+ i = $b;
+ ${evalB.code}
+ if (${evalA.nullTerm} && ${evalB.nullTerm}) {
+ // Nothing
+ } else if (${evalA.nullTerm}) {
+ return ${if (order.direction == Ascending) "-1" else "1"};
+ } else if (${evalB.nullTerm}) {
+ return ${if (order.direction == Ascending) "1" else "-1"};
} else {
- q"""return
${evalB.primitiveTerm}.compare(${evalA.primitiveTerm})"""
+ $compare
}
+ """
+ }.mkString("\n")
+
+ val code = s"""
+ import org.apache.spark.sql.Row;
+
+ public SpecificOrdering generate($exprType[] expr) {
+ return new SpecificOrdering(expr);
}
- q"""
- i = $a
- ..${evalA.code}
- i = $b
- ..${evalB.code}
- if (${evalA.nullTerm} && ${evalB.nullTerm}) {
- // Nothing
- } else if (${evalA.nullTerm}) {
- return ${if (order.direction == Ascending) q"-1" else q"1"}
- } else if (${evalB.nullTerm}) {
- return ${if (order.direction == Ascending) q"1" else q"-1"}
- } else {
- $compare
+ class SpecificOrdering extends ${typeOf[BaseOrdering]} {
+
+ private $exprType[] expressions = null;
+
+ public SpecificOrdering($exprType[] expr) {
+ expressions = expr;
}
- """
- }
- val q"class $orderingName extends $orderingType { ..$body }" = reify {
- class SpecificOrdering extends Ordering[Row] {
- val o = ordering
- }
- }.tree.children.head
-
- val code = q"""
- class $orderingName extends $orderingType {
- ..$body
- def compare(a: $rowType, b: $rowType): Int = {
- var i: $rowType = null // Holds current row being evaluated.
- ..$comparisons
- return 0
+ @Override
+ public int compare(Row a, Row b) {
+ Row i = null; // Holds current row being evaluated.
+ $comparisons
+ return 0;
}
- }
- new $orderingName()
- """
+ }"""
+
logDebug(s"Generated Ordering: $code")
- toolBox.eval(code).asInstanceOf[Ordering[Row]]
+
+ val c = compile(code)
+ val m = c.getDeclaredMethods()(0)
--- End diff --
Might use a comment?
---
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]