mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 23:21:59 +00:00
Make Vertical format prettier
This commit is contained in:
parent
6943b07ceb
commit
6054f43000
102
src/Formats/PrettyFormatHelpers.cpp
Normal file
102
src/Formats/PrettyFormatHelpers.cpp
Normal file
@ -0,0 +1,102 @@
|
||||
#include <Formats/PrettyFormatHelpers.h>
|
||||
#include <IO/WriteBuffer.h>
|
||||
#include <IO/WriteHelpers.h>
|
||||
#include <Processors/Chunk.h>
|
||||
#include <Common/formatReadable.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
void writeReadableNumberTipIfSingleValue(WriteBuffer & out, const Chunk & chunk, const FormatSettings & settings, bool color)
|
||||
{
|
||||
if (chunk.getNumRows() == 1 && chunk.getNumColumns() == 1)
|
||||
writeReadableNumberTip(out, *chunk.getColumns()[0], 0, settings, color);
|
||||
}
|
||||
|
||||
void writeReadableNumberTip(WriteBuffer & out, const IColumn & column, size_t row, const FormatSettings & settings, bool color)
|
||||
{
|
||||
if (column.isNullAt(row))
|
||||
return;
|
||||
|
||||
auto value = column.getFloat64(row);
|
||||
auto threshold = settings.pretty.output_format_pretty_single_large_number_tip_threshold;
|
||||
|
||||
if (threshold && isFinite(value) && abs(value) > threshold)
|
||||
{
|
||||
if (color)
|
||||
writeCString("\033[90m", out);
|
||||
writeCString(" -- ", out);
|
||||
formatReadableQuantity(value, out, 2);
|
||||
if (color)
|
||||
writeCString("\033[0m", out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
18
src/Formats/PrettyFormatHelpers.h
Normal file
18
src/Formats/PrettyFormatHelpers.h
Normal file
@ -0,0 +1,18 @@
|
||||
#include <base/types.h>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
class Chunk;
|
||||
class IColumn;
|
||||
class WriteBuffer;
|
||||
struct FormatSettings;
|
||||
|
||||
/// Prints text describing the number in the form of: -- 12.34 million
|
||||
void writeReadableNumberTip(WriteBuffer & out, const IColumn & column, size_t row, const FormatSettings & settings, bool color);
|
||||
void writeReadableNumberTipIfSingleValue(WriteBuffer & out, const Chunk & chunk, const FormatSettings & settings, bool color);
|
||||
|
||||
/// Underscores digit groups related to thousands using terminal ANSI escape sequences.
|
||||
String highlightDigitGroups(String source);
|
||||
|
||||
}
|
@ -795,9 +795,9 @@ BlockIO InterpreterSystemQuery::execute()
|
||||
case Type::WAIT_FAILPOINT:
|
||||
{
|
||||
getContext()->checkAccess(AccessType::SYSTEM_FAILPOINT);
|
||||
LOG_TRACE(log, "waiting for failpoint {}", query.fail_point_name);
|
||||
LOG_TRACE(log, "Waiting for failpoint {}", query.fail_point_name);
|
||||
FailPointInjection::pauseFailPoint(query.fail_point_name);
|
||||
LOG_TRACE(log, "finished failpoint {}", query.fail_point_name);
|
||||
LOG_TRACE(log, "Finished waiting for failpoint {}", query.fail_point_name);
|
||||
break;
|
||||
}
|
||||
case Type::RESET_COVERAGE:
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <Processors/Formats/Impl/PrettyBlockOutputFormat.h>
|
||||
#include <Formats/FormatFactory.h>
|
||||
#include <Formats/PrettyFormatHelpers.h>
|
||||
#include <IO/WriteBuffer.h>
|
||||
#include <IO/WriteHelpers.h>
|
||||
#include <IO/WriteBufferFromString.h>
|
||||
@ -352,7 +353,8 @@ void PrettyBlockOutputFormat::writeChunk(const Chunk & chunk, PortKind port_kind
|
||||
}
|
||||
|
||||
writeCString(grid_symbols.bar, out);
|
||||
writeReadableNumberTip(chunk);
|
||||
if (readable_number_tip)
|
||||
writeReadableNumberTipIfSingleValue(out, chunk, format_settings, color);
|
||||
writeCString("\n", out);
|
||||
}
|
||||
|
||||
@ -392,72 +394,6 @@ 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, size_t cut_to_width, bool align_right, bool is_number)
|
||||
@ -553,30 +489,6 @@ void PrettyBlockOutputFormat::writeSuffix()
|
||||
}
|
||||
}
|
||||
|
||||
void PrettyBlockOutputFormat::writeReadableNumberTip(const Chunk & chunk)
|
||||
{
|
||||
const auto & columns = chunk.getColumns();
|
||||
auto is_single_number = readable_number_tip && chunk.getNumRows() == 1 && chunk.getNumColumns() == 1;
|
||||
if (!is_single_number)
|
||||
return;
|
||||
|
||||
if (columns[0]->isNullAt(0))
|
||||
return;
|
||||
|
||||
auto value = columns[0]->getFloat64(0);
|
||||
auto threshold = format_settings.pretty.output_format_pretty_single_large_number_tip_threshold;
|
||||
|
||||
if (threshold && isFinite(value) && abs(value) > threshold)
|
||||
{
|
||||
if (color)
|
||||
writeCString("\033[90m", out);
|
||||
writeCString(" -- ", out);
|
||||
formatReadableQuantity(value, out, 2);
|
||||
if (color)
|
||||
writeCString("\033[0m", out);
|
||||
}
|
||||
}
|
||||
|
||||
void registerOutputFormatPretty(FormatFactory & factory)
|
||||
{
|
||||
registerPrettyFormatWithNoEscapesAndMonoBlock<PrettyBlockOutputFormat>(factory, "Pretty");
|
||||
|
@ -38,7 +38,6 @@ protected:
|
||||
virtual void writeChunk(const Chunk & chunk, PortKind port_kind);
|
||||
void writeMonoChunkIfNeeded();
|
||||
void writeSuffix() override;
|
||||
void writeReadableNumberTip(const Chunk & chunk);
|
||||
|
||||
void onRowsReadBeforeUpdate() override { total_rows = getRowsReadBefore(); }
|
||||
|
||||
@ -57,8 +56,10 @@ protected:
|
||||
|
||||
bool color;
|
||||
|
||||
private:
|
||||
protected:
|
||||
bool readable_number_tip = false;
|
||||
|
||||
private:
|
||||
bool mono_block;
|
||||
/// For mono_block == true only
|
||||
Chunk mono_chunk;
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <IO/WriteHelpers.h>
|
||||
#include <IO/Operators.h>
|
||||
#include <Formats/FormatFactory.h>
|
||||
#include <Formats/PrettyFormatHelpers.h>
|
||||
#include <Processors/Formats/Impl/PrettyCompactBlockOutputFormat.h>
|
||||
|
||||
|
||||
@ -189,7 +190,8 @@ void PrettyCompactBlockOutputFormat::writeRow(
|
||||
}
|
||||
|
||||
writeCString(grid_symbols.bar, out);
|
||||
writeReadableNumberTip(chunk);
|
||||
if (readable_number_tip)
|
||||
writeReadableNumberTipIfSingleValue(out, chunk, format_settings, color);
|
||||
writeCString("\n", out);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <Formats/FormatFactory.h>
|
||||
#include <Formats/PrettyFormatHelpers.h>
|
||||
#include <IO/WriteBuffer.h>
|
||||
#include <IO/WriteHelpers.h>
|
||||
#include <Processors/Formats/Impl/PrettySpaceBlockOutputFormat.h>
|
||||
@ -102,7 +103,8 @@ void PrettySpaceBlockOutputFormat::writeChunk(const Chunk & chunk, PortKind port
|
||||
writeValueWithPadding(
|
||||
*columns[column], *serializations[column], row, cur_width, max_widths[column], cut_to_width, type.shouldAlignRightInPrettyFormats(), isNumber(type));
|
||||
}
|
||||
writeReadableNumberTip(chunk);
|
||||
if (readable_number_tip)
|
||||
writeReadableNumberTipIfSingleValue(out, chunk, format_settings, color);
|
||||
writeChar('\n', out);
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,10 @@
|
||||
#include <IO/WriteBufferFromString.h>
|
||||
#include <Processors/Formats/Impl/VerticalRowOutputFormat.h>
|
||||
#include <Formats/FormatFactory.h>
|
||||
#include <Formats/PrettyFormatHelpers.h>
|
||||
#include <Common/UTF8Helpers.h>
|
||||
#include <DataTypes/DataTypeLowCardinality.h>
|
||||
#include <DataTypes/DataTypeNullable.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
@ -14,6 +17,8 @@ VerticalRowOutputFormat::VerticalRowOutputFormat(
|
||||
WriteBuffer & out_, const Block & header_, const FormatSettings & format_settings_)
|
||||
: IRowOutputFormat(header_, out_), format_settings(format_settings_)
|
||||
{
|
||||
color = format_settings.pretty.color == 1 || (format_settings.pretty.color == 2 && format_settings.is_writing_to_terminal);
|
||||
|
||||
const auto & sample = getPort(PortKind::Main).getHeader();
|
||||
size_t columns = sample.columns();
|
||||
|
||||
@ -31,6 +36,7 @@ VerticalRowOutputFormat::VerticalRowOutputFormat(
|
||||
}
|
||||
|
||||
names_and_paddings.resize(columns);
|
||||
is_number.resize(columns);
|
||||
for (size_t i = 0; i < columns; ++i)
|
||||
{
|
||||
WriteBufferFromString buf(names_and_paddings[i]);
|
||||
@ -42,6 +48,7 @@ VerticalRowOutputFormat::VerticalRowOutputFormat(
|
||||
{
|
||||
size_t new_size = max_name_width - name_widths[i] + names_and_paddings[i].size();
|
||||
names_and_paddings[i].resize(new_size, ' ');
|
||||
is_number[i] = isNumber(removeNullable(recursiveRemoveLowCardinality(sample.getByPosition(i).type)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,7 +68,26 @@ void VerticalRowOutputFormat::writeField(const IColumn & column, const ISerializ
|
||||
|
||||
void VerticalRowOutputFormat::writeValue(const IColumn & column, const ISerialization & serialization, size_t row_num) const
|
||||
{
|
||||
serialization.serializeText(column, row_num, out, format_settings);
|
||||
if (color && format_settings.pretty.highlight_digit_groups && is_number[field_number])
|
||||
{
|
||||
String serialized_value;
|
||||
{
|
||||
WriteBufferFromString buf(serialized_value);
|
||||
serialization.serializeText(column, row_num, buf, format_settings);
|
||||
}
|
||||
|
||||
/// Highlight groups of thousands.
|
||||
serialized_value = highlightDigitGroups(serialized_value);
|
||||
out.write(serialized_value.data(), serialized_value.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
serialization.serializeText(column, row_num, out, format_settings);
|
||||
}
|
||||
|
||||
/// Write a tip.
|
||||
if (is_number[field_number])
|
||||
writeReadableNumberTip(out, column, row_num, format_settings, color);
|
||||
}
|
||||
|
||||
|
||||
|
@ -56,6 +56,9 @@ private:
|
||||
|
||||
using NamesAndPaddings = std::vector<String>;
|
||||
NamesAndPaddings names_and_paddings;
|
||||
|
||||
std::vector<UInt8> is_number;
|
||||
bool color;
|
||||
};
|
||||
|
||||
}
|
||||
|
1532
tests/queries/0_stateless/03268_vertical_pretty_numbers.reference
Normal file
1532
tests/queries/0_stateless/03268_vertical_pretty_numbers.reference
Normal file
File diff suppressed because it is too large
Load Diff
11
tests/queries/0_stateless/03268_vertical_pretty_numbers.sql
Normal file
11
tests/queries/0_stateless/03268_vertical_pretty_numbers.sql
Normal file
@ -0,0 +1,11 @@
|
||||
SET output_format_pretty_color = 1, output_format_pretty_highlight_digit_groups = 1, output_format_pretty_single_large_number_tip_threshold = 1;
|
||||
SELECT exp2(number), exp10(number), 'test'||number FROM numbers(64) FORMAT Vertical;
|
||||
|
||||
SET output_format_pretty_color = 0, output_format_pretty_highlight_digit_groups = 1, output_format_pretty_single_large_number_tip_threshold = 1;
|
||||
SELECT exp2(number), exp10(number), 'test'||number FROM numbers(64) FORMAT Vertical;
|
||||
|
||||
SET output_format_pretty_color = 1, output_format_pretty_highlight_digit_groups = 0, output_format_pretty_single_large_number_tip_threshold = 1;
|
||||
SELECT exp2(number), exp10(number), 'test'||number FROM numbers(64) FORMAT Vertical;
|
||||
|
||||
SET output_format_pretty_color = 0, output_format_pretty_highlight_digit_groups = 0, output_format_pretty_single_large_number_tip_threshold = 0;
|
||||
SELECT exp2(number), exp10(number), 'test'||number FROM numbers(64) FORMAT Vertical;
|
Loading…
Reference in New Issue
Block a user