Copilot commented on code in PR #17076:
URL: https://github.com/apache/iotdb/pull/17076#discussion_r2726321552
##########
iotdb-client/cli/src/main/java/org/apache/iotdb/tool/data/ExportData.java:
##########
@@ -707,128 +705,157 @@ public static void writeCsvFile(
}
}
- public static void writeSqlFile(
- SessionDataSet sessionDataSet, String filePath, List<String> headers,
int linesPerFile)
+ private static void exportToSqlFileWithAlignDevice(
+ SessionDataSet sessionDataSet, String filePath, List<String>
measurementNames)
throws IOException, IoTDBConnectionException,
StatementExecutionException {
+
+ if (CollectionUtils.isEmpty(measurementNames) || measurementNames.size()
<= 1) {
+ return;
+ } else {
+ measurementNames.remove("Time");
+ measurementNames.remove("Device");
+ }
+ String sqlPrefix =
+ String.format(
+ "INSERT INTO %s(TIMESTAMP,%s) ALIGNED VALUES (%s);\n",
+ "%s", String.join(",", measurementNames), "%d,%s");
+
+ SessionDataSet.DataIterator iterator = sessionDataSet.iterator();
+ List<String> columnTypeList = iterator.getColumnTypeList();
+ int totalColumns = columnTypeList.size();
+ String deviceName = null;
int fileIndex = 0;
+ int currentLines = 0;
+ String filePathTemplate = filePath + "_%d" + ".sql";
+ FileWriter writer = null;
+ while (iterator.next()) {
+ if (writer == null) {
+ writer = new FileWriter(String.format(filePathTemplate, fileIndex));
+ }
+ deviceName = iterator.getString(2);
+ if (deviceName.startsWith(SYSTEM_DATABASE + ".")) {
+ continue;
+ }
+ List<String> values = new ArrayList<>();
+ for (int index = 2; index < totalColumns; index++) {
+ String dataType = columnTypeList.get(index);
+ String value = iterator.getString(index + 1);
+ if (value == null) {
+ values.add("null");
+ continue;
+ }
+ if ("TEXT".equalsIgnoreCase(dataType)
+ || "STRING".equalsIgnoreCase(dataType)
+ || "DATE".equalsIgnoreCase(dataType)) {
+ values.add(String.format("\"%s\"", value));
+ } else if ("BLOB".equalsIgnoreCase(dataType)) {
+ values.add(String.format("X'%s'", value.substring(2)));
+ } else {
+ values.add(value);
+ }
+ }
+ long timestamp = iterator.getLong(1);
+ writer.write(String.format(sqlPrefix, deviceName, timestamp,
String.join(",", values)));
+ currentLines += 1;
+
+ if (currentLines >= linesPerFile) {
+ writer.flush();
+ writer.close();
+ fileIndex += 1;
+ writer = null;
+ currentLines = 0;
+ }
+ }
+ if (writer != null) {
+ writer.flush();
+ writer.close();
+ }
+ ioTPrinter.print("\n");
+ }
+
+ private static void exportToSqlFileWithoutAlign(
+ SessionDataSet sessionDataSet, String filePath, List<String> headers)
+ throws IoTDBConnectionException, StatementExecutionException,
IOException {
+
+ List<String> measurementNames = new ArrayList<>();
String deviceName = null;
- boolean writeNull = false;
- List<String> seriesList = new ArrayList<>(headers);
if (CollectionUtils.isEmpty(headers) || headers.size() <= 1) {
- writeNull = true;
+ return;
} else {
- if (headers.contains("Device")) {
- seriesList.remove("Time");
- seriesList.remove("Device");
- } else {
- Path path = new Path(seriesList.get(1), true);
- deviceName = path.getDevice();
- seriesList.remove("Time");
- for (int i = 0; i < seriesList.size(); i++) {
- String series = seriesList.get(i);
- path = new Path(series, true);
- seriesList.set(i, path.getMeasurement());
+ headers.remove("Time");
+ Path path = new Path(headers.get(0), true);
+ deviceName = path.getDevice();
+ for (String header : headers) {
+ path = new Path(header, true);
+ String meas = path.getMeasurement();
+ if (path.getDevice().equals(deviceName)) {
+ measurementNames.add(meas);
}
}
}
- boolean hasNext = true;
- while (hasNext) {
- int i = 0;
- final String finalFilePath = filePath + "_" + fileIndex + ".sql";
- try (FileWriter writer = new FileWriter(finalFilePath)) {
- if (writeNull) {
- break;
+ if (deviceName.startsWith(SYSTEM_DATABASE + ".")) {
+ return;
+ }
+ String sqlPrefix =
+ String.format(
+ "INSERT INTO %s(TIMESTAMP,%s) VALUES (%s);\n",
+ "%s", String.join(",", measurementNames), "%d,%s");
+
+ SessionDataSet.DataIterator iterator = sessionDataSet.iterator();
+ List<String> columnTypeList = iterator.getColumnTypeList();
+ int totalColumns = measurementNames.size();
+ int fileIndex = 0;
+ int currentLines = 0;
+ String filePathTemplate = filePath + "_%d" + ".sql";
+ FileWriter writer = null;
+ while (iterator.next()) {
+ if (writer == null) {
+ writer = new FileWriter(String.format(filePathTemplate, fileIndex));
+ }
+ List<String> values = new ArrayList<>();
+ for (int index = 0; index < totalColumns; index++) {
+ String dataType = columnTypeList.get(index + 1);
+ String value = iterator.getString(index + 2);
+ if (value == null) {
+ values.add("null");
+ continue;
}
- while (i++ < linesPerFile) {
- if (sessionDataSet.hasNext()) {
- RowRecord rowRecord = sessionDataSet.next();
- List<Field> fields = rowRecord.getFields();
- List<String> headersTemp = new ArrayList<>(seriesList);
- List<String> timeseries = new ArrayList<>();
- if (headers.contains("Device")) {
- deviceName = fields.get(0).toString();
- if (deviceName.startsWith(SYSTEM_DATABASE + ".")) {
- continue;
- }
- for (String header : headersTemp) {
- timeseries.add(deviceName + "." + header);
- }
- } else {
- if (headers.get(1).startsWith(SYSTEM_DATABASE + ".")) {
- continue;
- }
- timeseries.addAll(headers);
- timeseries.remove(0);
- }
- String sqlMiddle = null;
- if (Boolean.TRUE.equals(aligned)) {
- sqlMiddle = " ALIGNED VALUES (" + rowRecord.getTimestamp() + ",";
- } else {
- sqlMiddle = " VALUES (" + rowRecord.getTimestamp() + ",";
- }
- List<String> values = new ArrayList<>();
- if (headers.contains("Device")) {
- fields.remove(0);
- }
- for (int index = 0; index < fields.size(); index++) {
- RowRecord next =
- session
- .executeQueryStatement("SHOW TIMESERIES " +
timeseries.get(index), timeout)
- .next();
- if (ObjectUtils.isNotEmpty(next)) {
- List<Field> timeseriesList = next.getFields();
- String value = fields.get(index).toString();
- if (value.equals("null")) {
- headersTemp.remove(seriesList.get(index));
- continue;
- }
- final String dataType = timeseriesList.get(3).getStringValue();
- if (TSDataType.TEXT.name().equalsIgnoreCase(dataType)
- || TSDataType.STRING.name().equalsIgnoreCase(dataType)) {
- values.add("\'" + value + "\'");
- } else if (TSDataType.BLOB.name().equalsIgnoreCase(dataType)) {
- final byte[] v = fields.get(index).getBinaryV().getValues();
- if (v == null) {
- values.add(null);
- } else {
- values.add(
-
BytesUtils.parseBlobByteArrayToString(v).replaceFirst("0x", "X'") + "'");
- }
- } else if (TSDataType.DATE.name().equalsIgnoreCase(dataType)) {
- final LocalDate dateV = fields.get(index).getDateV();
- if (dateV == null) {
- values.add(null);
- } else {
- values.add("'" + dateV.toString() + "'");
- }
- } else {
- values.add(value);
- }
- } else {
- headersTemp.remove(seriesList.get(index));
- continue;
- }
- }
- if (CollectionUtils.isNotEmpty(headersTemp)) {
- writer.write(
- "INSERT INTO "
- + deviceName
- + "(TIMESTAMP,"
- + String.join(",", headersTemp)
- + ")"
- + sqlMiddle
- + String.join(",", values)
- + ");\n");
- }
-
- } else {
- hasNext = false;
- break;
- }
+ if ("TEXT".equalsIgnoreCase(dataType)
+ || "STRING".equalsIgnoreCase(dataType)
+ || "DATE".equalsIgnoreCase(dataType)) {
+ values.add(String.format("\"%s\"", value));
+ } else if ("BLOB".equalsIgnoreCase(dataType)) {
+ values.add(String.format("X'%s'", value.substring(2)));
+ } else {
+ values.add(value);
}
- fileIndex++;
+ }
+ long timestamp = iterator.getLong(1);
+ writer.write(String.format(sqlPrefix, deviceName, timestamp,
String.join(",", values)));
+ currentLines += 1;
+
+ if (currentLines >= linesPerFile) {
writer.flush();
+ writer.close();
+ fileIndex += 1;
+ writer = null;
+ currentLines = 0;
}
}
+ if (writer != null) {
+ writer.flush();
+ writer.close();
+ }
+ ioTPrinter.print("\n");
+ }
+
+ public static void writeSqlFile(
+ SessionDataSet sessionDataSet, String filePath, List<String> headers,
int linesPerFile)
+ throws IOException, IoTDBConnectionException,
StatementExecutionException {
+ if (headers.contains("Device")) {
+ exportToSqlFileWithAlignDevice(sessionDataSet, filePath, headers);
+ } else {
+ exportToSqlFileWithoutAlign(sessionDataSet, filePath, headers);
+ }
}
Review Comment:
The `linesPerFile` parameter is passed to `writeSqlFile` but is not passed
to the helper methods `exportToSqlFileWithAlignDevice` and
`exportToSqlFileWithoutAlign`. These methods reference the class-level static
field `linesPerFile` directly instead. This means the parameter value passed to
`writeSqlFile` is ignored, and the class-level default value or previously set
value is used instead. The `linesPerFile` parameter should be added to both
helper method signatures and passed from `writeSqlFile`.
##########
iotdb-client/cli/src/main/java/org/apache/iotdb/tool/data/ExportData.java:
##########
@@ -707,128 +705,157 @@ public static void writeCsvFile(
}
}
- public static void writeSqlFile(
- SessionDataSet sessionDataSet, String filePath, List<String> headers,
int linesPerFile)
+ private static void exportToSqlFileWithAlignDevice(
+ SessionDataSet sessionDataSet, String filePath, List<String>
measurementNames)
throws IOException, IoTDBConnectionException,
StatementExecutionException {
+
+ if (CollectionUtils.isEmpty(measurementNames) || measurementNames.size()
<= 1) {
+ return;
+ } else {
+ measurementNames.remove("Time");
+ measurementNames.remove("Device");
+ }
+ String sqlPrefix =
+ String.format(
+ "INSERT INTO %s(TIMESTAMP,%s) ALIGNED VALUES (%s);\n",
+ "%s", String.join(",", measurementNames), "%d,%s");
+
+ SessionDataSet.DataIterator iterator = sessionDataSet.iterator();
+ List<String> columnTypeList = iterator.getColumnTypeList();
+ int totalColumns = columnTypeList.size();
+ String deviceName = null;
int fileIndex = 0;
+ int currentLines = 0;
+ String filePathTemplate = filePath + "_%d" + ".sql";
+ FileWriter writer = null;
+ while (iterator.next()) {
+ if (writer == null) {
+ writer = new FileWriter(String.format(filePathTemplate, fileIndex));
+ }
+ deviceName = iterator.getString(2);
+ if (deviceName.startsWith(SYSTEM_DATABASE + ".")) {
+ continue;
+ }
+ List<String> values = new ArrayList<>();
+ for (int index = 2; index < totalColumns; index++) {
+ String dataType = columnTypeList.get(index);
+ String value = iterator.getString(index + 1);
+ if (value == null) {
+ values.add("null");
+ continue;
+ }
+ if ("TEXT".equalsIgnoreCase(dataType)
+ || "STRING".equalsIgnoreCase(dataType)
+ || "DATE".equalsIgnoreCase(dataType)) {
+ values.add(String.format("\"%s\"", value));
+ } else if ("BLOB".equalsIgnoreCase(dataType)) {
+ values.add(String.format("X'%s'", value.substring(2)));
+ } else {
+ values.add(value);
+ }
+ }
+ long timestamp = iterator.getLong(1);
+ writer.write(String.format(sqlPrefix, deviceName, timestamp,
String.join(",", values)));
+ currentLines += 1;
+
+ if (currentLines >= linesPerFile) {
+ writer.flush();
+ writer.close();
+ fileIndex += 1;
+ writer = null;
+ currentLines = 0;
+ }
+ }
+ if (writer != null) {
+ writer.flush();
+ writer.close();
+ }
+ ioTPrinter.print("\n");
+ }
+
+ private static void exportToSqlFileWithoutAlign(
+ SessionDataSet sessionDataSet, String filePath, List<String> headers)
+ throws IoTDBConnectionException, StatementExecutionException,
IOException {
+
+ List<String> measurementNames = new ArrayList<>();
String deviceName = null;
- boolean writeNull = false;
- List<String> seriesList = new ArrayList<>(headers);
if (CollectionUtils.isEmpty(headers) || headers.size() <= 1) {
- writeNull = true;
+ return;
} else {
- if (headers.contains("Device")) {
- seriesList.remove("Time");
- seriesList.remove("Device");
- } else {
- Path path = new Path(seriesList.get(1), true);
- deviceName = path.getDevice();
- seriesList.remove("Time");
- for (int i = 0; i < seriesList.size(); i++) {
- String series = seriesList.get(i);
- path = new Path(series, true);
- seriesList.set(i, path.getMeasurement());
+ headers.remove("Time");
+ Path path = new Path(headers.get(0), true);
+ deviceName = path.getDevice();
+ for (String header : headers) {
+ path = new Path(header, true);
+ String meas = path.getMeasurement();
+ if (path.getDevice().equals(deviceName)) {
+ measurementNames.add(meas);
}
}
}
- boolean hasNext = true;
- while (hasNext) {
- int i = 0;
- final String finalFilePath = filePath + "_" + fileIndex + ".sql";
- try (FileWriter writer = new FileWriter(finalFilePath)) {
- if (writeNull) {
- break;
+ if (deviceName.startsWith(SYSTEM_DATABASE + ".")) {
+ return;
+ }
+ String sqlPrefix =
+ String.format(
+ "INSERT INTO %s(TIMESTAMP,%s) VALUES (%s);\n",
+ "%s", String.join(",", measurementNames), "%d,%s");
Review Comment:
If all headers have different devices than the first one, `measurementNames`
will be empty after the filtering loop (lines 788-794). This would result in a
malformed SQL statement with an empty column list in line 801. Consider adding
a check to return early if `measurementNames` is empty after filtering.
##########
iotdb-client/cli/src/main/java/org/apache/iotdb/tool/data/ExportData.java:
##########
@@ -707,128 +705,157 @@ public static void writeCsvFile(
}
}
- public static void writeSqlFile(
- SessionDataSet sessionDataSet, String filePath, List<String> headers,
int linesPerFile)
+ private static void exportToSqlFileWithAlignDevice(
+ SessionDataSet sessionDataSet, String filePath, List<String>
measurementNames)
throws IOException, IoTDBConnectionException,
StatementExecutionException {
+
+ if (CollectionUtils.isEmpty(measurementNames) || measurementNames.size()
<= 1) {
+ return;
+ } else {
+ measurementNames.remove("Time");
+ measurementNames.remove("Device");
Review Comment:
The size check at line 712 allows lists with size 2 to proceed, but if the
list contains exactly ["Time", "Device"], the subsequent removals (lines
715-716) will result in an empty `measurementNames` list. This would create a
malformed SQL statement with an empty column list at line 720. Consider
checking if `measurementNames.size() <= 2` or adding a check after the removals
to ensure the list is not empty.
```suggestion
measurementNames.remove("Device");
if (CollectionUtils.isEmpty(measurementNames)) {
// No measurement columns remain after removing Time and Device;
nothing to export.
return;
}
```
##########
iotdb-client/cli/src/main/java/org/apache/iotdb/tool/data/ExportData.java:
##########
@@ -707,128 +705,157 @@ public static void writeCsvFile(
}
}
- public static void writeSqlFile(
- SessionDataSet sessionDataSet, String filePath, List<String> headers,
int linesPerFile)
+ private static void exportToSqlFileWithAlignDevice(
+ SessionDataSet sessionDataSet, String filePath, List<String>
measurementNames)
throws IOException, IoTDBConnectionException,
StatementExecutionException {
+
+ if (CollectionUtils.isEmpty(measurementNames) || measurementNames.size()
<= 1) {
+ return;
+ } else {
+ measurementNames.remove("Time");
+ measurementNames.remove("Device");
+ }
+ String sqlPrefix =
+ String.format(
+ "INSERT INTO %s(TIMESTAMP,%s) ALIGNED VALUES (%s);\n",
+ "%s", String.join(",", measurementNames), "%d,%s");
+
+ SessionDataSet.DataIterator iterator = sessionDataSet.iterator();
+ List<String> columnTypeList = iterator.getColumnTypeList();
+ int totalColumns = columnTypeList.size();
+ String deviceName = null;
int fileIndex = 0;
+ int currentLines = 0;
+ String filePathTemplate = filePath + "_%d" + ".sql";
+ FileWriter writer = null;
+ while (iterator.next()) {
+ if (writer == null) {
+ writer = new FileWriter(String.format(filePathTemplate, fileIndex));
+ }
+ deviceName = iterator.getString(2);
+ if (deviceName.startsWith(SYSTEM_DATABASE + ".")) {
+ continue;
+ }
+ List<String> values = new ArrayList<>();
+ for (int index = 2; index < totalColumns; index++) {
+ String dataType = columnTypeList.get(index);
+ String value = iterator.getString(index + 1);
+ if (value == null) {
+ values.add("null");
+ continue;
+ }
+ if ("TEXT".equalsIgnoreCase(dataType)
+ || "STRING".equalsIgnoreCase(dataType)
+ || "DATE".equalsIgnoreCase(dataType)) {
+ values.add(String.format("\"%s\"", value));
+ } else if ("BLOB".equalsIgnoreCase(dataType)) {
+ values.add(String.format("X'%s'", value.substring(2)));
+ } else {
+ values.add(value);
+ }
+ }
+ long timestamp = iterator.getLong(1);
+ writer.write(String.format(sqlPrefix, deviceName, timestamp,
String.join(",", values)));
+ currentLines += 1;
+
+ if (currentLines >= linesPerFile) {
+ writer.flush();
+ writer.close();
+ fileIndex += 1;
+ writer = null;
+ currentLines = 0;
+ }
+ }
+ if (writer != null) {
+ writer.flush();
+ writer.close();
+ }
+ ioTPrinter.print("\n");
+ }
+
+ private static void exportToSqlFileWithoutAlign(
+ SessionDataSet sessionDataSet, String filePath, List<String> headers)
+ throws IoTDBConnectionException, StatementExecutionException,
IOException {
+
+ List<String> measurementNames = new ArrayList<>();
String deviceName = null;
- boolean writeNull = false;
- List<String> seriesList = new ArrayList<>(headers);
if (CollectionUtils.isEmpty(headers) || headers.size() <= 1) {
- writeNull = true;
+ return;
} else {
- if (headers.contains("Device")) {
- seriesList.remove("Time");
- seriesList.remove("Device");
- } else {
- Path path = new Path(seriesList.get(1), true);
- deviceName = path.getDevice();
- seriesList.remove("Time");
- for (int i = 0; i < seriesList.size(); i++) {
- String series = seriesList.get(i);
- path = new Path(series, true);
- seriesList.set(i, path.getMeasurement());
+ headers.remove("Time");
+ Path path = new Path(headers.get(0), true);
+ deviceName = path.getDevice();
+ for (String header : headers) {
Review Comment:
The method directly modifies the `headers` parameter by removing the "Time"
entry. This mutation affects the caller's data structure and could cause
unintended side effects. Consider creating a copy of the list before
modification.
```suggestion
List<String> localHeaders = new ArrayList<>(headers);
localHeaders.remove("Time");
Path path = new Path(localHeaders.get(0), true);
deviceName = path.getDevice();
for (String header : localHeaders) {
```
##########
iotdb-client/cli/src/main/java/org/apache/iotdb/tool/data/ExportData.java:
##########
@@ -707,128 +705,157 @@ public static void writeCsvFile(
}
}
- public static void writeSqlFile(
- SessionDataSet sessionDataSet, String filePath, List<String> headers,
int linesPerFile)
+ private static void exportToSqlFileWithAlignDevice(
+ SessionDataSet sessionDataSet, String filePath, List<String>
measurementNames)
throws IOException, IoTDBConnectionException,
StatementExecutionException {
+
+ if (CollectionUtils.isEmpty(measurementNames) || measurementNames.size()
<= 1) {
+ return;
+ } else {
+ measurementNames.remove("Time");
+ measurementNames.remove("Device");
+ }
+ String sqlPrefix =
+ String.format(
+ "INSERT INTO %s(TIMESTAMP,%s) ALIGNED VALUES (%s);\n",
+ "%s", String.join(",", measurementNames), "%d,%s");
Review Comment:
The method directly modifies the `measurementNames` parameter by removing
"Time" and "Device" entries. Since the `headers` list is passed from the caller
and this method receives it as `measurementNames`, this mutation could affect
the caller's data structure. Consider creating a copy of the list before
modification to avoid unintended side effects.
```suggestion
List<String> effectiveMeasurementNames = new
ArrayList<>(measurementNames);
if (CollectionUtils.isEmpty(effectiveMeasurementNames) ||
effectiveMeasurementNames.size() <= 1) {
return;
} else {
effectiveMeasurementNames.remove("Time");
effectiveMeasurementNames.remove("Device");
}
String sqlPrefix =
String.format(
"INSERT INTO %s(TIMESTAMP,%s) ALIGNED VALUES (%s);\n",
"%s", String.join(",", effectiveMeasurementNames), "%d,%s");
```
##########
iotdb-client/cli/src/main/java/org/apache/iotdb/tool/data/ExportData.java:
##########
@@ -707,128 +705,157 @@ public static void writeCsvFile(
}
}
- public static void writeSqlFile(
- SessionDataSet sessionDataSet, String filePath, List<String> headers,
int linesPerFile)
+ private static void exportToSqlFileWithAlignDevice(
+ SessionDataSet sessionDataSet, String filePath, List<String>
measurementNames)
throws IOException, IoTDBConnectionException,
StatementExecutionException {
+
+ if (CollectionUtils.isEmpty(measurementNames) || measurementNames.size()
<= 1) {
+ return;
+ } else {
+ measurementNames.remove("Time");
+ measurementNames.remove("Device");
+ }
+ String sqlPrefix =
+ String.format(
+ "INSERT INTO %s(TIMESTAMP,%s) ALIGNED VALUES (%s);\n",
+ "%s", String.join(",", measurementNames), "%d,%s");
+
+ SessionDataSet.DataIterator iterator = sessionDataSet.iterator();
+ List<String> columnTypeList = iterator.getColumnTypeList();
+ int totalColumns = columnTypeList.size();
+ String deviceName = null;
int fileIndex = 0;
+ int currentLines = 0;
+ String filePathTemplate = filePath + "_%d" + ".sql";
+ FileWriter writer = null;
+ while (iterator.next()) {
+ if (writer == null) {
+ writer = new FileWriter(String.format(filePathTemplate, fileIndex));
+ }
+ deviceName = iterator.getString(2);
+ if (deviceName.startsWith(SYSTEM_DATABASE + ".")) {
+ continue;
+ }
+ List<String> values = new ArrayList<>();
+ for (int index = 2; index < totalColumns; index++) {
+ String dataType = columnTypeList.get(index);
+ String value = iterator.getString(index + 1);
+ if (value == null) {
+ values.add("null");
+ continue;
+ }
+ if ("TEXT".equalsIgnoreCase(dataType)
+ || "STRING".equalsIgnoreCase(dataType)
+ || "DATE".equalsIgnoreCase(dataType)) {
+ values.add(String.format("\"%s\"", value));
+ } else if ("BLOB".equalsIgnoreCase(dataType)) {
+ values.add(String.format("X'%s'", value.substring(2)));
Review Comment:
The BLOB value formatting assumes the string value starts with "0x" (line
752: `value.substring(2)`). If the getString method returns a BLOB value in a
different format, this will cause a StringIndexOutOfBoundsException. Consider
adding validation or using a safer approach to handle BLOB values.
```suggestion
if (value.length() > 2 && (value.startsWith("0x") ||
value.startsWith("0X"))) {
values.add(String.format("X'%s'", value.substring(2)));
} else {
// Fallback: use the value as-is without stripping a prefix to
avoid exceptions
values.add(String.format("X'%s'", value));
}
```
##########
iotdb-client/cli/src/main/java/org/apache/iotdb/tool/data/ExportData.java:
##########
@@ -707,128 +705,157 @@ public static void writeCsvFile(
}
}
- public static void writeSqlFile(
- SessionDataSet sessionDataSet, String filePath, List<String> headers,
int linesPerFile)
+ private static void exportToSqlFileWithAlignDevice(
+ SessionDataSet sessionDataSet, String filePath, List<String>
measurementNames)
throws IOException, IoTDBConnectionException,
StatementExecutionException {
+
+ if (CollectionUtils.isEmpty(measurementNames) || measurementNames.size()
<= 1) {
+ return;
+ } else {
+ measurementNames.remove("Time");
+ measurementNames.remove("Device");
+ }
+ String sqlPrefix =
+ String.format(
+ "INSERT INTO %s(TIMESTAMP,%s) ALIGNED VALUES (%s);\n",
+ "%s", String.join(",", measurementNames), "%d,%s");
+
+ SessionDataSet.DataIterator iterator = sessionDataSet.iterator();
+ List<String> columnTypeList = iterator.getColumnTypeList();
+ int totalColumns = columnTypeList.size();
+ String deviceName = null;
int fileIndex = 0;
+ int currentLines = 0;
+ String filePathTemplate = filePath + "_%d" + ".sql";
+ FileWriter writer = null;
+ while (iterator.next()) {
+ if (writer == null) {
+ writer = new FileWriter(String.format(filePathTemplate, fileIndex));
+ }
+ deviceName = iterator.getString(2);
+ if (deviceName.startsWith(SYSTEM_DATABASE + ".")) {
+ continue;
+ }
+ List<String> values = new ArrayList<>();
+ for (int index = 2; index < totalColumns; index++) {
+ String dataType = columnTypeList.get(index);
+ String value = iterator.getString(index + 1);
+ if (value == null) {
+ values.add("null");
+ continue;
+ }
+ if ("TEXT".equalsIgnoreCase(dataType)
+ || "STRING".equalsIgnoreCase(dataType)
+ || "DATE".equalsIgnoreCase(dataType)) {
+ values.add(String.format("\"%s\"", value));
+ } else if ("BLOB".equalsIgnoreCase(dataType)) {
+ values.add(String.format("X'%s'", value.substring(2)));
+ } else {
+ values.add(value);
+ }
+ }
+ long timestamp = iterator.getLong(1);
+ writer.write(String.format(sqlPrefix, deviceName, timestamp,
String.join(",", values)));
+ currentLines += 1;
+
+ if (currentLines >= linesPerFile) {
+ writer.flush();
+ writer.close();
+ fileIndex += 1;
+ writer = null;
+ currentLines = 0;
+ }
+ }
+ if (writer != null) {
+ writer.flush();
+ writer.close();
+ }
+ ioTPrinter.print("\n");
+ }
+
+ private static void exportToSqlFileWithoutAlign(
+ SessionDataSet sessionDataSet, String filePath, List<String> headers)
+ throws IoTDBConnectionException, StatementExecutionException,
IOException {
+
+ List<String> measurementNames = new ArrayList<>();
String deviceName = null;
- boolean writeNull = false;
- List<String> seriesList = new ArrayList<>(headers);
if (CollectionUtils.isEmpty(headers) || headers.size() <= 1) {
- writeNull = true;
+ return;
} else {
- if (headers.contains("Device")) {
- seriesList.remove("Time");
- seriesList.remove("Device");
- } else {
- Path path = new Path(seriesList.get(1), true);
- deviceName = path.getDevice();
- seriesList.remove("Time");
- for (int i = 0; i < seriesList.size(); i++) {
- String series = seriesList.get(i);
- path = new Path(series, true);
- seriesList.set(i, path.getMeasurement());
+ headers.remove("Time");
+ Path path = new Path(headers.get(0), true);
+ deviceName = path.getDevice();
+ for (String header : headers) {
+ path = new Path(header, true);
+ String meas = path.getMeasurement();
+ if (path.getDevice().equals(deviceName)) {
+ measurementNames.add(meas);
}
}
}
- boolean hasNext = true;
- while (hasNext) {
- int i = 0;
- final String finalFilePath = filePath + "_" + fileIndex + ".sql";
- try (FileWriter writer = new FileWriter(finalFilePath)) {
- if (writeNull) {
- break;
+ if (deviceName.startsWith(SYSTEM_DATABASE + ".")) {
+ return;
+ }
+ String sqlPrefix =
+ String.format(
+ "INSERT INTO %s(TIMESTAMP,%s) VALUES (%s);\n",
+ "%s", String.join(",", measurementNames), "%d,%s");
+
+ SessionDataSet.DataIterator iterator = sessionDataSet.iterator();
+ List<String> columnTypeList = iterator.getColumnTypeList();
+ int totalColumns = measurementNames.size();
+ int fileIndex = 0;
+ int currentLines = 0;
+ String filePathTemplate = filePath + "_%d" + ".sql";
+ FileWriter writer = null;
+ while (iterator.next()) {
+ if (writer == null) {
+ writer = new FileWriter(String.format(filePathTemplate, fileIndex));
+ }
+ List<String> values = new ArrayList<>();
+ for (int index = 0; index < totalColumns; index++) {
+ String dataType = columnTypeList.get(index + 1);
+ String value = iterator.getString(index + 2);
+ if (value == null) {
+ values.add("null");
+ continue;
}
- while (i++ < linesPerFile) {
- if (sessionDataSet.hasNext()) {
- RowRecord rowRecord = sessionDataSet.next();
- List<Field> fields = rowRecord.getFields();
- List<String> headersTemp = new ArrayList<>(seriesList);
- List<String> timeseries = new ArrayList<>();
- if (headers.contains("Device")) {
- deviceName = fields.get(0).toString();
- if (deviceName.startsWith(SYSTEM_DATABASE + ".")) {
- continue;
- }
- for (String header : headersTemp) {
- timeseries.add(deviceName + "." + header);
- }
- } else {
- if (headers.get(1).startsWith(SYSTEM_DATABASE + ".")) {
- continue;
- }
- timeseries.addAll(headers);
- timeseries.remove(0);
- }
- String sqlMiddle = null;
- if (Boolean.TRUE.equals(aligned)) {
- sqlMiddle = " ALIGNED VALUES (" + rowRecord.getTimestamp() + ",";
- } else {
- sqlMiddle = " VALUES (" + rowRecord.getTimestamp() + ",";
- }
- List<String> values = new ArrayList<>();
- if (headers.contains("Device")) {
- fields.remove(0);
- }
- for (int index = 0; index < fields.size(); index++) {
- RowRecord next =
- session
- .executeQueryStatement("SHOW TIMESERIES " +
timeseries.get(index), timeout)
- .next();
- if (ObjectUtils.isNotEmpty(next)) {
- List<Field> timeseriesList = next.getFields();
- String value = fields.get(index).toString();
- if (value.equals("null")) {
- headersTemp.remove(seriesList.get(index));
- continue;
- }
- final String dataType = timeseriesList.get(3).getStringValue();
- if (TSDataType.TEXT.name().equalsIgnoreCase(dataType)
- || TSDataType.STRING.name().equalsIgnoreCase(dataType)) {
- values.add("\'" + value + "\'");
- } else if (TSDataType.BLOB.name().equalsIgnoreCase(dataType)) {
- final byte[] v = fields.get(index).getBinaryV().getValues();
- if (v == null) {
- values.add(null);
- } else {
- values.add(
-
BytesUtils.parseBlobByteArrayToString(v).replaceFirst("0x", "X'") + "'");
- }
- } else if (TSDataType.DATE.name().equalsIgnoreCase(dataType)) {
- final LocalDate dateV = fields.get(index).getDateV();
- if (dateV == null) {
- values.add(null);
- } else {
- values.add("'" + dateV.toString() + "'");
- }
- } else {
- values.add(value);
- }
- } else {
- headersTemp.remove(seriesList.get(index));
- continue;
- }
- }
- if (CollectionUtils.isNotEmpty(headersTemp)) {
- writer.write(
- "INSERT INTO "
- + deviceName
- + "(TIMESTAMP,"
- + String.join(",", headersTemp)
- + ")"
- + sqlMiddle
- + String.join(",", values)
- + ");\n");
- }
-
- } else {
- hasNext = false;
- break;
- }
+ if ("TEXT".equalsIgnoreCase(dataType)
+ || "STRING".equalsIgnoreCase(dataType)
+ || "DATE".equalsIgnoreCase(dataType)) {
+ values.add(String.format("\"%s\"", value));
+ } else if ("BLOB".equalsIgnoreCase(dataType)) {
+ values.add(String.format("X'%s'", value.substring(2)));
+ } else {
+ values.add(value);
}
- fileIndex++;
+ }
+ long timestamp = iterator.getLong(1);
+ writer.write(String.format(sqlPrefix, deviceName, timestamp,
String.join(",", values)));
+ currentLines += 1;
+
+ if (currentLines >= linesPerFile) {
writer.flush();
+ writer.close();
+ fileIndex += 1;
+ writer = null;
+ currentLines = 0;
}
}
+ if (writer != null) {
+ writer.flush();
+ writer.close();
+ }
+ ioTPrinter.print("\n");
+ }
Review Comment:
The FileWriter is not managed with try-with-resources or try-finally blocks.
If an exception occurs during the iteration loop (e.g., at lines 815-832), the
writer may not be properly closed, leading to resource leaks. Consider wrapping
the writer management in a try-finally block or using try-with-resources to
ensure proper cleanup even in case of exceptions.
##########
iotdb-client/cli/src/main/java/org/apache/iotdb/tool/data/ExportData.java:
##########
@@ -707,128 +705,157 @@ public static void writeCsvFile(
}
}
- public static void writeSqlFile(
- SessionDataSet sessionDataSet, String filePath, List<String> headers,
int linesPerFile)
+ private static void exportToSqlFileWithAlignDevice(
+ SessionDataSet sessionDataSet, String filePath, List<String>
measurementNames)
throws IOException, IoTDBConnectionException,
StatementExecutionException {
+
+ if (CollectionUtils.isEmpty(measurementNames) || measurementNames.size()
<= 1) {
+ return;
+ } else {
+ measurementNames.remove("Time");
+ measurementNames.remove("Device");
+ }
+ String sqlPrefix =
+ String.format(
+ "INSERT INTO %s(TIMESTAMP,%s) ALIGNED VALUES (%s);\n",
+ "%s", String.join(",", measurementNames), "%d,%s");
+
+ SessionDataSet.DataIterator iterator = sessionDataSet.iterator();
+ List<String> columnTypeList = iterator.getColumnTypeList();
+ int totalColumns = columnTypeList.size();
+ String deviceName = null;
int fileIndex = 0;
+ int currentLines = 0;
+ String filePathTemplate = filePath + "_%d" + ".sql";
+ FileWriter writer = null;
+ while (iterator.next()) {
+ if (writer == null) {
+ writer = new FileWriter(String.format(filePathTemplate, fileIndex));
+ }
+ deviceName = iterator.getString(2);
+ if (deviceName.startsWith(SYSTEM_DATABASE + ".")) {
+ continue;
+ }
+ List<String> values = new ArrayList<>();
+ for (int index = 2; index < totalColumns; index++) {
+ String dataType = columnTypeList.get(index);
+ String value = iterator.getString(index + 1);
+ if (value == null) {
+ values.add("null");
+ continue;
+ }
+ if ("TEXT".equalsIgnoreCase(dataType)
+ || "STRING".equalsIgnoreCase(dataType)
+ || "DATE".equalsIgnoreCase(dataType)) {
+ values.add(String.format("\"%s\"", value));
+ } else if ("BLOB".equalsIgnoreCase(dataType)) {
+ values.add(String.format("X'%s'", value.substring(2)));
+ } else {
+ values.add(value);
+ }
+ }
+ long timestamp = iterator.getLong(1);
+ writer.write(String.format(sqlPrefix, deviceName, timestamp,
String.join(",", values)));
+ currentLines += 1;
+
+ if (currentLines >= linesPerFile) {
+ writer.flush();
+ writer.close();
+ fileIndex += 1;
+ writer = null;
+ currentLines = 0;
+ }
+ }
+ if (writer != null) {
+ writer.flush();
+ writer.close();
+ }
+ ioTPrinter.print("\n");
+ }
+
+ private static void exportToSqlFileWithoutAlign(
+ SessionDataSet sessionDataSet, String filePath, List<String> headers)
+ throws IoTDBConnectionException, StatementExecutionException,
IOException {
+
+ List<String> measurementNames = new ArrayList<>();
String deviceName = null;
- boolean writeNull = false;
- List<String> seriesList = new ArrayList<>(headers);
if (CollectionUtils.isEmpty(headers) || headers.size() <= 1) {
- writeNull = true;
+ return;
} else {
- if (headers.contains("Device")) {
- seriesList.remove("Time");
- seriesList.remove("Device");
- } else {
- Path path = new Path(seriesList.get(1), true);
- deviceName = path.getDevice();
- seriesList.remove("Time");
- for (int i = 0; i < seriesList.size(); i++) {
- String series = seriesList.get(i);
- path = new Path(series, true);
- seriesList.set(i, path.getMeasurement());
+ headers.remove("Time");
+ Path path = new Path(headers.get(0), true);
+ deviceName = path.getDevice();
+ for (String header : headers) {
+ path = new Path(header, true);
+ String meas = path.getMeasurement();
+ if (path.getDevice().equals(deviceName)) {
+ measurementNames.add(meas);
}
}
}
- boolean hasNext = true;
- while (hasNext) {
- int i = 0;
- final String finalFilePath = filePath + "_" + fileIndex + ".sql";
- try (FileWriter writer = new FileWriter(finalFilePath)) {
- if (writeNull) {
- break;
+ if (deviceName.startsWith(SYSTEM_DATABASE + ".")) {
+ return;
+ }
+ String sqlPrefix =
+ String.format(
+ "INSERT INTO %s(TIMESTAMP,%s) VALUES (%s);\n",
+ "%s", String.join(",", measurementNames), "%d,%s");
+
+ SessionDataSet.DataIterator iterator = sessionDataSet.iterator();
+ List<String> columnTypeList = iterator.getColumnTypeList();
+ int totalColumns = measurementNames.size();
+ int fileIndex = 0;
+ int currentLines = 0;
+ String filePathTemplate = filePath + "_%d" + ".sql";
+ FileWriter writer = null;
+ while (iterator.next()) {
+ if (writer == null) {
+ writer = new FileWriter(String.format(filePathTemplate, fileIndex));
+ }
+ List<String> values = new ArrayList<>();
+ for (int index = 0; index < totalColumns; index++) {
+ String dataType = columnTypeList.get(index + 1);
+ String value = iterator.getString(index + 2);
+ if (value == null) {
+ values.add("null");
+ continue;
}
- while (i++ < linesPerFile) {
- if (sessionDataSet.hasNext()) {
- RowRecord rowRecord = sessionDataSet.next();
- List<Field> fields = rowRecord.getFields();
- List<String> headersTemp = new ArrayList<>(seriesList);
- List<String> timeseries = new ArrayList<>();
- if (headers.contains("Device")) {
- deviceName = fields.get(0).toString();
- if (deviceName.startsWith(SYSTEM_DATABASE + ".")) {
- continue;
- }
- for (String header : headersTemp) {
- timeseries.add(deviceName + "." + header);
- }
- } else {
- if (headers.get(1).startsWith(SYSTEM_DATABASE + ".")) {
- continue;
- }
- timeseries.addAll(headers);
- timeseries.remove(0);
- }
- String sqlMiddle = null;
- if (Boolean.TRUE.equals(aligned)) {
- sqlMiddle = " ALIGNED VALUES (" + rowRecord.getTimestamp() + ",";
- } else {
- sqlMiddle = " VALUES (" + rowRecord.getTimestamp() + ",";
- }
- List<String> values = new ArrayList<>();
- if (headers.contains("Device")) {
- fields.remove(0);
- }
- for (int index = 0; index < fields.size(); index++) {
- RowRecord next =
- session
- .executeQueryStatement("SHOW TIMESERIES " +
timeseries.get(index), timeout)
- .next();
- if (ObjectUtils.isNotEmpty(next)) {
- List<Field> timeseriesList = next.getFields();
- String value = fields.get(index).toString();
- if (value.equals("null")) {
- headersTemp.remove(seriesList.get(index));
- continue;
- }
- final String dataType = timeseriesList.get(3).getStringValue();
- if (TSDataType.TEXT.name().equalsIgnoreCase(dataType)
- || TSDataType.STRING.name().equalsIgnoreCase(dataType)) {
- values.add("\'" + value + "\'");
- } else if (TSDataType.BLOB.name().equalsIgnoreCase(dataType)) {
- final byte[] v = fields.get(index).getBinaryV().getValues();
- if (v == null) {
- values.add(null);
- } else {
- values.add(
-
BytesUtils.parseBlobByteArrayToString(v).replaceFirst("0x", "X'") + "'");
- }
- } else if (TSDataType.DATE.name().equalsIgnoreCase(dataType)) {
- final LocalDate dateV = fields.get(index).getDateV();
- if (dateV == null) {
- values.add(null);
- } else {
- values.add("'" + dateV.toString() + "'");
- }
- } else {
- values.add(value);
- }
- } else {
- headersTemp.remove(seriesList.get(index));
- continue;
- }
- }
- if (CollectionUtils.isNotEmpty(headersTemp)) {
- writer.write(
- "INSERT INTO "
- + deviceName
- + "(TIMESTAMP,"
- + String.join(",", headersTemp)
- + ")"
- + sqlMiddle
- + String.join(",", values)
- + ");\n");
- }
-
- } else {
- hasNext = false;
- break;
- }
+ if ("TEXT".equalsIgnoreCase(dataType)
+ || "STRING".equalsIgnoreCase(dataType)
+ || "DATE".equalsIgnoreCase(dataType)) {
+ values.add(String.format("\"%s\"", value));
+ } else if ("BLOB".equalsIgnoreCase(dataType)) {
+ values.add(String.format("X'%s'", value.substring(2)));
Review Comment:
The BLOB value formatting assumes the string value starts with "0x" (line
828: `value.substring(2)`). If the getString method returns a BLOB value in a
different format, this will cause a StringIndexOutOfBoundsException. Consider
adding validation or using a safer approach to handle BLOB values.
```suggestion
String hexValue = value;
if (hexValue.length() >= 2
&& (hexValue.startsWith("0x") || hexValue.startsWith("0X"))) {
hexValue = hexValue.substring(2);
}
values.add(String.format("X'%s'", hexValue));
```
##########
iotdb-client/cli/src/main/java/org/apache/iotdb/tool/data/ExportData.java:
##########
@@ -707,128 +705,157 @@ public static void writeCsvFile(
}
}
- public static void writeSqlFile(
- SessionDataSet sessionDataSet, String filePath, List<String> headers,
int linesPerFile)
+ private static void exportToSqlFileWithAlignDevice(
+ SessionDataSet sessionDataSet, String filePath, List<String>
measurementNames)
throws IOException, IoTDBConnectionException,
StatementExecutionException {
+
+ if (CollectionUtils.isEmpty(measurementNames) || measurementNames.size()
<= 1) {
+ return;
+ } else {
+ measurementNames.remove("Time");
+ measurementNames.remove("Device");
+ }
+ String sqlPrefix =
+ String.format(
+ "INSERT INTO %s(TIMESTAMP,%s) ALIGNED VALUES (%s);\n",
+ "%s", String.join(",", measurementNames), "%d,%s");
+
+ SessionDataSet.DataIterator iterator = sessionDataSet.iterator();
+ List<String> columnTypeList = iterator.getColumnTypeList();
+ int totalColumns = columnTypeList.size();
+ String deviceName = null;
int fileIndex = 0;
+ int currentLines = 0;
+ String filePathTemplate = filePath + "_%d" + ".sql";
+ FileWriter writer = null;
+ while (iterator.next()) {
+ if (writer == null) {
+ writer = new FileWriter(String.format(filePathTemplate, fileIndex));
+ }
+ deviceName = iterator.getString(2);
+ if (deviceName.startsWith(SYSTEM_DATABASE + ".")) {
+ continue;
+ }
+ List<String> values = new ArrayList<>();
+ for (int index = 2; index < totalColumns; index++) {
+ String dataType = columnTypeList.get(index);
+ String value = iterator.getString(index + 1);
+ if (value == null) {
+ values.add("null");
+ continue;
+ }
+ if ("TEXT".equalsIgnoreCase(dataType)
+ || "STRING".equalsIgnoreCase(dataType)
+ || "DATE".equalsIgnoreCase(dataType)) {
+ values.add(String.format("\"%s\"", value));
+ } else if ("BLOB".equalsIgnoreCase(dataType)) {
+ values.add(String.format("X'%s'", value.substring(2)));
+ } else {
+ values.add(value);
+ }
+ }
+ long timestamp = iterator.getLong(1);
+ writer.write(String.format(sqlPrefix, deviceName, timestamp,
String.join(",", values)));
+ currentLines += 1;
+
+ if (currentLines >= linesPerFile) {
+ writer.flush();
+ writer.close();
+ fileIndex += 1;
+ writer = null;
+ currentLines = 0;
+ }
+ }
+ if (writer != null) {
+ writer.flush();
+ writer.close();
+ }
+ ioTPrinter.print("\n");
+ }
Review Comment:
The FileWriter is not managed with try-with-resources or try-finally blocks.
If an exception occurs during the iteration loop (e.g., at lines 735-758), the
writer may not be properly closed, leading to resource leaks. Consider wrapping
the writer management in a try-finally block or using try-with-resources to
ensure proper cleanup even in case of exceptions.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]