You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flink.apache.org by di...@apache.org on 2022/10/08 07:43:46 UTC
[flink] branch master updated: [FLINK-29354][table] Support TO_DATE and TO_TIMESTAMP built-in function in the Table API
This is an automated email from the ASF dual-hosted git repository.
dianfu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/flink.git
The following commit(s) were added to refs/heads/master by this push:
new 946949eda11 [FLINK-29354][table] Support TO_DATE and TO_TIMESTAMP built-in function in the Table API
946949eda11 is described below
commit 946949eda11184c02f56272a2fb24200b6badb29
Author: zhangjingcun <cu...@163.com>
AuthorDate: Tue Oct 4 17:58:32 2022 +0800
[FLINK-29354][table] Support TO_DATE and TO_TIMESTAMP built-in function in the Table API
This closes #20948.
---
docs/data/sql_functions.yml | 2 +
docs/data/sql_functions_zh.yml | 2 +
flink-python/pyflink/table/expressions.py | 29 ++++++++++++++
.../pyflink/table/tests/test_expression.py | 9 ++++-
.../org/apache/flink/table/api/Expressions.java | 44 ++++++++++++++++++++++
.../table/api/ImplicitExpressionConversions.scala | 30 +++++++++++++++
.../functions/BuiltInFunctionDefinitions.java | 26 +++++++++++++
.../expressions/converter/DirectConvertRule.java | 4 ++
.../planner/expressions/TemporalTypesTest.scala | 11 +++++-
9 files changed, 155 insertions(+), 2 deletions(-)
diff --git a/docs/data/sql_functions.yml b/docs/data/sql_functions.yml
index e91b3ef5cd2..a2b467f54e1 100644
--- a/docs/data/sql_functions.yml
+++ b/docs/data/sql_functions.yml
@@ -495,11 +495,13 @@ temporal:
- sql: UNIX_TIMESTAMP(string1[, string2])
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])
+ table: toDate(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 represents TO_TIMESTAMP_LTZ(epochSeconds, 0), the 3 represents TO_TIMESTAMP_LTZ(epochMilliseconds, 3)."
- sql: TO_TIMESTAMP(string1[, string2])
+ table: toTimestamp(STRING1[, STRING2])
description: "Converts date time string string1 with format string2 (by default: 'yyyy-MM-dd HH:mm:ss') under the 'UTC+0' time zone to a timestamp."
- sql: CURRENT_WATERMARK(rowtime)
description: |
diff --git a/docs/data/sql_functions_zh.yml b/docs/data/sql_functions_zh.yml
index c9b825e8914..a0667c4604b 100644
--- a/docs/data/sql_functions_zh.yml
+++ b/docs/data/sql_functions_zh.yml
@@ -623,6 +623,7 @@ temporal:
使用表配置中指定的时区将格式为 string2 的日期时间字符串 string1(如果未指定默认情况下:yyyy-MM-dd HH:mm:ss)
转换为 Unix 时间戳(以秒为单位)。
- sql: TO_DATE(string1[, string2])
+ table: toDate(STRING1[, STRING2])
description: 将格式为 string2(默认为 'yyyy-MM-dd')的字符串 string1 转换为日期。
- sql: TO_TIMESTAMP_LTZ(numeric, precision)
table: toTimestampLtz(numeric, PRECISION)
@@ -630,6 +631,7 @@ temporal:
将纪元秒或纪元毫秒转换为 TIMESTAMP_LTZ,有效精度为 0 或 3,0 代表 `TO_TIMESTAMP_LTZ(epochSeconds, 0)`,
3 代表` TO_TIMESTAMP_LTZ(epochMilliseconds, 3)`。
- sql: TO_TIMESTAMP(string1[, string2])
+ table: toTimestamp(STRING1[, STRING2])
description: 将 'UTC+0' 时区下格式为 string2(默认为:'yyyy-MM-dd HH:mm:ss')的字符串 string1 转换为时间戳。
- sql: CURRENT_WATERMARK(rowtime)
description: |
diff --git a/flink-python/pyflink/table/expressions.py b/flink-python/pyflink/table/expressions.py
index 33114183746..70cac00d9c3 100644
--- a/flink-python/pyflink/table/expressions.py
+++ b/flink-python/pyflink/table/expressions.py
@@ -272,6 +272,35 @@ def local_timestamp() -> Expression:
return _leaf_op("localTimestamp")
+def to_date(date_str: str, format: str = None) -> Expression:
+ """
+ Converts the date string with the given format (by default 'yyyy-MM-dd') to a date.
+
+ :param date_str: The date string
+ :param format: The format of the string
+ :return: The date value with DATE type.
+ """
+ if format is None:
+ return _unary_op("toDate", date_str)
+ else:
+ return _binary_op("toDate", date_str, format)
+
+
+def to_timestamp(timestamp_str: str, format: str = None) -> Expression:
+ """
+ Converts the date time string with the given format (by default: 'yyyy-MM-dd HH:mm:ss')
+ under the 'UTC+0' time zone to a timestamp.
+
+ :param timestamp_str: The date time string
+ :param format: The format of the string
+ :return: The date value with TIMESTAMP type.
+ """
+ if format is None:
+ return _unary_op("toTimestamp", timestamp_str)
+ else:
+ return _binary_op("toTimestamp", timestamp_str, format)
+
+
def to_timestamp_ltz(numeric_epoch_time, precision) -> Expression:
"""
Converts a numeric type epoch time to TIMESTAMP_LTZ.
diff --git a/flink-python/pyflink/table/tests/test_expression.py b/flink-python/pyflink/table/tests/test_expression.py
index a2423c20111..ad10f528ac7 100644
--- a/flink-python/pyflink/table/tests/test_expression.py
+++ b/flink-python/pyflink/table/tests/test_expression.py
@@ -26,7 +26,7 @@ from pyflink.table.expressions import (col, lit, range_, and_, or_, current_date
timestamp_diff, array, row, map_, row_interval, pi, e,
rand, rand_integer, atan2, negative, concat, concat_ws, uuid,
null_of, log, if_then_else, with_columns, call,
- to_timestamp_ltz, from_unixtime)
+ to_timestamp_ltz, from_unixtime, to_date, to_timestamp)
from pyflink.testing.test_case_utils import PyFlinkTestCase
@@ -257,7 +257,14 @@ class PyFlinkBatchExpressionTests(PyFlinkTestCase):
self.assertEqual('currentTimestamp()', str(current_timestamp()))
self.assertEqual('localTime()', str(local_time()))
self.assertEqual('localTimestamp()', str(local_timestamp()))
+ self.assertEqual("toDate('2018-03-18')", str(to_date('2018-03-18')))
+ self.assertEqual("toDate('2018-03-18', 'yyyy-MM-dd')",
+ str(to_date('2018-03-18', 'yyyy-MM-dd')))
self.assertEqual('toTimestampLtz(123, 0)', str(to_timestamp_ltz(123, 0)))
+ self.assertEqual("toTimestamp('1970-01-01 08:01:40')",
+ str(to_timestamp('1970-01-01 08:01:40')))
+ self.assertEqual("toTimestamp('1970-01-01 08:01:40', 'yyyy-MM-dd HH:mm:ss')",
+ str(to_timestamp('1970-01-01 08:01:40', 'yyyy-MM-dd HH:mm:ss')))
self.assertEqual("temporalOverlaps(cast('2:55:00', TIME(0)), 3600000, "
"cast('3:30:00', TIME(0)), 7200000)",
str(temporal_overlaps(
diff --git a/flink-table/flink-table-api-java/src/main/java/org/apache/flink/table/api/Expressions.java b/flink-table/flink-table-api-java/src/main/java/org/apache/flink/table/api/Expressions.java
index 29d30858fda..fb523648ef8 100644
--- a/flink-table/flink-table-api-java/src/main/java/org/apache/flink/table/api/Expressions.java
+++ b/flink-table/flink-table-api-java/src/main/java/org/apache/flink/table/api/Expressions.java
@@ -303,6 +303,50 @@ public final class Expressions {
return apiCall(BuiltInFunctionDefinitions.LOCAL_TIMESTAMP);
}
+ /**
+ * Converts the given date string with format 'yyyy-MM-dd' to {@link DataTypes#DATE()}.
+ *
+ * @param dateStr The date string.
+ * @return The date value of {@link DataTypes#DATE()} type.
+ */
+ public static ApiExpression toDate(Object dateStr) {
+ return apiCall(BuiltInFunctionDefinitions.TO_DATE, dateStr);
+ }
+
+ /**
+ * Converts the date string with the specified format to {@link DataTypes#DATE()}.
+ *
+ * @param dateStr The date string.
+ * @param format The format of the string.
+ * @return The date value of {@link DataTypes#DATE()} type.
+ */
+ public static ApiExpression toDate(Object dateStr, Object format) {
+ return apiCall(BuiltInFunctionDefinitions.TO_DATE, dateStr, format);
+ }
+
+ /**
+ * Converts the given date time string with format 'yyyy-MM-dd HH:mm:ss' under the 'UTC+0' time
+ * zone to {@link DataTypes#TIMESTAMP()}.
+ *
+ * @param timestampStr The date time string.
+ * @return The timestamp value with {@link DataTypes#TIMESTAMP()} type.
+ */
+ public static ApiExpression toTimestamp(Object timestampStr) {
+ return apiCall(BuiltInFunctionDefinitions.TO_TIMESTAMP, timestampStr);
+ }
+
+ /**
+ * Converts the given time string with the specified format under the 'UTC+0' time zone to
+ * {@link DataTypes#TIMESTAMP()}.
+ *
+ * @param timestampStr The date time string.
+ * @param format The format of the string.
+ * @return The timestamp value with {@link DataTypes#TIMESTAMP()} type.
+ */
+ public static ApiExpression toTimestamp(Object timestampStr, Object format) {
+ return apiCall(BuiltInFunctionDefinitions.TO_TIMESTAMP, timestampStr, format);
+ }
+
/**
* Converts a numeric type epoch time to {@link DataTypes#TIMESTAMP_LTZ(int)}.
*
diff --git a/flink-table/flink-table-api-scala/src/main/scala/org/apache/flink/table/api/ImplicitExpressionConversions.scala b/flink-table/flink-table-api-scala/src/main/scala/org/apache/flink/table/api/ImplicitExpressionConversions.scala
index 90261590143..8638dc6cdda 100644
--- a/flink-table/flink-table-api-scala/src/main/scala/org/apache/flink/table/api/ImplicitExpressionConversions.scala
+++ b/flink-table/flink-table-api-scala/src/main/scala/org/apache/flink/table/api/ImplicitExpressionConversions.scala
@@ -481,6 +481,36 @@ trait ImplicitExpressionConversions {
Expressions.localTimestamp()
}
+ /**
+ * Converts the date string with format 'yyyy-MM-dd' to a date value of [[DataTypes.DATE]] type.
+ */
+ def toDate(dateStr: Expression): Expression = {
+ Expressions.toDate(dateStr)
+ }
+
+ /**
+ * Converts the date string with the specified format to a date value of [[DataTypes.DATE]] type.
+ */
+ def toDate(dateStr: Expression, format: Expression): Expression = {
+ Expressions.toDate(dateStr, format)
+ }
+
+ /**
+ * Converts the date time string with format 'yyyy-MM-dd HH:mm:ss' under the 'UTC+0' time zone
+ * to a timestamp value of [[DataTypes.TIMESTAMP]].
+ */
+ def toTimestamp(timestampStr: Expression): Expression = {
+ Expressions.toTimestamp(timestampStr)
+ }
+
+ /**
+ * Converts the date time string with the specified format under the 'UTC+0' time zone
+ * to a timestamp value of [[DataTypes.TIMESTAMP]].
+ */
+ def toTimestamp(timestampStr: Expression, format: Expression): Expression = {
+ Expressions.toTimestamp(timestampStr, format)
+ }
+
/**
* Converts a numeric type epoch time to [[DataTypes#TIMESTAMP_LTZ]].
*
diff --git a/flink-table/flink-table-common/src/main/java/org/apache/flink/table/functions/BuiltInFunctionDefinitions.java b/flink-table/flink-table-common/src/main/java/org/apache/flink/table/functions/BuiltInFunctionDefinitions.java
index 23b293a9c5f..875f4c0aaca 100644
--- a/flink-table/flink-table-common/src/main/java/org/apache/flink/table/functions/BuiltInFunctionDefinitions.java
+++ b/flink-table/flink-table-common/src/main/java/org/apache/flink/table/functions/BuiltInFunctionDefinitions.java
@@ -1548,6 +1548,19 @@ public final class BuiltInFunctionDefinitions {
.outputTypeStrategy(nullableIfArgs(explicit(STRING())))
.build();
+ public static final BuiltInFunctionDefinition TO_DATE =
+ BuiltInFunctionDefinition.newBuilder()
+ .name("toDate")
+ .kind(SCALAR)
+ .inputTypeStrategy(
+ or(
+ sequence(logical(LogicalTypeFamily.CHARACTER_STRING)),
+ sequence(
+ logical(LogicalTypeFamily.CHARACTER_STRING),
+ logical(LogicalTypeFamily.CHARACTER_STRING))))
+ .outputTypeStrategy(nullableIfArgs(explicit(DATE())))
+ .build();
+
public static final BuiltInFunctionDefinition TO_TIMESTAMP_LTZ =
BuiltInFunctionDefinition.newBuilder()
.name("toTimestampLtz")
@@ -1559,6 +1572,19 @@ public final class BuiltInFunctionDefinitions {
.outputTypeStrategy(SpecificTypeStrategies.TO_TIMESTAMP_LTZ)
.build();
+ public static final BuiltInFunctionDefinition TO_TIMESTAMP =
+ BuiltInFunctionDefinition.newBuilder()
+ .name("toTimestamp")
+ .kind(SCALAR)
+ .inputTypeStrategy(
+ or(
+ sequence(logical(LogicalTypeFamily.CHARACTER_STRING)),
+ sequence(
+ logical(LogicalTypeFamily.CHARACTER_STRING),
+ logical(LogicalTypeFamily.CHARACTER_STRING))))
+ .outputTypeStrategy(nullableIfArgs(explicit(TIMESTAMP(3))))
+ .build();
+
// --------------------------------------------------------------------------------------------
// Collection functions
// --------------------------------------------------------------------------------------------
diff --git a/flink-table/flink-table-planner/src/main/java/org/apache/flink/table/planner/expressions/converter/DirectConvertRule.java b/flink-table/flink-table-planner/src/main/java/org/apache/flink/table/planner/expressions/converter/DirectConvertRule.java
index 47aad8acb16..b293e642248 100644
--- a/flink-table/flink-table-planner/src/main/java/org/apache/flink/table/planner/expressions/converter/DirectConvertRule.java
+++ b/flink-table/flink-table-planner/src/main/java/org/apache/flink/table/planner/expressions/converter/DirectConvertRule.java
@@ -207,9 +207,13 @@ public class DirectConvertRule implements CallExpressionConvertRule {
BuiltInFunctionDefinitions.DATE_FORMAT, FlinkSqlOperatorTable.DATE_FORMAT);
DEFINITION_OPERATOR_MAP.put(
BuiltInFunctionDefinitions.FROM_UNIXTIME, FlinkSqlOperatorTable.FROM_UNIXTIME);
+ DEFINITION_OPERATOR_MAP.put(
+ BuiltInFunctionDefinitions.TO_DATE, FlinkSqlOperatorTable.TO_DATE);
DEFINITION_OPERATOR_MAP.put(
BuiltInFunctionDefinitions.TO_TIMESTAMP_LTZ,
FlinkSqlOperatorTable.TO_TIMESTAMP_LTZ);
+ DEFINITION_OPERATOR_MAP.put(
+ BuiltInFunctionDefinitions.TO_TIMESTAMP, FlinkSqlOperatorTable.TO_TIMESTAMP);
// catalog functions
DEFINITION_OPERATOR_MAP.put(
diff --git a/flink-table/flink-table-planner/src/test/scala/org/apache/flink/table/planner/expressions/TemporalTypesTest.scala b/flink-table/flink-table-planner/src/test/scala/org/apache/flink/table/planner/expressions/TemporalTypesTest.scala
index e9824afe835..ceeaf953e87 100644
--- a/flink-table/flink-table-planner/src/test/scala/org/apache/flink/table/planner/expressions/TemporalTypesTest.scala
+++ b/flink-table/flink-table-planner/src/test/scala/org/apache/flink/table/planner/expressions/TemporalTypesTest.scala
@@ -611,7 +611,16 @@ class TemporalTypesTest extends ExpressionTestBase {
testSqlApi("CAST('12:44:31' AS TIME)", "12:44:31")
testSqlApi("CAST('2018-03-18' AS DATE)", "2018-03-18")
testSqlApi("TIME '12:44:31'", "12:44:31")
- testSqlApi("TO_DATE('2018-03-18')", "2018-03-18")
+
+ testAllApis(toDate("2018-03-18", "yyyy-MM-dd"), "TO_DATE('2018-03-18')", "2018-03-18")
+ testAllApis(
+ toTimestamp("1970-01-01 08:01:40"),
+ "TO_TIMESTAMP('1970-01-01 08:01:40')",
+ "1970-01-01 08:01:40.000")
+ testAllApis(
+ toTimestamp("1970-01-01 08:01:40", "yyyy-MM-dd HH:mm:ss"),
+ "TO_TIMESTAMP('1970-01-01 08:01:40', 'yyyy-MM-dd HH:mm:ss')",
+ "1970-01-01 08:01:40.000")
// EXTRACT
// testSqlApi("TO_DATE(1521331200)", "2018-03-18")