Skip to content

Commit cee92bd

Browse files
committed
avoid evaluation 2 times
1 parent 22ecd9a commit cee92bd

File tree

2 files changed

+50
-9
lines changed

2 files changed

+50
-9
lines changed

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/Expression.scala

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,29 @@ abstract class Expression extends TreeNode[Expression] {
153153
}
154154
}
155155

156+
/**
157+
* Evaluation helper function for 1 Fractional children expression.
158+
* if the expression result is null, the evaluation result should be null.
159+
*/
160+
@inline
161+
protected final def f1(i: Row, e1: Expression, f: ((Fractional[Any], Any) => Any)): Any = {
162+
val evalE1 = e1.eval(i: Row)
163+
if(evalE1 == null) {
164+
null
165+
} else {
166+
e1.dataType match {
167+
case ft: FractionalType =>
168+
f.asInstanceOf[(Fractional[ft.JvmType], ft.JvmType) => ft.JvmType](
169+
ft.fractional, evalE1.asInstanceOf[ft.JvmType])
170+
case other => sys.error(s"Type $other does not support fractional operations")
171+
}
172+
}
173+
}
174+
156175
/**
157176
* Evaluation helper function for 2 Integral children expressions. Those expressions are
158177
* supposed to be in the same data type, and also the return type.
159-
* Either one of the expressions result is null, the evaluation result should be null.
178+
* if the expression result is null, the evaluation result should be null.
160179
*/
161180
@inline
162181
protected final def i2(
@@ -189,6 +208,28 @@ abstract class Expression extends TreeNode[Expression] {
189208
}
190209
}
191210

211+
/**
212+
* Evaluation helper function for 1 Integral children expression.
213+
* Either one of the expressions result is null, the evaluation result should be null.
214+
*/
215+
@inline
216+
protected final def i1(i: Row, e1: Expression, f: ((Integral[Any], Any) => Any)): Any = {
217+
val evalE1 = e1.eval(i)
218+
if(evalE1 == null) {
219+
null
220+
} else {
221+
e1.dataType match {
222+
case i: IntegralType =>
223+
f.asInstanceOf[(Integral[i.JvmType], i.JvmType) => i.JvmType](
224+
i.integral, evalE1.asInstanceOf[i.JvmType])
225+
case i: FractionalType =>
226+
f.asInstanceOf[(Integral[i.JvmType], i.JvmType) => i.JvmType](
227+
i.asIntegral, evalE1.asInstanceOf[i.JvmType])
228+
case other => sys.error(s"Type $other does not support numeric operations")
229+
}
230+
}
231+
}
232+
192233
/**
193234
* Evaluation helper function for 2 Comparable children expressions. Those expressions are
194235
* supposed to be in the same data type, and the return type should be Integer:

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/arithmetic.scala

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -108,15 +108,15 @@ case class Divide(left: Expression, right: Expression) extends BinaryArithmetic
108108

109109
override def nullable = true
110110

111-
override def eval(input: Row): Any =
112-
if(right.eval(input) == 0) {
113-
null
114-
} else {
115-
dataType match {
116-
case _: FractionalType => f2(input, left, right, _.div(_, _))
117-
case _: IntegralType => i2(input, left , right, _.quot(_, _))
118-
}
111+
override def eval(input: Row): Any = {
112+
val evalE2 = right.eval(input)
113+
dataType match {
114+
case _ if evalE2 == null => null
115+
case _ if evalE2 == 0 => null
116+
case ft: FractionalType => f1(input, left, _.div(_, evalE2.asInstanceOf[ft.JvmType]))
117+
case it: IntegralType => i1(input, left, _.quot(_, evalE2.asInstanceOf[it.JvmType]))
119118
}
119+
}
120120

121121
}
122122

0 commit comments

Comments
 (0)