Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions iotdb-client/cli/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@
<artifactId>iotdb-antlr</artifactId>
<version>2.0.11-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.iotdb</groupId>
<artifactId>iotdb-relational-grammar</artifactId>
<version>2.0.11-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.iotdb</groupId>
<artifactId>node-commons</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,23 @@ public final class CliMessages {
MESSAGE_INVALID_ARGS_REQUIRED_VALUES_FOR_OPTION_TABLE_NOT_PROVIDED_4BC3FCFA =
"Invalid args: Required values for option table not provided.";

// Data import/export
public static final String EXCEPTION_FAILED_TO_INSERT_CSV_BATCH_ARG_159E0269 =
"Failed to insert CSV batch: %s";
public static final String MESSAGE_ARG_UNEXPECTED_ERROR_OCCURRED_ARG_E7255EE6 =
"[%s] - Unexpected error occurred: %s";
public static final String
EXCEPTION_SQL_TSFILE_EXPORT_REQUIRES_A_QUERY_FROM_A_SINGLE_TABLE_IN_DATABASE_ARG_C9EB3768 =
"SQL/TsFile export requires a query from a single table in database %s.";
public static final String
MESSAGE_QUERY_TO_EXPORT_TABLE_SQL_TSFILE_QUERIES_REQUIRE_A_SINGLE_TABLE_WITHOUT_JOINS_SUBQUERIES_OR_CTES_OVERRIDES_TABLE_START_TIME_AND_END_TIME_OPTIONAL_CC12D400 =
"Query to export. Table SQL/TsFile queries require a single table without joins, subqueries or CTEs. Overrides -table, -start_time and -end_time. (optional)";
public static final String
MESSAGE_MULTIPLE_CSV_HEADERS_RESOLVE_TO_THE_SAME_TARGET_COLUMN_99189563 =
"Multiple CSV headers resolve to the same target column.";

private CliMessages() {}

// ---------------------------------------------------------------------------
// Additional auto-collected messages
// ---------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,23 @@ public final class CliMessages {
MESSAGE_INVALID_ARGS_REQUIRED_VALUES_FOR_OPTION_TABLE_NOT_PROVIDED_4BC3FCFA =
"参数无效:未提供 table 选项的必填值。";

// Data import/export
public static final String EXCEPTION_FAILED_TO_INSERT_CSV_BATCH_ARG_159E0269 =
"CSV 批次写入失败:%s";
public static final String MESSAGE_ARG_UNEXPECTED_ERROR_OCCURRED_ARG_E7255EE6 =
"[%s] - 发生意外错误:%s";
public static final String
EXCEPTION_SQL_TSFILE_EXPORT_REQUIRES_A_QUERY_FROM_A_SINGLE_TABLE_IN_DATABASE_ARG_C9EB3768 =
"SQL/TsFile 导出要求查询仅来自数据库 %s 中的一张表。";
public static final String
MESSAGE_QUERY_TO_EXPORT_TABLE_SQL_TSFILE_QUERIES_REQUIRE_A_SINGLE_TABLE_WITHOUT_JOINS_SUBQUERIES_OR_CTES_OVERRIDES_TABLE_START_TIME_AND_END_TIME_OPTIONAL_CC12D400 =
"导出查询。表模型 SQL/TsFile 查询要求仅包含一张表,不支持联接、子查询或 CTE。指定后忽略 -table、-start_time 和 -end_time。(可选)";
public static final String
MESSAGE_MULTIPLE_CSV_HEADERS_RESOLVE_TO_THE_SAME_TARGET_COLUMN_99189563 =
"多个 CSV 表头映射到同一目标列。";

private CliMessages() {}

// ---------------------------------------------------------------------------
// Additional auto-collected messages
// ---------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

package org.apache.iotdb.tool.common;

import org.apache.iotdb.cli.i18n.CliMessages;

import org.apache.tsfile.enums.TSDataType;

import java.text.SimpleDateFormat;
Expand Down Expand Up @@ -222,7 +224,8 @@ public class Constants {
public static final String QUERY_COMMAND_NAME = "query";
public static final String QUERY_COMMAND_ARGS_NAME = "query_command";
public static final String QUERY_COMMAND_DESC =
"The query command that you want to execute.If sql_dialect is table The 'q' parameter is only applicable to export types of CSV, and is not available for other types.If the '- q' parameter is not empty, then the parameters' creatTime ',' EndTime 'and' table 'are not effective.(optional)";
CliMessages
.MESSAGE_QUERY_TO_EXPORT_TABLE_SQL_TSFILE_QUERIES_REQUIRE_A_SINGLE_TABLE_WITHOUT_JOINS_SUBQUERIES_OR_CTES_OVERRIDES_TABLE_START_TIME_AND_END_TIME_OPTIONAL_CC12D400;

public static final String TARGET_FILE_ARGS = "pfn";
public static final String TARGET_FILE_NAME = "prefix_file_name";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@

import org.apache.iotdb.cli.utils.IoTPrinter;

import java.io.IOException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

public enum ImportTsFileOperation {
NONE,
MV,
Expand All @@ -29,6 +38,56 @@ public enum ImportTsFileOperation {
DELETE,
;

/** Process a TsFile together with its sidecars without replacing existing archive files. */
public void processFileGroup(Path source, Path target) throws IOException {
List<String> suffixes = new ArrayList<>();
suffixes.add("");
for (String suffix : new String[] {".resource", ".mods"}) {
if (Files.exists(Paths.get(source + suffix))) {
suffixes.add(suffix);
}
}
if (this == CP || this == HARDLINK || this == MV) {
// Check every destination before moving any file in the TsFile/sidecar group.
for (String suffix : suffixes) {
Path destination = Paths.get(target + suffix);
if (Files.exists(destination, LinkOption.NOFOLLOW_LINKS)) {
throw new FileAlreadyExistsException(destination.toString());
}
}
Files.createDirectories(target.getParent());
}
for (String suffix : suffixes) {
ImportTsFileOperation operation = this == HARDLINK && !suffix.isEmpty() ? CP : this;
operation.processFile(Paths.get(source + suffix), Paths.get(target + suffix));
}
}

private void processFile(Path source, Path target) throws IOException {
switch (this) {
case DELETE:
Files.deleteIfExists(source);
break;
case CP:
Files.copy(source, target);
break;
case HARDLINK:
try {
Files.createLink(target, source);
} catch (FileAlreadyExistsException e) {
throw e;
} catch (IOException | UnsupportedOperationException e) {
Files.copy(source, target);
}
break;
case MV:
Files.move(source, target);
break;
default:
break;
}
}

public static boolean isValidOperation(String operation) {
return "none".equalsIgnoreCase(operation)
|| "mv".equalsIgnoreCase(operation)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package org.apache.iotdb.tool.data;

import org.apache.iotdb.cli.utils.IoTPrinter;
import org.apache.iotdb.isession.SessionDataSet;
import org.apache.iotdb.rpc.IoTDBConnectionException;
import org.apache.iotdb.rpc.RpcUtils;
import org.apache.iotdb.rpc.StatementExecutionException;
Expand All @@ -30,6 +31,8 @@
import java.time.Instant;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

Expand All @@ -40,7 +43,31 @@ public abstract class AbstractExportData extends AbstractDataTool {
public abstract void init()
throws IoTDBConnectionException, StatementExecutionException, TException;

public abstract void exportBySql(String sql, int index);
public abstract boolean exportBySql(String sql, int index);

protected static String formatSqlValue(String value, String type) {
if (value == null) {
return "NULL";
}
if ("TEXT".equalsIgnoreCase(type) || "STRING".equalsIgnoreCase(type)) {
return "'" + value.replace("'", "''") + "'";
}
return value;
}

protected static List<String> getCsvHeaders(SessionDataSet dataSet, boolean treeModel) {
List<String> headers = new ArrayList<>(dataSet.getColumnNames());
if (Boolean.TRUE.equals(needDataTypePrinted)) {
List<String> types = dataSet.getColumnTypes();
for (int i = 0; i < headers.size(); i++) {
String name = headers.get(i);
if (!"Time".equalsIgnoreCase(name) && !(treeModel && "Device".equals(name))) {
headers.set(i, String.format("%s(%s)", name, types.get(i)));
}
}
}
return headers;
}

protected static void legalCheck(String sql) {
String aggregatePattern =
Expand Down
Loading
Loading