add setting output_format_pretty_grid_charset

This setting allows to chose charset for printing grids (either UTF-8 or
ASCII).
This commit is contained in:
Maxim Sabyanin 2020-07-10 00:02:37 +03:00
parent a256e7e117
commit 40f7ec71d3
9 changed files with 277 additions and 37 deletions

View File

@ -439,6 +439,7 @@ struct Settings : public SettingsCollection<Settings>
M(SettingUInt64, output_format_pretty_max_column_pad_width, 250, "Maximum width to pad all values in a column in Pretty formats.", 0) \
M(SettingUInt64, output_format_pretty_max_value_width, 10000, "Maximum width of value to display in Pretty formats. If greater - it will be cut.", 0) \
M(SettingBool, output_format_pretty_color, true, "Use ANSI escape sequences to paint colors in Pretty formats", 0) \
M(SettingString, output_format_pretty_grid_charset, "UTF-8", "Charset for printing grid borders. Available charsets: ASCII, UTF-8 (default one).", 0) \
M(SettingUInt64, output_format_parquet_row_group_size, 1000000, "Row group size in rows.", 0) \
M(SettingString, output_format_avro_codec, "", "Compression codec used for output. Possible values: 'null', 'deflate', 'snappy'.", 0) \
M(SettingUInt64, output_format_avro_sync_interval, 16 * 1024, "Sync interval in bytes.", 0) \

View File

@ -419,7 +419,12 @@ void DataTypeNullable::serializeText(const IColumn & column, size_t row_num, Wri
/// This assumes UTF-8 and proper font support. This is Ok, because Pretty formats are "presentational", not for data exchange.
if (col.isNullAt(row_num))
{
if (settings.pretty.charset == FormatSettings::Pretty::Charset::UTF8)
writeCString("ᴺᵁᴸᴸ", ostr);
else
writeCString("null", ostr);
}
else
nested_data_type->serializeAsText(col.getNestedColumn(), row_num, ostr, settings);
}

View File

@ -105,6 +105,9 @@ static FormatSettings getOutputFormatSetting(const Settings & settings, const Co
format_settings.pretty.max_column_pad_width = settings.output_format_pretty_max_column_pad_width;
format_settings.pretty.max_value_width = settings.output_format_pretty_max_value_width;
format_settings.pretty.color = settings.output_format_pretty_color;
format_settings.pretty.charset = settings.output_format_pretty_grid_charset.toString() == "ASCII" ?
FormatSettings::Pretty::Charset::ASCII :
FormatSettings::Pretty::Charset::UTF8;
format_settings.template_settings.resultset_format = settings.format_template_resultset;
format_settings.template_settings.row_format = settings.format_template_row;
format_settings.template_settings.row_between_delimiter = settings.format_template_rows_between_delimiter;

View File

@ -194,6 +194,7 @@ void registerOutputFormatNull(FormatFactory & factory);
void registerOutputFormatProcessorPretty(FormatFactory & factory);
void registerOutputFormatProcessorPrettyCompact(FormatFactory & factory);
void registerOutputFormatProcessorPrettySpace(FormatFactory & factory);
void registerOutputFormatProcessorPrettyASCII(FormatFactory & factory);
void registerOutputFormatProcessorVertical(FormatFactory & factory);
void registerOutputFormatProcessorJSON(FormatFactory & factory);
void registerOutputFormatProcessorJSONCompact(FormatFactory & factory);

View File

@ -44,6 +44,14 @@ struct FormatSettings
UInt64 max_column_pad_width = 250;
UInt64 max_value_width = 10000;
bool color = true;
enum class Charset
{
UTF8,
ASCII,
};
Charset charset = Charset::UTF8;
};
Pretty pretty;

View File

