This is an automated email from the ASF dual-hosted git repository.
haonan 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 db268afc910 Add datatype check for restapi insertRecords and fix query
bug (#12631)
db268afc910 is described below
commit db268afc910ac1af4ecb3abb7175e9708e47537e
Author: Haonan <[email protected]>
AuthorDate: Fri May 31 19:36:45 2024 +0800
Add datatype check for restapi insertRecords and fix query bug (#12631)
---
.../metadata/DataTypeMismatchException.java | 13 +++++++++++
.../db/protocol/rest/utils/InsertRowDataUtils.java | 20 +++++++++++++++-
.../v2/handler/StatementConstructionHandler.java | 27 +++++++++++++++++++++-
.../schemaregion/utils/ResourceByPathUtils.java | 3 ++-
4 files changed, 60 insertions(+), 3 deletions(-)
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/exception/metadata/DataTypeMismatchException.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/exception/metadata/DataTypeMismatchException.java
index 8165f291765..12a04e1d282 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/exception/metadata/DataTypeMismatchException.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/exception/metadata/DataTypeMismatchException.java
@@ -48,6 +48,19 @@ public class DataTypeMismatchException extends
MetadataException {
value == null ? "null" : processValue(value.toString())));
}
+ public DataTypeMismatchException(
+ String deviceName, String measurementName, TSDataType insertType, long
time, Object value) {
+ super(
+ String.format(
+ "data type and value of %s.%s is not consistent, "
+ + "inserting type %s, timestamp %s, value %s",
+ deviceName,
+ measurementName,
+ insertType,
+ time,
+ value == null ? "null" : processValue(value.toString())));
+ }
+
private static String processValue(String value) {
return value.length() < 100 ? value : value.substring(0, 100);
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/utils/InsertRowDataUtils.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/utils/InsertRowDataUtils.java
index d963def3c43..fae611dcf77 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/utils/InsertRowDataUtils.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/utils/InsertRowDataUtils.java
@@ -25,6 +25,7 @@ import org.apache.tsfile.utils.Binary;
import java.nio.charset.StandardCharsets;
import java.util.List;
+import java.util.Map;
import static org.apache.iotdb.session.Session.MSG_UNSUPPORTED_DATA_TYPE;
@@ -68,7 +69,8 @@ public class InsertRowDataUtils {
return valuesList.isEmpty();
}
- public static List<Object> reGenValues(List<TSDataType> types, List<Object>
values)
+ public static List<Object> reGenValues(
+ List<TSDataType> types, List<Object> values, Map<Integer, Object>
mismatchedInfo)
throws IoTDBConnectionException {
for (int i = 0; i < values.size(); i++) {
if (values.get(i) == null) {
@@ -77,23 +79,38 @@ public class InsertRowDataUtils {
Object val = values.get(i);
switch (types.get(i)) {
case BOOLEAN:
+ if (!(val instanceof Boolean)) {
+ mismatchedInfo.put(i, val);
+ }
+ break;
case INT32:
case DATE:
+ if (val instanceof Number) {
+ values.set(i, ((Number) val).intValue());
+ } else {
+ mismatchedInfo.put(i, val);
+ }
break;
case INT64:
case TIMESTAMP:
if (val instanceof Number) {
values.set(i, ((Number) val).longValue());
+ } else {
+ mismatchedInfo.put(i, val);
}
break;
case FLOAT:
if (val instanceof Number) {
values.set(i, ((Number) val).floatValue());
+ } else {
+ mismatchedInfo.put(i, val);
}
break;
case DOUBLE:
if (val instanceof Number) {
values.set(i, ((Number) val).doubleValue());
+ } else {
+ mismatchedInfo.put(i, val);
}
break;
case TEXT:
@@ -105,6 +122,7 @@ public class InsertRowDataUtils {
throw new IoTDBConnectionException(MSG_UNSUPPORTED_DATA_TYPE +
types.get(i));
}
}
+
return values;
}
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v2/handler/StatementConstructionHandler.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v2/handler/StatementConstructionHandler.java
index c24089616fa..c0559b40c2d 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v2/handler/StatementConstructionHandler.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v2/handler/StatementConstructionHandler.java
@@ -20,6 +20,7 @@ package org.apache.iotdb.db.protocol.rest.v2.handler;
import org.apache.iotdb.commons.exception.MetadataException;
import org.apache.iotdb.commons.utils.PathUtils;
import org.apache.iotdb.db.exception.WriteProcessRejectException;
+import org.apache.iotdb.db.exception.metadata.DataTypeMismatchException;
import org.apache.iotdb.db.protocol.rest.utils.InsertRowDataUtils;
import org.apache.iotdb.db.protocol.rest.v2.model.InsertRecordsRequest;
import org.apache.iotdb.db.protocol.rest.v2.model.InsertTabletRequest;
@@ -36,8 +37,10 @@ import org.apache.tsfile.utils.BitMap;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import java.util.Locale;
+import java.util.Map;
public class StatementConstructionHandler {
private StatementConstructionHandler() {}
@@ -221,15 +224,37 @@ public class StatementConstructionHandler {
TimestampPrecisionUtils.checkTimestampPrecision(insertRecordsRequest.getTimestamps().get(i));
statement.setTime(insertRecordsRequest.getTimestamps().get(i));
statement.setDataTypes(dataTypesList.get(i).toArray(new TSDataType[0]));
+ Map<Integer, Object> dataTypeMismatchInfo = new HashMap<>();
List<Object> values =
InsertRowDataUtils.reGenValues(
- dataTypesList.get(i),
insertRecordsRequest.getValuesList().get(i));
+ dataTypesList.get(i),
+ insertRecordsRequest.getValuesList().get(i),
+ dataTypeMismatchInfo);
statement.setValues(values.toArray());
statement.setAligned(insertRecordsRequest.getIsAligned());
// skip empty statement
if (statement.isEmpty()) {
continue;
}
+ if (!dataTypeMismatchInfo.isEmpty()) {
+ for (Map.Entry<Integer, Object> entry :
dataTypeMismatchInfo.entrySet()) {
+ int index = entry.getKey();
+ String measurement = statement.getMeasurements()[index];
+ TSDataType dataType = statement.getDataTypes()[index];
+ statement.markFailedMeasurement(
+ index,
+ new DataTypeMismatchException(
+ insertRecordsRequest.getDevices().get(i),
+ statement.getMeasurements()[index],
+ statement.getDataTypes()[index],
+ statement.getTime(),
+ entry.getValue()));
+ // markFailedMeasurement will set datatype and measurements null
+ // setting them back in order to pass the schema validation
+ statement.getDataTypes()[index] = dataType;
+ statement.getMeasurements()[index] = measurement;
+ }
+ }
insertRowStatementList.add(statement);
}
insertStatement.setInsertRowStatementList(insertRowStatementList);
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/utils/ResourceByPathUtils.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/utils/ResourceByPathUtils.java
index d25248af44b..a58277d8d88 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/utils/ResourceByPathUtils.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/utils/ResourceByPathUtils.java
@@ -266,7 +266,8 @@ class AlignedResourceByPathUtils extends
ResourceByPathUtils {
// if all the sub sensors doesn't exist, it will be false
boolean exits = false;
for (List<ChunkMetadata> chunkMetadata : valueChunkMetadataList) {
- boolean currentExist = i < chunkMetadata.size();
+ boolean currentExist =
+ i < chunkMetadata.size() &&
chunkMetadata.get(i).getNumOfPoints() > 0;
exits = (exits || currentExist);
valueChunkMetadata.add(currentExist ? chunkMetadata.get(i) : null);
}