Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't cut single value in Pretty formats. #61795

Merged
merged 13 commits into from Mar 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Core/Settings.h
Expand Up @@ -1090,6 +1090,7 @@ class IColumn;
M(UInt64, output_format_pretty_max_rows, 10000, "Rows limit for Pretty formats.", 0) \
M(UInt64, output_format_pretty_max_column_pad_width, 250, "Maximum width to pad all values in a column in Pretty formats.", 0) \
M(UInt64, output_format_pretty_max_value_width, 10000, "Maximum width of value to display in Pretty formats. If greater - it will be cut.", 0) \
M(UInt64, output_format_pretty_max_value_width_apply_for_single_value, false, "Only cut values (see the `output_format_pretty_max_value_width` setting) when it is not a single value in a block. Otherwise output it entirely, which is useful for the `SHOW CREATE TABLE` query.", 0) \
M(UInt64Auto, output_format_pretty_color, "auto", "Use ANSI escape sequences in Pretty formats. 0 - disabled, 1 - enabled, 'auto' - enabled if a terminal.", 0) \
M(String, output_format_pretty_grid_charset, "UTF-8", "Charset for printing grid borders. Available charsets: ASCII, UTF-8 (default one).", 0) \
M(UInt64, output_format_parquet_row_group_size, 1000000, "Target row group size in rows.", 0) \
Expand Down
1 change: 1 addition & 0 deletions src/Core/SettingsChangesHistory.h
Expand Up @@ -105,6 +105,7 @@ static std::map<ClickHouseVersion, SettingsChangesHistory::SettingsChanges> sett
{"keeper_retry_max_backoff_ms", 5000, 5000, "Max backoff timeout for general keeper operations"},
{"s3queue_allow_experimental_sharded_mode", false, false, "Enable experimental sharded mode of S3Queue table engine. It is experimental because it will be rewritten"},
{"merge_tree_read_split_ranges_into_intersecting_and_non_intersecting_injection_probability", 0.0, 0.0, "For testing of `PartsSplitter` - split read ranges into intersecting and non intersecting every time you read from MergeTree with the specified probability."},
{"output_format_pretty_max_value_width_apply_for_single_value", true, false, "Single values in Pretty formats won't be cut."},
{"output_format_parquet_string_as_string", false, true, "ClickHouse allows arbitrary binary data in the String data type, which is typically UTF-8. Parquet/ORC/Arrow Strings only support UTF-8. That's why you can choose which Arrow's data type to use for the ClickHouse String data type - String or Binary. While Binary would be more correct and compatible, using String by default will correspond to user expectations in most cases."},
{"output_format_orc_string_as_string", false, true, "ClickHouse allows arbitrary binary data in the String data type, which is typically UTF-8. Parquet/ORC/Arrow Strings only support UTF-8. That's why you can choose which Arrow's data type to use for the ClickHouse String data type - String or Binary. While Binary would be more correct and compatible, using String by default will correspond to user expectations in most cases."},
{"output_format_arrow_string_as_string", false, true, "ClickHouse allows arbitrary binary data in the String data type, which is typically UTF-8. Parquet/ORC/Arrow Strings only support UTF-8. That's why you can choose which Arrow's data type to use for the ClickHouse String data type - String or Binary. While Binary would be more correct and compatible, using String by default will correspond to user expectations in most cases."},
Expand Down
1 change: 1 addition & 0 deletions src/Formats/FormatFactory.cpp
Expand Up @@ -167,6 +167,7 @@ FormatSettings getFormatSettings(const ContextPtr & context, const Settings & se
format_settings.pretty.max_column_pad_width = settings.output_format_pretty_max_column_pad_width;
format_settings.pretty.max_rows = settings.output_format_pretty_max_rows;
format_settings.pretty.max_value_width = settings.output_format_pretty_max_value_width;
format_settings.pretty.max_value_width_apply_for_single_value = settings.output_format_pretty_max_value_width_apply_for_single_value;
format_settings.pretty.highlight_digit_groups = settings.output_format_pretty_highlight_digit_groups;
format_settings.pretty.output_format_pretty_row_numbers = settings.output_format_pretty_row_numbers;
format_settings.pretty.output_format_pretty_single_large_number_tip_threshold = settings.output_format_pretty_single_large_number_tip_threshold;
Expand Down
1 change: 1 addition & 0 deletions src/Formats/FormatSettings.h
Expand Up @@ -275,6 +275,7 @@ struct FormatSettings
UInt64 max_rows = 10000;
UInt64 max_column_pad_width = 250;
UInt64 max_value_width = 10000;
UInt64 max_value_width_apply_for_single_value = false;
bool highlight_digit_groups = true;
SettingFieldUInt64Auto color{"auto"};

Expand Down
10 changes: 7 additions & 3 deletions src/Processors/Formats/Impl/PrettyBlockOutputFormat.cpp
Expand Up @@ -164,6 +164,10 @@ void PrettyBlockOutputFormat::writeChunk(const Chunk & chunk, PortKind port_kind
const auto & columns = chunk.getColumns();
const auto & header = getPort(port_kind).getHeader();

size_t cut_to_width = format_settings.pretty.max_value_width;
if (!format_settings.pretty.max_value_width_apply_for_single_value && num_rows == 1 && num_columns == 1 && total_rows == 0)
cut_to_width = 0;

WidthsPerColumn widths;
Widths max_widths;
Widths name_widths;
Expand Down Expand Up @@ -303,7 +307,7 @@ void PrettyBlockOutputFormat::writeChunk(const Chunk & chunk, PortKind port_kind
const auto & type = *header.getByPosition(j).type;
writeValueWithPadding(*columns[j], *serializations[j], i,
widths[j].empty() ? max_widths[j] : widths[j][i],
max_widths[j], type.shouldAlignRightInPrettyFormats(), isNumber(type));
max_widths[j], cut_to_width, type.shouldAlignRightInPrettyFormats(), isNumber(type));
}

writeCString(grid_symbols.bar, out);
Expand Down Expand Up @@ -390,15 +394,15 @@ static String highlightDigitGroups(String source)

void PrettyBlockOutputFormat::writeValueWithPadding(
const IColumn & column, const ISerialization & serialization, size_t row_num,
size_t value_width, size_t pad_to_width, bool align_right, bool is_number)
size_t value_width, size_t pad_to_width, size_t cut_to_width, bool align_right, bool is_number)
{
String serialized_value = " ";
{
WriteBufferFromString out_serialize(serialized_value, AppendModeTag());
serialization.serializeText(column, row_num, out_serialize, format_settings);
}

if (value_width > format_settings.pretty.max_value_width)
if (cut_to_width && value_width > cut_to_width)
{
serialized_value.resize(UTF8::computeBytesBeforeWidth(
reinterpret_cast<const UInt8 *>(serialized_value.data()), serialized_value.size(), 0, 1 + format_settings.pretty.max_value_width));
Expand Down
2 changes: 1 addition & 1 deletion src/Processors/Formats/Impl/PrettyBlockOutputFormat.h
Expand Up @@ -48,7 +48,7 @@ class PrettyBlockOutputFormat : public IOutputFormat

void writeValueWithPadding(
const IColumn & column, const ISerialization & serialization, size_t row_num,
size_t value_width, size_t pad_to_width, bool align_right, bool is_number);
size_t value_width, size_t pad_to_width, size_t cut_to_width, bool align_right, bool is_number);

void resetFormatterImpl() override
{
Expand Down
Expand Up @@ -160,6 +160,10 @@ void PrettyCompactBlockOutputFormat::writeRow(
size_t num_columns = max_widths.size();
const auto & columns = chunk.getColumns();

size_t cut_to_width = format_settings.pretty.max_value_width;
if (!format_settings.pretty.max_value_width_apply_for_single_value && chunk.getNumRows() == 1 && num_columns == 1 && total_rows == 0)
cut_to_width = 0;

writeCString(grid_symbols.bar, out);

for (size_t j = 0; j < num_columns; ++j)
Expand All @@ -169,7 +173,7 @@ void PrettyCompactBlockOutputFormat::writeRow(

const auto & type = *header.getByPosition(j).type;
const auto & cur_widths = widths[j].empty() ? max_widths[j] : widths[j][row_num];
writeValueWithPadding(*columns[j], *serializations[j], row_num, cur_widths, max_widths[j], type.shouldAlignRightInPrettyFormats(), isNumber(type));
writeValueWithPadding(*columns[j], *serializations[j], row_num, cur_widths, max_widths[j], cut_to_width, type.shouldAlignRightInPrettyFormats(), isNumber(type));
}

writeCString(grid_symbols.bar, out);
Expand Down
6 changes: 5 additions & 1 deletion src/Processors/Formats/Impl/PrettySpaceBlockOutputFormat.cpp
Expand Up @@ -24,6 +24,10 @@ void PrettySpaceBlockOutputFormat::writeChunk(const Chunk & chunk, PortKind port
const auto & header = getPort(port_kind).getHeader();
const auto & columns = chunk.getColumns();

size_t cut_to_width = format_settings.pretty.max_value_width;
if (!format_settings.pretty.max_value_width_apply_for_single_value && num_rows == 1 && num_columns == 1 && total_rows == 0)
cut_to_width = 0;

WidthsPerColumn widths;
Widths max_widths;
Widths name_widths;
Expand Down Expand Up @@ -84,7 +88,7 @@ void PrettySpaceBlockOutputFormat::writeChunk(const Chunk & chunk, PortKind port
const auto & type = *header.getByPosition(column).type;
auto & cur_width = widths[column].empty() ? max_widths[column] : widths[column][row];
writeValueWithPadding(
*columns[column], *serializations[column], row, cur_width, max_widths[column], type.shouldAlignRightInPrettyFormats(), isNumber(type));
*columns[column], *serializations[column], row, cur_width, max_widths[column], cut_to_width, type.shouldAlignRightInPrettyFormats(), isNumber(type));
}

writeReadableNumberTip(chunk);
Expand Down
20 changes: 10 additions & 10 deletions tests/queries/0_stateless/01293_pretty_max_value_width.reference
Expand Up @@ -84,31 +84,31 @@
┏━━━┳━━━┓
┃ x ┃ y ┃
┡━━━╇━━━┩
⋯⋯
приветмир
└───┴───┘
┌─x─┬─y─┐
⋯⋯
приветмир
└───┴───┘
x y

⋯ ⋯
привет мир
┏━━━┳━━━┓
┃ x ┃ y ┃
┡━━━╇━━━┩
⋯⋯
приветмир
├───┼───┤
⋯⋯
мирпривет
└───┴───┘
┌─x─┬─y─┐
⋯⋯
⋯⋯
приветмир
мирпривет
└───┴───┘
x y

⋯ ⋯
⋯ ⋯
привет мир
мир привет
┏━━━┳━━━┓
┃ x ┃ y ┃
┡━━━╇━━━┩
приветмир
└───┴───┘
2 changes: 1 addition & 1 deletion tests/queries/0_stateless/01293_pretty_max_value_width.sql
@@ -1,4 +1,4 @@
SET output_format_pretty_color=1;
SET output_format_pretty_color = 1, output_format_pretty_max_value_width_apply_for_single_value = 1, output_format_pretty_row_numbers = 0;
SELECT 'привет' AS x, 'мир' AS y FORMAT Pretty;

SET output_format_pretty_max_value_width = 5;
Expand Down
@@ -0,0 +1,4 @@
COMMENT 'Contains history of metrics values from tables system.metrics and system.events, periodically flushed to disk.' │
COMMENT 'Contains history of metrics values from tables system.metrics and system.events, periodically flushed to disk.' │
COMMENT 'Contains history of metrics values from tables system.metrics and system.events, periodically flushed to disk.'
\nCOMMENT \'Contains history of metrics values from tables system.metrics and system.events, periodically flushed to disk.\'
@@ -0,0 +1,17 @@
#!/usr/bin/env bash

CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
# shellcheck source=../shell_config.sh
. "$CURDIR"/../shell_config.sh

# The metric_log table has a large number of columns, so its definition is also large.
# And it is larger than the default value of `output_format_pretty_max_value_width`.
# But cutting it in the result of SHOW CREATE TABLE will be bad for a user.
# That's why we control it with the setting `output_format_pretty_max_value_width_apply_for_single_value`.

${CLICKHOUSE_CLIENT} --query "SHOW CREATE TABLE system.metric_log" --format Pretty | grep -P '^COMMENT'
${CLICKHOUSE_CLIENT} --query "SHOW CREATE TABLE system.metric_log" --format PrettyCompact | grep -P '^COMMENT'
${CLICKHOUSE_CLIENT} --query "SHOW CREATE TABLE system.metric_log" --format PrettySpace | grep -P '^COMMENT'

# Just in case, non-Pretty format:
${CLICKHOUSE_CLIENT} --query "SHOW CREATE TABLE system.metric_log" --format TSV | grep -o -P '\\nCOMMENT.+$'