Skip to content
Open
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ public void testInsertUnsupportedTimeExpressions() throws SQLException {
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)"};
String[] expressions = {"?", "1.5", "true", "abs(1)"};
for (String expression : expressions) {
for (String columns : new String[] {" (time, device_id, value)", ""}) {
assertUnsupportedInsertExpression(
Expand Down Expand Up @@ -453,7 +453,10 @@ private static void assertUnsupportedInsertExpression(Statement statement, Strin
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:"));
assertTrue(
message,
message.contains("Unsupported expression:")
|| message.contains("Insert expression must be constant after constant folding:"));
assertFalse(message, message.contains("ClassCastException"));
assertFalse(message, message.contains("cannot be cast"));
assertFalse(message, message.contains("org.apache.iotdb"));
Expand All @@ -467,7 +470,12 @@ public void testInsertSupportedTimeValues() throws SQLException {
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"
"1735660800000",
"'2025-01-01T00:00:00+08:00'",
"1735660799000 + 1000",
"NOW()",
"NOW() + 1d",
"NOW() - 1d"
};
for (boolean explicitColumns : new boolean[] {true, false}) {
for (int i = 0; i < expressions.length; i++) {
Expand All @@ -491,10 +499,10 @@ public void testInsertSupportedTimeValues() throws SQLException {
+ "'")) {
assertTrue(resultSet.next());
long timestamp = resultSet.getLong(1);
if (i < 2) {
if (i < 3) {
assertEquals(1735660800000L, timestamp);
} else {
long offset = i == 3 ? 86400000L : i == 4 ? -86400000L : 0;
long offset = i == 4 ? 86400000L : i == 5 ? -86400000L : 0;
// Allow clock skew between the test client and cluster nodes.
assertTrue(timestamp >= before + offset - 10000);
assertTrue(timestamp <= after + offset + 10000);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,29 +260,36 @@ public void insertWrongTimeSqlTest()
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)");
"create table wrong_time(color string tag, device_id string tag,city string attribute,"
+ " value int32 field)");
try {
session.executeNonQueryStatement("insert into wrong_time values('aa','bb','cc','dd')");
session.executeNonQueryStatement("insert into wrong_time values('aa','bb','cc','dd',1)");
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());
session.executeNonQueryStatement("insert into wrong_time values(1+1,'bb','cc','dd',1)");
try (SessionDataSet dataSet =
session.executeQueryStatement("select * from wrong_time where time = 2")) {
assertTrue(dataSet.hasNext());
RowRecord rowRecord = dataSet.next();
assertEquals(2L, rowRecord.getFields().get(0).getLongV());
assertEquals("bb", rowRecord.getFields().get(1).getBinaryV().toString());
assertEquals("cc", rowRecord.getFields().get(2).getBinaryV().toString());
assertEquals("dd", rowRecord.getFields().get(3).getBinaryV().toString());
assertEquals(1, rowRecord.getFields().get(4).getIntV());
assertFalse(dataSet.hasNext());
}
try {
session.executeNonQueryStatement("insert into wrong_time values(1.0,'bb','cc','dd')");
session.executeNonQueryStatement("insert into wrong_time values(1.0,'bb','cc','dd',1)");
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')");
session.executeNonQueryStatement("insert into wrong_time values(true,'bb','cc','dd',1)");
fail("No exception thrown");
} catch (StatementExecutionException e) {
assertEquals("701: Unsupported expression: true", e.getMessage());
Expand Down Expand Up @@ -335,6 +342,14 @@ public void insertRelationalSqlTest()
row, "tag:" + row, "attr:" + row, row));
}

session.executeNonQueryStatement(
"INSERT INTO table1 (time, tag1, attr1, m1) "
+ "VALUES (if(true, 50, 0), if(true, 'tag:50', 'x'), "
+ "if(false, 'x', 'attr:50'), if(true, 50.0, 0.0))");
session.executeNonQueryStatement(
"INSERT INTO table1 VALUES (if(true, 51, 0), if(true, 'tag:51', 'x'), "
+ "if(true, 'attr:51', 'x'), if(false, 0, 51))");

SessionDataSet dataSet = session.executeQueryStatement("select * from table1 order by time");
int cnt = 0;
while (dataSet.hasNext()) {
Expand All @@ -345,7 +360,7 @@ public void insertRelationalSqlTest()
assertEquals(timestamp * 1.0, rowRecord.getFields().get(3).getDoubleV(), 0.0001);
cnt++;
}
assertEquals(50, cnt);
assertEquals(52, cnt);

// sql cannot create column
assertThrows(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3941,4 +3941,37 @@ private DataNodeQueryMessages() {}
public static final String EXCEPTION_ONLY_INMEMORYDEVICEENTRYDATASET_SUPPORTS_GET_INLINE_DEVICE_ENTRIES_07A52CAB =
"Only InMemoryDeviceEntryDataSet supports get inline device entries";


public static final String EXCEPTION_DATABASENAME_IS_NULL_A811DE1B =
"databaseName is null";

public static final String EXCEPTION_VALUES_IS_NULL_A580EDAA =
"values is null";

public static final String EXCEPTION_ZONEID_IS_NULL_7DAA5E2C =
"zoneId is null";

public static final String EXCEPTION_INSERT_TARGET_TABLE_DOES_NOT_EXIST_ARG_ARG_78F05787 =
"Insert target table does not exist: %s.%s";

public static final String EXCEPTION_EXPRESSIONS_AND_COLUMNS_DO_NOT_MATCH_EXPRESSIONS_SIZE_ARG_COLUMNS_SIZE_ARG_F933A8C1 =
"expressions and columns do not match, expressions size: %s, columns size: %s";

public static final String EXCEPTION_INSERT_EXPRESSION_MUST_BE_CONSTANT_AFTER_CONSTANT_FOLDING_ARG_FOLDED_TO_ARG_D9EE1433 =
"Insert expression must be constant after constant folding: %s (folded to %s)";

public static final String EXCEPTION_CANNOT_EVALUATE_INSERT_EXPRESSION_AS_A_CONSTANT_ARG_ARG_F478C134 =
"Cannot evaluate insert expression as a constant: %s. %s";

public static final String EXCEPTION_THE_ARG_IS_OUT_OF_RANGE_OF_INT_F8E58471 =
"The %s is out of range of int.";

public static final String EXCEPTION_THE_ARG_IS_OUT_OF_RANGE_OF_LONG_9B1C872A =
"The %s is out of range of long.";

public static final String EXCEPTION_INT_OVERFLOW_ARG_ARG_BB287017 =
"int overflow: %s / %s";

public static final String EXCEPTION_LONG_OVERFLOW_ARG_ARG_46CC95E2 =
"long overflow: %s / %s";
}
Original file line number Diff line number Diff line change
Expand Up @@ -4697,4 +4697,37 @@ private DataNodeQueryMessages() {}
public static final String EXCEPTION_ONLY_INMEMORYDEVICEENTRYDATASET_SUPPORTS_GET_INLINE_DEVICE_ENTRIES_07A52CAB =
"只有 InMemoryDeviceEntryDataSet 支持获取内存中的设备条目";


public static final String EXCEPTION_DATABASENAME_IS_NULL_A811DE1B =
"databaseName 为空";

public static final String EXCEPTION_VALUES_IS_NULL_A580EDAA =
"values 为空";

public static final String EXCEPTION_ZONEID_IS_NULL_7DAA5E2C =
"zoneId 为空";

public static final String EXCEPTION_INSERT_TARGET_TABLE_DOES_NOT_EXIST_ARG_ARG_78F05787 =
"写入目标表不存在:%s.%s";

public static final String EXCEPTION_EXPRESSIONS_AND_COLUMNS_DO_NOT_MATCH_EXPRESSIONS_SIZE_ARG_COLUMNS_SIZE_ARG_F933A8C1 =
"表达式与列不匹配,表达式数量:%s,列数量:%s";

public static final String EXCEPTION_INSERT_EXPRESSION_MUST_BE_CONSTANT_AFTER_CONSTANT_FOLDING_ARG_FOLDED_TO_ARG_D9EE1433 =
"写入表达式在常量折叠后必须为常量:%s(折叠结果为 %s)";

public static final String EXCEPTION_CANNOT_EVALUATE_INSERT_EXPRESSION_AS_A_CONSTANT_ARG_ARG_F478C134 =
"无法将写入表达式计算为常量:%s。%s";

public static final String EXCEPTION_THE_ARG_IS_OUT_OF_RANGE_OF_INT_F8E58471 =
"%s 超出 int 的范围。";

public static final String EXCEPTION_THE_ARG_IS_OUT_OF_RANGE_OF_LONG_9B1C872A =
"%s 超出 long 的范围。";

public static final String EXCEPTION_INT_OVERFLOW_ARG_ARG_BB287017 =
"int 溢出:%s / %s";

public static final String EXCEPTION_LONG_OVERFLOW_ARG_ARG_46CC95E2 =
"long 溢出:%s / %s";
}
Original file line number Diff line number Diff line change
Expand Up @@ -197,17 +197,17 @@ public List<WritePlanNode> splitByPartition(IAnalysis analysis) {
List<WritePlanNode> writePlanNodeList = new ArrayList<>();
Map<TRegionReplicaSet, RelationalInsertRowsNode> splitMap = new HashMap<>();
List<TEndPoint> redirectInfo = new ArrayList<>();
String databaseName = getDatabaseName(analysis);
for (int i = 0; i < getInsertRowNodeList().size(); i++) {
InsertRowNode insertRowNode = getInsertRowNodeList().get(i);
// Data region for insert row node
// each row may belong to different database, pass null for auto-detection
TRegionReplicaSet dataRegionReplicaSet =
analysis
.getDataPartitionInfo()
.getDataRegionReplicaSetForWriting(
insertRowNode.getDeviceID(),
TimePartitionUtils.getTimePartitionSlot(insertRowNode.getTime()),
analysis.getDatabaseName());
databaseName);

// Collect redirectInfo
redirectInfo.add(dataRegionReplicaSet.getDataNodeLocations().get(0).getClientRpcEndPoint());
Expand All @@ -230,6 +230,14 @@ public List<WritePlanNode> splitByPartition(IAnalysis analysis) {
return writePlanNodeList;
}

private String getDatabaseName(IAnalysis analysis) {
if (analysis.getDataPartitionInfo() != null
&& analysis.getDataPartitionInfo().getDataPartitionMap().size() == 1) {
return analysis.getDataPartitionInfo().getDataPartitionMap().keySet().iterator().next();
}
return analysis.getDatabaseName();
}

public RelationalInsertRowsNode emptyClone() {
return new RelationalInsertRowsNode(this.getPlanNodeId());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.InsertRow;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.InsertRows;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.InsertTablet;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.InsertValues;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.LoadTsFile;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.PipeEnriched;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Property;
Expand Down Expand Up @@ -1335,6 +1336,11 @@ public Scope visitInsertRows(InsertRows node, Optional<Scope> context) {
}

private Scope visitInsert(WrappedInsertStatement insert, Optional<Scope> scope) {
if (insert instanceof InsertValues) {
((InsertValues) insert)
.materialize(new PlannerContext(metadata, typeManager), sessionContext);
}

final Scope ret = Scope.create();

final MPPQueryContext context = insert.getContext();
Expand Down
Loading
Loading