This is an automated email from the ASF dual-hosted git repository. jiangtian pushed a commit to branch fix_null_timestamp in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 57fdff57ab3f5c537ba4699749ff8c4535e5906b Author: Tian Jiang <[email protected]> AuthorDate: Mon Mar 24 16:50:01 2025 +0800 fix insertion with null timestamp --- .../it/session/IoTDBSessionRelationalIT.java | 59 ++++++++++++++++++++++ .../plan/relational/sql/parser/AstBuilder.java | 10 +--- .../plan/relational/sql/util/AstUtil.java | 22 ++++++++ 3 files changed, 82 insertions(+), 9 deletions(-) diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/session/IoTDBSessionRelationalIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/session/IoTDBSessionRelationalIT.java index 543d48c9230..2a7508a2013 100644 --- a/integration-test/src/test/java/org/apache/iotdb/relational/it/session/IoTDBSessionRelationalIT.java +++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/session/IoTDBSessionRelationalIT.java @@ -232,6 +232,65 @@ public class IoTDBSessionRelationalIT { } } + @Test + public void insertAllNullSqlTest() throws IoTDBConnectionException, StatementExecutionException { + try (ITableSession session = EnvFactory.getEnv().getTableSessionConnection()) { + session.executeNonQueryStatement("USE \"db1\""); + session.executeNonQueryStatement( + "create table all_null(color string tag, device_id string tag,city string attribute)"); + try { + session.executeNonQueryStatement("insert into all_null values(null,null,null,null)"); + fail("No exception thrown"); + } catch (StatementExecutionException e) { + assertEquals("701: Timestamp cannot be null", e.getMessage()); + } + session.executeNonQueryStatement("drop table all_null"); + } + } + + @Test + public void insertWrongTimeSqlTest() + throws IoTDBConnectionException, StatementExecutionException { + try (ITableSession session = EnvFactory.getEnv().getTableSessionConnection()) { + session.executeNonQueryStatement("USE \"db1\""); + session.executeNonQueryStatement( + "create table wrong_time(color string tag, device_id string tag,city string attribute)"); + try { + session.executeNonQueryStatement("insert into wrong_time values('aa','bb','cc','dd')"); + fail("No exception thrown"); + } catch (StatementExecutionException e) { + assertEquals( + "701: Input time format aa error. Input like yyyy-MM-dd HH:mm:ss, yyyy-MM-ddTHH:mm:ss or refer to user document for more info.", + e.getMessage()); + } + try { + session.executeNonQueryStatement("insert into wrong_time values(1+1,'bb','cc','dd')"); + fail("No exception thrown"); + } catch (StatementExecutionException e) { + assertEquals( + "701: Unsupported expression: (1 + 1)", + e.getMessage()); + } + try { + session.executeNonQueryStatement("insert into wrong_time values(1.0,'bb','cc','dd')"); + fail("No exception thrown"); + } catch (StatementExecutionException e) { + assertEquals( + "701: Unsupported expression: 1E0", + e.getMessage()); + } + try { + session.executeNonQueryStatement("insert into wrong_time values(true,'bb','cc','dd')"); + fail("No exception thrown"); + } catch (StatementExecutionException e) { + assertEquals( + "701: Unsupported expression: true", + e.getMessage()); + } + session.executeNonQueryStatement("drop table wrong_time"); + } + } + @Test public void insertRelationalSqlTest() throws IoTDBConnectionException, StatementExecutionException { 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 cc40c2f1096..86ffbcec7d5 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 @@ -657,15 +657,7 @@ public class AstBuilder extends RelationalSqlBaseVisitor<Node> { Expression expression = expressions.get(i); if (columnSchema.getColumnCategory().equals(TIME)) { - if (expression instanceof LongLiteral) { - timestamp = ((LongLiteral) expression).getParsedValue(); - } else { - timestamp = - parseDateTimeFormat( - ((StringLiteral) expression).getValue(), - CommonDateTimeUtils.currentTime(), - zoneId); - } + timestamp = AstUtil.expressionToTimestamp(expression, zoneId); } else { Object value = AstUtil.expressionToTsValue(expression); nonTimeValues[nonTimeColumnIndex] = value; diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/util/AstUtil.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/util/AstUtil.java index c9854ea52b6..cb17a90c04f 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/util/AstUtil.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/util/AstUtil.java @@ -19,15 +19,20 @@ package org.apache.iotdb.db.queryengine.plan.relational.sql.util; +import org.apache.iotdb.commons.utils.CommonDateTimeUtils; import org.apache.iotdb.db.exception.sql.SemanticException; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Expression; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Identifier; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Literal; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.LongLiteral; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Node; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.NullLiteral; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.StringLiteral; import com.google.common.graph.SuccessorsFunction; import com.google.common.graph.Traverser; +import java.time.ZoneId; import java.util.List; import java.util.OptionalInt; import java.util.function.BiFunction; @@ -36,6 +41,7 @@ import java.util.stream.Stream; import static com.google.common.collect.Streams.stream; import static java.util.Objects.requireNonNull; +import static org.apache.iotdb.db.queryengine.plan.parser.ASTVisitor.parseDateTimeFormat; public final class AstUtil { @@ -110,5 +116,21 @@ public final class AstUtil { throw new SemanticException("Unsupported expression: " + expression); } + public static long expressionToTimestamp(Expression expression, ZoneId zoneId) { + long timestamp; + if (expression instanceof LongLiteral) { + timestamp = ((LongLiteral) expression).getParsedValue(); + } else if (expression instanceof NullLiteral) { + throw new SemanticException("Timestamp cannot be null"); + } else if (expression instanceof StringLiteral) { + timestamp = + parseDateTimeFormat( + ((StringLiteral) expression).getValue(), CommonDateTimeUtils.currentTime(), zoneId); + } else { + throw new SemanticException("Unsupported expression: " + expression); + } + return timestamp; + } + private AstUtil() {} }
