From 07bab5193f20e4bf7b8dca91bb25bb90ffb86c4b Mon Sep 17 00:00:00 2001 From: kssenii Date: Fri, 29 Oct 2021 15:04:08 +0300 Subject: [PATCH] Delayed interactive --- programs/client/Client.cpp | 70 +++++++++++-------- programs/client/Client.h | 1 + programs/local/LocalServer.cpp | 34 +++++++-- programs/local/LocalServer.h | 1 + src/Client/ClientBase.cpp | 2 + src/Client/ClientBase.h | 2 + ...clickhouse_client_with_queries_file.expect | 30 ++++++++ ...ckhouse_client_with_queries_file.reference | 0 .../02112_delayed_clickhouse_local.expect | 24 +++++++ ..._delayed_clickhouse_local.expect.reference | 0 .../02112_delayed_clickhouse_local.reference | 0 ..._clickhouse_local_with_queries_file.expect | 30 ++++++++ ...ickhouse_local_with_queries_file.reference | 0 .../0_stateless/helpers/02112_clean.sh | 6 ++ .../0_stateless/helpers/02112_prepare.sh | 7 ++ 15 files changed, 169 insertions(+), 38 deletions(-) create mode 100755 tests/queries/0_stateless/02112_delayed_clickhouse_client_with_queries_file.expect create mode 100644 tests/queries/0_stateless/02112_delayed_clickhouse_client_with_queries_file.reference create mode 100755 tests/queries/0_stateless/02112_delayed_clickhouse_local.expect create mode 100644 tests/queries/0_stateless/02112_delayed_clickhouse_local.expect.reference create mode 100644 tests/queries/0_stateless/02112_delayed_clickhouse_local.reference create mode 100755 tests/queries/0_stateless/02112_delayed_clickhouse_local_with_queries_file.expect create mode 100644 tests/queries/0_stateless/02112_delayed_clickhouse_local_with_queries_file.reference create mode 100755 tests/queries/0_stateless/helpers/02112_clean.sh create mode 100755 tests/queries/0_stateless/helpers/02112_prepare.sh diff --git a/programs/client/Client.cpp b/programs/client/Client.cpp index 4951106f595..8985196bb0e 100644 --- a/programs/client/Client.cpp +++ b/programs/client/Client.cpp @@ -403,6 +403,33 @@ void Client::initialize(Poco::Util::Application & self) } +void Client::prepareForInteractive() +{ + clearTerminal(); + showClientVersion(); + + /// Load Warnings at the beginning of connection + if (!config().has("no-warnings")) + { + try + { + std::vector messages = loadWarningMessages(); + if (!messages.empty()) + { + std::cout << "Warnings:" << std::endl; + for (const auto & message : messages) + std::cout << " * " << message << std::endl; + std::cout << std::endl; + } + } + catch (...) + { + /// Ignore exception + } + } +} + + int Client::main(const std::vector & /*args*/) try { @@ -429,36 +456,11 @@ try processConfig(); - if (is_interactive) - { - clearTerminal(); - showClientVersion(); - } - connect(); - if (is_interactive) + if (is_interactive && !delayed_interactive) { - /// Load Warnings at the beginning of connection - if (!config().has("no-warnings")) - { - try - { - std::vector messages = loadWarningMessages(); - if (!messages.empty()) - { - std::cout << "Warnings:" << std::endl; - for (const auto & message : messages) - std::cout << " * " << message << std::endl; - std::cout << std::endl; - } - } - catch (...) - { - /// Ignore exception - } - } - + prepareForInteractive(); runInteractive(); } else @@ -482,6 +484,12 @@ try // case so that at least we don't lose an error. return -1; } + + if (delayed_interactive) + { + prepareForInteractive(); + runInteractive(); + } } return 0; @@ -1161,11 +1169,11 @@ void Client::processConfig() /// - stdin is not a terminal. In this case queries are read from it. /// - -qf (--queries-file) command line option is present. /// The value of the option is used as file with query (or of multiple queries) to execute. - if (stdin_is_a_tty && !config().has("query") && queries_files.empty()) - { - if (config().has("query") && config().has("queries-file")) - throw Exception("Specify either `query` or `queries-file` option", ErrorCodes::BAD_ARGUMENTS); + delayed_interactive = config().has("interactive") && (config().has("query") || config().has("queries-file")); + if (stdin_is_a_tty + && (delayed_interactive || (!config().has("query") && queries_files.empty()))) + { is_interactive = true; } else diff --git a/programs/client/Client.h b/programs/client/Client.h index 2def74ef3fc..b146134bc94 100644 --- a/programs/client/Client.h +++ b/programs/client/Client.h @@ -20,6 +20,7 @@ protected: bool processWithFuzzing(const String & full_query) override; void connect() override; + void prepareForInteractive() override; void processError(const String & query) const override; String getName() const override { return "client"; } diff --git a/programs/local/LocalServer.cpp b/programs/local/LocalServer.cpp index 2a2fe4a78c8..c4e4c10777c 100644 --- a/programs/local/LocalServer.cpp +++ b/programs/local/LocalServer.cpp @@ -412,6 +412,14 @@ void LocalServer::connect() } +void LocalServer::prepareForInteractive() +{ + clearTerminal(); + showClientVersion(); + std::cerr << std::endl; +} + + int LocalServer::main(const std::vector & /*args*/) try { @@ -422,7 +430,10 @@ try std::cout << std::fixed << std::setprecision(3); std::cerr << std::fixed << std::setprecision(3); - is_interactive = stdin_is_a_tty && !config().has("query") && !config().has("table-structure") && queries_files.empty(); + is_interactive = stdin_is_a_tty + && (config().hasOption("interactive") + || (!config().has("query") && !config().has("table-structure") && queries_files.empty())); + if (!is_interactive) { /// We will terminate process on error @@ -443,17 +454,20 @@ try applyCmdSettings(global_context); connect(); - if (is_interactive) + if (is_interactive && !delayed_interactive) { - clearTerminal(); - showClientVersion(); - std::cerr << std::endl; - + prepareForInteractive(); runInteractive(); } else { runNonInteractive(); + + if (delayed_interactive) + { + prepareForInteractive(); + runInteractive(); + } } cleanup(); @@ -478,7 +492,8 @@ catch (...) void LocalServer::processConfig() { - if (is_interactive) + delayed_interactive = config().has("interactive") && (config().has("query") || config().has("queries-file")); + if (is_interactive && !delayed_interactive) { if (config().has("query") && config().has("queries-file")) throw Exception("Specify either `query` or `queries-file` option", ErrorCodes::BAD_ARGUMENTS); @@ -490,6 +505,11 @@ void LocalServer::processConfig() } else { + if (delayed_interactive) + { + load_suggestions = true; + } + need_render_progress = config().getBool("progress", false); echo_queries = config().hasOption("echo") || config().hasOption("verbose"); ignore_error = config().getBool("ignore-error", false); diff --git a/programs/local/LocalServer.h b/programs/local/LocalServer.h index ce0df06c86a..e87e6bd9a0d 100644 --- a/programs/local/LocalServer.h +++ b/programs/local/LocalServer.h @@ -34,6 +34,7 @@ protected: bool executeMultiQuery(const String & all_queries_text) override; void connect() override; + void prepareForInteractive() override; void processError(const String & query) const override; String getName() const override { return "local"; } diff --git a/src/Client/ClientBase.cpp b/src/Client/ClientBase.cpp index ed90c777e20..de76a7aab2c 100644 --- a/src/Client/ClientBase.cpp +++ b/src/Client/ClientBase.cpp @@ -1612,6 +1612,8 @@ void ClientBase::init(int argc, char ** argv) ("hardware-utilization", "print hardware utilization information in progress bar") ("print-profile-events", po::value(&profile_events.print)->zero_tokens(), "Printing ProfileEvents packets") ("profile-events-delay-ms", po::value()->default_value(profile_events.delay_ms), "Delay between printing `ProfileEvents` packets (-1 - print only totals, 0 - print every single packet)") + + ("interactive", "Process queries-file or --query query and start interactive mode") ; addOptions(options_description); diff --git a/src/Client/ClientBase.h b/src/Client/ClientBase.h index f7b418ad13a..b37613f9910 100644 --- a/src/Client/ClientBase.h +++ b/src/Client/ClientBase.h @@ -57,6 +57,7 @@ protected: virtual bool executeMultiQuery(const String & all_queries_text) = 0; virtual void connect() = 0; + virtual void prepareForInteractive() = 0; virtual void processError(const String & query) const = 0; virtual String getName() const = 0; @@ -138,6 +139,7 @@ private: protected: bool is_interactive = false; /// Use either interactive line editing interface or batch mode. bool is_multiquery = false; + bool delayed_interactive = false; bool echo_queries = false; /// Print queries before execution in batch mode. bool ignore_error = false; /// In case of errors, don't print error message, continue to next query. Only applicable for non-interactive mode. diff --git a/tests/queries/0_stateless/02112_delayed_clickhouse_client_with_queries_file.expect b/tests/queries/0_stateless/02112_delayed_clickhouse_client_with_queries_file.expect new file mode 100755 index 00000000000..245253ac205 --- /dev/null +++ b/tests/queries/0_stateless/02112_delayed_clickhouse_client_with_queries_file.expect @@ -0,0 +1,30 @@ +#!/usr/bin/expect -f +# Tags: no-parallel, no-fasttest + +log_user 0 +set timeout 20 +match_max 100000 + +# A default timeout action is to fail +expect_after { + timeout { + exit 1 + } +} + + +spawn bash -c "\$CLICKHOUSE_TESTS_DIR/helpers/02112_prepare.sh" + +set basedir [file dirname $argv0] +spawn bash -c "source $basedir/../shell_config.sh ; \$CLICKHOUSE_CLIENT --disable_suggestion --interactive --queries-file \$CURDIR/file_02112" +expect ":) " + +send -- "select * from t format TSV\r" +expect "1" +expect ":) " + +send -- "exit\r" +expect eof + +spawn bash -c "\$CLICKHOUSE_TESTS_DIR/helpers/02112_clean.sh" + diff --git a/tests/queries/0_stateless/02112_delayed_clickhouse_client_with_queries_file.reference b/tests/queries/0_stateless/02112_delayed_clickhouse_client_with_queries_file.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/queries/0_stateless/02112_delayed_clickhouse_local.expect b/tests/queries/0_stateless/02112_delayed_clickhouse_local.expect new file mode 100755 index 00000000000..6bb9140ee35 --- /dev/null +++ b/tests/queries/0_stateless/02112_delayed_clickhouse_local.expect @@ -0,0 +1,24 @@ +#!/usr/bin/expect -f +# Tags: no-unbundled, no-fasttest + +log_user 0 +set timeout 20 +match_max 100000 + +# A default timeout action is to fail +expect_after { + timeout { + exit 1 + } +} + +set basedir [file dirname $argv0] +spawn bash -c "source $basedir/../shell_config.sh ; \$CLICKHOUSE_LOCAL --disable_suggestion --interactive --query 'create table t(i Int32) engine=Memory; insert into t select 1'" +expect ":) " + +send -- "select * from t format TSV\r" +expect "1" +expect ":) " + +send -- "exit\r" +expect eof diff --git a/tests/queries/0_stateless/02112_delayed_clickhouse_local.expect.reference b/tests/queries/0_stateless/02112_delayed_clickhouse_local.expect.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/queries/0_stateless/02112_delayed_clickhouse_local.reference b/tests/queries/0_stateless/02112_delayed_clickhouse_local.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/queries/0_stateless/02112_delayed_clickhouse_local_with_queries_file.expect b/tests/queries/0_stateless/02112_delayed_clickhouse_local_with_queries_file.expect new file mode 100755 index 00000000000..774d8d63714 --- /dev/null +++ b/tests/queries/0_stateless/02112_delayed_clickhouse_local_with_queries_file.expect @@ -0,0 +1,30 @@ +#!/usr/bin/expect -f +# Tags: no-parallel, no-fasttest + +log_user 0 +set timeout 20 +match_max 100000 + +# A default timeout action is to fail +expect_after { + timeout { + exit 1 + } +} + + +spawn bash -c "\$CLICKHOUSE_TESTS_DIR/helpers/02112_prepare.sh" + +set basedir [file dirname $argv0] +spawn bash -c "source $basedir/../shell_config.sh ; \$CLICKHOUSE_LOCAL --disable_suggestion --interactive --queries-file \$CURDIR/file_02112" +expect ":) " + +send -- "select * from t format TSV\r" +expect "1" +expect ":) " + +send -- "exit\r" +expect eof + +spawn bash -c "\$CLICKHOUSE_TESTS_DIR/helpers/02112_clean.sh" + diff --git a/tests/queries/0_stateless/02112_delayed_clickhouse_local_with_queries_file.reference b/tests/queries/0_stateless/02112_delayed_clickhouse_local_with_queries_file.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/queries/0_stateless/helpers/02112_clean.sh b/tests/queries/0_stateless/helpers/02112_clean.sh new file mode 100755 index 00000000000..910c0709955 --- /dev/null +++ b/tests/queries/0_stateless/helpers/02112_clean.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +FILE=${CURDIR}/file_02112 +if [ -f $FILE ]; then + rm $FILE +fi diff --git a/tests/queries/0_stateless/helpers/02112_prepare.sh b/tests/queries/0_stateless/helpers/02112_prepare.sh new file mode 100755 index 00000000000..1f371789f86 --- /dev/null +++ b/tests/queries/0_stateless/helpers/02112_prepare.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +FILE=${CURDIR}/file_02112 +if [ -f $FILE ]; then + rm $FILE +fi +echo "drop table if exists t;create table t(i Int32) engine=Memory; insert into t select 1" >> $FILE