@ -85,6 +85,54 @@ void PrettyBlockOutputFormat::calculateWidths(
}
}
namespace
{
/// Grid symbols are used for printing grid borders in a terminal.
/// Defaults values are UTF-8.
struct GridSymbols
{
const char * bold_left_top_corner = "";
const char * bold_right_top_corner = "";
const char * left_bottom_corner = "";
const char * right_bottom_corner = "";
const char * bold_left_separator = "";
const char * left_separator = "";
const char * bold_right_separator = "";
const char * right_separator = "";
const char * bold_top_separator = "";
const char * bold_middle_separator = "";
const char * middle_separator = "";
const char * bottom_separator = "";
const char * bold_dash = "";
const char * dash = "";
const char * bold_bar = "";
const char * bar = "";
};
GridSymbols utf8_grid_symbols;
GridSymbols ascii_grid_symbols {
"+",
"+",
"+",
"+",
"+",
"+",
"+",
"+",
"+",
"+",
"+",
"+",
"-",
"-",
"|",
"|"
};
}
void PrettyBlockOutputFormat::write(const Chunk & chunk, PortKind port_kind)
{
@ -106,38 +154,42 @@ void PrettyBlockOutputFormat::write(const Chunk & chunk, PortKind port_kind)
Widths name_widths;
calculateWidths(header, chunk, widths, max_widths, name_widths);
const GridSymbols & grid_symbols = format_settings.pretty.charset == FormatSettings::Pretty::Charset::UTF8 ?
utf8_grid_symbols :
ascii_grid_symbols;
/// Create separators
std::stringstream top_separator;
std::stringstream middle_names_separator;
std::stringstream middle_values_separator;
std::stringstream bottom_separator;
top_separator << "";
middle_names_separator << "";
middle_values_separator << "";
bottom_separator << "";
top_separator << grid_symbols.bold_left_top_corner;
middle_names_separator << grid_symbols.bold_left_separator;
middle_values_separator << grid_symbols.left_separator;
bottom_separator << grid_symbols.left_bottom_corner;
for (size_t i = 0; i < num_columns; ++i)
{
if (i != 0)
{
top_separator << "";
middle_names_separator << "";
middle_values_separator << "";
bottom_separator << "";
top_separator << grid_symbols.bold_top_separator;
middle_names_separator << grid_symbols.bold_middle_separator;
middle_values_separator << grid_symbols.middle_separator;
bottom_separator << grid_symbols.bottom_separator;
}
for (size_t j = 0; j < max_widths[i] + 2; ++j)
{
top_separator << "";
middle_names_separator << "";
middle_values_separator << "";
bottom_separator << "";
top_separator << grid_symbols.bold_dash;
middle_names_separator << grid_symbols.bold_dash;
middle_values_separator << grid_symbols.dash;
bottom_separator << grid_symbols.dash;
}
}
top_separator << "\n";
middle_names_separator << "\n";
middle_values_separator << "\n";
bottom_separator << "\n";
top_separator << grid_symbols.bold_right_top_corner << "\n";
middle_names_separator << grid_symbols.bold_right_separator << "\n";
middle_values_separator << grid_symbols.right_separator << "\n";
bottom_separator << grid_symbols.right_bottom_corner << "\n";
std::string top_separator_s = top_separator.str();
std::string middle_names_separator_s = middle_names_separator.str();
@ -148,11 +200,16 @@ void PrettyBlockOutputFormat::write(const Chunk & chunk, PortKind port_kind)
writeString(top_separator_s, out);
/// Names
writeCString("", out);
writeCString(grid_symbols.bold_bar, out);
writeCString(" ", out);
for (size_t i = 0; i < num_columns; ++i)
{
if (i != 0)
writeCString("", out);
{
writeCString(" ", out);
writeCString(grid_symbols.bold_bar, out);
writeCString(" ", out);
}
const auto & col = header.getByPosition(i);
@ -177,7 +234,9 @@ void PrettyBlockOutputFormat::write(const Chunk & chunk, PortKind port_kind)
if (format_settings.pretty.color)
writeCString("\033[0m", out);
}
writeCString("\n", out);
writeCString(" ", out);
writeCString(grid_symbols.bold_bar, out);
writeCString("\n", out);
writeString(middle_names_separator_s, out);
@ -186,12 +245,12 @@ void PrettyBlockOutputFormat::write(const Chunk & chunk, PortKind port_kind)
if (i != 0)
writeString(middle_values_separator_s, out);
writeCString("", out);
writeCString(grid_symbols.bar, out);
for (size_t j = 0; j < num_columns; ++j)
{
if (j != 0)
writeCString("", out);
writeCString(grid_symbols.bar, out);
const auto & type = *header.getByPosition(j).type;
writeValueWithPadding(*columns[j], type, i,
@ -199,7 +258,8 @@ void PrettyBlockOutputFormat::write(const Chunk & chunk, PortKind port_kind)
max_widths[j]);
}
writeCString("\n", out);
writeCString(grid_symbols.bar, out);
writeCString("\n", out);
}
writeString(bottom_separator_s, out);
@ -222,10 +282,16 @@ void PrettyBlockOutputFormat::writeValueWithPadding(
serialized_value.resize(UTF8::computeBytesBeforeWidth(
reinterpret_cast<const UInt8 *>(serialized_value.data()), serialized_value.size(), 0, 1 + format_settings.pretty.max_value_width));
const char *ellipsis = format_settings.pretty.charset == FormatSettings::Pretty::Charset::UTF8 ?
"" : "...";
if (format_settings.pretty.color)
serialized_value += "\033[31;1m⋯\033[0m";
{
serialized_value += "\033[31;1m";
serialized_value += ellipsis;
serialized_value += "\033[0m";
}
else
serialized_value += "";
serialized_value += ellipsis;
value_width = format_settings.pretty.max_value_width;
}

