-
Notifications
You must be signed in to change notification settings - Fork 29k
[SPARK-16323] [SQL] Add IntegerDivide to avoid unnecessary cast #14036
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
067b788
e4e42c3
5db17fd
faa2fd3
e30747a
699ff8b
054d54e
237a1ad
ff97457
f85433b
f35e605
e89ffc0
a4b39b3
2c02370
38f8bd4
a461e35
b2f4489
d057546
01f5ed2
feee3cd
ab6858c
8d9a04d
7e4e394
7bb3e43
1ba502f
16eff20
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -216,7 +216,6 @@ case class Divide(left: Expression, right: Expression) | |
| override def inputType: AbstractDataType = TypeCollection(DoubleType, DecimalType) | ||
|
|
||
| override def symbol: String = "/" | ||
| override def decimalMethod: String = "$div" | ||
| override def nullable: Boolean = true | ||
|
|
||
| private lazy val div: (Any, Any) => Any = dataType match { | ||
|
|
@@ -284,6 +283,75 @@ case class Divide(left: Expression, right: Expression) | |
| } | ||
| } | ||
|
|
||
| @ExpressionDescription( | ||
| usage = "a _FUNC_ b - Divides a by b.", | ||
|
||
| extended = "> SELECT 3 _FUNC_ 2;\n 1") | ||
| case class IntegerDivide(left: Expression, right: Expression) | ||
|
||
| extends BinaryArithmetic with NullIntolerant { | ||
|
|
||
| override def inputType: AbstractDataType = IntegralType | ||
|
|
||
| override def symbol: String = "/" | ||
| override def decimalMethod: String = "$div" | ||
| override def nullable: Boolean = true | ||
|
|
||
| private lazy val div: (Any, Any) => Any = dataType match { | ||
| case i: IntegralType => i.integral.asInstanceOf[Integral[Any]].quot | ||
| } | ||
|
|
||
| override def eval(input: InternalRow): Any = { | ||
| val input2 = right.eval(input) | ||
| if (input2 == null || input2 == 0) { | ||
| null | ||
| } else { | ||
| val input1 = left.eval(input) | ||
| if (input1 == null) { | ||
| null | ||
| } else { | ||
| div(input1, input2) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Special case handling due to division by 0 => null. | ||
| */ | ||
| override def doGenCode(ctx: CodegenContext, ev: ExprCode): ExprCode = { | ||
| val eval1 = left.genCode(ctx) | ||
| val eval2 = right.genCode(ctx) | ||
| val isZero = s"${eval2.value} == 0" | ||
| val javaType = ctx.javaType(dataType) | ||
| val divide = s"($javaType)(${eval1.value} $symbol ${eval2.value})" | ||
| if (!left.nullable && !right.nullable) { | ||
| ev.copy(code = s""" | ||
| ${eval2.code} | ||
| boolean ${ev.isNull} = false; | ||
| $javaType ${ev.value} = ${ctx.defaultValue(javaType)}; | ||
| if ($isZero) { | ||
| ${ev.isNull} = true; | ||
| } else { | ||
| ${eval1.code} | ||
| ${ev.value} = $divide; | ||
| }""") | ||
| } else { | ||
| ev.copy(code = s""" | ||
| ${eval2.code} | ||
| boolean ${ev.isNull} = false; | ||
| $javaType ${ev.value} = ${ctx.defaultValue(javaType)}; | ||
| if (${eval2.isNull} || $isZero) { | ||
| ${ev.isNull} = true; | ||
| } else { | ||
| ${eval1.code} | ||
| if (${eval1.isNull}) { | ||
| ${ev.isNull} = true; | ||
| } else { | ||
| ${ev.value} = $divide; | ||
| } | ||
| }""") | ||
| } | ||
| } | ||
| } | ||
|
|
||
| @ExpressionDescription( | ||
| usage = "a _FUNC_ b - Returns the remainder when dividing a by b.") | ||
| case class Remainder(left: Expression, right: Expression) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -731,6 +731,21 @@ class Column(protected[sql] val expr: Expression) extends Logging { | |
| */ | ||
| def / (other: Any): Column = withExpr { Divide(expr, lit(other).expr) } | ||
|
|
||
| /** | ||
| * Integer Division this expression by another expression. | ||
| * {{{ | ||
| * // Scala: The following divides a person's height by their weight. | ||
| * people.select( people("height") div people("weight") ) | ||
| * | ||
| * // Java: | ||
| * people.select( people("height").div(people("weight")) ); | ||
| * }}} | ||
| * | ||
| * @group expr_ops | ||
| * @since 2.1.0 | ||
| */ | ||
| def div (other: Any): Column = withExpr { IntegerDivide(expr, lit(other).expr) } | ||
|
||
|
|
||
| /** | ||
| * Division this expression by another expression. | ||
| * {{{ | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does hive support this syntax? i.e.
div(4, 2)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cloud-fan yes, hive support div and / .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lianhuiwang doing
div(4,2)givesThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'select 4 div 2' is the right code.