This is an automated email from the ASF dual-hosted git repository.
haonan pushed a commit to branch rel/1.2
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/rel/1.2 by this push:
new 7534feb9f0b [To rel/1.2] Feature add insertRecords method to rest
service (#10838)
7534feb9f0b is described below
commit 7534feb9f0b215ce25d01b3efdde3d53ea19fdd5
Author: CloudWise-Lukemiao
<[email protected]>
AuthorDate: Tue Aug 29 14:53:44 2023 +0800
[To rel/1.2] Feature add insertRecords method to rest service (#10838)
Co-authored-by: Cloudwise_Luke <[email protected]>
---
.../db/protocol/rest/utils/InsertRowDataUtils.java | 105 +++++++++++++++++++++
.../rest/v1/handler/RequestValidationHandler.java | 12 +++
.../v1/handler/StatementConstructionHandler.java | 60 +++++++++++-
.../protocol/rest/v1/impl/RestApiServiceImpl.java | 47 +++++++++
.../rest/v2/handler/RequestValidationHandler.java | 12 +++
.../v2/handler/StatementConstructionHandler.java | 61 +++++++++++-
.../protocol/rest/v2/impl/RestApiServiceImpl.java | 47 +++++++++
.../openapi/src/main/openapi3/iotdb_rest_v1.yaml | 52 ++++++++++
.../openapi/src/main/openapi3/iotdb_rest_v2.yaml | 52 ++++++++++
9 files changed, 444 insertions(+), 4 deletions(-)
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
new file mode 100644
index 00000000000..ba54c77c8dd
--- /dev/null
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/utils/InsertRowDataUtils.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.iotdb.db.protocol.rest.utils;
+
+import org.apache.iotdb.rpc.IoTDBConnectionException;
+import org.apache.iotdb.rpc.NoValidValueException;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+import org.apache.iotdb.tsfile.utils.Binary;
+
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+import static org.apache.iotdb.session.Session.MSG_UNSUPPORTED_DATA_TYPE;
+
+public class InsertRowDataUtils {
+
+ private static final String ALL_INSERT_DATA_IS_NULL = "All inserted data is
null.";
+
+ public static void filterNullValueAndMeasurement(
+ List<String> deviceIds,
+ List<Long> times,
+ List<List<String>> measurementsList,
+ List<List<Object>> valuesList,
+ List<List<TSDataType>> typesList) {
+ for (int i = valuesList.size() - 1; i >= 0; i--) {
+ List<Object> values = valuesList.get(i);
+ List<String> measurements = measurementsList.get(i);
+ List<TSDataType> types = typesList.get(i);
+ boolean isAllValuesNull = getValuesIsEmpty(measurements, types, values);
+ if (isAllValuesNull) {
+ valuesList.remove(i);
+ measurementsList.remove(i);
+ deviceIds.remove(i);
+ times.remove(i);
+ typesList.remove(i);
+ }
+ }
+ if (valuesList.isEmpty()) {
+ throw new NoValidValueException(ALL_INSERT_DATA_IS_NULL);
+ }
+ }
+
+ private static boolean getValuesIsEmpty(
+ List<String> measurementsList, List<TSDataType> types, List<Object>
valuesList) {
+ for (int i = valuesList.size() - 1; i >= 0; i--) {
+ if (valuesList.get(i) == null) {
+ valuesList.remove(i);
+ measurementsList.remove(i);
+ types.remove(i);
+ }
+ }
+ return valuesList.isEmpty();
+ }
+
+ public static List<Object> reGenValues(List<TSDataType> types, List<Object>
values)
+ throws IoTDBConnectionException {
+ for (int i = 0; i < values.size(); i++) {
+ if (values.get(i) == null) {
+ continue;
+ }
+ Object val = values.get(i);
+ switch (types.get(i)) {
+ case BOOLEAN:
+ case INT32:
+ break;
+ case INT64:
+ if (val instanceof Number) {
+ values.set(i, ((Number) val).longValue());
+ }
+ break;
+ case FLOAT:
+ if (val instanceof Number) {
+ values.set(i, ((Number) val).floatValue());
+ }
+ break;
+ case DOUBLE:
+ if (val instanceof Number) {
+ values.set(i, ((Number) val).doubleValue());
+ }
+ break;
+ case TEXT:
+ values.set(i, new
Binary(val.toString().getBytes(StandardCharsets.UTF_8)));
+ break;
+ default:
+ 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/v1/handler/RequestValidationHandler.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v1/handler/RequestValidationHandler.java
index 32e97d36fec..dc9dafbf0e3 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v1/handler/RequestValidationHandler.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v1/handler/RequestValidationHandler.java
@@ -18,6 +18,7 @@
package org.apache.iotdb.db.protocol.rest.v1.handler;
import org.apache.iotdb.db.protocol.rest.v1.model.ExpressionRequest;
+import org.apache.iotdb.db.protocol.rest.v1.model.InsertRecordsRequest;
import org.apache.iotdb.db.protocol.rest.v1.model.InsertTabletRequest;
import org.apache.iotdb.db.protocol.rest.v1.model.SQL;
@@ -44,6 +45,17 @@ public class RequestValidationHandler {
Objects.requireNonNull(insertTabletRequest.getValues(), "values should not
be null");
}
+ public static void validateInsertRecordsRequest(InsertRecordsRequest
insertRecordsRequest) {
+ Objects.requireNonNull(insertRecordsRequest.getTimestamps(), "timestamps
should not be null");
+ Objects.requireNonNull(insertRecordsRequest.getIsAligned(), "isAligned
should not be null");
+ Objects.requireNonNull(insertRecordsRequest.getDeviceIds(), "deviceIds
should not be null");
+ Objects.requireNonNull(
+ insertRecordsRequest.getDataTypesList(), "dataTypesList should not be
null");
+ Objects.requireNonNull(insertRecordsRequest.getValuesList(), "valuesList
should not be null");
+ Objects.requireNonNull(
+ insertRecordsRequest.getMeasurementsList(), "measurementsList should
not be null");
+ }
+
public static void validateExpressionRequest(ExpressionRequest
expressionRequest) {
Objects.requireNonNull(expressionRequest.getExpression(), "expression
should not be null");
Objects.requireNonNull(expressionRequest.getPrefixPath(), "prefixPath
should not be null");
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v1/handler/StatementConstructionHandler.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v1/handler/StatementConstructionHandler.java
index 420132c8442..8b570ba2297 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v1/handler/StatementConstructionHandler.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v1/handler/StatementConstructionHandler.java
@@ -19,14 +19,20 @@ package org.apache.iotdb.db.protocol.rest.v1.handler;
import org.apache.iotdb.commons.exception.IllegalPathException;
import org.apache.iotdb.db.exception.WriteProcessRejectException;
+import org.apache.iotdb.db.protocol.rest.utils.InsertRowDataUtils;
+import org.apache.iotdb.db.protocol.rest.v1.model.InsertRecordsRequest;
import org.apache.iotdb.db.protocol.rest.v1.model.InsertTabletRequest;
import
org.apache.iotdb.db.queryengine.plan.analyze.cache.schema.DataNodeDevicePathCache;
+import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertRowStatement;
+import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertRowsStatement;
import
org.apache.iotdb.db.queryengine.plan.statement.crud.InsertTabletStatement;
+import org.apache.iotdb.rpc.IoTDBConnectionException;
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
import org.apache.iotdb.tsfile.utils.Binary;
import org.apache.iotdb.tsfile.utils.BitMap;
import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
@@ -115,7 +121,7 @@ public class StatementConstructionHandler {
if (data == null) {
bitMaps[columnIndex].mark(rowIndex);
} else {
- floatValues[rowIndex] = Float.valueOf(String.valueOf(data));
+ floatValues[rowIndex] = Float.parseFloat(String.valueOf(data));
}
}
columns[columnIndex] = floatValues;
@@ -127,7 +133,7 @@ public class StatementConstructionHandler {
bitMaps[columnIndex].mark(rowIndex);
} else {
doubleValues[rowIndex] =
-
Double.valueOf(String.valueOf(rawData.get(columnIndex).get(rowIndex)));
+
Double.parseDouble(String.valueOf(rawData.get(columnIndex).get(rowIndex)));
}
}
columns[columnIndex] = doubleValues;
@@ -164,4 +170,54 @@ public class StatementConstructionHandler {
insertStatement.setAligned(insertTabletRequest.getIsAligned());
return insertStatement;
}
+
+ public static InsertRowsStatement createInsertRowsStatement(
+ InsertRecordsRequest insertRecordsRequest)
+ throws IllegalPathException, IoTDBConnectionException {
+
+ // construct insert statement
+ InsertRowsStatement insertStatement = new InsertRowsStatement();
+ List<InsertRowStatement> insertRowStatementList = new ArrayList<>();
+ List<List<TSDataType>> dataTypesList = new ArrayList<>();
+
+ for (int i = 0; i < insertRecordsRequest.getDataTypesList().size(); i++) {
+ List<TSDataType> dataTypes = new ArrayList<>();
+ for (int c = 0; c <
insertRecordsRequest.getDataTypesList().get(i).size(); c++) {
+ dataTypes.add(
+ TSDataType.valueOf(
+
insertRecordsRequest.getDataTypesList().get(i).get(c).toUpperCase(Locale.ROOT)));
+ }
+ dataTypesList.add(dataTypes);
+ }
+
+ InsertRowDataUtils.filterNullValueAndMeasurement(
+ insertRecordsRequest.getDeviceIds(),
+ insertRecordsRequest.getTimestamps(),
+ insertRecordsRequest.getMeasurementsList(),
+ insertRecordsRequest.getValuesList(),
+ dataTypesList);
+
+ for (int i = 0; i < insertRecordsRequest.getDeviceIds().size(); i++) {
+ InsertRowStatement statement = new InsertRowStatement();
+ statement.setDevicePath(
+ DataNodeDevicePathCache.getInstance()
+ .getPartialPath(insertRecordsRequest.getDeviceIds().get(i)));
+ statement.setMeasurements(
+ insertRecordsRequest.getMeasurementsList().get(i).toArray(new
String[0]));
+ statement.setTime(insertRecordsRequest.getTimestamps().get(i));
+ statement.setDataTypes(dataTypesList.get(i).toArray(new TSDataType[0]));
+ List<Object> values =
+ InsertRowDataUtils.reGenValues(
+ dataTypesList.get(i),
insertRecordsRequest.getValuesList().get(i));
+ statement.setValues(values.toArray());
+ statement.setAligned(insertRecordsRequest.getIsAligned());
+ if (statement.isEmpty()) {
+ continue;
+ }
+ insertRowStatementList.add(statement);
+ }
+ insertStatement.setInsertRowStatementList(insertRowStatementList);
+
+ return insertStatement;
+ }
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v1/impl/RestApiServiceImpl.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v1/impl/RestApiServiceImpl.java
index ab6096179b5..b2c5296515e 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v1/impl/RestApiServiceImpl.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v1/impl/RestApiServiceImpl.java
@@ -29,6 +29,7 @@ import
org.apache.iotdb.db.protocol.rest.v1.handler.QueryDataSetHandler;
import org.apache.iotdb.db.protocol.rest.v1.handler.RequestValidationHandler;
import
org.apache.iotdb.db.protocol.rest.v1.handler.StatementConstructionHandler;
import org.apache.iotdb.db.protocol.rest.v1.model.ExecutionStatus;
+import org.apache.iotdb.db.protocol.rest.v1.model.InsertRecordsRequest;
import org.apache.iotdb.db.protocol.rest.v1.model.InsertTabletRequest;
import org.apache.iotdb.db.protocol.rest.v1.model.SQL;
import org.apache.iotdb.db.protocol.session.SessionManager;
@@ -41,6 +42,7 @@ import
org.apache.iotdb.db.queryengine.plan.execution.ExecutionResult;
import org.apache.iotdb.db.queryengine.plan.execution.IQueryExecution;
import org.apache.iotdb.db.queryengine.plan.parser.StatementGenerator;
import org.apache.iotdb.db.queryengine.plan.statement.Statement;
+import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertRowsStatement;
import
org.apache.iotdb.db.queryengine.plan.statement.crud.InsertTabletStatement;
import org.apache.iotdb.db.utils.SetThreadName;
import org.apache.iotdb.rpc.TSStatusCode;
@@ -185,6 +187,51 @@ public class RestApiServiceImpl extends RestApiService {
}
}
+ @Override
+ public Response insertRecords(
+ InsertRecordsRequest insertRecordsRequest, SecurityContext
securityContext) {
+ Long queryId = null;
+ try {
+
RequestValidationHandler.validateInsertRecordsRequest(insertRecordsRequest);
+
+ InsertRowsStatement insertRowsStatement =
+
StatementConstructionHandler.createInsertRowsStatement(insertRecordsRequest);
+
+ Response response = authorizationHandler.checkAuthority(securityContext,
insertRowsStatement);
+ if (response != null) {
+ return response;
+ }
+ queryId = SESSION_MANAGER.requestQueryId();
+ ExecutionResult result =
+ COORDINATOR.execute(
+ insertRowsStatement,
+ SESSION_MANAGER.requestQueryId(),
+ null,
+ "",
+ partitionFetcher,
+ schemaFetcher,
+ config.getQueryTimeoutThreshold());
+
+ return Response.ok()
+ .entity(
+ (result.status.code ==
TSStatusCode.SUCCESS_STATUS.getStatusCode()
+ || result.status.code ==
TSStatusCode.REDIRECTION_RECOMMEND.getStatusCode())
+ ? new ExecutionStatus()
+ .code(TSStatusCode.SUCCESS_STATUS.getStatusCode())
+ .message(TSStatusCode.SUCCESS_STATUS.name())
+ : new ExecutionStatus()
+ .code(result.status.getCode())
+ .message(result.status.getMessage()))
+ .build();
+ } catch (Exception e) {
+ return
Response.ok().entity(ExceptionHandler.tryCatchException(e)).build();
+ } finally {
+ if (queryId != null) {
+ COORDINATOR.cleanupQueryExecution(queryId);
+ }
+ }
+ }
+
@Override
public Response insertTablet(
InsertTabletRequest insertTabletRequest, SecurityContext
securityContext) {
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v2/handler/RequestValidationHandler.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v2/handler/RequestValidationHandler.java
index 2b7f568edea..b7f71f7be6d 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v2/handler/RequestValidationHandler.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v2/handler/RequestValidationHandler.java
@@ -18,6 +18,7 @@
package org.apache.iotdb.db.protocol.rest.v2.handler;
import org.apache.iotdb.db.protocol.rest.v2.model.ExpressionRequest;
+import org.apache.iotdb.db.protocol.rest.v2.model.InsertRecordsRequest;
import org.apache.iotdb.db.protocol.rest.v2.model.InsertTabletRequest;
import org.apache.iotdb.db.protocol.rest.v2.model.SQL;
@@ -44,6 +45,17 @@ public class RequestValidationHandler {
Objects.requireNonNull(insertTabletRequest.getValues(), "values should not
be null");
}
+ public static void validateInsertRecordsRequest(InsertRecordsRequest
insertRecordsRequest) {
+ Objects.requireNonNull(insertRecordsRequest.getTimestamps(), "timestamps
should not be null");
+ Objects.requireNonNull(insertRecordsRequest.getIsAligned(), "is_aligned
should not be null");
+ Objects.requireNonNull(insertRecordsRequest.getDevices(), "devices should
not be null");
+ Objects.requireNonNull(
+ insertRecordsRequest.getDataTypesList(), "data_types_list should not
be null");
+ Objects.requireNonNull(insertRecordsRequest.getValuesList(), "values_list
should not be null");
+ Objects.requireNonNull(
+ insertRecordsRequest.getMeasurementsList(), "measurements_list should
not be null");
+ }
+
public static void validateExpressionRequest(ExpressionRequest
expressionRequest) {
Objects.requireNonNull(expressionRequest.getExpression(), "expression
should not be null");
Objects.requireNonNull(expressionRequest.getPrefixPath(), "prefix_path
should not be null");
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 8ef8401b3cb..794daff8372 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
@@ -19,14 +19,20 @@ package org.apache.iotdb.db.protocol.rest.v2.handler;
import org.apache.iotdb.commons.exception.IllegalPathException;
import org.apache.iotdb.db.exception.WriteProcessRejectException;
+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;
import
org.apache.iotdb.db.queryengine.plan.analyze.cache.schema.DataNodeDevicePathCache;
+import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertRowStatement;
+import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertRowsStatement;
import
org.apache.iotdb.db.queryengine.plan.statement.crud.InsertTabletStatement;
+import org.apache.iotdb.rpc.IoTDBConnectionException;
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
import org.apache.iotdb.tsfile.utils.Binary;
import org.apache.iotdb.tsfile.utils.BitMap;
import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
@@ -115,7 +121,7 @@ public class StatementConstructionHandler {
if (data == null) {
bitMaps[columnIndex].mark(rowIndex);
} else {
- floatValues[rowIndex] = Float.valueOf(String.valueOf(data));
+ floatValues[rowIndex] = Float.parseFloat(String.valueOf(data));
}
}
columns[columnIndex] = floatValues;
@@ -127,7 +133,7 @@ public class StatementConstructionHandler {
bitMaps[columnIndex].mark(rowIndex);
} else {
doubleValues[rowIndex] =
-
Double.valueOf(String.valueOf(rawData.get(columnIndex).get(rowIndex)));
+
Double.parseDouble(String.valueOf(rawData.get(columnIndex).get(rowIndex)));
}
}
columns[columnIndex] = doubleValues;
@@ -164,4 +170,55 @@ public class StatementConstructionHandler {
insertStatement.setAligned(insertTabletRequest.getIsAligned());
return insertStatement;
}
+
+ public static InsertRowsStatement createInsertRowsStatement(
+ InsertRecordsRequest insertRecordsRequest)
+ throws IllegalPathException, IoTDBConnectionException {
+
+ // construct insert statement
+ InsertRowsStatement insertStatement = new InsertRowsStatement();
+ List<InsertRowStatement> insertRowStatementList = new ArrayList<>();
+ List<List<TSDataType>> dataTypesList = new ArrayList<>();
+
+ for (int i = 0; i < insertRecordsRequest.getDataTypesList().size(); i++) {
+ List<TSDataType> dataTypes = new ArrayList<>();
+ for (int c = 0; c <
insertRecordsRequest.getDataTypesList().get(i).size(); c++) {
+ dataTypes.add(
+ TSDataType.valueOf(
+
insertRecordsRequest.getDataTypesList().get(i).get(c).toUpperCase(Locale.ROOT)));
+ }
+ dataTypesList.add(dataTypes);
+ }
+
+ InsertRowDataUtils.filterNullValueAndMeasurement(
+ insertRecordsRequest.getDevices(),
+ insertRecordsRequest.getTimestamps(),
+ insertRecordsRequest.getMeasurementsList(),
+ insertRecordsRequest.getValuesList(),
+ dataTypesList);
+
+ for (int i = 0; i < insertRecordsRequest.getDevices().size(); i++) {
+ InsertRowStatement statement = new InsertRowStatement();
+ statement.setDevicePath(
+ DataNodeDevicePathCache.getInstance()
+ .getPartialPath(insertRecordsRequest.getDevices().get(i)));
+ statement.setMeasurements(
+ insertRecordsRequest.getMeasurementsList().get(i).toArray(new
String[0]));
+ statement.setTime(insertRecordsRequest.getTimestamps().get(i));
+ statement.setDataTypes(dataTypesList.get(i).toArray(new TSDataType[0]));
+ List<Object> values =
+ InsertRowDataUtils.reGenValues(
+ dataTypesList.get(i),
insertRecordsRequest.getValuesList().get(i));
+ statement.setValues(values.toArray());
+ statement.setAligned(insertRecordsRequest.getIsAligned());
+ // skip empty statement
+ if (statement.isEmpty()) {
+ continue;
+ }
+ insertRowStatementList.add(statement);
+ }
+ insertStatement.setInsertRowStatementList(insertRowStatementList);
+
+ return insertStatement;
+ }
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v2/impl/RestApiServiceImpl.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v2/impl/RestApiServiceImpl.java
index f1e03ba86bc..c2fc177ba31 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v2/impl/RestApiServiceImpl.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v2/impl/RestApiServiceImpl.java
@@ -29,6 +29,7 @@ import
org.apache.iotdb.db.protocol.rest.v2.handler.QueryDataSetHandler;
import org.apache.iotdb.db.protocol.rest.v2.handler.RequestValidationHandler;
import
org.apache.iotdb.db.protocol.rest.v2.handler.StatementConstructionHandler;
import org.apache.iotdb.db.protocol.rest.v2.model.ExecutionStatus;
+import org.apache.iotdb.db.protocol.rest.v2.model.InsertRecordsRequest;
import org.apache.iotdb.db.protocol.rest.v2.model.InsertTabletRequest;
import org.apache.iotdb.db.protocol.rest.v2.model.SQL;
import org.apache.iotdb.db.protocol.session.SessionManager;
@@ -41,6 +42,7 @@ import
org.apache.iotdb.db.queryengine.plan.execution.ExecutionResult;
import org.apache.iotdb.db.queryengine.plan.execution.IQueryExecution;
import org.apache.iotdb.db.queryengine.plan.parser.StatementGenerator;
import org.apache.iotdb.db.queryengine.plan.statement.Statement;
+import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertRowsStatement;
import
org.apache.iotdb.db.queryengine.plan.statement.crud.InsertTabletStatement;
import org.apache.iotdb.db.utils.SetThreadName;
import org.apache.iotdb.rpc.TSStatusCode;
@@ -185,6 +187,51 @@ public class RestApiServiceImpl extends RestApiService {
}
}
+ @Override
+ public Response insertRecords(
+ InsertRecordsRequest insertRecordsRequest, SecurityContext
securityContext) {
+ Long queryId = null;
+ try {
+
RequestValidationHandler.validateInsertRecordsRequest(insertRecordsRequest);
+
+ InsertRowsStatement insertRowsStatement =
+
StatementConstructionHandler.createInsertRowsStatement(insertRecordsRequest);
+
+ Response response = authorizationHandler.checkAuthority(securityContext,
insertRowsStatement);
+ if (response != null) {
+ return response;
+ }
+ queryId = SESSION_MANAGER.requestQueryId();
+ ExecutionResult result =
+ COORDINATOR.execute(
+ insertRowsStatement,
+ SESSION_MANAGER.requestQueryId(),
+ null,
+ "",
+ partitionFetcher,
+ schemaFetcher,
+ config.getQueryTimeoutThreshold());
+
+ return Response.ok()
+ .entity(
+ (result.status.code ==
TSStatusCode.SUCCESS_STATUS.getStatusCode()
+ || result.status.code ==
TSStatusCode.REDIRECTION_RECOMMEND.getStatusCode())
+ ? new ExecutionStatus()
+ .code(TSStatusCode.SUCCESS_STATUS.getStatusCode())
+ .message(TSStatusCode.SUCCESS_STATUS.name())
+ : new ExecutionStatus()
+ .code(result.status.getCode())
+ .message(result.status.getMessage()))
+ .build();
+ } catch (Exception e) {
+ return
Response.ok().entity(ExceptionHandler.tryCatchException(e)).build();
+ } finally {
+ if (queryId != null) {
+ COORDINATOR.cleanupQueryExecution(queryId);
+ }
+ }
+ }
+
@Override
public Response insertTablet(
InsertTabletRequest insertTabletRequest, SecurityContext
securityContext) {
diff --git a/iotdb-protocol/openapi/src/main/openapi3/iotdb_rest_v1.yaml
b/iotdb-protocol/openapi/src/main/openapi3/iotdb_rest_v1.yaml
index 18080c693ab..f2e439d4400 100644
--- a/iotdb-protocol/openapi/src/main/openapi3/iotdb_rest_v1.yaml
+++ b/iotdb-protocol/openapi/src/main/openapi3/iotdb_rest_v1.yaml
@@ -49,6 +49,24 @@ paths:
schema:
$ref: '#/components/schemas/ExecutionStatus'
+ /rest/v1/insertRecords:
+ post:
+ summary: insertRecords
+ description: insertRecords
+ operationId: insertRecords
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InsertRecordsRequest'
+ responses:
+ "200":
+ description: ExecutionStatus
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ExecutionStatus'
+
/rest/v1/nonQuery:
post:
summary: executeNonQueryStatement
@@ -195,6 +213,40 @@ components:
deviceId:
type: string
+ InsertRecordsRequest:
+ title: InsertRecordsRequest
+ type: object
+ properties:
+ timestamps:
+ type: array
+ items:
+ type: integer
+ format: int64
+ measurementsList:
+ type: array
+ items:
+ type: array
+ items:
+ type: string
+ dataTypesList:
+ type: array
+ items:
+ type: array
+ items:
+ type: string
+ valuesList:
+ type: array
+ items:
+ type: array
+ items:
+ type: object
+ isAligned:
+ type: boolean
+ deviceIds:
+ type: array
+ items:
+ type: string
+
ExecutionStatus:
type: object
properties:
diff --git a/iotdb-protocol/openapi/src/main/openapi3/iotdb_rest_v2.yaml
b/iotdb-protocol/openapi/src/main/openapi3/iotdb_rest_v2.yaml
index 4dfdb14cb91..68dac502d94 100644
--- a/iotdb-protocol/openapi/src/main/openapi3/iotdb_rest_v2.yaml
+++ b/iotdb-protocol/openapi/src/main/openapi3/iotdb_rest_v2.yaml
@@ -49,6 +49,24 @@ paths:
schema:
$ref: '#/components/schemas/ExecutionStatus'
+ /rest/v2/insertRecords:
+ post:
+ summary: insertRecords
+ description: insertRecords
+ operationId: insertRecords
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InsertRecordsRequest'
+ responses:
+ "200":
+ description: ExecutionStatus
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ExecutionStatus'
+
/rest/v2/nonQuery:
post:
summary: executeNonQueryStatement
@@ -195,6 +213,40 @@ components:
device:
type: string
+ InsertRecordsRequest:
+ title: InsertRecordsRequest
+ type: object
+ properties:
+ timestamps:
+ type: array
+ items:
+ type: integer
+ format: int64
+ measurements_list:
+ type: array
+ items:
+ type: array
+ items:
+ type: string
+ data_types_list:
+ type: array
+ items:
+ type: array
+ items:
+ type: string
+ values_list:
+ type: array
+ items:
+ type: array
+ items:
+ type: object
+ is_aligned:
+ type: boolean
+ devices:
+ type: array
+ items:
+ type: string
+
ExecutionStatus:
type: object
properties: