diff --git a/src/Core/Settings.h b/src/Core/Settings.h index d6fcc07f591b..993016074c4d 100644 --- a/src/Core/Settings.h +++ b/src/Core/Settings.h @@ -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) \ diff --git a/src/Core/SettingsChangesHistory.h b/src/Core/SettingsChangesHistory.h index b74dd541a99e..0f5ef9470eba 100644 --- a/src/Core/SettingsChangesHistory.h +++ b/src/Core/SettingsChangesHistory.h @@ -105,6 +105,7 @@ static std::map 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."}, diff --git a/src/Formats/FormatFactory.cpp b/src/Formats/FormatFactory.cpp index 9e01709f788f..f60f0b676d60 100644 --- a/src/Formats/FormatFactory.cpp +++ b/src/Formats/FormatFactory.cpp @@ -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; diff --git a/src/Formats/FormatSettings.h b/src/Formats/FormatSettings.h index d1b7f5b4d25a..928c7bb8da02 100644 --- a/src/Formats/FormatSettings.h +++ b/src/Formats/FormatSettings.h @@ -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"}; diff --git a/src/Processors/Formats/Impl/PrettyBlockOutputFormat.cpp b/src/Processors/Formats/Impl/PrettyBlockOutputFormat.cpp index c1b7bd1dc03a..3f22ea26187c 100644 --- a/src/Processors/Formats/Impl/PrettyBlockOutputFormat.cpp +++ b/src/Processors/Formats/Impl/PrettyBlockOutputFormat.cpp @@ -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; @@ -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); @@ -390,7 +394,7 @@ 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 = " "; { @@ -398,7 +402,7 @@ void PrettyBlockOutputFormat::writeValueWithPadding( 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(serialized_value.data()), serialized_value.size(), 0, 1 + format_settings.pretty.max_value_width)); diff --git a/src/Processors/Formats/Impl/PrettyBlockOutputFormat.h b/src/Processors/Formats/Impl/PrettyBlockOutputFormat.h index d185df392f3d..4c52300fbd18 100644 --- a/src/Processors/Formats/Impl/PrettyBlockOutputFormat.h +++ b/src/Processors/Formats/Impl/PrettyBlockOutputFormat.h @@ -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 { diff --git a/src/Processors/Formats/Impl/PrettyCompactBlockOutputFormat.cpp b/src/Processors/Formats/Impl/PrettyCompactBlockOutputFormat.cpp index 99a83a8b0945..3bb275a19ae5 100644 --- a/src/Processors/Formats/Impl/PrettyCompactBlockOutputFormat.cpp +++ b/src/Processors/Formats/Impl/PrettyCompactBlockOutputFormat.cpp @@ -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) @@ -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); diff --git a/src/Processors/Formats/Impl/PrettySpaceBlockOutputFormat.cpp b/src/Processors/Formats/Impl/PrettySpaceBlockOutputFormat.cpp index 7b1758a45662..0176bb25be89 100644 --- a/src/Processors/Formats/Impl/PrettySpaceBlockOutputFormat.cpp +++ b/src/Processors/Formats/Impl/PrettySpaceBlockOutputFormat.cpp @@ -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; @@ -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); diff --git a/tests/queries/0_stateless/01293_pretty_max_value_width.reference b/tests/queries/0_stateless/01293_pretty_max_value_width.reference index 9887169f7af7..3c82bd8d7edd 100644 --- a/tests/queries/0_stateless/01293_pretty_max_value_width.reference +++ b/tests/queries/0_stateless/01293_pretty_max_value_width.reference @@ -84,31 +84,31 @@ ┏━━━┳━━━┓ ┃ x ┃ y ┃ ┡━━━╇━━━┩ -│ ⋯ │ ⋯ │ +│ привет │ мир │ └───┴───┘ ┌─x─┬─y─┐ -│ ⋯ │ ⋯ │ +│ привет │ мир │ └───┴───┘ x y - ⋯ ⋯ + привет мир ┏━━━┳━━━┓ ┃ x ┃ y ┃ ┡━━━╇━━━┩ -│ ⋯ │ ⋯ │ +│ привет │ мир │ ├───┼───┤ -│ ⋯ │ ⋯ │ +│ мир │ привет │ └───┴───┘ ┌─x─┬─y─┐ -│ ⋯ │ ⋯ │ -│ ⋯ │ ⋯ │ +│ привет │ мир │ +│ мир │ привет │ └───┴───┘ x y - ⋯ ⋯ - ⋯ ⋯ + привет мир + мир привет ┏━━━┳━━━┓ ┃ x ┃ y ┃ ┡━━━╇━━━┩ -│ ⋯ │ ⋯ │ +│ привет │ мир │ └───┴───┘ diff --git a/tests/queries/0_stateless/01293_pretty_max_value_width.sql b/tests/queries/0_stateless/01293_pretty_max_value_width.sql index 2c9c56d0076e..a8e0f19f58ec 100644 --- a/tests/queries/0_stateless/01293_pretty_max_value_width.sql +++ b/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; diff --git a/tests/queries/0_stateless/03020_long_values_pretty_are_not_cut_if_single.reference b/tests/queries/0_stateless/03020_long_values_pretty_are_not_cut_if_single.reference new file mode 100644 index 000000000000..71f9c3011957 --- /dev/null +++ b/tests/queries/0_stateless/03020_long_values_pretty_are_not_cut_if_single.reference @@ -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.\' diff --git a/tests/queries/0_stateless/03020_long_values_pretty_are_not_cut_if_single.sh b/tests/queries/0_stateless/03020_long_values_pretty_are_not_cut_if_single.sh new file mode 100755 index 000000000000..fa9e9f6d3e15 --- /dev/null +++ b/tests/queries/0_stateless/03020_long_values_pretty_are_not_cut_if_single.sh @@ -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.+$'