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:
Alexey Milovidov 2014-08-15 04:08:15 +04:00
parent 65cf115313
commit 047e5e30df
5 changed files with 66 additions and 55 deletions

View File

@ -49,6 +49,16 @@
#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.
*/
@ -61,11 +71,7 @@ using Poco::SharedPtr;
class Client : public Poco::Util::Application
{
public:
Client() : is_interactive(true), stdin_is_not_tty(false),
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)
{
}
Client() {}
private:
typedef std::unordered_set<String> StringSet;
@ -77,24 +83,24 @@ private:
"q", "й", "\\q", "\\Q", "\\й", "\\Й", ":q", "Жй"
};
bool is_interactive; /// Использовать readline интерфейс или batch режим.
bool stdin_is_not_tty; /// stdin - не терминал.
bool is_interactive = true; /// Использовать readline интерфейс или batch режим.
bool stdin_is_not_tty = false; /// stdin - не терминал.
SharedPtr<Connection> connection; /// Соединение с БД.
String query; /// Текущий запрос.
String format; /// Формат вывода результата в консоль.
size_t format_max_block_size; /// Максимальный размер блока при выводе в консоль.
size_t format_max_block_size = 0; /// Максимальный размер блока при выводе в консоль.
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;
/// Чтение из stdin для batch режима
ReadBufferFromFileDescriptor std_in;
ReadBufferFromFileDescriptor std_in {STDIN_FILENO};
/// Вывод в консоль
WriteBufferFromFileDescriptor std_out;
WriteBufferFromFileDescriptor std_out {STDOUT_FILENO};
BlockOutputStreamPtr block_std_out;
String home_path;
@ -105,7 +111,7 @@ private:
String history_file;
/// Строк прочитано или записано.
size_t processed_rows;
size_t processed_rows = 0;
/// Распарсенный запрос. Оттуда берутся некоторые настройки (формат).
ASTPtr parsed_query;
@ -115,10 +121,10 @@ private:
Stopwatch watch;
size_t rows_read_on_server;
size_t bytes_read_on_server;
size_t written_progress_chars;
bool written_first_block;
size_t rows_read_on_server = 0;
size_t bytes_read_on_server = 0;
size_t written_progress_chars = 0;
bool written_first_block = false;
/// Информация о внешних таблицах
std::list<ExternalTable> external_tables;
@ -755,12 +761,7 @@ private:
void onData(Block & block)
{
if (written_progress_chars)
{
for (size_t i = 0; i < written_progress_chars; ++i)
std::cerr << "\b \b";
written_progress_chars = 0;
}
clearProgress();
if (!block)
return;
@ -813,8 +814,18 @@ private:
}
void clearProgress()
{
std::cerr << RESTORE_CURSOR_POSITION CLEAR_TO_END_OF_LINE;
written_progress_chars = 0;
}
void writeProgress()
{
if (!is_interactive)
return;
static size_t increment = 0;
static const char * indicators[8] =
{
@ -825,12 +836,13 @@ private:
"\033[1;34m←\033[0m",
"\033[1;35m↖\033[0m",
"\033[1;36m↑\033[0m",
"\033[1;37m↗\033[0m",
"\033[1m↗\033[0m",
};
if (is_interactive)
{
std::cerr << std::string(written_progress_chars, '\b');
if (written_progress_chars)
clearProgress();
else
std::cerr << SAVE_CURSOR_POSITION;
std::stringstream message;
message << indicators[increment % 8]
@ -846,10 +858,9 @@ private:
message << ". ";
written_progress_chars = message.str().size() - 13;
std::cerr << message.rdbuf();
std::cerr << DISABLE_LINE_WRAPPING << message.rdbuf() << ENABLE_LINE_WRAPPING;
++increment;
}
}
void writeFinalProgress()

View File

@ -140,7 +140,7 @@ void PrettyBlockOutputStream::write(const Block & block_)
const ColumnWithNameAndType & col = block.getByPosition(i);
if (!no_escapes)
writeCString("\033[1;37m", ostr);
writeCString("\033[1m", ostr);
if (col.type->isNumeric())
{

View File

@ -29,7 +29,7 @@ void PrettyCompactBlockOutputStream::writeHeader(
writeCString("", ostr);
if (!no_escapes)
writeCString("\033[1;37m", ostr);
writeCString("\033[1m", ostr);
writeEscapedString(col.name, ostr);
if (!no_escapes)
writeCString("\033[0m", ostr);
@ -37,7 +37,7 @@ void PrettyCompactBlockOutputStream::writeHeader(
else
{
if (!no_escapes)
writeCString("\033[1;37m", ostr);
writeCString("\033[1m", ostr);
writeEscapedString(col.name, ostr);
if (!no_escapes)
writeCString("\033[0m", ostr);

View File

@ -48,7 +48,7 @@ void PrettySpaceBlockOutputStream::write(const Block & block_)
writeChar(' ', ostr);
if (!no_escapes)
writeCString("\033[1;37m", ostr);
writeCString("\033[1m", ostr);
writeEscapedString(col.name, ostr);
if (!no_escapes)
writeCString("\033[0m", ostr);
@ -56,7 +56,7 @@ void PrettySpaceBlockOutputStream::write(const Block & block_)
else
{
if (!no_escapes)
writeCString("\033[1;37m", ostr);
writeCString("\033[1m", ostr);
writeEscapedString(col.name, ostr);
if (!no_escapes)
writeCString("\033[0m", ostr);

View File

@ -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_function = "\033[0;33m";
static const char * hilite_operator = "\033[1;33m";