This is an automated email from the ASF dual-hosted git repository. FrankChen021 pushed a commit to branch codex/fix-invalid-timestamp-constant in repository https://gitbox.apache.org/repos/asf/druid.git
commit 077a3d030f5ac268af876c2023bf688f1724d657 Author: Frank Chen <[email protected]> AuthorDate: Fri Sep 11 18:16:03 2026 +0800 test(sql): cover invalid timestamp expression forms --- .../sql/calcite/planner/DruidRexExecutor.java | 13 +++++-- .../org/apache/druid/sql/http/SqlResourceTest.java | 40 ++++++++++++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidRexExecutor.java b/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidRexExecutor.java index 7c14c98ac67..378a89f25b8 100644 --- a/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidRexExecutor.java +++ b/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidRexExecutor.java @@ -118,7 +118,10 @@ public class DruidRexExecutor implements RexExecutor // There can be implicit casts of VARCHAR to TIMESTAMP where the VARCHAR is an invalid timestamp, but the // TIMESTAMP type is not nullable. In this case it's best to throw an error, since it likely means the // user's SQL query contains an invalid literal. - throw InvalidSqlInput.exception("Invalid TIMESTAMP value [%s]", getTimestampValue(constExp)); + throw InvalidSqlInput.exception( + "Invalid TIMESTAMP value [%s]", + getInputValueOrExpression(constExp) + ); } } else { try { @@ -130,7 +133,11 @@ public class DruidRexExecutor implements RexExecutor ); } catch (IllegalArgumentException e) { - throw InvalidSqlInput.exception(e, "Invalid TIMESTAMP value [%s]", getTimestampValue(constExp)); + throw InvalidSqlInput.exception( + e, + "Invalid TIMESTAMP value [%s]", + getInputValueOrExpression(constExp) + ); } } } else if (SqlTypeName.NUMERIC_TYPES.contains(sqlTypeName)) { @@ -229,7 +236,7 @@ public class DruidRexExecutor implements RexExecutor } } - private static String getTimestampValue(final RexNode constExp) + private static String getInputValueOrExpression(final RexNode constExp) { if (constExp.isA(SqlKind.CAST)) { final RexNode operand = ((RexCall) constExp).getOperands().get(0); diff --git a/sql/src/test/java/org/apache/druid/sql/http/SqlResourceTest.java b/sql/src/test/java/org/apache/druid/sql/http/SqlResourceTest.java index 668d3dcd792..0909be0671c 100644 --- a/sql/src/test/java/org/apache/druid/sql/http/SqlResourceTest.java +++ b/sql/src/test/java/org/apache/druid/sql/http/SqlResourceTest.java @@ -1619,6 +1619,46 @@ public class SqlResourceTest extends CalciteTestBase ); } + @Test + public void testInvalidTimestampExpressionWithoutCast() throws Exception + { + final ErrorResponse errorResponse = postSyncForException( + "SELECT MILLIS_TO_TIMESTAMP(253402300800000)", + Status.BAD_REQUEST.getStatusCode() + ); + + validateInvalidSqlError( + errorResponse, + "Invalid TIMESTAMP value [MILLIS_TO_TIMESTAMP(253402300800000:BIGINT)]" + ); + Assertions.assertTrue(lifecycleManager.getAll("id").isEmpty()); + stubServiceEmitter.verifyEmitted("sqlQuery/time", 1); + Assertions.assertEquals( + Status.BAD_REQUEST.getStatusCode(), + stubServiceEmitter.getMetricEvents("sqlQuery/time").get(0).toMap().get(DruidMetrics.STATUS_CODE) + ); + } + + @Test + public void testInvalidTimestampLiteralWithExplicitCast() throws Exception + { + final ErrorResponse errorResponse = postSyncForException( + "SELECT CAST('20260-09-11 00:00:00' AS TIMESTAMP)", + Status.BAD_REQUEST.getStatusCode() + ); + + validateInvalidSqlError( + errorResponse, + "Invalid TIMESTAMP value [20260-09-11 00:00:00]" + ); + Assertions.assertTrue(lifecycleManager.getAll("id").isEmpty()); + stubServiceEmitter.verifyEmitted("sqlQuery/time", 1); + Assertions.assertEquals( + Status.BAD_REQUEST.getStatusCode(), + stubServiceEmitter.getMetricEvents("sqlQuery/time").get(0).toMap().get(DruidMetrics.STATUS_CODE) + ); + } + @Test public void testResourceLimitExceeded() throws Exception { --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
