Skip to content

Commit

Permalink
[FLINK-21984][table] Change precision argument from optional to requi…
Browse files Browse the repository at this point in the history
…red in TO_TIMESTAMP_LTZ(numeric, precision)

This closes apache#15379.
  • Loading branch information
leonardBang committed Mar 27, 2021
1 parent 0736500 commit 1af31a5
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 107 deletions.
6 changes: 3 additions & 3 deletions docs/data/sql_functions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -478,9 +478,9 @@ temporal:
description: 'Converts date time string string1 in format string2 (by default: yyyy-MM-dd HH:mm:ss if not specified) to Unix timestamp (in seconds), using the specified timezone in table config.'
- sql: TO_DATE(string1[, string2])
description: Converts a date string string1 with format string2 (by default 'yyyy-MM-dd') to a date.
- sql: TO_TIMESTAMP_LTZ(numeric[, precision])
table: toTimestampLtz(NUMERIC[, PRECISION])
description: "Converts a epoch seconds or epoch milliseconds to a TIMESTAMP_LTZ, the valid precision is 0 or 3, the 0 is default value which means TO_TIMESTAMP_LTZ(epochSeconds, 0), the 3 represents TO_TIMESTAMP_LTZ(epochMilliseconds, 3)."
- sql: TO_TIMESTAMP_LTZ(numeric, precision)
table: toTimestampLtz(NUMERIC, PRECISION)
description: "Converts a epoch seconds or epoch milliseconds to a TIMESTAMP_LTZ, the valid precision is 0 or 3, the 0 represents TO_TIMESTAMP_LTZ(epochSeconds, 0), the 3 represents TO_TIMESTAMP_LTZ(epochMilliseconds, 3)."
- sql: TO_TIMESTAMP(string1[, string2])
description: "Converts date time string string1 with format string2 (by default: 'yyyy-MM-dd HH:mm:ss') under the session time zone (specified by TableConfig) to a timestamp."

