You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ta...@apache.org on 2021/11/27 05:24:21 UTC
[iotdb] 03/10: [IOTDB-1673] CLI refactor and upgrade to JLine3 (#4458)
This is an automated email from the ASF dual-hosted git repository.
tanxinyu pushed a commit to branch master_performance
in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 89d5c48e9978d38463579d462a5be9e8f2e8b869
Author: Zhong Wang <wa...@alibaba-inc.com>
AuthorDate: Thu Nov 25 22:58:15 2021 +0800
[IOTDB-1673] CLI refactor and upgrade to JLine3 (#4458)
* [IOTDB-1673] CLI refactor
1. Upgrade to Jline3.
2. Remove the CLI implmentation for Windows since Jline3 is platform independent.
3. Support persisted command history.
4. Support multi-line edition.
5. Exit by pressing CTRL+D or CTRL+C twice.
6. Add auto pair and auto suggestion widgets.
7. Add keyword highlighter and completer.
* Resolve comment
1. Update LICENSE-binary
---
LICENSE-binary | 6 +-
.../org/apache/iotdb/db/qp/sql/IoTDBSqlLexer.g4 | 4 +-
cli/pom.xml | 11 +-
cli/src/assembly/resources/sbin/start-cli.bat | 2 +-
cli/src/main/java/org/apache/iotdb/cli/Cli.java | 40 +++--
.../apache/iotdb/cli/IoTDBSyntaxHighlighter.java | 76 +++++++++
cli/src/main/java/org/apache/iotdb/cli/WinCli.java | 175 ---------------------
.../org/apache/iotdb/cli/utils/JlineUtils.java | 107 +++++++++++++
.../org/apache/iotdb/tool/AbstractCsvTool.java | 3 +-
.../main/java/org/apache/iotdb/tool/ExportCsv.java | 19 ++-
pom.xml | 6 +-
11 files changed, 240 insertions(+), 209 deletions(-)
diff --git a/LICENSE-binary b/LICENSE-binary
index ce5c2aa..de449d9 100644
--- a/LICENSE-binary
+++ b/LICENSE-binary
@@ -271,16 +271,12 @@ org.xerial.snappy:snappy-java:1.1.8.4
io.airlift.airline:0.8
net.minidev:accessors-smart:1.2
-BSD 2-Clause
-------------
-jline:jline:2.14.5
-
BSD 3-Clause
------------
org.antlr:antlr-runtime:4.8-1
org.ow2.asm:asm:5.0.4
-org.jline:jline:3.10.0
+org.jline:jline:3.21.0
MIT License
diff --git a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlLexer.g4 b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlLexer.g4
index fdcd67f..be310fb 100644
--- a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlLexer.g4
+++ b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlLexer.g4
@@ -23,9 +23,11 @@ lexer grammar IoTDBSqlLexer;
* 1. Whitespace
*/
+// Instead of discarding whitespace completely, send them to a channel invisable to the parser, so
+// that the lexer could still produce WS tokens for the CLI's highlighter.
WS
:
- [ \u000B\t\r\n]+ -> skip
+ [ \u000B\t\r\n]+ -> channel(HIDDEN)
;
diff --git a/cli/pom.xml b/cli/pom.xml
index 9bcb861..741ff6d 100644
--- a/cli/pom.xml
+++ b/cli/pom.xml
@@ -66,10 +66,19 @@
<version>0.9.2</version>
</dependency>
<dependency>
- <groupId>jline</groupId>
+ <groupId>org.jline</groupId>
<artifactId>jline</artifactId>
</dependency>
<dependency>
+ <groupId>net.java.dev.jna</groupId>
+ <artifactId>jna</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.iotdb</groupId>
+ <artifactId>iotdb-antlr</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
<groupId>org.apache.iotdb</groupId>
<artifactId>iotdb-server</artifactId>
<version>${project.version}</version>
diff --git a/cli/src/assembly/resources/sbin/start-cli.bat b/cli/src/assembly/resources/sbin/start-cli.bat
index 99da3fd..3868786 100644
--- a/cli/src/assembly/resources/sbin/start-cli.bat
+++ b/cli/src/assembly/resources/sbin/start-cli.bat
@@ -28,7 +28,7 @@ pushd %~dp0..
if NOT DEFINED IOTDB_CLI_HOME set IOTDB_CLI_HOME=%CD%
popd
-if NOT DEFINED MAIN_CLASS set MAIN_CLASS=org.apache.iotdb.cli.WinCli
+if NOT DEFINED MAIN_CLASS set MAIN_CLASS=org.apache.iotdb.cli.Cli
if NOT DEFINED JAVA_HOME goto :err
@REM -----------------------------------------------------------------------------
diff --git a/cli/src/main/java/org/apache/iotdb/cli/Cli.java b/cli/src/main/java/org/apache/iotdb/cli/Cli.java
index 6e57d27..6d7675f 100644
--- a/cli/src/main/java/org/apache/iotdb/cli/Cli.java
+++ b/cli/src/main/java/org/apache/iotdb/cli/Cli.java
@@ -18,12 +18,12 @@
*/
package org.apache.iotdb.cli;
+import org.apache.iotdb.cli.utils.JlineUtils;
import org.apache.iotdb.exception.ArgsErrorException;
import org.apache.iotdb.jdbc.Config;
import org.apache.iotdb.jdbc.IoTDBConnection;
import org.apache.iotdb.rpc.RpcUtils;
-import jline.console.ConsoleReader;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
@@ -31,6 +31,9 @@ import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.thrift.TException;
+import org.jline.reader.EndOfFileException;
+import org.jline.reader.LineReader;
+import org.jline.reader.UserInterruptException;
import java.io.IOException;
import java.sql.DriverManager;
@@ -42,6 +45,7 @@ import static org.apache.iotdb.cli.utils.IoTPrinter.println;
public class Cli extends AbstractCli {
private static CommandLine commandLine;
+ private static LineReader lineReader;
/**
* IoTDB Client main function.
@@ -49,7 +53,7 @@ public class Cli extends AbstractCli {
* @param args launch arguments
* @throws ClassNotFoundException ClassNotFoundException
*/
- public static void main(String[] args) throws ClassNotFoundException {
+ public static void main(String[] args) throws ClassNotFoundException, IOException {
Class.forName(Config.JDBC_DRIVER_NAME);
Options options = createOptions();
HelpFormatter hf = new HelpFormatter();
@@ -72,6 +76,7 @@ public class Cli extends AbstractCli {
return;
}
+ lineReader = JlineUtils.getLineReader();
serve();
}
@@ -129,13 +134,10 @@ public class Cli extends AbstractCli {
println(IOTDB_CLI_PREFIX + "> can't execute sql because" + e.getMessage());
}
}
- try (ConsoleReader reader = new ConsoleReader()) {
- reader.setExpandEvents(false);
- if (password == null) {
- password = reader.readLine("please input your password:", '\0');
- }
- receiveCommands(reader);
+ if (password == null) {
+ password = lineReader.readLine("please input your password:", '\0');
}
+ receiveCommands(lineReader);
} catch (ArgsErrorException e) {
println(IOTDB_CLI_PREFIX + "> input params error because" + e.getMessage());
} catch (Exception e) {
@@ -143,7 +145,7 @@ public class Cli extends AbstractCli {
}
}
- private static void receiveCommands(ConsoleReader reader) throws TException, IOException {
+ private static void receiveCommands(LineReader reader) throws TException {
try (IoTDBConnection connection =
(IoTDBConnection)
DriverManager.getConnection(
@@ -157,10 +159,22 @@ public class Cli extends AbstractCli {
displayLogo(properties.getVersion());
println(IOTDB_CLI_PREFIX + "> login successfully");
while (true) {
- s = reader.readLine(IOTDB_CLI_PREFIX + "> ", null);
- boolean continues = processCommand(s, connection);
- if (!continues) {
- break;
+ try {
+ s = reader.readLine(IOTDB_CLI_PREFIX + "> ", null);
+ boolean continues = processCommand(s, connection);
+ if (!continues) {
+ break;
+ }
+ } catch (UserInterruptException e) {
+ // Exit on signal INT requires confirmation.
+ try {
+ reader.readLine("Press CTRL+C again to exit, or press ENTER to continue", '\0');
+ } catch (UserInterruptException | EndOfFileException e2) {
+ System.exit(0);
+ }
+ } catch (EndOfFileException e) {
+ // Exit on EOF (usually by pressing CTRL+D).
+ System.exit(0);
}
}
} catch (SQLException e) {
diff --git a/cli/src/main/java/org/apache/iotdb/cli/IoTDBSyntaxHighlighter.java b/cli/src/main/java/org/apache/iotdb/cli/IoTDBSyntaxHighlighter.java
new file mode 100644
index 0000000..82e9866
--- /dev/null
+++ b/cli/src/main/java/org/apache/iotdb/cli/IoTDBSyntaxHighlighter.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.cli;
+
+import org.apache.iotdb.cli.utils.JlineUtils;
+import org.apache.iotdb.db.qp.sql.IoTDBSqlLexer;
+
+import org.antlr.v4.runtime.CharStream;
+import org.antlr.v4.runtime.CharStreams;
+import org.antlr.v4.runtime.Token;
+import org.jline.reader.Highlighter;
+import org.jline.reader.LineReader;
+import org.jline.utils.AttributedString;
+import org.jline.utils.AttributedStringBuilder;
+import org.jline.utils.AttributedStyle;
+
+import java.util.regex.Pattern;
+
+import static org.jline.utils.AttributedStyle.DEFAULT;
+import static org.jline.utils.AttributedStyle.GREEN;
+
+public class IoTDBSyntaxHighlighter implements Highlighter {
+
+ private static final AttributedStyle KEYWORD_STYLE = DEFAULT.foreground(GREEN);
+
+ @Override
+ public AttributedString highlight(LineReader reader, String buffer) {
+ CharStream stream = CharStreams.fromString(buffer);
+ IoTDBSqlLexer tokenSource = new IoTDBSqlLexer(stream);
+ tokenSource.removeErrorListeners();
+ AttributedStringBuilder builder = new AttributedStringBuilder();
+ while (true) {
+ Token token = tokenSource.nextToken();
+ int type = token.getType();
+ if (type == Token.EOF) {
+ break;
+ }
+ String text = token.getText();
+
+ if (isKeyword(text)) {
+ builder.styled(KEYWORD_STYLE, text);
+ } else {
+ builder.append(text);
+ }
+ }
+
+ return builder.toAttributedString();
+ }
+
+ @Override
+ public void setErrorPattern(Pattern errorPattern) {}
+
+ @Override
+ public void setErrorIndex(int errorIndex) {}
+
+ private boolean isKeyword(String token) {
+ return JlineUtils.SQL_KEYWORDS.contains(token.toUpperCase());
+ }
+}
diff --git a/cli/src/main/java/org/apache/iotdb/cli/WinCli.java b/cli/src/main/java/org/apache/iotdb/cli/WinCli.java
deleted file mode 100644
index 7d9e938..0000000
--- a/cli/src/main/java/org/apache/iotdb/cli/WinCli.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.iotdb.cli;
-
-import org.apache.iotdb.exception.ArgsErrorException;
-import org.apache.iotdb.jdbc.Config;
-import org.apache.iotdb.jdbc.IoTDBConnection;
-import org.apache.iotdb.rpc.RpcUtils;
-
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.CommandLineParser;
-import org.apache.commons.cli.DefaultParser;
-import org.apache.commons.cli.HelpFormatter;
-import org.apache.commons.cli.Options;
-import org.apache.commons.cli.ParseException;
-import org.apache.thrift.TException;
-
-import java.io.Console;
-import java.sql.DriverManager;
-import java.sql.SQLException;
-import java.util.Scanner;
-
-import static org.apache.iotdb.cli.utils.IoTPrinter.print;
-import static org.apache.iotdb.cli.utils.IoTPrinter.println;
-
-/** args[]: -h 127.0.0.1 -p 6667 -u root -pw root */
-public class WinCli extends AbstractCli {
-
- private static CommandLine commandLine;
-
- /**
- * main function.
- *
- * @param args -console args
- */
- public static void main(String[] args) throws ClassNotFoundException {
- Class.forName(Config.JDBC_DRIVER_NAME);
- Options options = createOptions();
- HelpFormatter hf = new HelpFormatter();
- hf.setWidth(MAX_HELP_CONSOLE_WIDTH);
- commandLine = null;
-
- if (args == null || args.length == 0) {
- println("Require more params input, please check the following hint.");
- hf.printHelp(IOTDB_CLI_PREFIX, options, true);
- return;
- }
-
- init();
- String[] newArgs = removePasswordArgs(args);
- String[] newArgs2 = processExecuteArgs(newArgs);
- boolean continues = parseCommandLine(options, newArgs2, hf);
- if (!continues) {
- return;
- }
-
- serve();
- }
-
- private static String readPassword() {
- Console c = System.console();
- if (c == null) { // IN ECLIENTPSE IDE
- print(IOTDB_CLI_PREFIX + "> please input password: ");
- Scanner scanner = new Scanner(System.in);
- return scanner.nextLine();
- } else { // Outside Eclipse IDE
- return new String(c.readPassword(IOTDB_CLI_PREFIX + "> please input password: "));
- }
- }
-
- private static boolean parseCommandLine(Options options, String[] newArgs, HelpFormatter hf) {
- try {
- CommandLineParser parser = new DefaultParser();
- commandLine = parser.parse(options, newArgs);
- if (commandLine.hasOption(HELP_ARGS)) {
- hf.printHelp(IOTDB_CLI_PREFIX, options, true);
- return false;
- }
- if (commandLine.hasOption(RPC_COMPRESS_ARGS)) {
- Config.rpcThriftCompressionEnable = true;
- }
- if (commandLine.hasOption(ISO8601_ARGS)) {
- timeFormat = RpcUtils.setTimeFormat("long");
- }
- if (commandLine.hasOption(MAX_PRINT_ROW_COUNT_ARGS)) {
- setMaxDisplayNumber(commandLine.getOptionValue(MAX_PRINT_ROW_COUNT_ARGS));
- }
- } catch (ParseException e) {
- println("Require more params input, please check the following hint.");
- hf.printHelp(IOTDB_CLI_PREFIX, options, true);
- return false;
- } catch (NumberFormatException e) {
- println(
- IOTDB_CLI_PREFIX
- + "> error format of max print row count, it should be an integer number");
- return false;
- }
- return true;
- }
-
- private static void serve() {
- try (Scanner scanner = new Scanner(System.in)) {
- host = checkRequiredArg(HOST_ARGS, HOST_NAME, commandLine, false, host);
- port = checkRequiredArg(PORT_ARGS, PORT_NAME, commandLine, false, port);
- username = checkRequiredArg(USERNAME_ARGS, USERNAME_NAME, commandLine, true, null);
- password = commandLine.getOptionValue(PASSWORD_ARGS);
- if (password == null) {
- password = readPassword();
- }
- if (hasExecuteSQL) {
- try (IoTDBConnection connection =
- (IoTDBConnection)
- DriverManager.getConnection(
- Config.IOTDB_URL_PREFIX + host + ":" + port + "/", username, password)) {
- properties = connection.getServerProperties();
- timestampPrecision = properties.getTimestampPrecision();
- AGGREGRATE_TIME_LIST.addAll(properties.getSupportedTimeAggregationOperations());
- processCommand(execute, connection);
- return;
- } catch (SQLException e) {
- println(IOTDB_CLI_PREFIX + "> can't execute sql because" + e.getMessage());
- }
- }
-
- receiveCommands(scanner);
- } catch (ArgsErrorException e) {
- println(IOTDB_CLI_PREFIX + "> input params error because" + e.getMessage());
- } catch (Exception e) {
- println(IOTDB_CLI_PREFIX + "> exit cli with error " + e.getMessage());
- }
- }
-
- private static void receiveCommands(Scanner scanner) throws TException {
- try (IoTDBConnection connection =
- (IoTDBConnection)
- DriverManager.getConnection(
- Config.IOTDB_URL_PREFIX + host + ":" + port + "/", username, password)) {
- properties = connection.getServerProperties();
- AGGREGRATE_TIME_LIST.addAll(properties.getSupportedTimeAggregationOperations());
- timestampPrecision = properties.getTimestampPrecision();
-
- echoStarting();
- displayLogo(properties.getVersion());
- println(IOTDB_CLI_PREFIX + "> login successfully");
- while (true) {
- print(IOTDB_CLI_PREFIX + "> ");
- String s = scanner.nextLine();
- boolean continues = processCommand(s, connection);
- if (!continues) {
- break;
- }
- }
- } catch (SQLException e) {
- println(
- String.format(
- "%s> %s Host is %s, port is %s.", IOTDB_CLI_PREFIX, e.getMessage(), host, port));
- }
- }
-}
diff --git a/cli/src/main/java/org/apache/iotdb/cli/utils/JlineUtils.java b/cli/src/main/java/org/apache/iotdb/cli/utils/JlineUtils.java
new file mode 100644
index 0000000..e2f5c7d
--- /dev/null
+++ b/cli/src/main/java/org/apache/iotdb/cli/utils/JlineUtils.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.cli.utils;
+
+import org.apache.iotdb.cli.IoTDBSyntaxHighlighter;
+import org.apache.iotdb.db.qp.sql.IoTDBSqlLexer;
+
+import org.jline.reader.LineReader;
+import org.jline.reader.LineReader.Option;
+import org.jline.reader.LineReaderBuilder;
+import org.jline.reader.impl.DefaultParser.Bracket;
+import org.jline.reader.impl.completer.StringsCompleter;
+import org.jline.terminal.Size;
+import org.jline.terminal.Terminal;
+import org.jline.terminal.Terminal.Signal;
+import org.jline.terminal.TerminalBuilder;
+import org.jline.utils.OSUtils;
+import org.jline.widget.AutopairWidgets;
+import org.jline.widget.AutosuggestionWidgets;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Objects;
+import java.util.Set;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+public class JlineUtils {
+
+ public static final Pattern SQL_KEYWORD_PATTERN = Pattern.compile("([A-Z_]+)");
+ public static final Set<String> SQL_KEYWORDS =
+ IntStream.range(0, IoTDBSqlLexer.VOCABULARY.getMaxTokenType())
+ .mapToObj(IoTDBSqlLexer.VOCABULARY::getDisplayName)
+ .filter(Objects::nonNull)
+ .filter(w -> SQL_KEYWORD_PATTERN.matcher(w).matches())
+ .collect(Collectors.toSet());
+
+ public static LineReader getLineReader() throws IOException {
+ Terminal terminal = TerminalBuilder.builder().build();
+ if (terminal.getWidth() == 0 || terminal.getHeight() == 0) {
+ // Hard coded terminal size when redirecting.
+ terminal.setSize(new Size(120, 40));
+ }
+ Thread executeThread = Thread.currentThread();
+ // Register signal handler. Instead of shutting down the process, interrupt the current thread
+ // when signal INT is received (usually by pressing CTRL+C).
+ terminal.handle(Signal.INT, signal -> executeThread.interrupt());
+
+ LineReaderBuilder builder = LineReaderBuilder.builder();
+ builder.terminal(terminal);
+
+ // Handle the command history. By default, the number of commands will not exceed 500 and the
+ // size of the history fill will be less than 10 KB. See:
+ // org.jline.reader.impl.history#DefaultHistory
+ String historyFile = ".iotdb.history";
+ String historyFilePath = System.getProperty("user.home") + File.separator + historyFile;
+ builder.variable(LineReader.HISTORY_FILE, new File(historyFilePath));
+
+ builder.highlighter(new IoTDBSyntaxHighlighter());
+
+ builder.completer(new StringsCompleter(SQL_KEYWORDS));
+
+ builder.option(Option.CASE_INSENSITIVE_SEARCH, true);
+ builder.option(Option.CASE_INSENSITIVE, true);
+ // See: https://www.gnu.org/software/bash/manual/html_node/Event-Designators.html
+ builder.option(Option.DISABLE_EVENT_EXPANSION, true);
+
+ org.jline.reader.impl.DefaultParser parser = new org.jline.reader.impl.DefaultParser();
+ // Make multi-line edition be triggered by unclosed brackets and unclosed quotes.
+ parser.setEofOnUnclosedBracket(Bracket.CURLY, Bracket.SQUARE, Bracket.ROUND);
+ parser.setEofOnUnclosedQuote(true);
+ builder.parser(parser);
+ LineReader lineReader = builder.build();
+ if (OSUtils.IS_WINDOWS) {
+ // If enabled cursor remains in begin parenthesis (gitbash).
+ lineReader.setVariable(LineReader.BLINK_MATCHING_PAREN, 0);
+ }
+
+ // Create auto-pair widgets
+ AutopairWidgets autopairWidgets = new AutopairWidgets(lineReader);
+ // Enable auto-pair
+ autopairWidgets.enable();
+ // Create autosuggestion widgets
+ AutosuggestionWidgets autosuggestionWidgets = new AutosuggestionWidgets(lineReader);
+ // Enable autosuggestions
+ autosuggestionWidgets.enable();
+ return lineReader;
+ }
+}
diff --git a/cli/src/main/java/org/apache/iotdb/tool/AbstractCsvTool.java b/cli/src/main/java/org/apache/iotdb/tool/AbstractCsvTool.java
index f03275d..3294406 100644
--- a/cli/src/main/java/org/apache/iotdb/tool/AbstractCsvTool.java
+++ b/cli/src/main/java/org/apache/iotdb/tool/AbstractCsvTool.java
@@ -23,7 +23,6 @@ import org.apache.iotdb.rpc.IoTDBConnectionException;
import org.apache.iotdb.rpc.StatementExecutionException;
import org.apache.iotdb.session.Session;
-import jline.internal.Nullable;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
@@ -210,7 +209,7 @@ public abstract class AbstractCsvTool {
* @param filePath the directory to save the file
*/
public static Boolean writeCsvFile(
- @Nullable List<String> headerNames, List<List<Object>> records, String filePath) {
+ List<String> headerNames, List<List<Object>> records, String filePath) {
try {
CSVPrinter printer =
CSVFormat.DEFAULT
diff --git a/cli/src/main/java/org/apache/iotdb/tool/ExportCsv.java b/cli/src/main/java/org/apache/iotdb/tool/ExportCsv.java
index 3450121..6d77a36 100644
--- a/cli/src/main/java/org/apache/iotdb/tool/ExportCsv.java
+++ b/cli/src/main/java/org/apache/iotdb/tool/ExportCsv.java
@@ -19,6 +19,7 @@
package org.apache.iotdb.tool;
+import org.apache.iotdb.cli.utils.JlineUtils;
import org.apache.iotdb.exception.ArgsErrorException;
import org.apache.iotdb.rpc.IoTDBConnectionException;
import org.apache.iotdb.rpc.RpcUtils;
@@ -28,7 +29,6 @@ import org.apache.iotdb.session.SessionDataSet;
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
import org.apache.iotdb.tsfile.read.common.RowRecord;
-import jline.console.ConsoleReader;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
@@ -39,8 +39,13 @@ import org.apache.commons.cli.ParseException;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import org.apache.commons.csv.QuoteMode;
+import org.jline.reader.LineReader;
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintWriter;
import java.time.Instant;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
@@ -83,7 +88,7 @@ public class ExportCsv extends AbstractCsvTool {
private static final int EXPORT_PER_LINE_COUNT = 10000;
/** main function of export csv tool. */
- public static void main(String[] args) throws IOException {
+ public static void main(String[] args) {
Options options = createOptions();
HelpFormatter hf = new HelpFormatter();
CommandLine commandLine;
@@ -124,15 +129,13 @@ public class ExportCsv extends AbstractCsvTool {
String sql;
if (sqlFile == null) {
- ConsoleReader reader = new ConsoleReader();
- reader.setExpandEvents(false);
- sql = reader.readLine(TSFILEDB_CLI_PREFIX + "> please input query: ");
+ LineReader lineReader = JlineUtils.getLineReader();
+ sql = lineReader.readLine(TSFILEDB_CLI_PREFIX + "> please input query: ");
System.out.println(sql);
String[] values = sql.trim().split(";");
for (int i = 0; i < values.length; i++) {
dumpResult(values[i], i);
}
- reader.close();
} else {
dumpFromSqlFile(sqlFile);
}
@@ -335,7 +338,7 @@ public class ExportCsv extends AbstractCsvTool {
}
}
} else {
- names.forEach(name -> headers.add(name));
+ headers.addAll(names);
}
printer.printRecord(headers);
diff --git a/pom.xml b/pom.xml
index 6286eef..37f2f27 100644
--- a/pom.xml
+++ b/pom.xml
@@ -137,7 +137,7 @@
<common.pool2.version>2.11.1</common.pool2.version>
<org.slf4j.version>1.7.32</org.slf4j.version>
<guava.version>24.1.1</guava.version>
- <jline.version>2.14.6</jline.version>
+ <jline.version>3.21.0</jline.version>
<jetty.version>9.4.35.v20201120</jetty.version>
<metrics.version>4.2.4</metrics.version>
<javax.xml.bind.version>2.4.0-b180830.0359</javax.xml.bind.version>
@@ -269,7 +269,7 @@
<version>${javax.xml.bind.version}</version>
</dependency>
<dependency>
- <groupId>jline</groupId>
+ <groupId>org.jline</groupId>
<artifactId>jline</artifactId>
<version>${jline.version}</version>
</dependency>
@@ -508,7 +508,7 @@
<artifactId>gson</artifactId>
<version>${gson.version}</version>
</dependency>
- <!-- for test container -->
+ <!-- for cli and test container -->
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>