• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

apache / iotdb / #10006

06 Sep 2023 05:15AM CUT coverage: 47.697% (+0.006%) from 47.691%
#10006

push

travis_ci

web-flow
[RatisConsensus] retry cache expiration time should be longer than retriable-client wait duration (#11045) (#11052)

13 of 13 new or added lines in 1 file covered. (100.0%)

80213 of 168172 relevant lines covered (47.7%)

0.48 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/ExportCsv.java
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one
3
 * or more contributor license agreements.  See the NOTICE file
4
 * distributed with this work for additional information
5
 * regarding copyright ownership.  The ASF licenses this file
6
 * to you under the Apache License, Version 2.0 (the
7
 * "License"); you may not use this file except in compliance
8
 * with the License.  You may obtain a copy of the License at
9
 *
10
 *     http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing,
13
 * software distributed under the License is distributed on an
14
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
 * KIND, either express or implied.  See the License for the
16
 * specific language governing permissions and limitations
17
 * under the License.
18
 */
19

20
package org.apache.iotdb.tool;
21

22
import org.apache.iotdb.cli.utils.IoTPrinter;
23
import org.apache.iotdb.cli.utils.JlineUtils;
24
import org.apache.iotdb.exception.ArgsErrorException;
25
import org.apache.iotdb.isession.SessionDataSet;
26
import org.apache.iotdb.rpc.IoTDBConnectionException;
27
import org.apache.iotdb.rpc.RpcUtils;
28
import org.apache.iotdb.rpc.StatementExecutionException;
29
import org.apache.iotdb.session.Session;
30
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
31
import org.apache.iotdb.tsfile.read.common.RowRecord;
32

33
import org.apache.commons.cli.CommandLine;
34
import org.apache.commons.cli.CommandLineParser;
35
import org.apache.commons.cli.DefaultParser;
36
import org.apache.commons.cli.HelpFormatter;
37
import org.apache.commons.cli.Option;
38
import org.apache.commons.cli.Options;
39
import org.apache.commons.cli.ParseException;
40
import org.apache.thrift.TException;
41
import org.jline.reader.LineReader;
42

43
import java.io.BufferedReader;
44
import java.io.File;
45
import java.io.FileReader;
46
import java.io.IOException;
47
import java.time.Instant;
48
import java.time.ZonedDateTime;
49
import java.time.format.DateTimeFormatter;
50
import java.util.ArrayList;
51
import java.util.List;
52

53
/**
54
 * Export CSV file.
55
 *
56
 * @version 1.0.0 20170719
57
 */
58
public class ExportCsv extends AbstractCsvTool {
×
59

60
  private static final String TARGET_DIR_ARGS = "td";
61
  private static final String TARGET_DIR_NAME = "targetDirectory";
62

63
  private static final String TARGET_FILE_ARGS = "f";
64
  private static final String TARGET_FILE_NAME = "targetFile";
65

66
  private static final String SQL_FILE_ARGS = "s";
67
  private static final String SQL_FILE_NAME = "sqlfile";
68

69
  private static final String DATA_TYPE_ARGS = "datatype";
70
  private static final String DATA_TYPE_NAME = "datatype";
71

72
  private static final String QUERY_COMMAND_ARGS = "q";
73
  private static final String QUERY_COMMAND_NAME = "queryCommand";
74

75
  private static final String LINES_PER_FILE_ARGS = "linesPerFile";
76
  private static final String LINES_PER_FILE_ARGS_NAME = "Lines Per File";
77

78
  private static final String TSFILEDB_CLI_PREFIX = "ExportCsv";
79

80
  private static final String DUMP_FILE_NAME_DEFAULT = "dump";
81
  private static String targetFile = DUMP_FILE_NAME_DEFAULT;
×
82

83
  private static String targetDirectory;
84

85
  private static Boolean needDataTypePrinted;
86

87
  private static String queryCommand;
88

89
  private static String timestampPrecision;
90

91
  private static int linesPerFile = 10000;
×
92

93
  private static long timeout = -1;
×
94

95
  @SuppressWarnings({
96
    "squid:S3776",
97
    "squid:S2093"
98
  }) // Suppress high Cognitive Complexity warning, ignore try-with-resources
99
  /** main function of export csv tool. */
100
  public static void main(String[] args) {
101
    Options options = createOptions();
×
102
    HelpFormatter hf = new HelpFormatter();
×
103
    CommandLine commandLine = null;
×
104
    CommandLineParser parser = new DefaultParser();
×
105
    hf.setOptionComparator(null); // avoid reordering
×
106
    hf.setWidth(MAX_HELP_CONSOLE_WIDTH);
×
107

108
    if (args == null || args.length == 0) {
×
109
      IoTPrinter.println("Too few params input, please check the following hint.");
×
110
      hf.printHelp(TSFILEDB_CLI_PREFIX, options, true);
×
111
      System.exit(CODE_ERROR);
×
112
    }
113
    try {
114
      commandLine = parser.parse(options, args);
×
115
    } catch (ParseException e) {
×
116
      IoTPrinter.println(e.getMessage());
×
117
      hf.printHelp(TSFILEDB_CLI_PREFIX, options, true);
×
118
      System.exit(CODE_ERROR);
×
119
    }
×
120
    if (commandLine.hasOption(HELP_ARGS)) {
×
121
      hf.printHelp(TSFILEDB_CLI_PREFIX, options, true);
×
122
      System.exit(CODE_ERROR);
×
123
    }
124
    int exitCode = CODE_OK;
×
125
    try {
126
      parseBasicParams(commandLine);
×
127
      parseSpecialParams(commandLine);
×
128
      if (!checkTimeFormat()) {
×
129
        System.exit(CODE_ERROR);
×
130
      }
131
      session = new Session(host, Integer.parseInt(port), username, password);
×
132
      session.open(false);
×
133
      timestampPrecision = session.getTimestampPrecision();
×
134
      setTimeZone();
×
135

136
      if (queryCommand == null) {
×
137
        String sqlFile = commandLine.getOptionValue(SQL_FILE_ARGS);
×
138
        String sql;
139

140
        if (sqlFile == null) {
×
141
          LineReader lineReader = JlineUtils.getLineReader(username, host, port);
×
142
          sql = lineReader.readLine(TSFILEDB_CLI_PREFIX + "> please input query: ");
×
143
          IoTPrinter.println(sql);
×
144
          String[] values = sql.trim().split(";");
×
145
          for (int i = 0; i < values.length; i++) {
×
146
            dumpResult(values[i], i);
×
147
          }
148
        } else {
×
149
          dumpFromSqlFile(sqlFile);
×
150
        }
151
      } else {
×
152
        dumpResult(queryCommand, 0);
×
153
      }
154

155
    } catch (IOException e) {
×
156
      IoTPrinter.println("Failed to operate on file, because " + e.getMessage());
×
157
      exitCode = CODE_ERROR;
×
158
    } catch (ArgsErrorException e) {
×
159
      IoTPrinter.println("Invalid args: " + e.getMessage());
×
160
      exitCode = CODE_ERROR;
×
161
    } catch (IoTDBConnectionException | StatementExecutionException e) {
×
162
      IoTPrinter.println("Connect failed because " + e.getMessage());
×
163
      exitCode = CODE_ERROR;
×
164
    } catch (TException e) {
×
165
      IoTPrinter.println(
×
166
          "Can not get the timestamp precision from server because " + e.getMessage());
×
167
      exitCode = CODE_ERROR;
×
168
    } finally {
169
      if (session != null) {
×
170
        try {
171
          session.close();
×
172
        } catch (IoTDBConnectionException e) {
×
173
          exitCode = CODE_ERROR;
×
174
          IoTPrinter.println(
×
175
              "Encounter an error when closing session, error is: " + e.getMessage());
×
176
        }
×
177
      }
178
    }
179
    System.exit(exitCode);
×
180
  }
×
181

182
  private static void parseSpecialParams(CommandLine commandLine) throws ArgsErrorException {
183
    targetDirectory = checkRequiredArg(TARGET_DIR_ARGS, TARGET_DIR_NAME, commandLine);
×
184
    targetFile = commandLine.getOptionValue(TARGET_FILE_ARGS);
×
185
    needDataTypePrinted = Boolean.valueOf(commandLine.getOptionValue(DATA_TYPE_ARGS));
×
186
    queryCommand = commandLine.getOptionValue(QUERY_COMMAND_ARGS);
×
187
    String timeoutString = commandLine.getOptionValue(TIMEOUT_ARGS);
×
188
    if (timeoutString != null) {
×
189
      timeout = Long.parseLong(timeoutString);
×
190
    }
191
    if (needDataTypePrinted == null) {
×
192
      needDataTypePrinted = true;
×
193
    }
194
    if (targetFile == null) {
×
195
      targetFile = DUMP_FILE_NAME_DEFAULT;
×
196
    }
197
    timeFormat = commandLine.getOptionValue(TIME_FORMAT_ARGS);
×
198
    if (timeFormat == null) {
×
199
      timeFormat = "default";
×
200
    }
201
    timeZoneID = commandLine.getOptionValue(TIME_ZONE_ARGS);
×
202
    if (!targetDirectory.endsWith("/") && !targetDirectory.endsWith("\\")) {
×
203
      targetDirectory += File.separator;
×
204
    }
205
    if (commandLine.getOptionValue(LINES_PER_FILE_ARGS) != null) {
×
206
      linesPerFile = Integer.parseInt(commandLine.getOptionValue(LINES_PER_FILE_ARGS));
×
207
    }
208
  }
×
209

210
  /**
211
   * commandline option create.
212
   *
213
   * @return object Options
214
   */
215
  private static Options createOptions() {
216
    Options options = createNewOptions();
×
217

218
    Option opTargetFile =
×
219
        Option.builder(TARGET_DIR_ARGS)
×
220
            .required()
×
221
            .argName(TARGET_DIR_NAME)
×
222
            .hasArg()
×
223
            .desc("Target File Directory (required)")
×
224
            .build();
×
225
    options.addOption(opTargetFile);
×
226

227
    Option targetFileName =
×
228
        Option.builder(TARGET_FILE_ARGS)
×
229
            .argName(TARGET_FILE_NAME)
×
230
            .hasArg()
×
231
            .desc("Export file name (optional)")
×
232
            .build();
×
233
    options.addOption(targetFileName);
×
234

235
    Option opSqlFile =
×
236
        Option.builder(SQL_FILE_ARGS)
×
237
            .argName(SQL_FILE_NAME)
×
238
            .hasArg()
×
239
            .desc("SQL File Path (optional)")
×
240
            .build();
×
241
    options.addOption(opSqlFile);
×
242

243
    Option opTimeFormat =
×
244
        Option.builder(TIME_FORMAT_ARGS)
×
245
            .argName(TIME_FORMAT_NAME)
×
246
            .hasArg()
×
247
            .desc(
×
248
                "Output time Format in csv file. "
249
                    + "You can choose 1) timestamp, number, long 2) ISO8601, default 3) "
250
                    + "user-defined pattern like yyyy-MM-dd\\ HH:mm:ss, default ISO8601 (optional)")
251
            .build();
×
252
    options.addOption(opTimeFormat);
×
253

254
    Option opTimeZone =
×
255
        Option.builder(TIME_ZONE_ARGS)
×
256
            .argName(TIME_ZONE_NAME)
×
257
            .hasArg()
×
258
            .desc("Time Zone eg. +08:00 or -01:00 (optional)")
×
259
            .build();
×
260
    options.addOption(opTimeZone);
×
261

262
    Option opDataType =
×
263
        Option.builder(DATA_TYPE_ARGS)
×
264
            .argName(DATA_TYPE_NAME)
×
265
            .hasArg()
×
266
            .desc(
×
267
                "Will the data type of timeseries be printed in the head line of the CSV file?"
268
                    + '\n'
269
                    + "You can choose true) or false) . (optional)")
270
            .build();
×
271
    options.addOption(opDataType);
×
272

273
    Option opQuery =
×
274
        Option.builder(QUERY_COMMAND_ARGS)
×
275
            .argName(QUERY_COMMAND_NAME)
×
276
            .hasArg()
×
277
            .desc("The query command that you want to execute. (optional)")
×
278
            .build();
×
279
    options.addOption(opQuery);
×
280

281
    Option opLinesPerFile =
×
282
        Option.builder(LINES_PER_FILE_ARGS)
×
283
            .argName(LINES_PER_FILE_ARGS_NAME)
×
284
            .hasArg()
×
285
            .desc("Lines per dump file.")
×
286
            .build();
×
287
    options.addOption(opLinesPerFile);
×
288

289
    Option opHelp =
×
290
        Option.builder(HELP_ARGS)
×
291
            .longOpt(HELP_ARGS)
×
292
            .hasArg(false)
×
293
            .desc("Display help information")
×
294
            .build();
×
295
    options.addOption(opHelp);
×
296

297
    Option opTimeout =
×
298
        Option.builder(TIMEOUT_ARGS)
×
299
            .longOpt(TIMEOUT_NAME)
×
300
            .hasArg()
×
301
            .desc("Timeout for session query")
×
302
            .build();
×
303
    options.addOption(opTimeout);
×
304
    return options;
×
305
  }
306

307
  /**
308
   * This method will be called, if the query commands are written in a sql file.
309
   *
310
   * @param filePath sql file path
311
   * @throws IOException exception
312
   */
313
  private static void dumpFromSqlFile(String filePath) throws IOException {
314
    try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
×
315
      String sql;
316
      int index = 0;
×
317
      while ((sql = reader.readLine()) != null) {
×
318
        dumpResult(sql, index);
×
319
        index++;
×
320
      }
321
    }
322
  }
×
323

324
  /**
325
   * Dump files from database to CSV file.
326
   *
327
   * @param sql export the result of executing the sql
328
   * @param index used to create dump file name
329
   */
330
  private static void dumpResult(String sql, int index) {
331
    final String path = targetDirectory + targetFile + index;
×
332
    try {
333
      SessionDataSet sessionDataSet = session.executeQueryStatement(sql, timeout);
×
334
      List<Object> headers = new ArrayList<>();
×
335
      List<String> names = sessionDataSet.getColumnNames();
×
336
      List<String> types = sessionDataSet.getColumnTypes();
×
337
      if (Boolean.TRUE.equals(needDataTypePrinted)) {
×
338
        for (int i = 0; i < names.size(); i++) {
×
339
          if (!"Time".equals(names.get(i)) && !"Device".equals(names.get(i))) {
×
340
            headers.add(String.format("%s(%s)", names.get(i), types.get(i)));
×
341
          } else {
342
            headers.add(names.get(i));
×
343
          }
344
        }
345
      } else {
346
        headers.addAll(names);
×
347
      }
348
      writeCsvFile(sessionDataSet, path, headers, linesPerFile);
×
349
      sessionDataSet.closeOperationHandle();
×
350
      IoTPrinter.println("Export completely!");
×
351
    } catch (StatementExecutionException | IoTDBConnectionException | IOException e) {
×
352
      IoTPrinter.println("Cannot dump result because: " + e.getMessage());
×
353
    }
×
354
  }
×
355

356
  public static String timeTrans(Long time) {
357
    switch (timeFormat) {
×
358
      case "default":
359
        return RpcUtils.parseLongToDateWithPrecision(
×
360
            DateTimeFormatter.ISO_OFFSET_DATE_TIME, time, zoneId, timestampPrecision);
×
361
      case "timestamp":
362
      case "long":
363
      case "number":
364
        return String.valueOf(time);
×
365
      default:
366
        return ZonedDateTime.ofInstant(Instant.ofEpochMilli(time), zoneId)
×
367
            .format(DateTimeFormatter.ofPattern(timeFormat));
×
368
    }
369
  }
370

371
  @SuppressWarnings("squid:S3776") // Suppress high Cognitive Complexity warning
372
  public static void writeCsvFile(
373
      SessionDataSet sessionDataSet, String filePath, List<Object> headers, int linesPerFile)
374
      throws IOException, IoTDBConnectionException, StatementExecutionException {
375
    int fileIndex = 0;
×
376
    boolean hasNext = true;
×
377
    while (hasNext) {
×
378
      int i = 0;
×
379
      final String finalFilePath = filePath + "_" + fileIndex + ".csv";
×
380
      final CSVPrinterWrapper csvPrinterWrapper = new CSVPrinterWrapper(finalFilePath);
×
381
      csvPrinterWrapper.printRecord(headers);
×
382
      while (i++ < linesPerFile) {
×
383
        if (sessionDataSet.hasNext()) {
×
384
          RowRecord rowRecord = sessionDataSet.next();
×
385
          if (rowRecord.getTimestamp() != 0) {
×
386
            csvPrinterWrapper.print(timeTrans(rowRecord.getTimestamp()));
×
387
          }
388
          rowRecord
×
389
              .getFields()
×
390
              .forEach(
×
391
                  field -> {
392
                    String fieldStringValue = field.getStringValue();
×
393
                    if (!"null".equals(field.getStringValue())) {
×
394
                      if (field.getDataType() == TSDataType.TEXT
×
395
                          && !fieldStringValue.startsWith("root.")) {
×
396
                        fieldStringValue = "\"" + fieldStringValue + "\"";
×
397
                      }
398
                      csvPrinterWrapper.print(fieldStringValue);
×
399
                    } else {
400
                      csvPrinterWrapper.print("");
×
401
                    }
402
                  });
×
403
          csvPrinterWrapper.println();
×
404
        } else {
×
405
          hasNext = false;
×
406
          break;
×
407
        }
408
      }
409
      fileIndex++;
×
410
      csvPrinterWrapper.flush();
×
411
      csvPrinterWrapper.close();
×
412
    }
×
413
  }
×
414
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc