From 4cbecd0bbd6ebcc7376d7e4fdbd2f18552809b35 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Sat, 23 Mar 2024 04:20:52 +0100 Subject: [PATCH 1/4] Add a setting --- src/Core/Settings.h | 1 + src/Core/SettingsChangesHistory.h | 1 + src/Formats/FormatFactory.cpp | 1 + src/Formats/FormatSettings.h | 1 + .../Formats/Impl/PrettyBlockOutputFormat.cpp | 74 ++++++++++++++++++- .../Formats/Impl/PrettyBlockOutputFormat.h | 2 +- .../Impl/PrettyCompactBlockOutputFormat.cpp | 2 +- .../Impl/PrettySpaceBlockOutputFormat.cpp | 2 +- 8 files changed, 79 insertions(+), 5 deletions(-) diff --git a/src/Core/Settings.h b/src/Core/Settings.h index d9071ef592b4..ea582c187107 100644 --- a/src/Core/Settings.h +++ b/src/Core/Settings.h @@ -1139,6 +1139,7 @@ class IColumn; M(Bool, output_format_enable_streaming, false, "Enable streaming in output formats that support it.", 0) \ M(Bool, output_format_write_statistics, true, "Write statistics about read rows, bytes, time elapsed in suitable output formats.", 0) \ M(Bool, output_format_pretty_row_numbers, false, "Add row numbers before each row for pretty output format", 0) \ + M(Bool, output_format_pretty_highlight_digit_groups, true, "If enabled and if output is a terminal, highlight every digit corresponding to the number of thousands, millions, etc. with underline.", 0) \ M(UInt64, output_format_pretty_single_large_number_tip_threshold, 1'000'000, "Print a readable number tip on the right side of the table if the block consists of a single number which exceeds this value (except 0)", 0) \ M(Bool, insert_distributed_one_random_shard, false, "If setting is enabled, inserting into distributed table will choose a random shard to write when there is no sharding key", 0) \ \ diff --git a/src/Core/SettingsChangesHistory.h b/src/Core/SettingsChangesHistory.h index ee56b86d9f23..3f72dd4df6ed 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_highlight_digit_groups", false, true, "If enabled and if output is a terminal, highlight every digit corresponding to the number of thousands, millions, etc. with underline."}, }}, {"24.2", {{"allow_suspicious_variant_types", true, false, "Don't allow creating Variant type with suspicious variants by default"}, {"validate_experimental_and_suspicious_types_inside_nested_types", false, true, "Validate usage of experimental and suspicious types inside nested types"}, diff --git a/src/Formats/FormatFactory.cpp b/src/Formats/FormatFactory.cpp index e7dce2738699..9e01709f788f 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.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; format_settings.protobuf.input_flatten_google_wrappers = settings.input_format_protobuf_flatten_google_wrappers; diff --git a/src/Formats/FormatSettings.h b/src/Formats/FormatSettings.h index 42b21c77cefa..d1b7f5b4d25a 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; + bool highlight_digit_groups = true; SettingFieldUInt64Auto color{"auto"}; bool output_format_pretty_row_numbers = false; diff --git a/src/Processors/Formats/Impl/PrettyBlockOutputFormat.cpp b/src/Processors/Formats/Impl/PrettyBlockOutputFormat.cpp index c5db8f2e30a8..2bdffa295994 100644 --- a/src/Processors/Formats/Impl/PrettyBlockOutputFormat.cpp +++ b/src/Processors/Formats/Impl/PrettyBlockOutputFormat.cpp @@ -303,7 +303,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()); + max_widths[j], type.shouldAlignRightInPrettyFormats(), isNumber(type)); } writeCString(grid_symbols.bar, out); @@ -322,9 +322,75 @@ void PrettyBlockOutputFormat::writeChunk(const Chunk & chunk, PortKind port_kind } +static String highlightDigitGroups(String source) +{ + if (source.size() <= 4) + return source; + + bool is_regular_number = true; + size_t num_digits_before_decimal = 0; + for (auto c : source) + { + if (c == '-' || c == ' ') + continue; + if (c == '.') + break; + if (c >= '0' && c <= '9') + { + ++num_digits_before_decimal; + } + else + { + is_regular_number = false; + break; + } + } + + if (!is_regular_number || num_digits_before_decimal <= 4) + return source; + + String result; + size_t size = source.size(); + result.reserve(2 * size); + + bool before_decimal = true; + size_t digit_num = 0; + for (size_t i = 0; i < size; ++i) + { + auto c = source[i]; + if (before_decimal && c >= '0' && c <= '9') + { + ++digit_num; + size_t offset = num_digits_before_decimal - digit_num; + if (offset && offset % 3 == 0) + { + result += "\033[4m"; + result += c; + result += "\033[0m"; + } + else + { + result += c; + } + } + else if (c == '.') + { + before_decimal = false; + result += c; + } + else + { + result += c; + } + } + + return result; +} + + 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) + size_t value_width, size_t pad_to_width, bool align_right, bool is_number) { String serialized_value = " "; { @@ -359,6 +425,10 @@ void PrettyBlockOutputFormat::writeValueWithPadding( writeChar(' ', out); }; + /// Highlight groups of thousands. + if (color && is_number && format_settings.pretty.highlight_digit_groups) + serialized_value = highlightDigitGroups(serialized_value); + if (align_right) { write_padding(); diff --git a/src/Processors/Formats/Impl/PrettyBlockOutputFormat.h b/src/Processors/Formats/Impl/PrettyBlockOutputFormat.h index 071bfa92e356..d185df392f3d 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); + size_t value_width, size_t pad_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 bda517708380..99a83a8b0945 100644 --- a/src/Processors/Formats/Impl/PrettyCompactBlockOutputFormat.cpp +++ b/src/Processors/Formats/Impl/PrettyCompactBlockOutputFormat.cpp @@ -169,7 +169,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()); + writeValueWithPadding(*columns[j], *serializations[j], row_num, cur_widths, max_widths[j], 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 e92863c93fb5..7b1758a45662 100644 --- a/src/Processors/Formats/Impl/PrettySpaceBlockOutputFormat.cpp +++ b/src/Processors/Formats/Impl/PrettySpaceBlockOutputFormat.cpp @@ -84,7 +84,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()); + *columns[column], *serializations[column], row, cur_width, max_widths[column], type.shouldAlignRightInPrettyFormats(), isNumber(type)); } writeReadableNumberTip(chunk); From cd8cdb480a0cbb99b6d884215dc25c7535636cd9 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Sat, 23 Mar 2024 04:21:06 +0100 Subject: [PATCH 2/4] Fix error --- src/AggregateFunctions/AggregateFunctionQuantileBFloat16.cpp | 3 +++ .../AggregateFunctionQuantileBFloat16Weighted.cpp | 3 +++ src/AggregateFunctions/AggregateFunctionQuantileDD.cpp | 3 +++ .../AggregateFunctionQuantileDeterministic.cpp | 3 +++ src/AggregateFunctions/AggregateFunctionQuantileExact.cpp | 3 +++ .../AggregateFunctionQuantileExactExclusive.cpp | 3 +++ src/AggregateFunctions/AggregateFunctionQuantileExactHigh.cpp | 3 +++ .../AggregateFunctionQuantileExactInclusive.cpp | 3 +++ src/AggregateFunctions/AggregateFunctionQuantileExactLow.cpp | 3 +++ .../AggregateFunctionQuantileExactWeighted.cpp | 3 +++ src/AggregateFunctions/AggregateFunctionQuantileGK.cpp | 3 +++ .../AggregateFunctionQuantileInterpolatedWeighted.cpp | 3 +++ src/AggregateFunctions/AggregateFunctionQuantileTDigest.cpp | 3 +++ .../AggregateFunctionQuantileTDigestWeighted.cpp | 3 +++ src/AggregateFunctions/AggregateFunctionQuantileTiming.cpp | 3 +++ .../AggregateFunctionQuantileTimingWeighted.cpp | 3 +++ 16 files changed, 48 insertions(+) diff --git a/src/AggregateFunctions/AggregateFunctionQuantileBFloat16.cpp b/src/AggregateFunctions/AggregateFunctionQuantileBFloat16.cpp index 5e17a147924f..902083d36610 100644 --- a/src/AggregateFunctions/AggregateFunctionQuantileBFloat16.cpp +++ b/src/AggregateFunctions/AggregateFunctionQuantileBFloat16.cpp @@ -26,6 +26,9 @@ template