-
Notifications
You must be signed in to change notification settings - Fork 29k
[SPARK-29387][SQL] Support * and / operators for intervals
#26132
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 1 commit
af2e7ab
4227915
379a20a
3e9ed0f
670a7c6
3ae94cf
3bce68e
754109c
166dbd8
b4dc59a
1e2a9a6
a6b6d81
6e569c0
69a3cc7
001d17b
014cde5
049f428
1ca7c89
9e6745a
b428070
8ad4001
91337e5
2bb916f
6ba53f0
719fe6c
d05ffa4
34f6605
00ede6c
690d9c1
5b25432
2265449
e559fb9
35ab9c0
dbc39e8
8244460
b70c0f8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -355,15 +355,15 @@ public CalendarInterval subtract(CalendarInterval that) { | |
| return new CalendarInterval(months, microseconds); | ||
| } | ||
|
|
||
| public CalendarInterval multiply(long num) { | ||
| int months = Math.toIntExact(Math.multiplyExact(this.months, num)); | ||
| long microseconds = Math.multiplyExact(this.microseconds, num); | ||
| public CalendarInterval multiply(double num) { | ||
| int months = Math.toIntExact((long)(num * this.months)); | ||
|
||
| long microseconds = (long)(num * this.microseconds); | ||
| return new CalendarInterval(months, microseconds); | ||
| } | ||
|
|
||
| public CalendarInterval divide(long num) { | ||
| int months = Math.toIntExact(this.months / num); | ||
| long microseconds = this.microseconds / num; | ||
| public CalendarInterval divide(double num) { | ||
| int months = Math.toIntExact((long)(this.months / num)); | ||
| long microseconds = (long)(this.microseconds / num); | ||
| return new CalendarInterval(months, microseconds); | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -847,11 +847,11 @@ object TypeCoercion { | |
| Cast(TimeAdd(l, r), l.dataType) | ||
| case Subtract(l, r @ CalendarIntervalType()) if acceptedTypes.contains(l.dataType) => | ||
| Cast(TimeSub(l, r), l.dataType) | ||
| case Multiply(l @ CalendarIntervalType(), r @ IntegralType()) => | ||
| case Multiply(l @ CalendarIntervalType(), r @ NumericType()) => | ||
| MultiplyInterval(l, r) | ||
| case Multiply(l @ IntegralType(), r @ CalendarIntervalType()) => | ||
| case Multiply(l @ NumericType(), r @ CalendarIntervalType()) => | ||
| MultiplyInterval(r, l) | ||
| case Divide(l @ CalendarIntervalType(), r @ IntegralType()) => | ||
| case Divide(l @ CalendarIntervalType(), r @ NumericType()) => | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. postgres=# select interval '1 year' / '365';
?column?
---------------
23:40:16.4064
(1 row)could this be supported?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Taking into account the discussion in #26165, I am not sure. @cloud-fan Should I support this?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can, but this should only apply to literals, not string columns.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we want to support it, please open another PR. |
||
| DivideInterval(l, r) | ||
|
|
||
| case Add(l @ DateType(), r @ IntegerType()) => DateAdd(l, r) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,26 +18,26 @@ | |
| package org.apache.spark.sql.catalyst.expressions | ||
|
|
||
| import org.apache.spark.sql.catalyst.expressions.codegen.{CodegenContext, ExprCode} | ||
| import org.apache.spark.sql.types.{AbstractDataType, CalendarIntervalType, DataType, LongType} | ||
| import org.apache.spark.sql.types.{AbstractDataType, CalendarIntervalType, DataType, DoubleType} | ||
| import org.apache.spark.unsafe.types.CalendarInterval | ||
|
|
||
| abstract class IntervalNumOperation( | ||
| interval: Expression, | ||
| num: Expression, | ||
| operation: (CalendarInterval, Long) => CalendarInterval, | ||
| operation: (CalendarInterval, Double) => CalendarInterval, | ||
| operationName: String) | ||
| extends BinaryExpression with ImplicitCastInputTypes with Serializable { | ||
| override def left: Expression = interval | ||
| override def right: Expression = num | ||
|
|
||
| override def inputTypes: Seq[AbstractDataType] = Seq(CalendarIntervalType, LongType) | ||
| override def inputTypes: Seq[AbstractDataType] = Seq(CalendarIntervalType, DoubleType) | ||
| override def dataType: DataType = CalendarIntervalType | ||
|
|
||
| override def nullable: Boolean = true | ||
|
|
||
| override def nullSafeEval(interval: Any, num: Any): Any = { | ||
| try { | ||
| operation(interval.asInstanceOf[CalendarInterval], num.asInstanceOf[Long]) | ||
| operation(interval.asInstanceOf[CalendarInterval], num.asInstanceOf[Double]) | ||
| } catch { | ||
| case _: java.lang.ArithmeticException => null | ||
| } | ||
|
|
@@ -62,12 +62,12 @@ case class MultiplyInterval(interval: Expression, num: Expression) | |
| extends IntervalNumOperation( | ||
| interval, | ||
| num, | ||
| (i: CalendarInterval, n: Long) => i.multiply(n), | ||
| (i: CalendarInterval, n: Double) => i.multiply(n), | ||
| "multiply") | ||
|
|
||
| case class DivideInterval(interval: Expression, num: Expression) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| extends IntervalNumOperation( | ||
| interval, | ||
| num, | ||
| (i: CalendarInterval, n: Long) => i.divide(n), | ||
| (i: CalendarInterval, n: Double) => i.divide(n), | ||
| "divide") | ||
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.
shall we use decimal instead? double is approximate value and we may truncate.
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.
If it is ok, I will switch to decimals.
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.
OK let's use double if it's what pgsql uses.
Can we move the
add,subtract,multiplyanddividetoIntervalUtils? In case we want to change them in the future.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.
Do you want to move
+and-in this PR? I just want to double check this because those methods are not related to this PR directly.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.
both are fine. We can move them tother, or have a followup PR to move +/-
Uh oh!
There was an error while loading. Please reload this page.
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.
Double is not big enough to support the average aggregate for interval #26347, I prefer decimal personally
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.
@yaooqinn Could you explain what do you mean? I could image that
doubleis not precise enough but not big though ...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.
yea, precise, not big.