Expand Down
2 changes: 1 addition & 1 deletion flink-python/pyflink/table/tests/test_expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ def test_expressions(self):
self.assertEqual('currentTimestamp()', str(current_timestamp()))
self.assertEqual('localTime()', str(local_time()))
self.assertEqual('localTimestamp()', str(local_timestamp()))
self.assertEquals('toTimestampLtz(123, 1)', str(to_timestamp_ltz(123, 1)))
self.assertEquals('toTimestampLtz(123, 0)', str(to_timestamp_ltz(123, 0)))
self.assertEqual("temporalOverlaps(cast('2:55:00', TIME(0)), 3600000, "
"cast('3:30:00', TIME(0)), 7200000)",
str(temporal_overlaps(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -461,13 +461,6 @@ trait ImplicitExpressionConversions {
Expressions.localTimestamp()
}

/**
* Converts a numeric type epoch seconds to [[DataTypes#TIMESTAMP_LTZ]].
*/
def toTimestampLtz(numericEpochTime: Expression): Expression = {
Expressions.toTimestampLtz(numericEpochTime, lit(0))
}

/**
* Converts a numeric type epoch time to [[DataTypes#TIMESTAMP_LTZ]].
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -754,9 +754,7 @@ public boolean isDeterministic() {
ReturnTypes.explicit(SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE, 3),
SqlTypeTransforms.FORCE_NULLABLE),
null,
OperandTypes.or(
OperandTypes.family(SqlTypeFamily.NUMERIC),
OperandTypes.family(SqlTypeFamily.NUMERIC, SqlTypeFamily.INTEGER)),
OperandTypes.family(SqlTypeFamily.NUMERIC, SqlTypeFamily.INTEGER),
SqlFunctionCategory.TIMEDATE);

public static final SqlFunction TO_DATE =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -347,31 +347,16 @@ object BuiltInMethods {
"toTimestamp",
classOf[DecimalData])

val LONG_TO_TIMESTAMP_LTZ = Types.lookupMethod(
classOf[SqlDateTimeUtils],
"toTimestampData",
classOf[Long])

val LONG_TO_TIMESTAMP_LTZ_WITH_PRECISION = Types.lookupMethod(
classOf[SqlDateTimeUtils],
"toTimestampData",
classOf[Long], classOf[Int])

val DOUBLE_TO_TIMESTAMP_LTZ = Types.lookupMethod(
classOf[SqlDateTimeUtils],
"toTimestampData",
classOf[Double])

val DOUBLE_TO_TIMESTAMP_LTZ_WITH_PRECISION = Types.lookupMethod(
classOf[SqlDateTimeUtils],
"toTimestampData",
classOf[Double], classOf[Int])

val DECIMAL_TO_TIMESTAMP_LTZ = Types.lookupMethod(
classOf[SqlDateTimeUtils],
"toTimestampData",
classOf[DecimalData])

val DECIMAL_TO_TIMESTAMP_LTZ_WITH_PRECISION = Types.lookupMethod(
classOf[SqlDateTimeUtils],
"toTimestampData",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -702,31 +702,18 @@ class FunctionGenerator private(config: TableConfig) {

INTEGRAL_TYPES foreach (
dt => {
addSqlFunctionMethod(
TO_TIMESTAMP_LTZ,
Seq(dt),
BuiltInMethods.LONG_TO_TIMESTAMP_LTZ)
addSqlFunctionMethod(
TO_TIMESTAMP_LTZ,
Seq(dt, INTEGER),
BuiltInMethods.LONG_TO_TIMESTAMP_LTZ_WITH_PRECISION)})

FRACTIONAL_TYPES foreach (
dt => {
addSqlFunctionMethod(
TO_TIMESTAMP_LTZ,
Seq(dt),
BuiltInMethods.DOUBLE_TO_TIMESTAMP_LTZ)
addSqlFunctionMethod(
TO_TIMESTAMP_LTZ,
Seq(dt, INTEGER),
BuiltInMethods.DOUBLE_TO_TIMESTAMP_LTZ_WITH_PRECISION)})

addSqlFunctionMethod(
TO_TIMESTAMP_LTZ,
Seq(DECIMAL),
BuiltInMethods.DECIMAL_TO_TIMESTAMP_LTZ)

addSqlFunctionMethod(
TO_TIMESTAMP_LTZ,
Seq(DECIMAL, INTEGER),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ case class ToTimestampLtz(
.assertNumericExpr(precision.resultType, "toTimestampLtz").isFailure) {
return ValidationFailure(
s"$this requires numeric type for the second input, " +
s"but the actual type '${numericEpochTime.resultType}'.")
s"but the actual type '${precision.resultType}'.")
}
ValidationSuccess
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1030,8 +1030,8 @@ class TemporalTypesTest extends ExpressionTestBase {

// test null value input
testAllApis(
toTimestampLtz(nullOf(DataTypes.BIGINT())),
"TO_TIMESTAMP_LTZ(cast(NULL as BIGINT))",
toTimestampLtz(nullOf(DataTypes.BIGINT()), 0),
"TO_TIMESTAMP_LTZ(cast(NULL as BIGINT), 0)",
nullable)
}

Expand Down Expand Up @@ -1329,42 +1329,42 @@ class TemporalTypesTest extends ExpressionTestBase {

// INT -> TIMESTAMP_LTZ
testAllApis(
toTimestampLtz(100),
"TO_TIMESTAMP_LTZ(100)",
toTimestampLtz(100, 0),
"TO_TIMESTAMP_LTZ(100, 0)",
"1970-01-01 08:01:40.000")

// TINYINT -> TIMESTAMP_LTZ
testAllApis(
toTimestampLtz(100.cast(DataTypes.TINYINT())),
"TO_TIMESTAMP_LTZ(CAST(100 AS TINYINT))",
toTimestampLtz(100.cast(DataTypes.TINYINT()), 0),
"TO_TIMESTAMP_LTZ(CAST(100 AS TINYINT), 0)",
"1970-01-01 08:01:40.000")

// BIGINT -> TIMESTAMP_LTZ
testAllApis(
toTimestampLtz(100.cast(DataTypes.BIGINT())),
"TO_TIMESTAMP_LTZ(CAST(100 AS BIGINT))",
toTimestampLtz(100.cast(DataTypes.BIGINT()), 0),
"TO_TIMESTAMP_LTZ(CAST(100 AS BIGINT), 0)",
"1970-01-01 08:01:40.000")

// FLOAT -> TIMESTAMP_LTZ
testAllApis(
toTimestampLtz(100.01.cast(DataTypes.FLOAT())),
"TO_TIMESTAMP_LTZ(CAST(100.01 AS FLOAT))",
toTimestampLtz(100.01.cast(DataTypes.FLOAT()), 0),
"TO_TIMESTAMP_LTZ(CAST(100.01 AS FLOAT), 0)",
"1970-01-01 08:01:40.010")

// DOUBLE -> TIMESTAMP_LTZ
testAllApis(
toTimestampLtz(100.123.cast(DataTypes.DOUBLE())),
"TO_TIMESTAMP_LTZ(CAST(100.123 AS DOUBLE))",
toTimestampLtz(100.123.cast(DataTypes.DOUBLE()), 0),
"TO_TIMESTAMP_LTZ(CAST(100.123 AS DOUBLE), 0)",
"1970-01-01 08:01:40.123")

// DECIMAL -> TIMESTAMP_LTZ
testAllApis(
toTimestampLtz(100.cast(DataTypes.DECIMAL(38, 18))),
toTimestampLtz(100.cast(DataTypes.DECIMAL(38, 18)), 0),
"TO_TIMESTAMP_LTZ(100, 0)",
"1970-01-01 08:01:40.000")
testAllApis(
toTimestampLtz(-100.cast(DataTypes.DECIMAL(38, 18))),
"TO_TIMESTAMP_LTZ(-100)",
toTimestampLtz(-100.cast(DataTypes.DECIMAL(38, 18)), 0),
"TO_TIMESTAMP_LTZ(-100, 0)",
"1970-01-01 07:58:20.000")

// keep scale
Expand All @@ -1383,8 +1383,8 @@ class TemporalTypesTest extends ExpressionTestBase {
def testToTimestampLtzUTC(): Unit = {
config.setLocalTimeZone(ZoneId.of("UTC"))
testAllApis(
toTimestampLtz(100),
"TO_TIMESTAMP_LTZ(100)",
toTimestampLtz(100, 0),
"TO_TIMESTAMP_LTZ(100, 0)",
"1970-01-01 00:01:40.000")

testAllApis(
Expand All @@ -1398,8 +1398,8 @@ class TemporalTypesTest extends ExpressionTestBase {
"1970-01-01 00:00:01.234")

testAllApis(
toTimestampLtz(-100),
"TO_TIMESTAMP_LTZ(-100)",
toTimestampLtz(-100, 0),
"TO_TIMESTAMP_LTZ(-100, 0)",
"1969-12-31 23:58:20.000")
}

Expand All @@ -1409,62 +1409,62 @@ class TemporalTypesTest extends ExpressionTestBase {

// INT
testAllApis(
toTimestampLtz(JInt.MIN_VALUE.cast(DataTypes.INT())),
s"TO_TIMESTAMP_LTZ(CAST(${JInt.MIN_VALUE} AS INTEGER))",
toTimestampLtz(JInt.MIN_VALUE.cast(DataTypes.INT()), 0),
s"TO_TIMESTAMP_LTZ(CAST(${JInt.MIN_VALUE} AS INTEGER), 0)",
"1901-12-13 20:45:52.000")
testAllApis(
toTimestampLtz(JInt.MAX_VALUE.cast(DataTypes.INT())),
s"TO_TIMESTAMP_LTZ(CAST(${JInt.MAX_VALUE} AS INTEGER))",
toTimestampLtz(JInt.MAX_VALUE.cast(DataTypes.INT()), 0),
s"TO_TIMESTAMP_LTZ(CAST(${JInt.MAX_VALUE} AS INTEGER), 0)",
"2038-01-19 03:14:07.000")

// TINYINT
testAllApis(
toTimestampLtz(-128.cast(DataTypes.TINYINT())),
s"TO_TIMESTAMP_LTZ(CAST(-128 AS TINYINT))",
toTimestampLtz(-128.cast(DataTypes.TINYINT()), 0),
s"TO_TIMESTAMP_LTZ(CAST(-128 AS TINYINT), 0)",
"1969-12-31 23:57:52.000")
testAllApis(
toTimestampLtz(127.cast(DataTypes.TINYINT())),
s"TO_TIMESTAMP_LTZ(CAST(127 AS TINYINT))",
toTimestampLtz(127.cast(DataTypes.TINYINT()), 0),
s"TO_TIMESTAMP_LTZ(CAST(127 AS TINYINT), 0)",
"1970-01-01 00:02:07.000")

// BIGINT
testAllApis(
toTimestampLtz(JLong.MIN_VALUE.cast(DataTypes.BIGINT())),
s"TO_TIMESTAMP_LTZ(CAST(${JLong.MIN_VALUE} AS BIGINT))",
toTimestampLtz(JLong.MIN_VALUE.cast(DataTypes.BIGINT()), 0),
s"TO_TIMESTAMP_LTZ(CAST(${JLong.MIN_VALUE} AS BIGINT), 0)",
"null")
testAllApis(
toTimestampLtz(JLong.MAX_VALUE.cast(DataTypes.BIGINT())),
s"TO_TIMESTAMP_LTZ(CAST(${JLong.MAX_VALUE} AS BIGINT))",
toTimestampLtz(JLong.MAX_VALUE.cast(DataTypes.BIGINT()), 0),
s"TO_TIMESTAMP_LTZ(CAST(${JLong.MAX_VALUE} AS BIGINT), 0)",
"null")

// FLOAT
testAllApis(
toTimestampLtz((-JFloat.MAX_VALUE).cast(DataTypes.FLOAT())),
s"TO_TIMESTAMP_LTZ(CAST(-${JFloat.MAX_VALUE} AS FLOAT))",
toTimestampLtz((-JFloat.MAX_VALUE).cast(DataTypes.FLOAT()), 0),
s"TO_TIMESTAMP_LTZ(CAST(-${JFloat.MAX_VALUE} AS FLOAT), 0)",
"null")
testAllApis(
toTimestampLtz(JFloat.MAX_VALUE.cast(DataTypes.FLOAT())),
s"TO_TIMESTAMP_LTZ(CAST(${JFloat.MAX_VALUE} AS FLOAT))",
toTimestampLtz(JFloat.MAX_VALUE.cast(DataTypes.FLOAT()), 0),
s"TO_TIMESTAMP_LTZ(CAST(${JFloat.MAX_VALUE} AS FLOAT), 0)",
"null")

// DOUBLE
testAllApis(
toTimestampLtz((-JDouble.MAX_VALUE).cast(DataTypes.DOUBLE())),
s"TO_TIMESTAMP_LTZ(CAST(-${JDouble.MAX_VALUE} AS DOUBLE))",
toTimestampLtz((-JDouble.MAX_VALUE).cast(DataTypes.DOUBLE()), 0),
s"TO_TIMESTAMP_LTZ(CAST(-${JDouble.MAX_VALUE} AS DOUBLE), 0)",
"null")
testAllApis(
toTimestampLtz(JDouble.MAX_VALUE.cast(DataTypes.DOUBLE())),
s"TO_TIMESTAMP_LTZ(CAST(${JDouble.MAX_VALUE} AS DOUBLE))",
toTimestampLtz(JDouble.MAX_VALUE.cast(DataTypes.DOUBLE()), 0),
s"TO_TIMESTAMP_LTZ(CAST(${JDouble.MAX_VALUE} AS DOUBLE), 0)",
"null")

// DECIMAL
testAllApis(
toTimestampLtz((-JDouble.MAX_VALUE).cast(DataTypes.DECIMAL(38, 18))),
s"TO_TIMESTAMP_LTZ(-${JDouble.MAX_VALUE})",
toTimestampLtz((-JDouble.MAX_VALUE).cast(DataTypes.DECIMAL(38, 18)), 0),
s"TO_TIMESTAMP_LTZ(-${JDouble.MAX_VALUE}, 0)",
"null")
testAllApis(
toTimestampLtz(JDouble.MAX_VALUE.cast(DataTypes.DECIMAL(38, 18))),
s"TO_TIMESTAMP_LTZ(${JDouble.MAX_VALUE})",
toTimestampLtz(JDouble.MAX_VALUE.cast(DataTypes.DECIMAL(38, 18)), 0),
s"TO_TIMESTAMP_LTZ(${JDouble.MAX_VALUE}, 0)",
"null")

// test valid min/max epoch mills
Expand All @@ -1491,6 +1491,11 @@ class TemporalTypesTest extends ExpressionTestBase {
s"TO_TIMESTAMP_LTZ(253402300800000, 3)",
"null")

// test invalid number of arguments
testExpectedSqlException(
"TO_TIMESTAMP_LTZ(123)",
"Invalid number of arguments to function 'TO_TIMESTAMP_LTZ'. Was expecting 2 arguments")

// invalid precision
testExpectedAllApisException(
toTimestampLtz(12, 1),
Expand All @@ -1509,26 +1514,27 @@ class TemporalTypesTest extends ExpressionTestBase {

// invalid type for the first input
testExpectedSqlException(
"TO_TIMESTAMP_LTZ('test_string_type')",
"Cannot apply 'TO_TIMESTAMP_LTZ' to arguments of type 'TO_TIMESTAMP_LTZ(<CHAR(16)>)'." +
" Supported form(s): 'TO_TIMESTAMP_LTZ(<NUMERIC>)'" +
"\n'TO_TIMESTAMP_LTZ(<NUMERIC>, <INTEGER>)'",
"TO_TIMESTAMP_LTZ('test_string_type', 0)",
"Cannot apply 'TO_TIMESTAMP_LTZ' to arguments of type" +
" 'TO_TIMESTAMP_LTZ(<CHAR(16)>, <INTEGER>)'. Supported form(s):" +
" 'TO_TIMESTAMP_LTZ(<NUMERIC>, <INTEGER>)'",
classOf[ValidationException])
testExpectedTableApiException(
toTimestampLtz("test_string_type"),
toTimestampLtz("test_string_type", 0),
"toTimestampLtz(test_string_type, 0) requires numeric type for the first input," +
" but the actual type 'String'.")

// invalid type for the second input
testExpectedSqlException(
"TO_TIMESTAMP_LTZ(123, 'test_string_type')",
"Cannot apply 'TO_TIMESTAMP_LTZ' to arguments of type " +
"'TO_TIMESTAMP_LTZ(<INTEGER>, <CHAR(16)>)'. Supported form(s):" +
" 'TO_TIMESTAMP_LTZ(<NUMERIC>)'\n'TO_TIMESTAMP_LTZ(<NUMERIC>, <INTEGER>)'")
"Cannot apply 'TO_TIMESTAMP_LTZ' to arguments of type" +
" 'TO_TIMESTAMP_LTZ(<INTEGER>, <CHAR(16)>)'. Supported form(s):" +
" 'TO_TIMESTAMP_LTZ(<NUMERIC>, <INTEGER>)'")

testExpectedTableApiException(
toTimestampLtz(123, "test_string_type"),
"toTimestampLtz(123, test_string_type) requires numeric type for the second input," +
" but the actual type 'Integer'.")
" but the actual type 'String'.")
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,10 +244,6 @@ public static long toTimestamp(DecimalData v) {
// --------------------------------------------------------------------------------------------
// TO_TIMESTAMP_LTZ(numeric, precision) function supports precision 0 or 3.
// --------------------------------------------------------------------------------------------
public static TimestampData toTimestampData(long v) {
return toTimestampData(v, 0);
}

public static TimestampData toTimestampData(long v, int precision) {
switch (precision) {
case 0:
Expand All @@ -268,10 +264,6 @@ public static TimestampData toTimestampData(long v, int precision) {
}
}

public static TimestampData toTimestampData(double v) {
return toTimestampData(v, 0);
}

public static TimestampData toTimestampData(double v, int precision) {
switch (precision) {
case 0:
Expand All @@ -292,10 +284,6 @@ public static TimestampData toTimestampData(double v, int precision) {
}
}

public static TimestampData toTimestampData(DecimalData v) {
return toTimestampData(v, 0);
}

public static TimestampData toTimestampData(DecimalData v, int precision) {
long epochMills;
switch (precision) {
Expand Down

0 comments on commit 1af31a5

Please sign in to comment.