提交 4653ad38 编写于 作者: T twalthr

[FLINK-5124] [table] Support more temporal arithmetic

This closes #2851.
上级 4c23879a
......@@ -792,7 +792,7 @@ class CodeGenerator(
requireNumeric(right)
generateArithmeticOperator("-", nullCheck, resultType, left, right)
case MINUS if isTemporal(resultType) =>
case MINUS | MINUS_DATE if isTemporal(resultType) =>
val left = operands.head
val right = operands(1)
requireTemporal(left)
......
......@@ -656,38 +656,36 @@ object ScalarOperators {
right: GeneratedExpression)
: GeneratedExpression = {
val operator = if (plus) "+" else "-"
val op = if (plus) "+" else "-"
(left.resultType, right.resultType) match {
case (l: TimeIntervalTypeInfo[_], r: TimeIntervalTypeInfo[_]) if l == r =>
generateArithmeticOperator(operator, nullCheck, l, left, right)
generateArithmeticOperator(op, nullCheck, l, left, right)
case (SqlTimeTypeInfo.DATE, TimeIntervalTypeInfo.INTERVAL_MILLIS) =>
generateOperatorIfNotNull(nullCheck, SqlTimeTypeInfo.DATE, left, right) {
(l, r) => s"$l $op ((int) ($r / ${MILLIS_PER_DAY}L))"
}
case (SqlTimeTypeInfo.DATE, TimeIntervalTypeInfo.INTERVAL_MILLIS) |
(TimeIntervalTypeInfo.INTERVAL_MILLIS, SqlTimeTypeInfo.DATE) =>
case (SqlTimeTypeInfo.DATE, TimeIntervalTypeInfo.INTERVAL_MONTHS) =>
generateOperatorIfNotNull(nullCheck, SqlTimeTypeInfo.DATE, left, right) {
if (isTimePoint(left.resultType)) {
(leftTerm, rightTerm) => s"$leftTerm + ((int) ($rightTerm / ${MILLIS_PER_DAY}L))"
} else {
(leftTerm, rightTerm) => s"((int) ($leftTerm / ${MILLIS_PER_DAY}L)) + $rightTerm"
}
(l, r) => s"${qualifyMethod(BuiltInMethod.ADD_MONTHS.method)}($l, $op($r))"
}
case (SqlTimeTypeInfo.TIME, TimeIntervalTypeInfo.INTERVAL_MILLIS) |
(TimeIntervalTypeInfo.INTERVAL_MILLIS, SqlTimeTypeInfo.TIME) =>
case (SqlTimeTypeInfo.TIME, TimeIntervalTypeInfo.INTERVAL_MILLIS) =>
generateOperatorIfNotNull(nullCheck, SqlTimeTypeInfo.TIME, left, right) {
if (isTimePoint(left.resultType)) {
(leftTerm, rightTerm) => s"$leftTerm + ((int) ($rightTerm))"
} else {
(leftTerm, rightTerm) => s"((int) ($leftTerm)) + $rightTerm"
}
(l, r) => s"$l $op ((int) ($r))"
}
case (SqlTimeTypeInfo.TIMESTAMP, TimeIntervalTypeInfo.INTERVAL_MILLIS) =>
generateOperatorIfNotNull(nullCheck, SqlTimeTypeInfo.TIMESTAMP, left, right) {
(leftTerm, rightTerm) => s"$leftTerm + $rightTerm"
(l, r) => s"$l $op $r"
}
// TODO more operations when CALCITE-308 is fixed
case (SqlTimeTypeInfo.TIMESTAMP, TimeIntervalTypeInfo.INTERVAL_MONTHS) =>
generateOperatorIfNotNull(nullCheck, SqlTimeTypeInfo.TIMESTAMP, left, right) {
(l, r) => s"${qualifyMethod(BuiltInMethod.ADD_MONTHS.method)}($l, $op($r))"
}
case _ =>
throw new CodeGenException("Unsupported temporal arithmetic.")
......
......@@ -129,6 +129,10 @@ case class Minus(left: Expression, right: Expression) extends BinaryArithmetic {
override private[flink] def validateInput(): ValidationResult = {
if (isTimeInterval(left.resultType) && left.resultType == right.resultType) {
ValidationSuccess
} else if (isTimePoint(left.resultType) && isTimeInterval(right.resultType)) {
ValidationSuccess
} else if (isTimeInterval(left.resultType) && isTimePoint(right.resultType)) {
ValidationSuccess
} else {
super.validateInput()
}
......
......@@ -275,12 +275,23 @@ class TemporalTypesTest extends ExpressionTestBase {
@Test
def testTimeIntervalArithmetic(): Unit = {
// interval months comparison
testAllApis(
12.months < 24.months,
"12.months < 24.months",
"INTERVAL '12' MONTH < INTERVAL '24' MONTH",
"true")
testAllApis(
8.years === 8.years,
"8.years === 8.years",
"INTERVAL '8' YEAR = INTERVAL '8' YEAR",
"true")
// interval millis comparison
testAllApis(
8.millis > 10.millis,
"8.millis > 10.millis",
......@@ -288,17 +299,33 @@ class TemporalTypesTest extends ExpressionTestBase {
"false")
testAllApis(
8.years === 8.years,
"8.years === 8.years",
"INTERVAL '8' YEAR = INTERVAL '8' YEAR",
8.millis === 8.millis,
"8.millis === 8.millis",
"INTERVAL '0.008' SECOND = INTERVAL '0.008' SECOND",
"true")
// interval months addition/subtraction
testAllApis(
8.years + 10.months,
"8.years + 10.months",
"INTERVAL '8' YEAR + INTERVAL '10' MONTH",
"+8-10")
testAllApis(
2.years - 12.months,
"2.years - 12.months",
"INTERVAL '2' YEAR - INTERVAL '12' MONTH",
"+1-00")
testAllApis(
-2.years,
"-2.years",
"-INTERVAL '2' YEAR",
"-2-00")
// interval millis addition/subtraction
testAllApis(
8.hours + 10.minutes + 12.seconds + 5.millis,
"8.hours + 10.minutes + 12.seconds + 5.millis",
......@@ -312,46 +339,202 @@ class TemporalTypesTest extends ExpressionTestBase {
"+0 00:00:50.000")
testAllApis(
2.years - 12.months,
"2.years - 12.months",
"INTERVAL '2' YEAR - INTERVAL '12' MONTH",
"+1-00")
-10.seconds,
"-10.seconds",
"-INTERVAL '10' SECOND",
"-0 00:00:10.000")
testAllApis(
-'f9.cast(Types.INTERVAL_MONTHS),
"-f9.cast(INTERVAL_MONTHS)",
"-CAST(f9 AS INTERVAL YEAR)",
"-2-00")
// addition to date
// interval millis
testAllApis(
'f0 + 2.days,
"f0 + 2.days",
"f0 + INTERVAL '2' DAY",
"1990-10-16")
// interval millis
testAllApis(
30.days + 'f0,
"30.days + f0",
"INTERVAL '30' DAY + f0",
"1990-11-13")
// interval months
testAllApis(
'f0 + 2.months,
"f0 + 2.months",
"f0 + INTERVAL '2' MONTH",
"1990-12-14")
// interval months
testAllApis(
2.months + 'f0,
"2.months + f0",
"INTERVAL '2' MONTH + f0",
"1990-12-14")
// addition to time
// interval millis
testAllApis(
'f1 + 12.hours,
"f1 + 12.hours",
"f1 + INTERVAL '12' HOUR",
"22:20:45")
// interval millis
testAllApis(
24.hours + 'f1,
"24.hours + f1",
"INTERVAL '24' HOUR + f1",
"10:20:45")
12.hours + 'f1,
"12.hours + f1",
"INTERVAL '12' HOUR + f1",
"22:20:45")
// addition to timestamp
// interval millis
testAllApis(
'f2 + 10.days + 4.millis,
"f2 + 10.days + 4.millis",
"f2 + INTERVAL '10 00:00:00.004' DAY TO SECOND",
"1990-10-24 10:20:45.127")
// interval millis
testAllApis(
10.days + 'f2 + 4.millis,
"10.days + f2 + 4.millis",
"INTERVAL '10 00:00:00.004' DAY TO SECOND + f2",
"1990-10-24 10:20:45.127")
// interval months
testAllApis(
'f2 + 10.years,
"f2 + 10.years",
"f2 + INTERVAL '10' YEAR",
"2000-10-14 10:20:45.123")
// interval months
testAllApis(
10.years + 'f2,
"10.years + f2",
"INTERVAL '10' YEAR + f2",
"2000-10-14 10:20:45.123")
// subtraction from date
// interval millis
testAllApis(
'f0 - 2.days,
"f0 - 2.days",
"f0 - INTERVAL '2' DAY",
"1990-10-12")
// interval millis
testAllApis(
-30.days + 'f0,
"-30.days + f0",
"INTERVAL '-30' DAY + f0",
"1990-09-14")
// interval months
testAllApis(
'f0 - 2.months,
"f0 - 2.months",
"f0 - INTERVAL '2' MONTH",
"1990-08-14")
// interval months
testAllApis(
-2.months + 'f0,
"-2.months + f0",
"-INTERVAL '2' MONTH + f0",
"1990-08-14")
// subtraction from time
// interval millis
testAllApis(
'f1 - 12.hours,
"f1 - 12.hours",
"f1 - INTERVAL '12' HOUR",
"22:20:45")
// interval millis
testAllApis(
-12.hours + 'f1,
"-12.hours + f1",
"INTERVAL '-12' HOUR + f1",
"22:20:45")
// subtraction from timestamp
// interval millis
testAllApis(
'f2 - 10.days - 4.millis,
"f2 - 10.days - 4.millis",
"f2 - INTERVAL '10 00:00:00.004' DAY TO SECOND",
"1990-10-04 10:20:45.119")
// interval millis
testAllApis(
-10.days + 'f2 - 4.millis,
"-10.days + f2 - 4.millis",
"INTERVAL '-10 00:00:00.004' DAY TO SECOND + f2",
"1990-10-04 10:20:45.119")
// interval months
testAllApis(
'f2 - 10.years,
"f2 - 10.years",
"f2 - INTERVAL '10' YEAR",
"1980-10-14 10:20:45.123")
// interval months
testAllApis(
-10.years + 'f2,
"-10.years + f2",
"INTERVAL '-10' YEAR + f2",
"1980-10-14 10:20:45.123")
// casting
testAllApis(
-'f9.cast(Types.INTERVAL_MONTHS),
"-f9.cast(INTERVAL_MONTHS)",
"-CAST(f9 AS INTERVAL YEAR)",
"-2-00")
testAllApis(
-'f10.cast(Types.INTERVAL_MILLIS),
"-f10.cast(INTERVAL_MILLIS)",
"-CAST(f10 AS INTERVAL SECOND)",
"-0 00:00:12.000")
// addition/subtraction of interval millis and interval months
testAllApis(
'f0 + 2.days + 1.month,
"f0 + 2.days + 1.month",
"f0 + INTERVAL '2' DAY + INTERVAL '1' MONTH",
"1990-11-16")
testAllApis(
'f0 - 2.days - 1.month,
"f0 - 2.days - 1.month",
"f0 - INTERVAL '2' DAY - INTERVAL '1' MONTH",
"1990-09-12")
testAllApis(
'f2 + 2.days + 1.month,
"f2 + 2.days + 1.month",
"f2 + INTERVAL '2' DAY + INTERVAL '1' MONTH",
"1990-11-16 10:20:45.123")
testAllApis(
'f2 - 2.days - 1.month,
"f2 - 2.days - 1.month",
"f2 - INTERVAL '2' DAY - INTERVAL '1' MONTH",
"1990-09-12 10:20:45.123")
}
// ----------------------------------------------------------------------------------------------
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册