diff --git a/programs/client/Client.cpp b/programs/client/Client.cpp index 4b0e01ee10b..695d6bf3982 100644 --- a/programs/client/Client.cpp +++ b/programs/client/Client.cpp @@ -85,7 +85,6 @@ namespace ErrorCodes { extern const int BAD_ARGUMENTS; extern const int UNKNOWN_PACKET_FROM_SERVER; - extern const int INVALID_USAGE_OF_INPUT; extern const int SYNTAX_ERROR; extern const int TOO_DEEP_RECURSION; extern const int NETWORK_ERROR; @@ -132,77 +131,6 @@ void Client::processError(const String & query) const } -void Client::executeSignleQuery(const String & query_to_execute, ASTPtr parsed_query) -{ - { - /// Temporarily apply query settings to context. - std::optional old_settings; - SCOPE_EXIT_SAFE({ - if (old_settings) - global_context->setSettings(*old_settings); - }); - - auto apply_query_settings = [&](const IAST & settings_ast) - { - if (!old_settings) - old_settings.emplace(global_context->getSettingsRef()); - global_context->applySettingsChanges(settings_ast.as()->changes); - }; - - const auto * insert = parsed_query->as(); - if (insert && insert->settings_ast) - apply_query_settings(*insert->settings_ast); - - /// FIXME: try to prettify this cast using `as<>()` - const auto * with_output = dynamic_cast(parsed_query.get()); - if (with_output && with_output->settings_ast) - apply_query_settings(*with_output->settings_ast); - - if (!connection->checkConnected()) - connect(); - - ASTPtr input_function; - if (insert && insert->select) - insert->tryFindInputFunction(input_function); - - /// INSERT query for which data transfer is needed (not an INSERT SELECT or input()) is processed separately. - if (insert && (!insert->select || input_function) && !insert->watch) - { - if (input_function && insert->format.empty()) - throw Exception("FORMAT must be specified for function input()", ErrorCodes::INVALID_USAGE_OF_INPUT); - - processInsertQuery(query_to_execute, parsed_query); - } - else - processOrdinaryQuery(query_to_execute, parsed_query); - } - - /// Do not change context (current DB, settings) in case of an exception. - if (!have_error) - { - if (const auto * set_query = parsed_query->as()) - { - /// Save all changes in settings to avoid losing them if the connection is lost. - for (const auto & change : set_query->changes) - { - if (change.name == "profile") - current_profile = change.value.safeGet(); - else - global_context->applySettingChange(change); - } - } - if (const auto * use_query = parsed_query->as()) - { - const String & new_database = use_query->database; - /// If the client initiates the reconnection, it takes the settings from the config. - config().setString("database", new_database); - /// If the connection initiates the reconnection, it uses its variable. - connection->setDefaultDatabase(new_database); - } - } -} - - bool Client::executeMultiQuery(const String & all_queries_text) { // It makes sense not to base any control flow on this, so that it is diff --git a/programs/client/Client.h b/programs/client/Client.h index e8090126e63..43f6deae0b5 100644 --- a/programs/client/Client.h +++ b/programs/client/Client.h @@ -16,12 +16,12 @@ public: int main(const std::vector & /*args*/) override; protected: - void executeSignleQuery(const String & query_to_execute, ASTPtr parsed_query) override; bool executeMultiQuery(const String & all_queries_text) override; bool processWithFuzzing(const String & full_query) override; void connect() override; void processError(const String & query) const override; + String getName() const override { return "client"; } void printHelpMessage(const OptionsDescription & options_description) override; void addAndCheckOptions(OptionsDescription & options_description, po::variables_map & options, Arguments & arguments) override; diff --git a/programs/local/LocalServer.cpp b/programs/local/LocalServer.cpp index 87f0e43c892..0865106a6f3 100644 --- a/programs/local/LocalServer.cpp +++ b/programs/local/LocalServer.cpp @@ -93,26 +93,6 @@ void LocalServer::processError(const String & query) const } -void LocalServer::executeSignleQuery(const String & query_to_execute, ASTPtr parsed_query) -{ - const auto * insert = parsed_query->as(); - ASTPtr input_function; - if (insert && insert->select) - insert->tryFindInputFunction(input_function); - - /// INSERT query for which data transfer is needed (not an INSERT SELECT or input()) is processed separately. - if (insert && (!insert->select || input_function) && !insert->watch) - { - if (input_function && insert->format.empty()) - throw Exception("FORMAT must be specified for function input()", ErrorCodes::INVALID_USAGE_OF_INPUT); - - processInsertQuery(query_to_execute, parsed_query); - } - else - processOrdinaryQuery(query_to_execute, parsed_query); -} - - bool LocalServer::executeMultiQuery(const String & all_queries_text) { bool echo_query = echo_queries; diff --git a/programs/local/LocalServer.h b/programs/local/LocalServer.h index 0d40c95c01c..e14e18adced 100644 --- a/programs/local/LocalServer.h +++ b/programs/local/LocalServer.h @@ -31,11 +31,11 @@ public: int main(const std::vector & /*args*/) override; protected: - void executeSignleQuery(const String & query_to_execute, ASTPtr parsed_query) override; bool executeMultiQuery(const String & all_queries_text) override; void connect() override; void processError(const String & query) const override; + String getName() const override { return "local"; } String getQueryTextPrefix() override; void printHelpMessage(const OptionsDescription & options_description) override; diff --git a/src/Client/ClientBase.cpp b/src/Client/ClientBase.cpp index cf6efb96b40..f6f71fe13f8 100644 --- a/src/Client/ClientBase.cpp +++ b/src/Client/ClientBase.cpp @@ -67,6 +67,7 @@ namespace ErrorCodes extern const int UNKNOWN_PACKET_FROM_SERVER; extern const int NO_DATA_TO_INSERT; extern const int UNEXPECTED_PACKET_FROM_SERVER; + extern const int INVALID_USAGE_OF_INPUT; } } @@ -918,7 +919,72 @@ void ClientBase::processParsedSingleQuery(const String & full_query, const Strin written_first_block = false; progress_indication.resetProgress(); - executeSignleQuery(query_to_execute, parsed_query); + { + /// Temporarily apply query settings to context. + std::optional old_settings; + SCOPE_EXIT_SAFE({ + if (old_settings) + global_context->setSettings(*old_settings); + }); + + auto apply_query_settings = [&](const IAST & settings_ast) + { + if (!old_settings) + old_settings.emplace(global_context->getSettingsRef()); + global_context->applySettingsChanges(settings_ast.as()->changes); + }; + + const auto * insert = parsed_query->as(); + if (insert && insert->settings_ast) + apply_query_settings(*insert->settings_ast); + + /// FIXME: try to prettify this cast using `as<>()` + const auto * with_output = dynamic_cast(parsed_query.get()); + if (with_output && with_output->settings_ast) + apply_query_settings(*with_output->settings_ast); + + if (!connection->checkConnected()) + connect(); + + ASTPtr input_function; + if (insert && insert->select) + insert->tryFindInputFunction(input_function); + + /// INSERT query for which data transfer is needed (not an INSERT SELECT or input()) is processed separately. + if (insert && (!insert->select || input_function) && !insert->watch) + { + if (input_function && insert->format.empty()) + throw Exception("FORMAT must be specified for function input()", ErrorCodes::INVALID_USAGE_OF_INPUT); + + processInsertQuery(query_to_execute, parsed_query); + } + else + processOrdinaryQuery(query_to_execute, parsed_query); + } + + /// Do not change context (current DB, settings) in case of an exception. + if (!have_error) + { + if (const auto * set_query = parsed_query->as()) + { + /// Save all changes in settings to avoid losing them if the connection is lost. + for (const auto & change : set_query->changes) + { + if (change.name == "profile") + current_profile = change.value.safeGet(); + else + global_context->applySettingChange(change); + } + } + if (const auto * use_query = parsed_query->as()) + { + const String & new_database = use_query->database; + /// If the client initiates the reconnection, it takes the settings from the config. + config().setString("database", new_database); + /// If the connection initiates the reconnection, it uses its variable. + connection->setDefaultDatabase(new_database); + } + } if (is_interactive) { @@ -1253,7 +1319,7 @@ void ClientBase::clearTerminal() void ClientBase::showClientVersion() { - std::cout << DBMS_NAME << " client version " << VERSION_STRING << VERSION_OFFICIAL << "." << std::endl; + std::cout << DBMS_NAME << " " + getName() + " version " << VERSION_STRING << VERSION_OFFICIAL << "." << std::endl; } diff --git a/src/Client/ClientBase.h b/src/Client/ClientBase.h index 85b920b5341..1f9d140783b 100644 --- a/src/Client/ClientBase.h +++ b/src/Client/ClientBase.h @@ -46,11 +46,10 @@ protected: throw Exception("Query processing with fuzzing is not implemented", ErrorCodes::NOT_IMPLEMENTED); } - virtual void executeSignleQuery(const String & query_to_execute, ASTPtr parsed_query) = 0; virtual bool executeMultiQuery(const String & all_queries_text) = 0; - virtual void connect() = 0; virtual void processError(const String & query) const = 0; + virtual String getName() const = 0; void processOrdinaryQuery(const String & query_to_execute, ASTPtr parsed_query); void processInsertQuery(const String & query_to_execute, ASTPtr parsed_query); diff --git a/tests/queries/0_stateless/00385_storage_file_and_clickhouse-local_app_long.sh b/tests/queries/0_stateless/00385_storage_file_and_clickhouse-local_app_long.sh index 82c80325931..d77955a51bc 100755 --- a/tests/queries/0_stateless/00385_storage_file_and_clickhouse-local_app_long.sh +++ b/tests/queries/0_stateless/00385_storage_file_and_clickhouse-local_app_long.sh @@ -51,8 +51,8 @@ ${CLICKHOUSE_LOCAL} --max_rows_in_distinct=33 -q "SELECT name, value FROM system ${CLICKHOUSE_LOCAL} -q "SET max_rows_in_distinct=33; SELECT name, value FROM system.settings WHERE name = 'max_rows_in_distinct'" ${CLICKHOUSE_LOCAL} --max_bytes_before_external_group_by=1 --max_block_size=10 -q "SELECT sum(ignore(*)) FROM (SELECT number, count() FROM numbers(1000) GROUP BY number)" echo -# Check exta options -(${CLICKHOUSE_LOCAL} --ignore-error --echo -q "SELECT nothing_to_do();SELECT 42;" 2>/dev/null && echo "Wrong RC") || true +# Check exta options, we expect zero exit code and no stderr output +(${CLICKHOUSE_LOCAL} --ignore-error --echo -q "SELECT nothing_to_do();SELECT 42;" 2>/dev/null || echo "Wrong RC") echo ${CLICKHOUSE_LOCAL} -q "CREATE TABLE sophisticated_default ( diff --git a/tests/queries/0_stateless/00900_long_parquet_load.reference b/tests/queries/0_stateless/00900_long_parquet_load.reference index f8f5bb7e131..0fc050891f6 100644 --- a/tests/queries/0_stateless/00900_long_parquet_load.reference +++ b/tests/queries/0_stateless/00900_long_parquet_load.reference @@ -52,17 +52,17 @@ idx9 ['Which','Heaven','to','gaudy','day','denies'] idx10 ['This','is','a','test'] === Try load data from binary.parquet \0 - - - - - - - + + + + + + + \b \t \n - + === Try load data from byte_array_decimal.parquet 1 2