Skip to content

Commit

Permalink
rebase and address comments
Browse files Browse the repository at this point in the history
  • Loading branch information
leonardBang committed Mar 19, 2021
1 parent 7a28bbf commit b632dd2
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 67 deletions.
Expand Up @@ -167,6 +167,48 @@ object ScalarOperatorGens {

val op = if (plus) "+" else "-"

def isValidOpTypeForTsLtzArithmetic(opType: LogicalTypeRoot) : Boolean = {
opType match {
case TIMESTAMP_WITH_LOCAL_TIME_ZONE | TIMESTAMP_WITHOUT_TIME_ZONE |
TIME_WITHOUT_TIME_ZONE | DATE
=> true
case _
=> false
}
}

def generateTsLtzArithmetic(resultType: LogicalType) : GeneratedExpression = {
resultType.getTypeRoot match {
case INTERVAL_YEAR_MONTH =>
generateOperatorIfNotNull(ctx, resultType, left, right) {
(ll, rr) => (left.resultType.getTypeRoot, right.resultType.getTypeRoot) match {
case (TIMESTAMP_WITH_LOCAL_TIME_ZONE, TIMESTAMP_WITH_LOCAL_TIME_ZONE) =>
val leftTerm = s"$ll.getMillisecond()"
val rightTerm = s"$rr.getMillisecond()"
s"${qualifyMethod(BuiltInMethods.SUBTRACT_MONTHS)}($leftTerm, $rightTerm)"
case _ =>
throw new CodeGenException(
"TIMESTAMP_LTZ only supports diff between the same type.")
}
}

case INTERVAL_DAY_TIME =>
generateOperatorIfNotNull(ctx, resultType, left, right) {
(ll, rr) => (left.resultType.getTypeRoot, right.resultType.getTypeRoot) match {
case (TIMESTAMP_WITH_LOCAL_TIME_ZONE, TIMESTAMP_WITH_LOCAL_TIME_ZONE) =>
val leftTerm = s"$ll.getMillisecond()"
val rightTerm = s"$rr.getMillisecond()"
s"$leftTerm $op $rightTerm"
case _ =>
throw new CodeGenException(
"TIMESTAMP_LTZ only supports diff between the same type.")
}
}
case _ =>
throw new CodeGenException("Unsupported temporal arithmetic.")
}
}

(left.resultType.getTypeRoot, right.resultType.getTypeRoot) match {
// arithmetic of time point and time interval
case (INTERVAL_YEAR_MONTH, INTERVAL_YEAR_MONTH) |
Expand Down Expand Up @@ -273,48 +315,10 @@ object ScalarOperatorGens {
}

// minus arithmetic of time points (i.e. for TIMESTAMPDIFF for TIMESTAMP_LTZ)
case (TIMESTAMP_WITH_LOCAL_TIME_ZONE, TIMESTAMP_WITH_LOCAL_TIME_ZONE |
TIMESTAMP_WITHOUT_TIME_ZONE | TIME_WITHOUT_TIME_ZONE | DATE) |
(TIMESTAMP_WITH_LOCAL_TIME_ZONE | TIMESTAMP_WITHOUT_TIME_ZONE |
TIME_WITHOUT_TIME_ZONE | DATE, TIMESTAMP_WITH_LOCAL_TIME_ZONE) if !plus =>
resultType.getTypeRoot match {
case INTERVAL_YEAR_MONTH =>
generateOperatorIfNotNull(ctx, resultType, left, right) {
(ll, rr) => (left.resultType.getTypeRoot, right.resultType.getTypeRoot) match {
case (TIMESTAMP_WITH_LOCAL_TIME_ZONE, TIMESTAMP_WITH_LOCAL_TIME_ZONE) =>
val leftTerm = s"$ll.getMillisecond()"
val rightTerm = s"$rr.getMillisecond()"
s"${qualifyMethod(BuiltInMethods.SUBTRACT_MONTHS)}($leftTerm, $rightTerm)"
case _ =>
throw new CodeGenException(String.format(
"Unsupported TIMESTAMPDIFF(%s, %s, %s) which contains TIMESTAMP_LTZ type." +
" TIMESTAMP_LTZ type only supports TIMESTAMPDIFF(timepointunit," +
" timepoint1 with TIMESTAMP_LTZ type, timepoint2 with TIMESTAMP_LTZ type)," +
" you can also cast TIMESTAMP_LTZ to TIMESTAMP before compare with" +
" other temporal types.",
resultType, left.resultType, right.resultType))
}
}

case INTERVAL_DAY_TIME =>
generateOperatorIfNotNull(ctx, resultType, left, right) {
(ll, rr) => (left.resultType.getTypeRoot, right.resultType.getTypeRoot) match {
case (TIMESTAMP_WITH_LOCAL_TIME_ZONE, TIMESTAMP_WITH_LOCAL_TIME_ZONE) =>
val leftTerm = s"$ll.getMillisecond()"
val rightTerm = s"$rr.getMillisecond()"
s"$leftTerm $op $rightTerm"
case _ =>
throw new CodeGenException(String.format(
"Unsupported TIMESTAMPDIFF(%s, %s, %s) which contains TIMESTAMP_LTZ type." +
" TIMESTAMP_LTZ type only supports TIMESTAMPDIFF(timepointunit," +
" timepoint1 with TIMESTAMP_LTZ type, timepoint2 with TIMESTAMP_LTZ type)," +
" you can also cast TIMESTAMP_LTZ to TIMESTAMP before compare with" +
" other temporal types.",
resultType, left.resultType, right.resultType))
}
}
}

case (TIMESTAMP_WITH_LOCAL_TIME_ZONE, t) if isValidOpTypeForTsLtzArithmetic(t) && !plus =>
generateTsLtzArithmetic(resultType)
case (t, TIMESTAMP_WITH_LOCAL_TIME_ZONE) if isValidOpTypeForTsLtzArithmetic(t) && !plus =>
generateTsLtzArithmetic(resultType)
case _ =>
throw new CodeGenException("Unsupported temporal arithmetic.")
}
Expand Down
Expand Up @@ -1448,49 +1448,47 @@ class TemporalTypesTest extends ExpressionTestBase {
s"TIMESTAMPDIFF(SECOND, ${timestampTz("1970-01-01 00:00:00.123")}," +
s" ${timestampTz("1970-01-01 00:02:03.234")})",
"123")

// test null input
testSqlApi(
s"TIMESTAMPDIFF(SECOND, CAST(null AS TIMESTAMP_LTZ)," +
s" ${timestampTz("1970-01-01 00:02:03.234")})",
"null")
}

