Completion for clickhouse-local

This commit is contained in:
kssenii 2021-08-01 23:28:39 +03:00
parent 6e8eb598bf
commit 3982031215
5 changed files with 75 additions and 5 deletions

View File

@ -217,6 +217,15 @@ std::string LocalServer::getInitialCreateTableQuery()
}
void LocalServer::loadSuggestionData(Suggest & suggest)
{
if (!config().getBool("disable_suggestion", false))
{
suggest.load(query_context, config().getInt("suggestion_limit"));
}
}
void LocalServer::executeSingleQuery(const String & query_to_execute, ASTPtr /* parsed_query */)
{
ReadBufferFromString read_buf(query_to_execute);
@ -636,6 +645,10 @@ void LocalServer::addAndCheckOptions(OptionsDescription & options_description, p
("multiline,m", "multiline")
("multiquery,n", "multiquery")
("highlight", po::value<bool>()->default_value(true), "enable or disable basic syntax highlight in interactive command line")
("disable_suggestion,A", "Disable loading suggestion data. Note that suggestion data is loaded asynchronously through a second connection to ClickHouse server. Also it is reasonable to disable suggestion if you want to paste a query with TAB characters. Shorthand option -A is for those who get used to mysql client.")
("suggestion_limit", po::value<int>()->default_value(10000),
"Suggestion limit for how many databases, tables and columns to fetch.")
;
cmd_settings.addProgramOptions(options_description.main_description.value());
@ -715,6 +728,11 @@ void LocalServer::processOptions(const OptionsDescription &, const CommandLineOp
config().setBool("multiline", true);
if (options.count("multiquery"))
config().setBool("multiquery", true);
if (options.count("disable_suggestion"))
config().setBool("disable_suggestion", true);
if (options.count("suggestion_limit"))
config().setInt("suggestion_limit", options["suggestion_limit"].as<int>());
}
}

View File

@ -44,6 +44,8 @@ protected:
String getQueryTextPrefix() override;
void loadSuggestionData(Suggest &) override;
void readArguments(int argc, char ** argv, Arguments & common_arguments, std::vector<Arguments> &) override;

View File

@ -95,7 +95,7 @@ protected:
/// For non-interactive multi-query mode get queries text prefix.
virtual String getQueryTextPrefix() { return ""; }
virtual void loadSuggestionData(Suggest &) {}
virtual void loadSuggestionData(Suggest &) = 0;
void resetOutput();

View File

@ -3,6 +3,7 @@
#include <Core/Settings.h>
#include <Columns/ColumnString.h>
#include <Common/typeid_cast.h>
#include <Interpreters/executeQuery.h>
#include <IO/WriteBufferFromString.h>
#include <IO/Operators.h>
@ -70,6 +71,37 @@ void Suggest::load(const ConnectionParameters & connection_parameters, size_t su
});
}
void Suggest::load(ContextMutablePtr context, size_t suggestion_limit)
{
loading_thread = std::thread([context, suggestion_limit, this]
{
try
{
ThreadStatus thread_status;
CurrentThread::QueryScope query_scope_holder(context);
loadImpl(context, suggestion_limit);
}
catch (...)
{
std::cerr << "Cannot load data for command line suggestions: " << getCurrentExceptionMessage(false, true) << "\n";
}
/// Note that keyword suggestions are available even if we cannot load data from server.
std::sort(words.begin(), words.end());
words_no_case = words;
std::sort(words_no_case.begin(), words_no_case.end(), [](const std::string & str1, const std::string & str2)
{
return std::lexicographical_compare(begin(str1), end(str1), begin(str2), end(str2), [](const char char1, const char char2)
{
return std::tolower(char1) < std::tolower(char2);
});
});
ready = true;
});
}
Suggest::Suggest()
{
/// Keywords may be not up to date with ClickHouse parser.
@ -88,11 +120,10 @@ Suggest::Suggest()
"INTERVAL", "LIMITS", "ONLY", "TRACKING", "IP", "REGEXP", "ILIKE"};
}
void Suggest::loadImpl(Connection & connection, const ConnectionTimeouts & timeouts, size_t suggestion_limit)
static String getLoadSuggestionQuery(size_t suggestion_limit)
{
/// NOTE: Once you will update the completion list,
/// do not forget to update 01676_clickhouse_client_autocomplete.sh
WriteBufferFromOwnString query;
query << "SELECT DISTINCT arrayJoin(extractAll(name, '[\\\\w_]{2,}')) AS res FROM ("
"SELECT name FROM system.functions"
@ -133,8 +164,17 @@ void Suggest::loadImpl(Connection & connection, const ConnectionTimeouts & timeo
}
query << ") WHERE notEmpty(res)";
return query.str();
}
fetch(connection, timeouts, query.str());
void Suggest::loadImpl(Connection & connection, const ConnectionTimeouts & timeouts, size_t suggestion_limit)
{
fetch(connection, timeouts, getLoadSuggestionQuery(suggestion_limit));
}
void Suggest::loadImpl(ContextMutablePtr context, size_t suggestion_limit)
{
executeQuery(getLoadSuggestionQuery(suggestion_limit), context);
}
void Suggest::fetch(Connection & connection, const ConnectionTimeouts & timeouts, const std::string & query)

View File

@ -19,21 +19,31 @@ class Suggest : public LineReader::Suggest, boost::noncopyable
{
public:
Suggest();
~Suggest()
{
if (loading_thread.joinable())
loading_thread.join();
}
/// Load suggestions for clickhouse-client.
void load(const ConnectionParameters & connection_parameters, size_t suggestion_limit);
/// Load suggestions for clickhouse-local.
void load(ContextMutablePtr context, size_t suggestion_limit);
/// Older server versions cannot execute the query above.
static constexpr int MIN_SERVER_REVISION = 54406;
private:
void loadImpl(Connection & connection, const ConnectionTimeouts & timeouts, size_t suggestion_limit);
void loadImpl(ContextMutablePtr context, size_t suggestion_limit);
void fetch(Connection & connection, const ConnectionTimeouts & timeouts, const std::string & query);
void fetch(ContextMutablePtr context, const std::string & query);
void fillWordsFromBlock(const Block & block);
/// Words are fetched asynchronously.