Tabs in pretty format

This commit is contained in:
Volodya 2024-05-07 20:05:04 +00:00
parent 92bb69e062
commit e038d6a47d
6 changed files with 146 additions and 18 deletions

View File

@ -24,7 +24,7 @@ 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_padded_widths, Widths & name_widths) WidthsPerColumn & widths, Widths & max_padded_widths, Widths & name_widths, size_t table_border_width)
{ {
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);
@ -42,7 +42,7 @@ void PrettyBlockOutputFormat::calculateWidths(
/// Calculate widths of all values. /// Calculate widths of all values.
String serialized_value; String serialized_value;
size_t prefix = 2; // Tab character adjustment size_t prefix = format_settings.pretty.output_format_pretty_row_numbers ? row_number_width + table_border_width : table_border_width; // Tab character adjustment
for (size_t i = 0; i < num_columns; ++i) for (size_t i = 0; i < num_columns; ++i)
{ {
const auto & elem = header.getByPosition(i); const auto & elem = header.getByPosition(i);
@ -187,7 +187,7 @@ void PrettyBlockOutputFormat::writeChunk(const Chunk & chunk, PortKind port_kind
WidthsPerColumn widths; WidthsPerColumn widths;
Widths max_widths; Widths max_widths;
Widths name_widths; Widths name_widths;
calculateWidths(header, chunk, widths, max_widths, name_widths); calculateWidths(header, chunk, widths, max_widths, name_widths, 2);
const GridSymbols & grid_symbols = format_settings.pretty.charset == FormatSettings::Pretty::Charset::UTF8 ? const GridSymbols & grid_symbols = format_settings.pretty.charset == FormatSettings::Pretty::Charset::UTF8 ?
utf8_grid_symbols : utf8_grid_symbols :
@ -321,6 +321,7 @@ void PrettyBlockOutputFormat::writeChunk(const Chunk & chunk, PortKind port_kind
std::vector<String> transferred_row(num_columns); std::vector<String> transferred_row(num_columns);
bool has_transferred_row = false; bool has_transferred_row = false;
size_t prefix = format_settings.pretty.output_format_pretty_row_numbers ? row_number_width + 2 : 2;
for (size_t j = 0; j < num_columns; ++j) for (size_t j = 0; j < num_columns; ++j)
{ {
@ -334,11 +335,13 @@ void PrettyBlockOutputFormat::writeChunk(const Chunk & chunk, PortKind port_kind
serializations[j]->serializeText(*columns[j], i, out_serialize, format_settings); serializations[j]->serializeText(*columns[j], i, out_serialize, format_settings);
} }
if (cut_to_width) if (cut_to_width)
splitValueAtBreakLine(serialized_value, transferred_row[j], cur_width); splitValueAtBreakLine(serialized_value, transferred_row[j], cur_width, cut_to_width, prefix);
has_transferred_row |= !transferred_row[j].empty() && cur_width <= cut_to_width; has_transferred_row |= !transferred_row[j].empty();
writeValueWithPadding(serialized_value, cur_width, max_widths[j], cut_to_width, writeValueWithPadding(serialized_value, cur_width, max_widths[j], cut_to_width,
type.shouldAlignRightInPrettyFormats(), isNumber(type), !transferred_row[j].empty(), false); type.shouldAlignRightInPrettyFormats(), isNumber(type), !transferred_row[j].empty(), false);
prefix += max_widths[j] + 3;
} }
writeCString(grid_symbols.bar, out); writeCString(grid_symbols.bar, out);
@ -499,6 +502,7 @@ void PrettyBlockOutputFormat::writeTransferredRow(const Widths & max_widths, con
std::vector<String> new_transferred_row(num_columns); std::vector<String> new_transferred_row(num_columns);
bool has_transferred_row = false; bool has_transferred_row = false;
size_t prefix = format_settings.pretty.output_format_pretty_row_numbers ? row_number_width + 2 : 2;
for (size_t j = 0; j < num_columns; ++j) for (size_t j = 0; j < num_columns; ++j)
{ {
@ -510,11 +514,13 @@ void PrettyBlockOutputFormat::writeTransferredRow(const Widths & max_widths, con
const auto & type = *header.getByPosition(j).type; const auto & type = *header.getByPosition(j).type;
size_t cur_width = UTF8::computeWidth(reinterpret_cast<const UInt8 *>(transferred_row[j].data()), transferred_row[j].size()); size_t cur_width = UTF8::computeWidth(reinterpret_cast<const UInt8 *>(transferred_row[j].data()), transferred_row[j].size());
if (cut_to_width) if (cut_to_width)
splitValueAtBreakLine(transferred_row[j], new_transferred_row[j], cur_width); splitValueAtBreakLine(transferred_row[j], new_transferred_row[j], cur_width, cut_to_width, prefix);
has_transferred_row |= !new_transferred_row[j].empty() && cur_width <= cut_to_width; has_transferred_row |= !new_transferred_row[j].empty();
writeValueWithPadding(transferred_row[j], cur_width, max_widths[j], cut_to_width, writeValueWithPadding(transferred_row[j], cur_width, max_widths[j], cut_to_width,
type.shouldAlignRightInPrettyFormats(), isNumber(type), !new_transferred_row[j].empty(), !transferred_row[j].empty()); type.shouldAlignRightInPrettyFormats(), isNumber(type), !new_transferred_row[j].empty(), !transferred_row[j].empty());
prefix += max_widths[j] + 3;
} }
if (!space_block) if (!space_block)
@ -525,13 +531,14 @@ void PrettyBlockOutputFormat::writeTransferredRow(const Widths & max_widths, con
writeTransferredRow(max_widths, header, new_transferred_row, cut_to_width, space_block); writeTransferredRow(max_widths, header, new_transferred_row, cut_to_width, space_block);
} }
void PrettyBlockOutputFormat::splitValueAtBreakLine(String & value, String & transferred_value, size_t & value_width) void PrettyBlockOutputFormat::splitValueAtBreakLine(String & value, String & transferred_value, size_t & value_width, size_t cut_to_width, size_t prefix)
{ {
if (size_t break_line_pos = value.find_first_of('\n'); break_line_pos != String::npos) if (size_t break_line_pos = value.find_first_of('\n'); break_line_pos != String::npos)
{ {
transferred_value = value.substr(break_line_pos + 1); value_width = UTF8::computeWidth(reinterpret_cast<const UInt8 *>(value.data()), break_line_pos, prefix);
if (value_width <= cut_to_width)
transferred_value = value.substr(break_line_pos + 1);
value = value.substr(0, break_line_pos); value = value.substr(0, break_line_pos);
value_width = UTF8::computeWidth(reinterpret_cast<const UInt8 *>(value.data()), value.size());
} }
} }

View File

@ -44,7 +44,7 @@ protected:
void calculateWidths( void calculateWidths(
const Block & header, const Chunk & chunk, const Block & header, const Chunk & chunk,
WidthsPerColumn & widths, Widths & max_padded_widths, Widths & name_widths); WidthsPerColumn & widths, Widths & max_padded_widths, Widths & name_widths, size_t table_border_width);
void writeValueWithPadding( void writeValueWithPadding(
String & value, size_t value_width, size_t pad_to_width, size_t cut_to_width, String & value, size_t value_width, size_t pad_to_width, size_t cut_to_width,
@ -52,7 +52,7 @@ protected:
void writeTransferredRow(const Widths & max_widths, const Block & header, std::vector<String> & transferred_row, size_t cut_to_width, bool space_block); void writeTransferredRow(const Widths & max_widths, const Block & header, std::vector<String> & transferred_row, size_t cut_to_width, bool space_block);
void splitValueAtBreakLine(String & value, String & transferred_value, size_t & value_width); void splitValueAtBreakLine(String & value, String & transferred_value, size_t & value_width, size_t cut_to_width, size_t prefix);
void resetFormatterImpl() override void resetFormatterImpl() override
{ {

View File

@ -170,6 +170,8 @@ void PrettyCompactBlockOutputFormat::writeRow(
std::vector<String> transferred_row(num_columns); std::vector<String> transferred_row(num_columns);
bool has_transferred_row = false; bool has_transferred_row = false;
size_t prefix = format_settings.pretty.output_format_pretty_row_numbers ? row_number_width + 2 : 2;
for (size_t j = 0; j < num_columns; ++j) for (size_t j = 0; j < num_columns; ++j)
{ {
if (j != 0) if (j != 0)
@ -183,11 +185,13 @@ void PrettyCompactBlockOutputFormat::writeRow(
serializations[j]->serializeText(*columns[j], row_num, out_serialize, format_settings); serializations[j]->serializeText(*columns[j], row_num, out_serialize, format_settings);
} }
if (cut_to_width) if (cut_to_width)
splitValueAtBreakLine(serialized_value, transferred_row[j], cur_width); splitValueAtBreakLine(serialized_value, transferred_row[j], cur_width, cut_to_width, prefix);
has_transferred_row |= !transferred_row[j].empty() && cur_width <= cut_to_width; has_transferred_row |= !transferred_row[j].empty();
writeValueWithPadding(serialized_value, cur_width, max_widths[j], cut_to_width, writeValueWithPadding(serialized_value, cur_width, max_widths[j], cut_to_width,
type.shouldAlignRightInPrettyFormats(), isNumber(type), !transferred_row[j].empty(), false); type.shouldAlignRightInPrettyFormats(), isNumber(type), !transferred_row[j].empty(), false);
prefix += max_widths[j] + 3;
} }
writeCString(grid_symbols.bar, out); writeCString(grid_symbols.bar, out);
@ -208,7 +212,7 @@ void PrettyCompactBlockOutputFormat::writeChunk(const Chunk & chunk, PortKind po
WidthsPerColumn widths; WidthsPerColumn widths;
Widths max_widths; Widths max_widths;
Widths name_widths; Widths name_widths;
calculateWidths(header, chunk, widths, max_widths, name_widths); calculateWidths(header, chunk, widths, max_widths, name_widths, 2);
writeHeader(header, max_widths, name_widths); writeHeader(header, max_widths, name_widths);

View File

@ -31,7 +31,7 @@ void PrettySpaceBlockOutputFormat::writeChunk(const Chunk & chunk, PortKind port
WidthsPerColumn widths; WidthsPerColumn widths;
Widths max_widths; Widths max_widths;
Widths name_widths; Widths name_widths;
calculateWidths(header, chunk, widths, max_widths, name_widths); calculateWidths(header, chunk, widths, max_widths, name_widths, 1);
if (format_settings.pretty.output_format_pretty_row_numbers) if (format_settings.pretty.output_format_pretty_row_numbers)
writeString(String(row_number_width, ' '), out); writeString(String(row_number_width, ' '), out);
@ -88,6 +88,7 @@ void PrettySpaceBlockOutputFormat::writeChunk(const Chunk & chunk, PortKind port
writeCString("\033[0m", out); writeCString("\033[0m", out);
} }
size_t prefix = format_settings.pretty.output_format_pretty_row_numbers ? row_number_width + 1 : 1;
for (size_t column = 0; column < num_columns; ++column) for (size_t column = 0; column < num_columns; ++column)
{ {
if (column != 0) if (column != 0)
@ -101,11 +102,13 @@ void PrettySpaceBlockOutputFormat::writeChunk(const Chunk & chunk, PortKind port
serializations[column]->serializeText(*columns[column], row, out_serialize, format_settings); serializations[column]->serializeText(*columns[column], row, out_serialize, format_settings);
} }
if (cut_to_width) if (cut_to_width)
splitValueAtBreakLine(serialized_value, transferred_row[column], cur_width); splitValueAtBreakLine(serialized_value, transferred_row[column], cur_width, cur_width, prefix);
has_transferred_row |= !transferred_row[column].empty() && cur_width <= cut_to_width; has_transferred_row |= !transferred_row[column].empty();
writeValueWithPadding(serialized_value, cur_width, max_widths[column], cut_to_width, writeValueWithPadding(serialized_value, cur_width, max_widths[column], cut_to_width,
type.shouldAlignRightInPrettyFormats(), isNumber(type), !transferred_row[column].empty(), false); type.shouldAlignRightInPrettyFormats(), isNumber(type), !transferred_row[column].empty(), false);
prefix += max_widths[column] + 3;
} }
writeReadableNumberTip(chunk); writeReadableNumberTip(chunk);

View File

@ -0,0 +1,72 @@
┏━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┓
┃ id ┃ value ┃ value1 ┃
┡━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━━━━┩
│ 0 │ test test │ something │
└────┴───────────┴────────────────┘
┏━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━┓
┃ id ┃ value ┃ value1 ┃
┡━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━┩
1. │ 0 │ test test │ something │
└────┴───────────┴─────────────┘
┌─id─┬─value─┬─value1────┐
│ 0 │ test …│ something │
│ │… test │ │
└────┴───────┴───────────┘
┌─id─┬─value──────┬─value1────┐
1. │ 0 │ test …│ something │
│ │… test │ │
└────┴────────────┴───────────┘
id value value1
0 test … something
… test
id value value1
1. 0 test … something
… test
┌─id─┬─value─────┬─value1────┐
│ 0 │ something │ test …│
│ │ │… test │
└────┴───────────┴───────────┘
┌─id─┬─value─────┬─value1─┐
1. │ 0 │ something │ test …│
│ │ │… test │
└────┴───────────┴────────┘
id value value1
0 something test …
… test
id value value1
1. 0 something test …
… test
┏━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
┃ id ┃ value ┃ value1 ┃
┡━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
│ 0 │ something │ test …│
│ │ │… test │
├────┼───────────────────┼───────────┤
│ 1 │ some thing │ test …│
│ │ │… test │
└────┴───────────────────┴───────────┘
┏━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
┃ id ┃ value ┃ value1 ┃
┡━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
1. │ 0 │ something │ test …│
│ │ │… test │
├────┼────────────────────────┼───────────┤
2. │ 1 │ some thing │ test …│
│ │ │… test │
└────┴────────────────────────┴───────────┘
┏━━━━┳━━━━━━━┳━━━━━━━━┓
┃ id ┃ value ┃ value1 ┃
┡━━━━╇━━━━━━━╇━━━━━━━━┩
│ 0 │ somet⋯│ test …│
│ │ │…testt⋯ │
└────┴───────┴────────┘
┏━━━━┳━━━━━━━┳━━━━━━━━┓
┃ id ┃ value ┃ value1 ┃
┡━━━━╇━━━━━━━╇━━━━━━━━┩
1. │ 0 │ somet⋯│ test …│
│ │ │…testt⋯ │
└────┴───────┴────────┘

View File

@ -0,0 +1,42 @@
DROP TABLE IF EXISTS t_tabs;
CREATE TABLE t_tabs (id UInt64, value String, value1 String) ENGINE=MergeTree ORDER BY id;
INSERT INTO t_tabs VALUES(0, 'test test', '\tsomething');
SELECT * FROM t_tabs ORDER BY id FORMAT PrettyMonoBlock SETTINGS output_format_pretty_row_numbers = 0;
SELECT * FROM t_tabs ORDER BY id FORMAT PrettyMonoBlock;
TRUNCATE TABLE t_tabs;
INSERT INTO t_tabs VALUES(0, 'test\n\ttest', 'something');
SELECT * FROM t_tabs ORDER BY id FORMAT PrettyCompactNoEscapes SETTINGS output_format_pretty_row_numbers = 0;
SELECT * FROM t_tabs ORDER BY id FORMAT PrettyCompactNoEscapes;
SELECT * FROM t_tabs FORMAT PrettySpace SETTINGS output_format_pretty_row_numbers = 0;
SELECT * FROM t_tabs FORMAT PrettySpace;
TRUNCATE TABLE t_tabs;
INSERT INTO t_tabs VALUES(0, 'something', 'test\n\ttest');
SELECT * FROM t_tabs ORDER BY id FORMAT PrettyCompactNoEscapes SETTINGS output_format_pretty_row_numbers = 0;
SELECT * FROM t_tabs ORDER BY id FORMAT PrettyCompactNoEscapes;
SELECT * FROM t_tabs FORMAT PrettySpace SETTINGS output_format_pretty_row_numbers = 0;
SELECT * FROM t_tabs FORMAT PrettySpace;
INSERT INTO t_tabs VALUES(1, '\tsome\tthing\t', 'test\n\ttest');
SELECT * FROM t_tabs ORDER BY id FORMAT PrettyMonoBlock SETTINGS output_format_pretty_row_numbers = 0;
SELECT * FROM t_tabs ORDER BY id FORMAT PrettyMonoBlock;
TRUNCATE TABLE t_tabs;
SET output_format_pretty_max_value_width = 5;
INSERT INTO t_tabs VALUES(0, 'someth\ning\t', 'test\ntesttest');
SELECT * FROM t_tabs ORDER BY id FORMAT PrettyMonoBlock SETTINGS output_format_pretty_row_numbers = 0;
SELECT * FROM t_tabs ORDER BY id FORMAT PrettyMonoBlock;
DROP TABLE t_tabs;