@Test
def testInvalidTimestampLtzArithmetic(): Unit = {
val exceptionTemplate =
"Unsupported %s which contains TIMESTAMP_LTZ type." +
" TIMESTAMP_LTZ type only supports TIMESTAMPDIFF(timepointunit, timepoint1 with" +
" TIMESTAMP_LTZ type, timepoint2 with TIMESTAMP_LTZ type), you can also cast" +
" TIMESTAMP_LTZ to TIMESTAMP before compare with other temporal types."
val exceptionMsg = "TIMESTAMP_LTZ only supports diff between the same type."

testExpectExceptionThrown(
// unsupported operand type
testExpectedSqlException(
s"TIMESTAMPDIFF(MONTH, ${timestampTz("1970-01-01 00:00:00.123")}, TIME '00:00:01')",
"",
String.format(exceptionTemplate,
"TIMESTAMPDIFF(INTERVAL MONTH NOT NULL, TIME(0) NOT NULL," +
" TIMESTAMP(3) WITH LOCAL TIME ZONE NOT NULL)"),
exceptionMsg,
classOf[CodeGenException])

testExpectExceptionThrown(
testExpectedSqlException(
s"TIMESTAMPDIFF(MONTH, ${timestampTz("1970-01-01 00:00:00.123")}, DATE '1970-01-01')",
"",
String.format(exceptionTemplate,
"TIMESTAMPDIFF(INTERVAL MONTH NOT NULL, DATE NOT NULL," +
" TIMESTAMP(3) WITH LOCAL TIME ZONE NOT NULL)"),
exceptionMsg,
classOf[CodeGenException])

testExpectExceptionThrown(
testExpectedSqlException(
s"TIMESTAMPDIFF(MONTH, ${timestampTz("1970-01-01 00:00:00.123")}," +
s" TIMESTAMP '1970-01-01 00:00:00.123')",
"",
String.format(exceptionTemplate,
"TIMESTAMPDIFF(INTERVAL MONTH NOT NULL, TIMESTAMP(3) NOT NULL," +
" TIMESTAMP(3) WITH LOCAL TIME ZONE NOT NULL)"),
exceptionMsg,
classOf[CodeGenException])

testExpectExceptionThrown(
testExpectedSqlException(
s"TIMESTAMPDIFF(SECOND, ${timestampTz("1970-01-01 00:00:00.123")}," +
s" TIME '00:00:00.123')",
"",
String.format(exceptionTemplate,
"TIMESTAMPDIFF(INTERVAL SECOND(3) NOT NULL, TIME(0) NOT NULL," +
" TIMESTAMP(3) WITH LOCAL TIME ZONE NOT NULL)"),
exceptionMsg,
classOf[CodeGenException])

// invalid operand type
testExpectedSqlException(
s"TIMESTAMPDIFF(SECOND, ${timestampTz("1970-01-01 00:00:00.123")}, 'test_string_type')",
"Cannot apply 'TIMESTAMPDIFF' to arguments of type" +
" 'TIMESTAMPDIFF(<SYMBOL>, <TIMESTAMP_WITH_LOCAL_TIME_ZONE(3)>, <CHAR(16)>)'." +
" Supported form(s): 'TIMESTAMPDIFF(<ANY>, <DATETIME>, <DATETIME>)'")
}

// ----------------------------------------------------------------------------------------------
Expand Down

0 comments on commit b632dd2

Please sign in to comment.