mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-29 11:02:08 +00:00
dbms: Client: don't leave progress indicator in the middle of data; colors almost compatible with white backgrounds [#METR-11125].
This commit is contained in:
parent
65cf115313
commit
047e5e30df
@ -49,6 +49,16 @@
|
|||||||
|
|
||||||
#include <DB/Common/ExternalTable.h>
|
#include <DB/Common/ExternalTable.h>
|
||||||
|
|
||||||
|
|
||||||
|
/// http://en.wikipedia.org/wiki/ANSI_escape_code
|
||||||
|
#define SAVE_CURSOR_POSITION "\033[s"
|
||||||
|
#define RESTORE_CURSOR_POSITION "\033[u"
|
||||||
|
#define CLEAR_TO_END_OF_LINE "\033[K"
|
||||||
|
/// Эти коды, возможно, поддерживаются не везде.
|
||||||
|
#define DISABLE_LINE_WRAPPING "\033[?7l"
|
||||||
|
#define ENABLE_LINE_WRAPPING "\033[?7h"
|
||||||
|
|
||||||
|
|
||||||
/** Клиент командной строки СУБД ClickHouse.
|
/** Клиент командной строки СУБД ClickHouse.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -61,11 +71,7 @@ using Poco::SharedPtr;
|
|||||||
class Client : public Poco::Util::Application
|
class Client : public Poco::Util::Application
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Client() : is_interactive(true), stdin_is_not_tty(false),
|
Client() {}
|
||||||
format_max_block_size(0), std_in(STDIN_FILENO), std_out(STDOUT_FILENO), processed_rows(0),
|
|
||||||
rows_read_on_server(0), bytes_read_on_server(0), written_progress_chars(0), written_first_block(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::unordered_set<String> StringSet;
|
typedef std::unordered_set<String> StringSet;
|
||||||
@ -77,24 +83,24 @@ private:
|
|||||||
"q", "й", "\\q", "\\Q", "\\й", "\\Й", ":q", "Жй"
|
"q", "й", "\\q", "\\Q", "\\й", "\\Й", ":q", "Жй"
|
||||||
};
|
};
|
||||||
|
|
||||||
bool is_interactive; /// Использовать readline интерфейс или batch режим.
|
bool is_interactive = true; /// Использовать readline интерфейс или batch режим.
|
||||||
bool stdin_is_not_tty; /// stdin - не терминал.
|
bool stdin_is_not_tty = false; /// stdin - не терминал.
|
||||||
|
|
||||||
SharedPtr<Connection> connection; /// Соединение с БД.
|
SharedPtr<Connection> connection; /// Соединение с БД.
|
||||||
String query; /// Текущий запрос.
|
String query; /// Текущий запрос.
|
||||||
|
|
||||||
String format; /// Формат вывода результата в консоль.
|
String format; /// Формат вывода результата в консоль.
|
||||||
size_t format_max_block_size; /// Максимальный размер блока при выводе в консоль.
|
size_t format_max_block_size = 0; /// Максимальный размер блока при выводе в консоль.
|
||||||
String insert_format; /// Формат данных для INSERT-а при чтении их из stdin в batch режиме
|
String insert_format; /// Формат данных для INSERT-а при чтении их из stdin в batch режиме
|
||||||
size_t insert_format_max_block_size; /// Максимальный размер блока при чтении данных INSERT-а.
|
size_t insert_format_max_block_size = 0; /// Максимальный размер блока при чтении данных INSERT-а.
|
||||||
|
|
||||||
Context context;
|
Context context;
|
||||||
|
|
||||||
/// Чтение из stdin для batch режима
|
/// Чтение из stdin для batch режима
|
||||||
ReadBufferFromFileDescriptor std_in;
|
ReadBufferFromFileDescriptor std_in {STDIN_FILENO};
|
||||||
|
|
||||||
/// Вывод в консоль
|
/// Вывод в консоль
|
||||||
WriteBufferFromFileDescriptor std_out;
|
WriteBufferFromFileDescriptor std_out {STDOUT_FILENO};
|
||||||
BlockOutputStreamPtr block_std_out;
|
BlockOutputStreamPtr block_std_out;
|
||||||
|
|
||||||
String home_path;
|
String home_path;
|
||||||
@ -105,7 +111,7 @@ private:
|
|||||||
String history_file;
|
String history_file;
|
||||||
|
|
||||||
/// Строк прочитано или записано.
|
/// Строк прочитано или записано.
|
||||||
size_t processed_rows;
|
size_t processed_rows = 0;
|
||||||
|
|
||||||
/// Распарсенный запрос. Оттуда берутся некоторые настройки (формат).
|
/// Распарсенный запрос. Оттуда берутся некоторые настройки (формат).
|
||||||
ASTPtr parsed_query;
|
ASTPtr parsed_query;
|
||||||
@ -115,10 +121,10 @@ private:
|
|||||||
|
|
||||||
Stopwatch watch;
|
Stopwatch watch;
|
||||||
|
|
||||||
size_t rows_read_on_server;
|
size_t rows_read_on_server = 0;
|
||||||
size_t bytes_read_on_server;
|
size_t bytes_read_on_server = 0;
|
||||||
size_t written_progress_chars;
|
size_t written_progress_chars = 0;
|
||||||
bool written_first_block;
|
bool written_first_block = false;
|
||||||
|
|
||||||
/// Информация о внешних таблицах
|
/// Информация о внешних таблицах
|
||||||
std::list<ExternalTable> external_tables;
|
std::list<ExternalTable> external_tables;
|
||||||
@ -755,12 +761,7 @@ private:
|
|||||||
void onData(Block & block)
|
void onData(Block & block)
|
||||||
{
|
{
|
||||||
if (written_progress_chars)
|
if (written_progress_chars)
|
||||||
{
|
clearProgress();
|
||||||
for (size_t i = 0; i < written_progress_chars; ++i)
|
|
||||||
std::cerr << "\b \b";
|
|
||||||
|
|
||||||
written_progress_chars = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!block)
|
if (!block)
|
||||||
return;
|
return;
|
||||||
@ -813,8 +814,18 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void clearProgress()
|
||||||
|
{
|
||||||
|
std::cerr << RESTORE_CURSOR_POSITION CLEAR_TO_END_OF_LINE;
|
||||||
|
written_progress_chars = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void writeProgress()
|
void writeProgress()
|
||||||
{
|
{
|
||||||
|
if (!is_interactive)
|
||||||
|
return;
|
||||||
|
|
||||||
static size_t increment = 0;
|
static size_t increment = 0;
|
||||||
static const char * indicators[8] =
|
static const char * indicators[8] =
|
||||||
{
|
{
|
||||||
@ -825,12 +836,13 @@ private:
|
|||||||
"\033[1;34m←\033[0m",
|
"\033[1;34m←\033[0m",
|
||||||
"\033[1;35m↖\033[0m",
|
"\033[1;35m↖\033[0m",
|
||||||
"\033[1;36m↑\033[0m",
|
"\033[1;36m↑\033[0m",
|
||||||
"\033[1;37m↗\033[0m",
|
"\033[1m↗\033[0m",
|
||||||
};
|
};
|
||||||
|
|
||||||
if (is_interactive)
|
if (written_progress_chars)
|
||||||
{
|
clearProgress();
|
||||||
std::cerr << std::string(written_progress_chars, '\b');
|
else
|
||||||
|
std::cerr << SAVE_CURSOR_POSITION;
|
||||||
|
|
||||||
std::stringstream message;
|
std::stringstream message;
|
||||||
message << indicators[increment % 8]
|
message << indicators[increment % 8]
|
||||||
@ -846,10 +858,9 @@ private:
|
|||||||
message << ". ";
|
message << ". ";
|
||||||
|
|
||||||
written_progress_chars = message.str().size() - 13;
|
written_progress_chars = message.str().size() - 13;
|
||||||
std::cerr << message.rdbuf();
|
std::cerr << DISABLE_LINE_WRAPPING << message.rdbuf() << ENABLE_LINE_WRAPPING;
|
||||||
++increment;
|
++increment;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void writeFinalProgress()
|
void writeFinalProgress()
|
||||||
|
@ -140,7 +140,7 @@ void PrettyBlockOutputStream::write(const Block & block_)
|
|||||||
const ColumnWithNameAndType & col = block.getByPosition(i);
|
const ColumnWithNameAndType & col = block.getByPosition(i);
|
||||||
|
|
||||||
if (!no_escapes)
|
if (!no_escapes)
|
||||||
writeCString("\033[1;37m", ostr);
|
writeCString("\033[1m", ostr);
|
||||||
|
|
||||||
if (col.type->isNumeric())
|
if (col.type->isNumeric())
|
||||||
{
|
{
|
||||||
|
@ -29,7 +29,7 @@ void PrettyCompactBlockOutputStream::writeHeader(
|
|||||||
writeCString("─", ostr);
|
writeCString("─", ostr);
|
||||||
|
|
||||||
if (!no_escapes)
|
if (!no_escapes)
|
||||||
writeCString("\033[1;37m", ostr);
|
writeCString("\033[1m", ostr);
|
||||||
writeEscapedString(col.name, ostr);
|
writeEscapedString(col.name, ostr);
|
||||||
if (!no_escapes)
|
if (!no_escapes)
|
||||||
writeCString("\033[0m", ostr);
|
writeCString("\033[0m", ostr);
|
||||||
@ -37,7 +37,7 @@ void PrettyCompactBlockOutputStream::writeHeader(
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!no_escapes)
|
if (!no_escapes)
|
||||||
writeCString("\033[1;37m", ostr);
|
writeCString("\033[1m", ostr);
|
||||||
writeEscapedString(col.name, ostr);
|
writeEscapedString(col.name, ostr);
|
||||||
if (!no_escapes)
|
if (!no_escapes)
|
||||||
writeCString("\033[0m", ostr);
|
writeCString("\033[0m", ostr);
|
||||||
|
@ -48,7 +48,7 @@ void PrettySpaceBlockOutputStream::write(const Block & block_)
|
|||||||
writeChar(' ', ostr);
|
writeChar(' ', ostr);
|
||||||
|
|
||||||
if (!no_escapes)
|
if (!no_escapes)
|
||||||
writeCString("\033[1;37m", ostr);
|
writeCString("\033[1m", ostr);
|
||||||
writeEscapedString(col.name, ostr);
|
writeEscapedString(col.name, ostr);
|
||||||
if (!no_escapes)
|
if (!no_escapes)
|
||||||
writeCString("\033[0m", ostr);
|
writeCString("\033[0m", ostr);
|
||||||
@ -56,7 +56,7 @@ void PrettySpaceBlockOutputStream::write(const Block & block_)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!no_escapes)
|
if (!no_escapes)
|
||||||
writeCString("\033[1;37m", ostr);
|
writeCString("\033[1m", ostr);
|
||||||
writeEscapedString(col.name, ostr);
|
writeEscapedString(col.name, ostr);
|
||||||
if (!no_escapes)
|
if (!no_escapes)
|
||||||
writeCString("\033[0m", ostr);
|
writeCString("\033[0m", ostr);
|
||||||
|
@ -19,7 +19,7 @@ namespace DB
|
|||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
static const char * hilite_keyword = "\033[1;37m";
|
static const char * hilite_keyword = "\033[1m";
|
||||||
static const char * hilite_identifier = "\033[0;36m";
|
static const char * hilite_identifier = "\033[0;36m";
|
||||||
static const char * hilite_function = "\033[0;33m";
|
static const char * hilite_function = "\033[0;33m";
|
||||||
static const char * hilite_operator = "\033[1;33m";
|
static const char * hilite_operator = "\033[1;33m";
|
||||||
|
Loading…
Reference in New Issue
Block a user