Added setting "output_format_pretty_max_value_width"

This commit is contained in:
Alexey Milovidov 2020-06-01 01:12:13 +03:00
parent 4c2950b438
commit a76bd99e84
9 changed files with 206 additions and 29 deletions

View File

@ -143,7 +143,7 @@ static size_t computeWidthImpl(const UInt8 * data, size_t size, size_t prefix, s
++i; ++i;
} }
if (mode == BytesBeforLimit && width >= limit) if (mode == BytesBeforLimit && width > limit)
return i - (width - limit); return i - (width - limit);
switch (decoder.decode(data[i])) switch (decoder.decode(data[i]))
@ -172,7 +172,7 @@ static size_t computeWidthImpl(const UInt8 * data, size_t size, size_t prefix, s
else else
next_width += wcwidth(decoder.codepoint); next_width += wcwidth(decoder.codepoint);
if (mode == BytesBeforLimit && next_width >= limit) if (mode == BytesBeforLimit && next_width > limit)
return i - rollback; return i - rollback;
width = next_width; width = next_width;

View File

@ -99,6 +99,9 @@ int queryConvert(const CharT * bytes, int length)
/// and include `\t` to the nearest longer length with multiple of eight. /// and include `\t` to the nearest longer length with multiple of eight.
size_t computeWidth(const UInt8 * data, size_t size, size_t prefix = 0) noexcept; size_t computeWidth(const UInt8 * data, size_t size, size_t prefix = 0) noexcept;
/// Calculate the maximum number of bytes, so that substring of this size fits in 'limit' width.
size_t computeBytesBeforeWidth(const UInt8 * data, size_t size, size_t prefix, size_t limit) noexcept;
} }

View File

