This is an automated email from the ASF dual-hosted git repository.
jt2594838 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new 166883a1b2e Fix semantic error for unsupported table INSERT time
expressions (#18759)
166883a1b2e is described below
commit 166883a1b2ecaae85e73c90cec45abe4e4715136
Author: Hongzhi Gao <[email protected]>
AuthorDate: Wed Sep 30 10:05:41 2026 +0800
Fix semantic error for unsupported table INSERT time expressions (#18759)
* Fix semantic error for unsupported table INSERT time expressions
* Remove rejected insert time parameter integration test
---
.../relational/it/db/it/IoTDBInsertTableIT.java | 117 +++++++++++++++++++++
.../plan/relational/sql/parser/AstBuilder.java | 12 +--
2 files changed, 118 insertions(+), 11 deletions(-)
diff --git
a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertTableIT.java
b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertTableIT.java
index 802d388c08d..3abe7497130 100644
---
a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertTableIT.java
+++
b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertTableIT.java
@@ -74,6 +74,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -390,6 +391,122 @@ public class IoTDBInsertTableIT {
}
}
+ @Test
+ public void testInsertUnsupportedTimeExpressions() throws SQLException {
+ try (Connection connection = EnvFactory.getEnv().getTableConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute("USE test");
+ statement.execute(
+ "CREATE TABLE rejected_time_expression (device_id STRING TAG, value
INT64 FIELD)");
+ statement.execute(
+ "CREATE TABLE rejected_custom_time_expression "
+ + "(device_id STRING TAG, event_time TIMESTAMP TIME, value INT64
FIELD)");
+ String[] expressions = {"1735660800000 + 1000", "?", "1.5", "true",
"abs(1)"};
+ for (String expression : expressions) {
+ for (String columns : new String[] {" (time, device_id, value)", ""}) {
+ assertUnsupportedInsertExpression(
+ statement,
+ "INSERT INTO rejected_time_expression"
+ + columns
+ + " VALUES ("
+ + expression
+ + ", 'd1', 1)");
+ }
+ }
+ for (String sql :
+ new String[] {
+ "INSERT INTO rejected_time_expression (device_id, value, time)
VALUES ('d1', 1, ?)",
+ "INSERT INTO rejected_custom_time_expression (device_id,
event_time, value) "
+ + "VALUES ('d1', ?, 1)",
+ "INSERT INTO rejected_custom_time_expression VALUES ('d1', ?, 1)",
+ "INSERT INTO rejected_time_expression (time, device_id, value) "
+ + "VALUES (1735660800000, 'd1', ?)",
+ "INSERT INTO rejected_time_expression (time, device_id, value) "
+ + "VALUES (1735660800000, 'valid', 1), (?, 'invalid', 2)",
+ "INSERT INTO rejected_time_expression "
+ + "VALUES (1735660800000, 'valid', 1), (?, 'invalid', 2)"
+ }) {
+ assertUnsupportedInsertExpression(statement, sql);
+ }
+ for (String sql :
+ new String[] {
+ "INSERT INTO rejected_time_expression (time, device_id, value)
VALUES (NULL, 'd1', 1)",
+ "INSERT INTO rejected_time_expression VALUES (NULL, 'd1', 1)"
+ }) {
+ SQLException exception = assertThrows(SQLException.class, () ->
statement.execute(sql));
+ assertEquals(sql, TSStatusCode.SEMANTIC_ERROR.getStatusCode(),
exception.getErrorCode());
+ assertTrue(
+ exception.getMessage(), exception.getMessage().contains("Timestamp
cannot be null"));
+ }
+ for (String table :
+ new String[] {"rejected_time_expression",
"rejected_custom_time_expression"}) {
+ try (ResultSet resultSet = statement.executeQuery("SELECT count(*)
FROM " + table)) {
+ assertTrue(resultSet.next());
+ assertEquals(0, resultSet.getLong(1));
+ assertFalse(resultSet.next());
+ }
+ }
+ }
+ }
+
+ private static void assertUnsupportedInsertExpression(Statement statement,
String sql) {
+ SQLException exception = assertThrows(SQLException.class, () ->
statement.execute(sql));
+ assertEquals(sql, TSStatusCode.SEMANTIC_ERROR.getStatusCode(),
exception.getErrorCode());
+ String message = exception.getMessage();
+ assertTrue(message, message.contains("Unsupported expression:"));
+ assertFalse(message, message.contains("ClassCastException"));
+ assertFalse(message, message.contains("cannot be cast"));
+ assertFalse(message, message.contains("org.apache.iotdb"));
+ }
+
+ @Test
+ public void testInsertSupportedTimeValues() throws SQLException {
+ try (Connection connection = EnvFactory.getEnv().getTableConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute("USE test");
+ statement.execute(
+ "CREATE TABLE supported_time_expression (device_id STRING TAG, value
INT64 FIELD)");
+ String[] expressions = {
+ "1735660800000", "'2025-01-01T00:00:00+08:00'", "NOW()", "NOW() + 1d",
"NOW() - 1d"
+ };
+ for (boolean explicitColumns : new boolean[] {true, false}) {
+ for (int i = 0; i < expressions.length; i++) {
+ String deviceId = "d" + explicitColumns + i;
+ long before = System.currentTimeMillis();
+ statement.execute(
+ "INSERT INTO supported_time_expression"
+ + (explicitColumns ? " (time, device_id, value)" : "")
+ + " VALUES ("
+ + expressions[i]
+ + ", '"
+ + deviceId
+ + "', "
+ + i
+ + ")");
+ long after = System.currentTimeMillis();
+ try (ResultSet resultSet =
+ statement.executeQuery(
+ "SELECT time, value FROM supported_time_expression WHERE
device_id = '"
+ + deviceId
+ + "'")) {
+ assertTrue(resultSet.next());
+ long timestamp = resultSet.getLong(1);
+ if (i < 2) {
+ assertEquals(1735660800000L, timestamp);
+ } else {
+ long offset = i == 3 ? 86400000L : i == 4 ? -86400000L : 0;
+ // Allow clock skew between the test client and cluster nodes.
+ assertTrue(timestamp >= before + offset - 10000);
+ assertTrue(timestamp <= after + offset + 10000);
+ }
+ assertEquals(i, resultSet.getLong(2));
+ assertFalse(resultSet.next());
+ }
+ }
+ }
+ }
+ }
+
@Test
public void testInsertNaN() throws SQLException {
try (Connection connection =
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
index 62321675d2a..bde6f72cf80 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
@@ -1037,17 +1037,7 @@ public class AstBuilder extends
RelationalSqlBaseVisitor<Node> {
}
Expression timeExpression = expressions.get(timeColumnIndex);
- if (timeExpression instanceof LongLiteral) {
- timestamp = ((LongLiteral) timeExpression).getParsedValue();
- } else if (timeExpression instanceof NullLiteral) {
- throw new
SemanticException(DataNodeQueryMessages.TIMESTAMP_CANNOT_BE_NULL);
- } else {
- timestamp =
- parseDateTimeFormat(
- ((StringLiteral) timeExpression).getValue(),
- CommonDateTimeUtils.currentTime(),
- zoneId);
- }
+ timestamp = AstUtil.expressionToTimestamp(timeExpression, zoneId);
nonTimeColCnt = expressions.size() - 1;
}