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;
     }
 

Reply via email to