This is an automated email from the ASF dual-hosted git repository.
critas 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 fbc28c6e27a Fixed issues in the rest service module: BLOB, DATE, table
model parameters, and added statistical delay monitoring items to
FastLastQuery. (#15917)
fbc28c6e27a is described below
commit fbc28c6e27a12cb01a69d64d796138545fe2b457
Author: CloudWise-Lukemiao <[email protected]>
AuthorDate: Tue Jul 22 15:46:28 2025 +0800
Fixed issues in the rest service module: BLOB, DATE, table model
parameters, and added statistical delay monitoring items to FastLastQuery.
(#15917)
* The following issues have been fixed:
1、When querying BLOB data type through the /rest/v2/query interface, the
returned results display garbled characters.
2、For the DATE data type, it is recommended that the returned results be
displayed with separators, such as: 2025-01-01.
3、Added statistical delay monitoring items to FastLastQuery.
4、Fixed the spelling error of the column_categories parameter in the
insertTablet method of the table model.
* add it
* add it
* add it
* add it
---
.../java/org/apache/iotdb/TableHttpExample.java | 2 +-
.../java/org/apache/iotdb/TableHttpsExample.java | 2 +-
.../org/apache/iotdb/db/it/IoTDBRestServiceIT.java | 145 ++++++++++++++++++++-
.../relational/it/rest/it/IoTDBRestServiceIT.java | 32 ++++-
.../rest/table/v1/handler/QueryDataSetHandler.java | 36 +++--
.../table/v1/handler/RequestValidationHandler.java | 12 +-
.../v1/handler/StatementConstructionHandler.java | 4 +-
.../rest/v1/handler/QueryDataSetHandler.java | 54 ++++++--
.../rest/v2/handler/QueryDataSetHandler.java | 37 ++++--
.../protocol/rest/v2/impl/RestApiServiceImpl.java | 13 +-
.../queryengine/plan/statement/StatementType.java | 4 +-
.../src/main/openapi3/iotdb_rest_table_v1.yaml | 2 +-
12 files changed, 292 insertions(+), 51 deletions(-)
diff --git
a/example/rest-java-example/src/main/java/org/apache/iotdb/TableHttpExample.java
b/example/rest-java-example/src/main/java/org/apache/iotdb/TableHttpExample.java
index ba419eddd7f..b9651245d02 100644
---
a/example/rest-java-example/src/main/java/org/apache/iotdb/TableHttpExample.java
+++
b/example/rest-java-example/src/main/java/org/apache/iotdb/TableHttpExample.java
@@ -93,7 +93,7 @@ public class TableHttpExample {
try {
HttpPost httpPost =
getHttpPost("http://127.0.0.1:18080/rest/table/v1/insertTablet");
String json =
-
"{\"database\":\"test\",\"column_catogories\":[\"TAG\",\"ATTRIBUTE\",\"FIELD\"],\"timestamps\":[1635232143960,1635232153960,1635232163960,1635232173960,1635232183960],\"column_names\":[\"id1\",\"t1\",\"s1\"],\"data_types\":[\"STRING\",\"STRING\",\"FLOAT\"],\"values\":[[\"a11\",\"true\",11333],[\"a11\",\"false\",22333],[\"a13\",\"false1\",23333],[\"a14\",\"false2\",24],[\"a15\",\"false3\",25]],\"table\":\"sg211\"}";
+
"{\"database\":\"test\",\"column_categories\":[\"TAG\",\"ATTRIBUTE\",\"FIELD\"],\"timestamps\":[1635232143960,1635232153960,1635232163960,1635232173960,1635232183960],\"column_names\":[\"id1\",\"t1\",\"s1\"],\"data_types\":[\"STRING\",\"STRING\",\"FLOAT\"],\"values\":[[\"a11\",\"true\",11333],[\"a11\",\"false\",22333],[\"a13\",\"false1\",23333],[\"a14\",\"false2\",24],[\"a15\",\"false3\",25]],\"table\":\"sg211\"}";
httpPost.setEntity(new StringEntity(json, Charset.defaultCharset()));
response = httpClient.execute(httpPost);
HttpEntity responseEntity = response.getEntity();
diff --git
a/example/rest-java-example/src/main/java/org/apache/iotdb/TableHttpsExample.java
b/example/rest-java-example/src/main/java/org/apache/iotdb/TableHttpsExample.java
index c6d8d4709e4..200dbf66fdb 100644
---
a/example/rest-java-example/src/main/java/org/apache/iotdb/TableHttpsExample.java
+++
b/example/rest-java-example/src/main/java/org/apache/iotdb/TableHttpsExample.java
@@ -93,7 +93,7 @@ public class TableHttpsExample {
try {
HttpPost httpPost =
getHttpPost("https://127.0.0.1:18080/rest/table/v1/insertTablet");
String json =
-
"{\"database\":\"test\",\"column_catogories\":[\"TAG\",\"ATTRIBUTE\",\"FIELD\"],\"timestamps\":[1635232143960,1635232153960,1635232163960,1635232173960,1635232183960],\"column_names\":[\"id1\",\"t1\",\"s1\"],\"data_types\":[\"STRING\",\"STRING\",\"FLOAT\"],\"values\":[[\"a11\",\"true\",11333],[\"a11\",\"false\",22333],[\"a13\",\"false1\",23333],[\"a14\",\"false2\",24],[\"a15\",\"false3\",25]],\"table\":\"sg211\"}";
+
"{\"database\":\"test\",\"column_categories\":[\"TAG\",\"ATTRIBUTE\",\"FIELD\"],\"timestamps\":[1635232143960,1635232153960,1635232163960,1635232173960,1635232183960],\"column_names\":[\"id1\",\"t1\",\"s1\"],\"data_types\":[\"STRING\",\"STRING\",\"FLOAT\"],\"values\":[[\"a11\",\"true\",11333],[\"a11\",\"false\",22333],[\"a13\",\"false1\",23333],[\"a14\",\"false2\",24],[\"a15\",\"false3\",25]],\"table\":\"sg211\"}";
httpPost.setEntity(new StringEntity(json, Charset.defaultCharset()));
response = httpClient.execute(httpPost);
HttpEntity responseEntity = response.getEntity();
diff --git
a/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBRestServiceIT.java
b/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBRestServiceIT.java
index 7cde457761c..42dd2587881 100644
---
a/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBRestServiceIT.java
+++
b/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBRestServiceIT.java
@@ -385,7 +385,6 @@ public class IoTDBRestServiceIT {
@Test
public void insertAndQuery() {
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
- //
rightInsertTablet(httpClient);
query(httpClient);
queryGroupByLevel(httpClient);
@@ -717,7 +716,7 @@ public class IoTDBRestServiceIT {
errorInsertRecords(httpClient, json, hp);
}
}
-
+ insertDate();
try {
httpClient.close();
} catch (IOException e) {
@@ -2122,4 +2121,146 @@ public class IoTDBRestServiceIT {
Assert.assertEquals(values2.get(0), valuesResult.get(1).get(0));
Assert.assertEquals(values3, valuesResult.get(2));
}
+
+ public void insertDate() {
+ CloseableHttpClient httpClient = HttpClientBuilder.create().build();
+ HttpPost httpPost2 = getHttpPost("http://127.0.0.1:" + port +
"/rest/v1/nonQuery");
+ HttpPost httpPostV2 = getHttpPost("http://127.0.0.1:" + port +
"/rest/v2/nonQuery");
+ nonQuery(
+ httpClient,
+ "{\"sql\":\"CREATE TIMESERIES root.sg1.d1.s4 WITH DATATYPE=DATE,
ENCODING=PLAIN, COMPRESSOR=SNAPPY\"}",
+ httpPost2);
+ nonQuery(
+ httpClient,
+ "{\"sql\":\"CREATE TIMESERIES root.sg1.d1.s5 WITH DATATYPE=Blob,
ENCODING=PLAIN, COMPRESSOR=SNAPPY\"}",
+ httpPost2);
+
+ String sql =
+ "{\"sql\":\"insert into root.sg1.d1(time,s4,s5)
values(1,'2025-07-14',\\\"X'cafebabe'\\\")\"}";
+ nonQuery(httpClient, sql, httpPost2);
+ queryDateAndBlob(httpClient);
+ queryDateAndBlobV2(httpClient);
+ }
+
+ public void queryDateAndBlob(CloseableHttpClient httpClient) {
+ CloseableHttpResponse response = null;
+ try {
+ HttpPost httpPost = getHttpPost("http://127.0.0.1:" + port +
"/rest/v1/query");
+ String sql = "{\"sql\":\"select s4,s5 from root.sg1.d1\"}";
+ httpPost.setEntity(new StringEntity(sql, Charset.defaultCharset()));
+ response = httpClient.execute(httpPost);
+ HttpEntity responseEntity = response.getEntity();
+ String message = EntityUtils.toString(responseEntity, "utf-8");
+ ObjectMapper mapper = new ObjectMapper();
+ Map map = mapper.readValue(message, Map.class);
+ List<Long> timestampsResult = (List<Long>) map.get("timestamps");
+ List<Long> expressionsResult = (List<Long>) map.get("expressions");
+ List<List<Object>> valuesResult = (List<List<Object>>) map.get("values");
+ Assert.assertTrue(map.size() > 0);
+ List<Object> expressions =
+ new ArrayList<Object>() {
+ {
+ add("root.sg1.d1.s4");
+ add("root.sg1.d1.s5");
+ }
+ };
+ List<Object> timestamps =
+ new ArrayList<Object>() {
+ {
+ add(1);
+ }
+ };
+ List<Object> values1 =
+ new ArrayList<Object>() {
+ {
+ add("2025-07-14");
+ }
+ };
+ List<Object> values2 =
+ new ArrayList<Object>() {
+ {
+ add("0xcafebabe");
+ }
+ };
+
+ Assert.assertEquals(expressions, expressionsResult);
+ Assert.assertEquals(timestamps, timestampsResult);
+ Assert.assertEquals(values1, valuesResult.get(0));
+ Assert.assertEquals(values2, valuesResult.get(1));
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ } finally {
+ try {
+ if (response != null) {
+ response.close();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+ }
+
+ public void queryDateAndBlobV2(CloseableHttpClient httpClient) {
+ CloseableHttpResponse response = null;
+ try {
+ HttpPost httpPost = getHttpPost("http://127.0.0.1:" + port +
"/rest/v2/query");
+ String sql = "{\"sql\":\"select s4,s5 from root.sg1.d1\"}";
+ httpPost.setEntity(new StringEntity(sql, Charset.defaultCharset()));
+ response = httpClient.execute(httpPost);
+ HttpEntity responseEntity = response.getEntity();
+ String message = EntityUtils.toString(responseEntity, "utf-8");
+ ObjectMapper mapper = new ObjectMapper();
+ Map map = mapper.readValue(message, Map.class);
+ List<Long> timestampsResult = (List<Long>) map.get("timestamps");
+ List<Long> expressionsResult = (List<Long>) map.get("expressions");
+ List<List<Object>> valuesResult = (List<List<Object>>) map.get("values");
+ Assert.assertTrue(map.size() > 0);
+ List<Object> expressions =
+ new ArrayList<Object>() {
+ {
+ add("root.sg1.d1.s4");
+ add("root.sg1.d1.s5");
+ }
+ };
+ List<Object> timestamps =
+ new ArrayList<Object>() {
+ {
+ add(1);
+ }
+ };
+ List<Object> values1 =
+ new ArrayList<Object>() {
+ {
+ add("2025-07-14");
+ }
+ };
+ List<Object> values2 =
+ new ArrayList<Object>() {
+ {
+ add("0xcafebabe");
+ }
+ };
+
+ Assert.assertEquals(expressions, expressionsResult);
+ Assert.assertEquals(timestamps, timestampsResult);
+ Assert.assertEquals(values1, valuesResult.get(0));
+ Assert.assertEquals(values2, valuesResult.get(1));
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ } finally {
+ try {
+ if (response != null) {
+ response.close();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+ }
}
diff --git
a/integration-test/src/test/java/org/apache/iotdb/relational/it/rest/it/IoTDBRestServiceIT.java
b/integration-test/src/test/java/org/apache/iotdb/relational/it/rest/it/IoTDBRestServiceIT.java
index 156ecdeed32..0ee6d7afe5d 100644
---
a/integration-test/src/test/java/org/apache/iotdb/relational/it/rest/it/IoTDBRestServiceIT.java
+++
b/integration-test/src/test/java/org/apache/iotdb/relational/it/rest/it/IoTDBRestServiceIT.java
@@ -147,6 +147,7 @@ public class IoTDBRestServiceIT {
testQuery();
testQuery1();
testQuery2();
+ inertDateAndBlob();
}
public void testQuery() {
@@ -277,7 +278,7 @@ public class IoTDBRestServiceIT {
RestUtils.nonQuery(httpClient, port, sqlHandler("test", sql));
}
String json =
-
"{\"database\":\"test\",\"column_catogories\":[\"TAG\",\"ATTRIBUTE\",\"FIELD\"],\"timestamps\":[1635232143960,1635232153960,1635232163960,1635232173960,1635232183960],\"column_names\":[\"tag1\",\"t1\",\"s1\"],\"data_types\":[\"STRING\",\"STRING\",\"FLOAT\"],\"values\":[[\"a11\",\"true\",11],[\"a11\",\"false\",22],[\"a13\",\"false1\",23],[\"a14\",\"false2\",24],[\"a15\",\"false3\",25]],\"table\":\"sg211\"}";
+
"{\"database\":\"test\",\"column_categories\":[\"TAG\",\"ATTRIBUTE\",\"FIELD\"],\"timestamps\":[1635232143960,1635232153960,1635232163960,1635232173960,1635232183960],\"column_names\":[\"tag1\",\"t1\",\"s1\"],\"data_types\":[\"STRING\",\"STRING\",\"FLOAT\"],\"values\":[[\"a11\",\"true\",11],[\"a11\",\"false\",22],[\"a13\",\"false1\",23],[\"a14\",\"false2\",24],[\"a15\",\"false3\",25]],\"table\":\"sg211\"}";
rightInsertTablet(json);
}
@@ -289,7 +290,7 @@ public class IoTDBRestServiceIT {
RestUtils.nonQuery(httpClient, port, sqlHandler("test", sql));
}
String json =
-
"{\"database\":\"\",\"column_catogories\":[\"TAG\",\"ATTRIBUTE\",\"FIELD\"],\"timestamps\":[1635232143960,1635232153960,1635232163960,1635232173960,1635232183960],\"column_names\":[\"tag1\",\"t1\",\"s1\"],\"data_types\":[\"STRING\",\"STRING\",\"FLOAT\"],\"values\":[[\"a11\",\"true\",11],[\"a11\",\"false\",22],[\"a13\",\"false1\",23],[\"a14\",\"false2\",24],[\"a15\",\"false3\",25]],\"table\":\"sg211\"}";
+
"{\"database\":\"\",\"column_categories\":[\"TAG\",\"ATTRIBUTE\",\"FIELD\"],\"timestamps\":[1635232143960,1635232153960,1635232163960,1635232173960,1635232183960],\"column_names\":[\"tag1\",\"t1\",\"s1\"],\"data_types\":[\"STRING\",\"STRING\",\"FLOAT\"],\"values\":[[\"a11\",\"true\",11],[\"a11\",\"false\",22],[\"a13\",\"false1\",23],[\"a14\",\"false2\",24],[\"a15\",\"false3\",25]],\"table\":\"sg211\"}";
JsonObject result = RestUtils.insertTablet(httpClient, port, json);
assertEquals(305, Integer.parseInt(result.get("code").toString()));
}
@@ -302,11 +303,11 @@ public class IoTDBRestServiceIT {
RestUtils.nonQuery(httpClient, port, sqlHandler("test", sql));
}
String json =
-
"{\"database\":\"test\",\"column_catogories\":[\"ATTRIBUTE\",\"FIELD\"],\"timestamps\":[1635232143960,1635232153960,1635232163960,1635232173960,1635232183960],\"column_names\":[\"id1\",\"t1\",\"s1\"],\"data_types\":[\"STRING\",\"STRING\",\"FLOAT\"],\"values\":[[\"a11\",\"true\",11],[\"a11\",\"false\",22],[\"a13\",\"false1\",23],[\"a14\",\"false2\",24],[\"a15\",\"false3\",25]],\"table\":\"sg211\"}";
+
"{\"database\":\"test\",\"column_categories\":[\"ATTRIBUTE\",\"FIELD\"],\"timestamps\":[1635232143960,1635232153960,1635232163960,1635232173960,1635232183960],\"column_names\":[\"id1\",\"t1\",\"s1\"],\"data_types\":[\"STRING\",\"STRING\",\"FLOAT\"],\"values\":[[\"a11\",\"true\",11],[\"a11\",\"false\",22],[\"a13\",\"false1\",23],[\"a14\",\"false2\",24],[\"a15\",\"false3\",25]],\"table\":\"sg211\"}";
JsonObject result = RestUtils.insertTablet(httpClient, port, json);
assertEquals(305, Integer.parseInt(result.get("code").toString()));
assertEquals(
- "column_names and column_catogories should have the same
size,column_catogories and data_types should have the same size",
+ "column_names and column_categories should have the same
size,column_categories and data_types should have the same size",
result.get("message").getAsString());
}
@@ -318,7 +319,7 @@ public class IoTDBRestServiceIT {
RestUtils.nonQuery(httpClient, port, sqlHandler("test", sql));
}
String json =
-
"{\"database\":\"test\",\"column_catogories\":[\"TAG\",\"ATTRIBUTE\",\"FIELD\"],\"timestamps\":[1635232143960,1635232153960,1635232163960,1635232183960],\"column_names\":[\"tag1\",\"t1\",\"s1\"],\"data_types\":[\"STRING\",\"STRING\",\"FLOAT\"],\"values\":[[\"a11\",\"true\",11],[\"a11\",\"false\",22],[\"a13\",\"false1\",23],[\"a14\",\"false2\",24],[\"a15\",\"false3\",25]],\"table\":\"sg211\"}";
+
"{\"database\":\"test\",\"column_categories\":[\"TAG\",\"ATTRIBUTE\",\"FIELD\"],\"timestamps\":[1635232143960,1635232153960,1635232163960,1635232183960],\"column_names\":[\"tag1\",\"t1\",\"s1\"],\"data_types\":[\"STRING\",\"STRING\",\"FLOAT\"],\"values\":[[\"a11\",\"true\",11],[\"a11\",\"false\",22],[\"a13\",\"false1\",23],[\"a14\",\"false2\",24],[\"a15\",\"false3\",25]],\"table\":\"sg211\"}";
JsonObject result = RestUtils.insertTablet(httpClient, port, json);
assertEquals(305, Integer.parseInt(result.get("code").toString()));
assertEquals(
@@ -350,4 +351,25 @@ public class IoTDBRestServiceIT {
RestUtils.nonQuery(httpClient, port, jsonObject.toString());
}
}
+
+ public void inertDateAndBlob() {
+ RestUtils.nonQuery(httpClient, port, sqlHandler("", "create database
test"));
+ String sql = "CREATE TABLE tt (time TIMESTAMP TIME,d Blob FIELD,e date
FIELD)";
+ JsonObject result = RestUtils.nonQuery(httpClient, port,
sqlHandler("test", sql));
+
+ assertEquals(200, Integer.parseInt(result.get("code").toString()));
+ String insertSql = "insert into tt(time,e,d)
values(1,'2025-07-14',X'cafebabe')";
+ result = RestUtils.nonQuery(httpClient, port, sqlHandler("test",
insertSql));
+ System.out.println(result);
+ assertEquals(200, Integer.parseInt(result.get("code").toString()));
+
+ JsonObject queryResult =
+ RestUtils.query(httpClient, port, sqlHandler("test", "select time,e,d
from tt"));
+ JsonArray jsonArray = queryResult.get("values").getAsJsonArray();
+ System.out.println(jsonArray);
+ JsonArray jsonArray1 = jsonArray.get(0).getAsJsonArray();
+ assertEquals(1, jsonArray1.get(0).getAsInt());
+ assertEquals("2025-07-14", jsonArray1.get(1).getAsString());
+ assertEquals("0xcafebabe", jsonArray1.get(2).getAsString());
+ }
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/table/v1/handler/QueryDataSetHandler.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/table/v1/handler/QueryDataSetHandler.java
index 149b99fc028..25e331b38a8 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/table/v1/handler/QueryDataSetHandler.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/table/v1/handler/QueryDataSetHandler.java
@@ -30,6 +30,8 @@ import org.apache.tsfile.block.column.Column;
import org.apache.tsfile.common.conf.TSFileConfig;
import org.apache.tsfile.enums.TSDataType;
import org.apache.tsfile.read.common.block.TsBlock;
+import org.apache.tsfile.utils.BytesUtils;
+import org.apache.tsfile.utils.DateUtils;
import javax.ws.rs.core.Response;
@@ -101,10 +103,7 @@ public class QueryDataSetHandler {
if (column.isNull(i)) {
targetDataSetColumn.add(null);
} else {
- targetDataSetColumn.add(
- column.getDataType().equals(TSDataType.TEXT)
- ?
column.getBinary(i).getStringValue(TSFileConfig.STRING_CHARSET)
- : column.getObject(i));
+ addTypedValueToTarget(targetDataSet.getDataTypes(), k, i,
targetDataSetColumn, column);
}
}
if (k != columnNum - 1) {
@@ -116,6 +115,30 @@ public class QueryDataSetHandler {
return Response.ok().entity(targetDataSet).build();
}
+ private static void addTypedValueToTarget(
+ List<String> dataTypes,
+ int colIndex,
+ int rowIndex,
+ List<Object> targetColumnList,
+ Column column) {
+ String dataTypeName = dataTypes != null ? dataTypes.get(colIndex) : null;
+
+ if (TSDataType.TEXT.name().equals(dataTypeName)) {
+
targetColumnList.add(column.getBinary(rowIndex).getStringValue(TSFileConfig.STRING_CHARSET));
+ } else if (TSDataType.DATE.name().equals(dataTypeName)) {
+ int intValue = column.getInt(rowIndex);
+ targetColumnList.add(DateUtils.formatDate(intValue));
+ } else if (TSDataType.BLOB.name().equals(dataTypeName)) {
+ byte[] v = column.getBinary(rowIndex).getValues();
+ targetColumnList.add(BytesUtils.parseBlobByteArrayToString(v));
+ } else {
+ targetColumnList.add(
+ column.getDataType().equals(TSDataType.TEXT)
+ ?
column.getBinary(rowIndex).getStringValue(TSFileConfig.STRING_CHARSET)
+ : column.getObject(rowIndex));
+ }
+ }
+
private static Response fillOtherDataSet(
IQueryExecution queryExecution, final int actualRowSizeLimit) throws
IoTDBException {
QueryDataSet targetDataSet = new QueryDataSet();
@@ -184,10 +207,7 @@ public class QueryDataSetHandler {
if (column.isNull(i)) {
targetDataSetColumn.add(null);
} else {
- targetDataSetColumn.add(
- column.getDataType().equals(TSDataType.TEXT)
- ?
column.getBinary(i).getStringValue(TSFileConfig.STRING_CHARSET)
- : column.getObject(i));
+ addTypedValueToTarget(targetDataSet.getDataTypes(), k, i,
targetDataSetColumn, column);
}
}
if (k != columnNum - 1) {
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/table/v1/handler/RequestValidationHandler.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/table/v1/handler/RequestValidationHandler.java
index f58e6b447b6..8642f17b562 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/table/v1/handler/RequestValidationHandler.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/table/v1/handler/RequestValidationHandler.java
@@ -43,20 +43,20 @@ public class RequestValidationHandler {
Objects.requireNonNull(insertTabletRequest.getTable(), "table should not
be null");
Objects.requireNonNull(insertTabletRequest.getColumnNames(), "column_names
should not be null");
Objects.requireNonNull(
- insertTabletRequest.getColumnCatogories(), "column_catogories should
not be null");
+ insertTabletRequest.getColumnCategories(), "column_categories should
not be null");
Objects.requireNonNull(insertTabletRequest.getDataTypes(), "data_types
should not be null");
Objects.requireNonNull(insertTabletRequest.getTimestamps(), "timestamps
should not be null");
Objects.requireNonNull(insertTabletRequest.getValues(), "values should not
be null");
List<String> errorMessages = new ArrayList<>();
String table = insertTabletRequest.getTable();
- if (insertTabletRequest.getColumnCatogories().size() == 0
- || insertTabletRequest.getColumnCatogories().size()
+ if (insertTabletRequest.getColumnCategories().size() == 0
+ || insertTabletRequest.getColumnCategories().size()
!= insertTabletRequest.getColumnNames().size()) {
- errorMessages.add("column_names and column_catogories should have the
same size");
+ errorMessages.add("column_names and column_categories should have the
same size");
}
- if (insertTabletRequest.getColumnCatogories().size()
+ if (insertTabletRequest.getColumnCategories().size()
!= insertTabletRequest.getDataTypes().size()) {
- errorMessages.add("column_catogories and data_types should have the same
size");
+ errorMessages.add("column_categories and data_types should have the same
size");
}
if (insertTabletRequest.getTimestamps().size() !=
insertTabletRequest.getValues().size()) {
errorMessages.add("values and timestamps should have the same size");
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/table/v1/handler/StatementConstructionHandler.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/table/v1/handler/StatementConstructionHandler.java
index a5a19ebf0d1..70f3cfb826e 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/table/v1/handler/StatementConstructionHandler.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/table/v1/handler/StatementConstructionHandler.java
@@ -175,11 +175,11 @@ public class StatementConstructionHandler {
insertStatement.setAligned(false);
insertStatement.setWriteToTable(true);
TsTableColumnCategory[] columnCategories =
- new
TsTableColumnCategory[insertTabletReq.getColumnCatogories().size()];
+ new
TsTableColumnCategory[insertTabletReq.getColumnCategories().size()];
for (int i = 0; i < columnCategories.length; i++) {
columnCategories[i] =
TsTableColumnCategory.fromTsFileColumnCategory(
-
ColumnCategory.valueOf(insertTabletReq.getColumnCatogories().get(i)));
+
ColumnCategory.valueOf(insertTabletReq.getColumnCategories().get(i)));
}
insertStatement.setColumnCategories(columnCategories);
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v1/handler/QueryDataSetHandler.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v1/handler/QueryDataSetHandler.java
index c82b07c0603..8accae7991b 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v1/handler/QueryDataSetHandler.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v1/handler/QueryDataSetHandler.java
@@ -34,6 +34,8 @@ import org.apache.tsfile.block.column.Column;
import org.apache.tsfile.common.conf.TSFileConfig;
import org.apache.tsfile.enums.TSDataType;
import org.apache.tsfile.read.common.block.TsBlock;
+import org.apache.tsfile.utils.BytesUtils;
+import org.apache.tsfile.utils.DateUtils;
import javax.ws.rs.core.Response;
@@ -91,8 +93,10 @@ public class QueryDataSetHandler {
new org.apache.iotdb.db.protocol.rest.v1.model.QueryDataSet();
DatasetHeader datasetHeader = queryExecution.getDatasetHeader();
+ List<TSDataType> dataTypes = new ArrayList<>();
int[] targetDataSetIndexToSourceDataSetIndex = new
int[datasetHeader.getRespColumns().size()];
for (int i = 0; i < datasetHeader.getRespColumns().size(); i++) {
+ dataTypes.add(datasetHeader.getColumnHeaders().get(i).getColumnType());
targetDataSet.addExpressionsItem(datasetHeader.getRespColumns().get(i));
targetDataSet.addValuesItem(new ArrayList<>());
targetDataSetIndexToSourceDataSetIndex[i] =
@@ -100,7 +104,11 @@ public class QueryDataSetHandler {
}
return fillQueryDataSetWithoutTimestamps(
- queryExecution, targetDataSetIndexToSourceDataSetIndex,
actualRowSizeLimit, targetDataSet);
+ queryExecution,
+ targetDataSetIndexToSourceDataSetIndex,
+ actualRowSizeLimit,
+ targetDataSet,
+ dataTypes);
}
private static Response fillShowPlanDataSet(
@@ -113,7 +121,11 @@ public class QueryDataSetHandler {
queryExecution.getDatasetHeader(),
targetDataSetIndexToSourceDataSetIndex, targetDataSet);
return fillQueryDataSetWithoutTimestamps(
- queryExecution, targetDataSetIndexToSourceDataSetIndex,
actualRowSizeLimit, targetDataSet);
+ queryExecution,
+ targetDataSetIndexToSourceDataSetIndex,
+ actualRowSizeLimit,
+ targetDataSet,
+ null);
}
private static void initTargetDatasetOrderByOrderWithSourceDataSet(
@@ -141,6 +153,7 @@ public class QueryDataSetHandler {
DatasetHeader header = queryExecution.getDatasetHeader();
List<String> resultColumns = header.getRespColumns();
Map<String, Integer> headerMap = header.getColumnNameIndexMap();
+ List<TSDataType> dataTypes = header.getRespDataTypes();
for (String resultColumn : resultColumns) {
targetDataSet.addExpressionsItem(resultColumn);
targetDataSet.addValuesItem(new ArrayList<>());
@@ -184,10 +197,7 @@ public class QueryDataSetHandler {
if (column.isNull(i)) {
targetDataSetColumn.add(null);
} else {
- targetDataSetColumn.add(
- column.getDataType().equals(TSDataType.TEXT)
- ?
column.getBinary(i).getStringValue(TSFileConfig.STRING_CHARSET)
- : column.getObject(i));
+ addTypedValueToTarget(dataTypes, k, i, targetDataSetColumn,
column);
}
}
if (k != columnNum - 1) {
@@ -202,7 +212,8 @@ public class QueryDataSetHandler {
IQueryExecution queryExecution,
int[] targetDataSetIndexToSourceDataSetIndex,
int actualRowSizeLimit,
- org.apache.iotdb.db.protocol.rest.v1.model.QueryDataSet targetDataSet)
+ org.apache.iotdb.db.protocol.rest.v1.model.QueryDataSet targetDataSet,
+ List<TSDataType> dataTypes)
throws IoTDBException {
int fetched = 0;
int columnNum = queryExecution.getOutputValueColumnCount();
@@ -240,10 +251,7 @@ public class QueryDataSetHandler {
if (column.isNull(i)) {
targetDataSetColumn.add(null);
} else {
- targetDataSetColumn.add(
- column.getDataType().equals(TSDataType.TEXT)
- ?
column.getBinary(i).getStringValue(TSFileConfig.STRING_CHARSET)
- : column.getObject(i));
+ addTypedValueToTarget(dataTypes, k, i, targetDataSetColumn,
column);
}
}
if (k != columnNum - 1) {
@@ -254,6 +262,30 @@ public class QueryDataSetHandler {
return Response.ok().entity(targetDataSet).build();
}
+ private static void addTypedValueToTarget(
+ List<TSDataType> dataTypes,
+ int colIndex,
+ int rowIndex,
+ List<Object> targetColumnList,
+ Column column) {
+ String dataTypeName = dataTypes != null ? dataTypes.get(colIndex).name() :
null;
+
+ if (TSDataType.TEXT.name().equals(dataTypeName)) {
+
targetColumnList.add(column.getBinary(rowIndex).getStringValue(TSFileConfig.STRING_CHARSET));
+ } else if (TSDataType.DATE.name().equals(dataTypeName)) {
+ int intValue = column.getInt(rowIndex);
+ targetColumnList.add(DateUtils.formatDate(intValue));
+ } else if (TSDataType.BLOB.name().equals(dataTypeName)) {
+ byte[] v = column.getBinary(rowIndex).getValues();
+ targetColumnList.add(BytesUtils.parseBlobByteArrayToString(v));
+ } else {
+ targetColumnList.add(
+ column.getDataType().equals(TSDataType.TEXT)
+ ?
column.getBinary(rowIndex).getStringValue(TSFileConfig.STRING_CHARSET)
+ : column.getObject(rowIndex));
+ }
+ }
+
public static Response fillGrafanaVariablesResult(
IQueryExecution queryExecution, Statement statement) throws
IoTDBException {
List<String> results = new ArrayList<>();
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v2/handler/QueryDataSetHandler.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v2/handler/QueryDataSetHandler.java
index f3f7d68dd0b..fed6e3ec80a 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v2/handler/QueryDataSetHandler.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v2/handler/QueryDataSetHandler.java
@@ -34,6 +34,8 @@ import org.apache.tsfile.block.column.Column;
import org.apache.tsfile.common.conf.TSFileConfig;
import org.apache.tsfile.enums.TSDataType;
import org.apache.tsfile.read.common.block.TsBlock;
+import org.apache.tsfile.utils.BytesUtils;
+import org.apache.tsfile.utils.DateUtils;
import javax.ws.rs.core.Response;
@@ -188,10 +190,7 @@ public class QueryDataSetHandler {
if (column.isNull(i)) {
targetDataSetColumn.add(null);
} else {
- targetDataSetColumn.add(
- column.getDataType().equals(TSDataType.TEXT)
- ?
column.getBinary(i).getStringValue(TSFileConfig.STRING_CHARSET)
- : column.getObject(i));
+ addTypedValueToTarget(targetDataSet.getDataTypes(), k, i,
targetDataSetColumn, column);
}
}
if (k != columnNum - 1) {
@@ -210,6 +209,7 @@ public class QueryDataSetHandler {
throws IoTDBException {
int fetched = 0;
int columnNum = queryExecution.getOutputValueColumnCount();
+ List<String> dataTypes = targetDataSet.getDataTypes();
while (true) {
if (0 < actualRowSizeLimit && actualRowSizeLimit <= fetched) {
return Response.ok()
@@ -244,10 +244,7 @@ public class QueryDataSetHandler {
if (column.isNull(i)) {
targetDataSetColumn.add(null);
} else {
- targetDataSetColumn.add(
- column.getDataType().equals(TSDataType.TEXT)
- ?
column.getBinary(i).getStringValue(TSFileConfig.STRING_CHARSET)
- : column.getObject(i));
+ addTypedValueToTarget(dataTypes, k, i, targetDataSetColumn,
column);
}
}
if (k != columnNum - 1) {
@@ -258,6 +255,30 @@ public class QueryDataSetHandler {
return Response.ok().entity(targetDataSet).build();
}
+ private static void addTypedValueToTarget(
+ List<String> dataTypes,
+ int colIndex,
+ int rowIndex,
+ List<Object> targetColumnList,
+ Column column) {
+ String dataTypeName = dataTypes != null ? dataTypes.get(colIndex) : null;
+
+ if (TSDataType.TEXT.name().equals(dataTypeName)) {
+
targetColumnList.add(column.getBinary(rowIndex).getStringValue(TSFileConfig.STRING_CHARSET));
+ } else if (TSDataType.DATE.name().equals(dataTypeName)) {
+ int intValue = column.getInt(rowIndex);
+ targetColumnList.add(DateUtils.formatDate(intValue));
+ } else if (TSDataType.BLOB.name().equals(dataTypeName)) {
+ byte[] v = column.getBinary(rowIndex).getValues();
+ targetColumnList.add(BytesUtils.parseBlobByteArrayToString(v));
+ } else {
+ targetColumnList.add(
+ column.getDataType().equals(TSDataType.TEXT)
+ ?
column.getBinary(rowIndex).getStringValue(TSFileConfig.STRING_CHARSET)
+ : column.getObject(rowIndex));
+ }
+ }
+
public static Response fillGrafanaVariablesResult(
IQueryExecution queryExecution, Statement statement) throws
IoTDBException {
List<String> results = new ArrayList<>();
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 53699256761..e9ac41f833d 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
@@ -53,6 +53,7 @@ import
org.apache.iotdb.db.queryengine.plan.parser.StatementGenerator;
import
org.apache.iotdb.db.queryengine.plan.relational.metadata.fetcher.cache.TableDeviceSchemaCache;
import
org.apache.iotdb.db.queryengine.plan.relational.metadata.fetcher.cache.TableId;
import org.apache.iotdb.db.queryengine.plan.statement.Statement;
+import org.apache.iotdb.db.queryengine.plan.statement.StatementType;
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.schemaengine.SchemaEngine;
@@ -204,11 +205,13 @@ public class RestApiServiceImpl extends RestApiService {
return
Response.ok().entity(ExceptionHandler.tryCatchException(e)).build();
} finally {
long costTime = System.nanoTime() - startTime;
- Optional.ofNullable(statement)
- .ifPresent(
- s ->
- CommonUtils.addStatementExecutionLatency(
- OperationType.EXECUTE_QUERY_STATEMENT,
s.getType().name(), costTime));
+ String statementType =
+ Optional.ofNullable(statement)
+ .map(s -> s.getType().name())
+ .orElse(StatementType.FAST_LAST_QUERY.name());
+
+ CommonUtils.addStatementExecutionLatency(
+ OperationType.EXECUTE_QUERY_STATEMENT, statementType, costTime);
if (queryId != null) {
if (finish) {
long executionTime = COORDINATOR.getTotalExecutionTime(queryId);
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/StatementType.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/StatementType.java
index 4d5fe5dbf3f..748241d189b 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/StatementType.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/StatementType.java
@@ -185,5 +185,7 @@ public enum StatementType {
SHOW_SUBSCRIPTIONS,
DROP_SUBSCRIPTION,
- SET_CONFIGURATION
+ SET_CONFIGURATION,
+
+ FAST_LAST_QUERY
}
diff --git a/iotdb-protocol/openapi/src/main/openapi3/iotdb_rest_table_v1.yaml
b/iotdb-protocol/openapi/src/main/openapi3/iotdb_rest_table_v1.yaml
index 205174afab9..36cec631b54 100644
--- a/iotdb-protocol/openapi/src/main/openapi3/iotdb_rest_table_v1.yaml
+++ b/iotdb-protocol/openapi/src/main/openapi3/iotdb_rest_table_v1.yaml
@@ -112,7 +112,7 @@ components:
type: array
items:
type: string
- column_catogories:
+ column_categories:
type: array
items:
type: string