@ -211,6 +211,7 @@ struct Settings : public SettingsCollection<Settings>
\ \
M(SettingUInt64, output_format_pretty_max_rows, 10000, "Rows limit for Pretty formats.", 0) \ M(SettingUInt64, output_format_pretty_max_rows, 10000, "Rows limit for Pretty formats.", 0) \
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_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(SettingBool, output_format_pretty_color, true, "Use ANSI escape sequences to paint colors in Pretty formats", 0) \
M(SettingUInt64, output_format_parquet_row_group_size, 1000000, "Row group size in rows.", 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(SettingString, output_format_avro_codec, "", "Compression codec used for output. Possible values: 'null', 'deflate', 'snappy'.", 0) \

View File

@ -101,6 +101,7 @@ static FormatSettings getOutputFormatSetting(const Settings & settings, const Co
format_settings.csv.crlf_end_of_line = settings.output_format_csv_crlf_end_of_line; format_settings.csv.crlf_end_of_line = settings.output_format_csv_crlf_end_of_line;
format_settings.pretty.max_rows = settings.output_format_pretty_max_rows; format_settings.pretty.max_rows = settings.output_format_pretty_max_rows;
format_settings.pretty.max_column_pad_width = settings.output_format_pretty_max_column_pad_width; 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.color = settings.output_format_pretty_color;
format_settings.template_settings.resultset_format = settings.format_template_resultset; 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_format = settings.format_template_row;

View File

@ -30,14 +30,14 @@ PrettyBlockOutputFormat::PrettyBlockOutputFormat(
/// Note that number of code points is just a rough approximation of visible string width. /// Note that number of code points is just a rough approximation of visible string width.
void PrettyBlockOutputFormat::calculateWidths( void PrettyBlockOutputFormat::calculateWidths(
const Block & header, const Chunk & chunk, const Block & header, const Chunk & chunk,
WidthsPerColumn & widths, Widths & max_widths, Widths & name_widths) WidthsPerColumn & widths, Widths & max_padded_widths, Widths & name_widths)
{ {
size_t num_rows = std::min(chunk.getNumRows(), format_settings.pretty.max_rows); size_t num_rows = std::min(chunk.getNumRows(), format_settings.pretty.max_rows);
size_t num_columns = chunk.getNumColumns(); size_t num_columns = chunk.getNumColumns();
const auto & columns = chunk.getColumns(); const auto & columns = chunk.getColumns();
widths.resize(num_columns); widths.resize(num_columns);
max_widths.resize_fill(num_columns); max_padded_widths.resize_fill(num_columns);
name_widths.resize(num_columns); name_widths.resize(num_columns);
/// Calculate widths of all values. /// Calculate widths of all values.
@ -57,10 +57,10 @@ void PrettyBlockOutputFormat::calculateWidths(
elem.type->serializeAsText(*column, j, out_serialize, format_settings); elem.type->serializeAsText(*column, j, out_serialize, format_settings);
} }
widths[i][j] = std::min<UInt64>(format_settings.pretty.max_column_pad_width + 1, widths[i][j] = UTF8::computeWidth(reinterpret_cast<const UInt8 *>(serialized_value.data()), serialized_value.size(), prefix);
std::min(format_settings.pretty.max_value_width, max_padded_widths[i] = std::max(max_padded_widths[i],
UTF8::computeWidth(reinterpret_cast<const UInt8 *>(serialized_value.data()), serialized_value.size(), prefix))); std::min(format_settings.pretty.max_column_pad_width,
max_widths[i] = std::max(max_widths[i], widths[i][j]); std::min<UInt64>(format_settings.pretty.max_value_width, widths[i][j])));
} }
/// And also calculate widths for names of columns. /// And also calculate widths for names of columns.
@ -68,9 +68,9 @@ void PrettyBlockOutputFormat::calculateWidths(
// name string doesn't contain Tab, no need to pass `prefix` // name string doesn't contain Tab, no need to pass `prefix`
name_widths[i] = std::min<UInt64>(format_settings.pretty.max_column_pad_width, name_widths[i] = std::min<UInt64>(format_settings.pretty.max_column_pad_width,
UTF8::computeWidth(reinterpret_cast<const UInt8 *>(elem.name.data()), elem.name.size())); UTF8::computeWidth(reinterpret_cast<const UInt8 *>(elem.name.data()), elem.name.size()));
max_widths[i] = std::max(max_widths[i], name_widths[i]); max_padded_widths[i] = std::max(max_padded_widths[i], name_widths[i]);
} }
prefix += max_widths[i] + 3; prefix += max_padded_widths[i] + 3;
} }
} }
@ -175,18 +175,20 @@ void PrettyBlockOutputFormat::write(const Chunk & chunk, PortKind port_kind)
if (i != 0) if (i != 0)
writeString(middle_values_separator_s, out); writeString(middle_values_separator_s, out);
writeCString(" ", out); writeCString("", out);
for (size_t j = 0; j < num_columns; ++j) for (size_t j = 0; j < num_columns; ++j)
{ {
if (j != 0) if (j != 0)
writeCString(" ", out); writeCString("", out);
const auto & type = *header.getByPosition(j).type; const auto & type = *header.getByPosition(j).type;
writeValueWithPadding(*columns[j], type, i, widths[j].empty() ? max_widths[j] : widths[j][i], max_widths[j]); writeValueWithPadding(*columns[j], type, i,
widths[j].empty() ? max_widths[j] : widths[j][i],
max_widths[j]);
} }
writeCString(" \n", out); writeCString("\n", out);
} }
writeString(bottom_separator_s, out); writeString(bottom_separator_s, out);
@ -198,22 +200,33 @@ void PrettyBlockOutputFormat::write(const Chunk & chunk, PortKind port_kind)
void PrettyBlockOutputFormat::writeValueWithPadding( void PrettyBlockOutputFormat::writeValueWithPadding(
const IColumn & column, const IDataType & type, size_t row_num, size_t value_width, size_t pad_to_width) const IColumn & column, const IDataType & type, size_t row_num, size_t value_width, size_t pad_to_width)
{ {
auto write_padding = [&]() String serialized_value = " ";
{ {
for (size_t k = 0; k < pad_to_width - value_width; ++k) WriteBufferFromString out_serialize(serialized_value, WriteBufferFromString::AppendModeTag());
writeChar(' ', out);
};
String serialized_value;
{
WriteBufferFromString out_serialize(serialized_value);
type.serializeAsText(column, row_num, out_serialize, format_settings); type.serializeAsText(column, row_num, out_serialize, format_settings);
} }
if (serialized_value.size() > format_settings.pretty.max_value_width)
if (value_width > format_settings.pretty.max_value_width)
{ {
serialized_value.resize(format_settings.pretty.max_value_width); serialized_value.resize(UTF8::computeBytesBeforeWidth(
serialized_value += ""; reinterpret_cast<const UInt8 *>(serialized_value.data()), serialized_value.size(), 0, 1 + format_settings.pretty.max_value_width));
if (format_settings.pretty.color)
serialized_value += "\033[31;1m⋯\033[0m";
else
serialized_value += "";
value_width = format_settings.pretty.max_value_width;
} }
else
serialized_value += ' ';
auto write_padding = [&]()
{
if (pad_to_width > value_width)
for (size_t k = 0; k < pad_to_width - value_width; ++k)
writeChar(' ', out);
};
if (type.shouldAlignRightInPrettyFormats()) if (type.shouldAlignRightInPrettyFormats())
{ {

View File

@ -83,19 +83,19 @@ void PrettyCompactBlockOutputFormat::writeRow(
{ {
size_t num_columns = max_widths.size(); size_t num_columns = max_widths.size();
writeCString(" ", out); writeCString("", out);
for (size_t j = 0; j < num_columns; ++j) for (size_t j = 0; j < num_columns; ++j)
{ {
if (j != 0) if (j != 0)
writeCString(" ", out); writeCString("", out);
const auto & type = *header.getByPosition(j).type; const auto & type = *header.getByPosition(j).type;
const auto & cur_widths = widths[j].empty() ? max_widths[j] : widths[j][row_num]; 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]); writeValueWithPadding(*columns[j], type, row_num, cur_widths, max_widths[j]);
} }
writeCString(" \n", out); writeCString("\n", out);
} }
void PrettyCompactBlockOutputFormat::write(const Chunk & chunk, PortKind port_kind) void PrettyCompactBlockOutputFormat::write(const Chunk & chunk, PortKind port_kind)

View File

@ -34,6 +34,8 @@ void PrettySpaceBlockOutputFormat::write(const Chunk & chunk, PortKind port_kind
{ {
if (i != 0) if (i != 0)
writeCString(" ", out); writeCString(" ", out);
else
writeChar(' ', out);
const ColumnWithTypeAndName & col = header.getByPosition(i); const ColumnWithTypeAndName & col = header.getByPosition(i);
@ -67,7 +69,7 @@ void PrettySpaceBlockOutputFormat::write(const Chunk & chunk, PortKind port_kind
for (size_t column = 0; column < num_columns; ++column) for (size_t column = 0; column < num_columns; ++column)
{ {
if (column != 0) if (column != 0)
writeCString(" ", out); writeCString(" ", out);
const auto & type = *header.getByPosition(column).type; const auto & type = *header.getByPosition(column).type;
auto & cur_width = widths[column].empty() ? max_widths[column] : widths[column][row]; auto & cur_width = widths[column].empty() ? max_widths[column] : widths[column][row];

View File

@ -0,0 +1,114 @@
┏━━━━━━━━┳━━━━━┓
x  ┃ y  ┃
┡━━━━━━━━╇━━━━━┩
│ привет │ мир │
└────────┴─────┘
┏━━━━━━━┳━━━━━┓
x  ┃ y  ┃
┡━━━━━━━╇━━━━━┩
│ приве⋯│ мир │
└───────┴─────┘
┌─x─────┬─y───┐
│ приве⋯│ мир │
└───────┴─────┘
x y
приве⋯ мир
┏━━━━━━━┳━━━━━━━┓
x  ┃ y  ┃
┡━━━━━━━╇━━━━━━━┩
│ приве⋯│ мир │
├───────┼───────┤
│ мир │ приве⋯│
└───────┴───────┘
┌─x─────┬─y─────┐
│ приве⋯│ мир │
│ мир │ приве⋯│
└───────┴───────┘
x y
приве⋯ мир
мир приве⋯
┏━━━━━━━━┳━━━━━┓
x  ┃ y  ┃
┡━━━━━━━━╇━━━━━┩
│ привет │ мир │
└────────┴─────┘
┌─x──────┬─y───┐
│ привет │ мир │
└────────┴─────┘
x y
привет мир
┏━━━━━━━━┳━━━━━━━━┓
x  ┃ y  ┃
┡━━━━━━━━╇━━━━━━━━┩
│ привет │ мир │
├────────┼────────┤
│ мир │ привет │
└────────┴────────┘
┌─x──────┬─y──────┐
│ привет │ мир │
│ мир │ привет │
└────────┴────────┘
x y
привет мир
мир привет
┏━━━┳━━━┓
x ┃ y ┃
┡━━━╇━━━┩
│ п⋯│ м⋯│
└───┴───┘
┌─x─┬─y─┐
│ п⋯│ м⋯│
└───┴───┘
x y
п⋯ м⋯
┏━━━┳━━━┓
x ┃ y ┃
┡━━━╇━━━┩
│ п⋯│ м⋯│
├───┼───┤
│ м⋯│ п⋯│
└───┴───┘
┌─x─┬─y─┐
│ п⋯│ м⋯│
│ м⋯│ п⋯│
└───┴───┘
x y
п⋯ м⋯
м⋯ п⋯
┏━━━┳━━━┓
x ┃ y ┃
┡━━━╇━━━┩
⋯ │ ⋯ │
└───┴───┘
┌─x─┬─y─┐
⋯ │ ⋯ │
└───┴───┘
x y
⋯ ⋯
┏━━━┳━━━┓
x ┃ y ┃
┡━━━╇━━━┩
⋯ │ ⋯ │
├───┼───┤
⋯ │ ⋯ │
└───┴───┘
┌─x─┬─y─┐
⋯ │ ⋯ │
⋯ │ ⋯ │
└───┴───┘
x y
⋯ ⋯
⋯ ⋯
┏━━━┳━━━┓
┃ x ┃ y ┃
┡━━━╇━━━┩
│ ⋯ │ ⋯ │
└───┴───┘

View File

@ -0,0 +1,43 @@
SELECT 'привет' AS x, 'мир' AS y FORMAT Pretty;
SET output_format_pretty_max_value_width = 5;
SELECT 'привет' AS x, 'мир' AS y FORMAT Pretty;
SELECT 'привет' AS x, 'мир' AS y FORMAT PrettyCompact;
SELECT 'привет' AS x, 'мир' AS y FORMAT PrettySpace;
SELECT * FROM VALUES('x String, y String', ('привет', 'мир'), ('мир', 'привет')) FORMAT Pretty;
SELECT * FROM VALUES('x String, y String', ('привет', 'мир'), ('мир', 'привет')) FORMAT PrettyCompact;
SELECT * FROM VALUES('x String, y String', ('привет', 'мир'), ('мир', 'привет')) FORMAT PrettySpace;
SET output_format_pretty_max_value_width = 6;
SELECT 'привет' AS x, 'мир' AS y FORMAT Pretty;
SELECT 'привет' AS x, 'мир' AS y FORMAT PrettyCompact;
SELECT 'привет' AS x, 'мир' AS y FORMAT PrettySpace;
SELECT * FROM VALUES('x String, y String', ('привет', 'мир'), ('мир', 'привет')) FORMAT Pretty;
SELECT * FROM VALUES('x String, y String', ('привет', 'мир'), ('мир', 'привет')) FORMAT PrettyCompact;
SELECT * FROM VALUES('x String, y String', ('привет', 'мир'), ('мир', 'привет')) FORMAT PrettySpace;
SET output_format_pretty_max_value_width = 1;
SELECT 'привет' AS x, 'мир' AS y FORMAT Pretty;
SELECT 'привет' AS x, 'мир' AS y FORMAT PrettyCompact;
SELECT 'привет' AS x, 'мир' AS y FORMAT PrettySpace;
SELECT * FROM VALUES('x String, y String', ('привет', 'мир'), ('мир', 'привет')) FORMAT Pretty;
SELECT * FROM VALUES('x String, y String', ('привет', 'мир'), ('мир', 'привет')) FORMAT PrettyCompact;
SELECT * FROM VALUES('x String, y String', ('привет', 'мир'), ('мир', 'привет')) FORMAT PrettySpace;
SET output_format_pretty_max_value_width = 0;
SELECT 'привет' AS x, 'мир' AS y FORMAT Pretty;
SELECT 'привет' AS x, 'мир' AS y FORMAT PrettyCompact;
SELECT 'привет' AS x, 'мир' AS y FORMAT PrettySpace;
SELECT * FROM VALUES('x String, y String', ('привет', 'мир'), ('мир', 'привет')) FORMAT Pretty;
SELECT * FROM VALUES('x String, y String', ('привет', 'мир'), ('мир', 'привет')) FORMAT PrettyCompact;
SELECT * FROM VALUES('x String, y String', ('привет', 'мир'), ('мир', 'привет')) FORMAT PrettySpace;
SET output_format_pretty_color = 0;
SELECT 'привет' AS x, 'мир' AS y FORMAT Pretty;