View File

@ -13,6 +13,39 @@ namespace ErrorCodes
{
}
namespace
{
/// Grid symbols are used for printing grid borders in a terminal.
/// Defaults values are UTF-8.
struct GridSymbols
{
const char * left_top_corner = "";
const char * right_top_corner = "";
const char * left_bottom_corner = "";
const char * right_bottom_corner = "";
const char * top_separator = "";
const char * bottom_separator = "";
const char * dash = "";
const char * bar = "";
};
GridSymbols utf8_grid_symbols;
GridSymbols ascii_grid_symbols {
"+",
"+",
"+",
"+",
"+",
"+",
"-",
"|"
};
}
void PrettyCompactBlockOutputFormat::writeHeader(
@ -20,19 +53,28 @@ void PrettyCompactBlockOutputFormat::writeHeader(
const Widths & max_widths,
const Widths & name_widths)
{
const GridSymbols & gridSymbols = format_settings.pretty.charset == FormatSettings::Pretty::Charset::UTF8 ?
utf8_grid_symbols :
ascii_grid_symbols;
/// Names
writeCString("┌─", out);
writeCString(gridSymbols.left_top_corner, out);
writeCString(gridSymbols.dash, out);
for (size_t i = 0; i < max_widths.size(); ++i)
{
if (i != 0)
writeCString("─┬─", out);
{
writeCString(gridSymbols.dash, out);
writeCString(gridSymbols.top_separator, out);
writeCString(gridSymbols.dash, out);
}
const ColumnWithTypeAndName & col = block.getByPosition(i);
if (col.type->shouldAlignRightInPrettyFormats())
{
for (size_t k = 0; k < max_widths[i] - name_widths[i]; ++k)
writeCString("", out);
writeCString(gridSymbols.dash, out);
if (format_settings.pretty.color)
writeCString("\033[1m", out);
@ -49,27 +91,32 @@ void PrettyCompactBlockOutputFormat::writeHeader(
writeCString("\033[0m", out);
for (size_t k = 0; k < max_widths[i] - name_widths[i]; ++k)
writeCString("", out);
writeCString(gridSymbols.dash, out);
}
}
writeCString("─┐\n", out);
writeCString(gridSymbols.dash, out);
writeCString(gridSymbols.right_top_corner, out);
writeCString("\n", out);
}
void PrettyCompactBlockOutputFormat::writeBottom(const Widths & max_widths)
{
const GridSymbols & gridSymbols = format_settings.pretty.charset == FormatSettings::Pretty::Charset::UTF8 ?
utf8_grid_symbols :
ascii_grid_symbols;
/// Create delimiters
std::stringstream bottom_separator;
bottom_separator << "";
bottom_separator << gridSymbols.left_bottom_corner;
for (size_t i = 0; i < max_widths.size(); ++i)
{
if (i != 0)
bottom_separator << "";
bottom_separator << gridSymbols.bottom_separator;
for (size_t j = 0; j < max_widths[i] + 2; ++j)
bottom_separator << "";
bottom_separator << gridSymbols.dash;
}
bottom_separator << "\n";
bottom_separator << gridSymbols.right_bottom_corner << "\n";
writeString(bottom_separator.str(), out);
}
@ -81,21 +128,26 @@ void PrettyCompactBlockOutputFormat::writeRow(
const WidthsPerColumn & widths,
const Widths & max_widths)
{
const GridSymbols & grid_symbols = format_settings.pretty.charset == FormatSettings::Pretty::Charset::UTF8 ?
utf8_grid_symbols :
ascii_grid_symbols;
size_t num_columns = max_widths.size();
writeCString("", out);
writeCString(grid_symbols.bar, out);
for (size_t j = 0; j < num_columns; ++j)
{
if (j != 0)
writeCString("", out);
writeCString(grid_symbols.bar, out);
const auto & type = *header.getByPosition(j).type;
const auto & cur_widths = widths[j].empty() ? max_widths[j] : widths[j][row_num];
writeValueWithPadding(*columns[j], type, row_num, cur_widths, max_widths[j]);
}
writeCString("\n", out);
writeCString(grid_symbols.bar, out);
writeCString("\n", out);
}
void PrettyCompactBlockOutputFormat::write(const Chunk & chunk, PortKind port_kind)

View File

@ -211,3 +211,96 @@ Showed first 6.
5 5 (5,'5') 2
Showed first 6.
+-------+-------+---------+-----------------+
| hello | world | tuple  | sometimes_nulls |
+-------+-------+---------+-----------------+
| 0 | 0 | (0,'0') | null |
+-------+-------+---------+-----------------+
| 1 | 1 | (1,'1') | 1 |
+-------+-------+---------+-----------------+
| 2 | 2 | (2,'2') | 2 |
+-------+-------+---------+-----------------+
| 3 | 3 | (3,'3') | null |
+-------+-------+---------+-----------------+
| 4 | 4 | (4,'4') | 1 |
+-------+-------+---------+-----------------+
+-------+-------+---------+-----------------+
| hello | world | tuple  | sometimes_nulls |
+-------+-------+---------+-----------------+
| 5 | 5 | (5,'5') | 2 |
+-------+-------+---------+-----------------+
Showed first 6.
+-hello-+-world-+-tuple---+-sometimes_nulls-+
| 0 | 0 | (0,'0') | null |
| 1 | 1 | (1,'1') | 1 |
| 2 | 2 | (2,'2') | 2 |
| 3 | 3 | (3,'3') | null |
| 4 | 4 | (4,'4') | 1 |
+-------+-------+---------+-----------------+
+-hello-+-world-+-tuple---+-sometimes_nulls-+
| 5 | 5 | (5,'5') | 2 |
+-------+-------+---------+-----------------+
Showed first 6.
hello world tuple sometimes_nulls
0 0 (0,'0') null
1 1 (1,'1') 1
2 2 (2,'2') 2
3 3 (3,'3') null
4 4 (4,'4') 1
hello world tuple sometimes_nulls
5 5 (5,'5') 2
Showed first 6.
+-hello-+-world-+-tuple---+-sometimes_nulls-+
| 0 | 0 | (0,'0') | null |
| 1 | 1 | (1,'1') | 1 |
| 2 | 2 | (2,'2') | 2 |
| 3 | 3 | (3,'3') | null |
| 4 | 4 | (4,'4') | 1 |
| 5 | 5 | (5,'5') | 2 |
+-------+-------+---------+-----------------+
Showed first 6.
+-------+-------+---------+-----------------+
| hello | world | tuple | sometimes_nulls |
+-------+-------+---------+-----------------+
| 0 | 0 | (0,'0') | null |
+-------+-------+---------+-----------------+
| 1 | 1 | (1,'1') | 1 |
+-------+-------+---------+-----------------+
| 2 | 2 | (2,'2') | 2 |
+-------+-------+---------+-----------------+
| 3 | 3 | (3,'3') | null |
+-------+-------+---------+-----------------+
| 4 | 4 | (4,'4') | 1 |
+-------+-------+---------+-----------------+
+-------+-------+---------+-----------------+
| hello | world | tuple | sometimes_nulls |
+-------+-------+---------+-----------------+
| 5 | 5 | (5,'5') | 2 |
+-------+-------+---------+-----------------+
Showed first 6.
+-hello-+-world-+-tuple---+-sometimes_nulls-+
| 0 | 0 | (0,'0') | null |
| 1 | 1 | (1,'1') | 1 |
| 2 | 2 | (2,'2') | 2 |
| 3 | 3 | (3,'3') | null |
| 4 | 4 | (4,'4') | 1 |
+-------+-------+---------+-----------------+
+-hello-+-world-+-tuple---+-sometimes_nulls-+
| 5 | 5 | (5,'5') | 2 |
+-------+-------+---------+-----------------+
Showed first 6.
hello world tuple sometimes_nulls
0 0 (0,'0') null
1 1 (1,'1') 1
2 2 (2,'2') 2
3 3 (3,'3') null
4 4 (4,'4') 1
hello world tuple sometimes_nulls
5 5 (5,'5') 2
Showed first 6.

View File

@ -15,3 +15,14 @@ SELECT number AS hello, toString(number) AS world, (hello, world) AS tuple, null
SELECT number AS hello, toString(number) AS world, (hello, world) AS tuple, nullIf(hello % 3, 0) AS sometimes_nulls FROM system.numbers LIMIT 10 SETTINGS max_block_size = 5 FORMAT PrettyNoEscapes;
SELECT number AS hello, toString(number) AS world, (hello, world) AS tuple, nullIf(hello % 3, 0) AS sometimes_nulls FROM system.numbers LIMIT 10 SETTINGS max_block_size = 5 FORMAT PrettyCompactNoEscapes;
SELECT number AS hello, toString(number) AS world, (hello, world) AS tuple, nullIf(hello % 3, 0) AS sometimes_nulls FROM system.numbers LIMIT 10 SETTINGS max_block_size = 5 FORMAT PrettySpaceNoEscapes;
SET output_format_pretty_grid_charset = 'ASCII';
SELECT number AS hello, toString(number) AS world, (hello, world) AS tuple, nullIf(hello % 3, 0) AS sometimes_nulls FROM system.numbers LIMIT 10 SETTINGS max_block_size = 5 FORMAT Pretty;
SELECT number AS hello, toString(number) AS world, (hello, world) AS tuple, nullIf(hello % 3, 0) AS sometimes_nulls FROM system.numbers LIMIT 10 SETTINGS max_block_size = 5 FORMAT PrettyCompact;
SELECT number AS hello, toString(number) AS world, (hello, world) AS tuple, nullIf(hello % 3, 0) AS sometimes_nulls FROM system.numbers LIMIT 10 SETTINGS max_block_size = 5 FORMAT PrettySpace;
SELECT number AS hello, toString(number) AS world, (hello, world) AS tuple, nullIf(hello % 3, 0) AS sometimes_nulls FROM system.numbers LIMIT 10 SETTINGS max_block_size = 5 FORMAT PrettyCompactMonoBlock;
SELECT number AS hello, toString(number) AS world, (hello, world) AS tuple, nullIf(hello % 3, 0) AS sometimes_nulls FROM system.numbers LIMIT 10 SETTINGS max_block_size = 5 FORMAT PrettyNoEscapes;
SELECT number AS hello, toString(number) AS world, (hello, world) AS tuple, nullIf(hello % 3, 0) AS sometimes_nulls FROM system.numbers LIMIT 10 SETTINGS max_block_size = 5 FORMAT PrettyCompactNoEscapes;
SELECT number AS hello, toString(number) AS world, (hello, world) AS tuple, nullIf(hello % 3, 0) AS sometimes_nulls FROM system.numbers LIMIT 10 SETTINGS max_block_size = 5 FORMAT PrettySpaceNoEscapes;