diff --git a/babel/src/test/resources/sql/big-query.iq b/babel/src/test/resources/sql/big-query.iq index 0dce3ba5fdc..834bd65dd8d 100755 --- a/babel/src/test/resources/sql/big-query.iq +++ b/babel/src/test/resources/sql/big-query.iq @@ -2720,6 +2720,18 @@ SELECT TIMESTAMP(DATE "2008-12-25") AS timestamp_date; !ok +# This tests the no-op TIMESTAMP and DATETIME functions. +select TIMESTAMP(TIMESTAMP "2008-01-01 01:03:05") as ts, + DATETIME(DATETIME "2008-01-01 01:03:05") as dt; ++---------------------+---------------------+ +| ts | dt | ++---------------------+---------------------+ +| 2008-01-01 01:03:05 | 2008-01-01 01:03:05 | ++---------------------+---------------------+ +(1 row) + +!ok + # All these timestamps should be equal. # This tests the BQ timestamp literal string formatter # (optional 'T', optional leading zeros, optional offset with conversion). diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java index 4dd9a390fa0..680301cc472 100644 --- a/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java +++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java @@ -783,7 +783,9 @@ static RelDataType deriveTypeSplit(SqlOperatorBinding operatorBinding, // DATETIME(timestampLtz, timeZone) OperandTypes.sequence( "DATETIME(TIMESTAMP WITH LOCAL TIME ZONE, VARCHAR)", - OperandTypes.TIMESTAMP_LTZ, OperandTypes.CHARACTER)), + OperandTypes.TIMESTAMP_LTZ, OperandTypes.CHARACTER), + // DATETIME(timestamp) -- This is a no-op. + OperandTypes.TIMESTAMP_NTZ), SqlFunctionCategory.TIMEDATE); /** The "TIME" function. It has the following overloads: @@ -838,7 +840,9 @@ static RelDataType deriveTypeSplit(SqlOperatorBinding operatorBinding, OperandTypes.TIMESTAMP_NTZ, // TIMESTAMP(timestamp, timeZone) OperandTypes.sequence("TIMESTAMP(TIMESTAMP, VARCHAR)", - OperandTypes.TIMESTAMP_NTZ, OperandTypes.CHARACTER)), + OperandTypes.TIMESTAMP_NTZ, OperandTypes.CHARACTER), + // TIMESTAMP(timestampLtz) -- This is a no-op. + OperandTypes.TIMESTAMP_LTZ), SqlFunctionCategory.TIMEDATE); /** The "CURRENT_DATETIME([timezone])" function. */ diff --git a/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java b/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java index 6a43a487f70..9eacf4f5ec2 100644 --- a/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java +++ b/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java @@ -5099,4 +5099,24 @@ void checkUserDefinedOrderByOver(NullCollation nullCollation) { String sql = "SELECT CAST(CAST(? AS INTEGER) AS CHAR)"; sql(sql).ok(); } + + /** + * Test case for + * DATETIME and TIMESTAMP constructor + * functions that take single arguments with the same type as the function's return type. + * + *
The function counts as a no-op in this case.
+ */
+ @Test void testNoOpTimeDateFunctions() {
+ String sql = "SELECT TIMESTAMP(TIMESTAMP WITH LOCAL TIME ZONE '2023-12-21 12:34:56'), "
+ + "DATETIME(TIMESTAMP '2023-12-21 12:34:56') "
+ + "FROM emp";
+
+ fixture()
+ .withFactory(c ->
+ c.withOperatorTable(t ->
+ SqlValidatorTest.operatorTableFor(SqlLibrary.BIG_QUERY)))
+ .withSql(sql)
+ .ok();
+ }
}
diff --git a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
index bf246b3a0b2..adad333e559 100644
--- a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
@@ -4927,6 +4927,17 @@ LogicalProject(SKILL=[ROW($0)])
LogicalFilter(condition=[=($0, '')])
LogicalProject(TYPE=[$0.TYPE])
LogicalTableScan(table=[[CATALOG, SALES, DEPT_SINGLE]])
+]]>
+
+
+