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]

Reply via email to