diff --git a/dbms/src/DataStreams/FormatFactory.cpp b/dbms/src/DataStreams/FormatFactory.cpp index dabbbecaa54..d67a718ef7d 100644 --- a/dbms/src/DataStreams/FormatFactory.cpp +++ b/dbms/src/DataStreams/FormatFactory.cpp @@ -155,9 +155,11 @@ static BlockOutputStreamPtr getOutputImpl(const String & name, WriteBuffer & buf else if (name == "PrettySpaceNoEscapes") return std::make_shared(buf, true, settings.output_format_pretty_max_rows, context); else if (name == "Vertical") - return std::make_shared(std::make_shared(buf, sample, context)); + return std::make_shared(std::make_shared( + buf, sample, settings.output_format_pretty_max_rows, context)); else if (name == "VerticalRaw") - return std::make_shared(std::make_shared(buf, sample, context)); + return std::make_shared(std::make_shared( + buf, sample, settings.output_format_pretty_max_rows, context)); else if (name == "Values") return std::make_shared(std::make_shared(buf)); else if (name == "JSON") diff --git a/dbms/src/DataStreams/VerticalRowOutputStream.cpp b/dbms/src/DataStreams/VerticalRowOutputStream.cpp index 9e2bec95336..68fa681a65e 100644 --- a/dbms/src/DataStreams/VerticalRowOutputStream.cpp +++ b/dbms/src/DataStreams/VerticalRowOutputStream.cpp @@ -10,8 +10,9 @@ namespace DB { -VerticalRowOutputStream::VerticalRowOutputStream(WriteBuffer & ostr_, const Block & sample_, const Context & context) - : ostr(ostr_), sample(sample_) +VerticalRowOutputStream::VerticalRowOutputStream( + WriteBuffer & ostr_, const Block & sample_, size_t max_rows_, const Context & context) + : ostr(ostr_), sample(sample_), max_rows(max_rows_) { size_t columns = sample.columns(); @@ -60,6 +61,9 @@ void VerticalRowOutputStream::flush() void VerticalRowOutputStream::writeField(const IColumn & column, const IDataType & type, size_t row_num) { + if (row_number > max_rows) + return; + writeString(names_and_paddings[field_number], ostr); writeValue(column, type, row_num); writeChar('\n', ostr); @@ -82,6 +86,10 @@ void VerticalRawRowOutputStream::writeValue(const IColumn & column, const IDataT void VerticalRowOutputStream::writeRowStartDelimiter() { ++row_number; + + if (row_number > max_rows) + return; + writeCString("Row ", ostr); writeIntText(row_number, ostr); writeCString(":\n", ostr); @@ -95,9 +103,77 @@ void VerticalRowOutputStream::writeRowStartDelimiter() void VerticalRowOutputStream::writeRowBetweenDelimiter() { + if (row_number > max_rows) + return; + writeCString("\n", ostr); field_number = 0; } +void VerticalRowOutputStream::writeSuffix() +{ + if (row_number > max_rows) + { + writeCString("Showed first ", ostr); + writeIntText(max_rows, ostr); + writeCString(".\n", ostr); + } + + if (totals || extremes) + { + writeCString("\n", ostr); + writeTotals(); + writeExtremes(); + } +} + + +void VerticalRowOutputStream::writeSpecialRow(const Block & block, size_t row_num, const char * title) +{ + writeCString("\n", ostr); + + row_number = 0; + field_number = 0; + + size_t columns = block.columns(); + + writeCString(title, ostr); + writeCString(":\n", ostr); + + size_t width = strlen(title) + 1; + for (size_t i = 0; i < width; ++i) + writeCString("─", ostr); + writeChar('\n', ostr); + + for (size_t i = 0; i < columns; ++i) + { + if (i != 0) + writeFieldDelimiter(); + + auto & col = block.getByPosition(i); + writeField(*col.column.get(), *col.type.get(), row_num); + } +} + + +void VerticalRowOutputStream::writeTotals() +{ + if (totals) + { + writeSpecialRow(totals, 0, "Totals"); + } +} + + +void VerticalRowOutputStream::writeExtremes() +{ + if (extremes) + { + writeSpecialRow(extremes, 0, "Min"); + writeSpecialRow(extremes, 1, "Max"); + } +} + + } diff --git a/dbms/src/DataStreams/VerticalRowOutputStream.h b/dbms/src/DataStreams/VerticalRowOutputStream.h index 98e440a6b15..f3a4444734a 100644 --- a/dbms/src/DataStreams/VerticalRowOutputStream.h +++ b/dbms/src/DataStreams/VerticalRowOutputStream.h @@ -18,24 +18,37 @@ class Context; class VerticalRowOutputStream : public IRowOutputStream { public: - VerticalRowOutputStream(WriteBuffer & ostr_, const Block & sample_, const Context & context); + VerticalRowOutputStream(WriteBuffer & ostr_, const Block & sample_, size_t max_rows_, const Context & context); void writeField(const IColumn & column, const IDataType & type, size_t row_num) override; void writeRowStartDelimiter() override; void writeRowBetweenDelimiter() override; + void writeSuffix() override; void flush() override; + void setTotals(const Block & totals_) override { totals = totals_; } + void setExtremes(const Block & extremes_) override { extremes = extremes_; } + protected: virtual void writeValue(const IColumn & column, const IDataType & type, size_t row_num) const; + void writeTotals(); + void writeExtremes(); + /// For totals and extremes. + void writeSpecialRow(const Block & block, size_t row_num, const char * title); + WriteBuffer & ostr; const Block sample; + size_t max_rows; size_t field_number = 0; size_t row_number = 0; using NamesAndPaddings = std::vector; NamesAndPaddings names_and_paddings; + + Block totals; + Block extremes; }; @@ -44,8 +57,7 @@ protected: class VerticalRawRowOutputStream final : public VerticalRowOutputStream { public: - VerticalRawRowOutputStream(WriteBuffer & ostr_, const Block & sample_, const Context & context) - : VerticalRowOutputStream(ostr_, sample_, context) {} + using VerticalRowOutputStream::VerticalRowOutputStream; protected: void writeValue(const IColumn & column, const IDataType & type, size_t row_num) const override; diff --git a/dbms/tests/queries/0_stateless/00460_vertical_and_totals_extremes.reference b/dbms/tests/queries/0_stateless/00460_vertical_and_totals_extremes.reference new file mode 100644 index 00000000000..b142a014283 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00460_vertical_and_totals_extremes.reference @@ -0,0 +1,298 @@ +Row 1: +────── +k: 0 +count(): 20 + +Row 2: +────── +k: 1 +count(): 20 + +Row 3: +────── +k: 2 +count(): 20 + +Row 4: +────── +k: 3 +count(): 20 + +Row 5: +────── +k: 4 +count(): 20 + + +Totals: +─────── +k: 0 +count(): 100 +Row 1: +────── +k: 0 +count(): 20 + +Row 2: +────── +k: 1 +count(): 20 + +Row 3: +────── +k: 2 +count(): 20 + +Row 4: +────── +k: 3 +count(): 20 + +Row 5: +────── +k: 4 +count(): 20 + + +Totals: +─────── +k: 0 +count(): 100 + +Min: +──── +k: 0 +count(): 20 + +Max: +──── +k: 4 +count(): 20 +Row 1: +────── +k: 0 +count(): 20 + +Row 2: +────── +k: 1 +count(): 20 + +Row 3: +────── +k: 2 +count(): 20 + +Row 4: +────── +k: 3 +count(): 20 + +Row 5: +────── +k: 4 +count(): 20 + + +Totals: +─────── +k: 0 +count(): 100 + +Min: +──── +k: 0 +count(): 20 + +Max: +──── +k: 4 +count(): 20 +Row 1: +────── +k: 0 +count(): 20 + +Row 2: +────── +k: 1 +count(): 20 + +Row 3: +────── +k: 2 +count(): 20 + +Row 4: +────── +k: 3 +count(): 20 + + Showed first 4. + + +Totals: +─────── +k: 0 +count(): 100 + +Min: +──── +k: 0 +count(): 20 + +Max: +──── +k: 4 +count(): 20 +Row 1: +────── +k: 0 +count(): 20 + +Row 2: +────── +k: 1 +count(): 20 + +Row 3: +────── +k: 2 +count(): 20 + +Row 4: +────── +k: 3 +count(): 20 + + Showed first 4. + + +Totals: +─────── +k: 0 +count(): 100 + +Min: +──── +k: 0 +count(): 20 + +Max: +──── +k: 4 +count(): 20 +Row 1: +────── +k: 0 +count(): 20 + +Row 2: +────── +k: 1 +count(): 20 + +Row 3: +────── +k: 2 +count(): 20 + +Row 4: +────── +k: 3 +count(): 20 + + Showed first 4. + + +Totals: +─────── +k: 0 +count(): 100 + +Min: +──── +k: 0 +count(): 20 + +Max: +──── +k: 4 +count(): 20 +Row 1: +────── +k: 0 +count(): 20 + +Row 2: +────── +k: 1 +count(): 20 + +Row 3: +────── +k: 2 +count(): 20 + +Row 4: +────── +k: 3 +count(): 20 + +Row 5: +────── +k: 4 +count(): 20 + + +Totals: +─────── +k: 0 +count(): 100 + +Min: +──── +k: 0 +count(): 20 + +Max: +──── +k: 4 +count(): 20 +Row 1: +────── +k: 0 +count(): 20 + +Row 2: +────── +k: 1 +count(): 20 + +Row 3: +────── +k: 2 +count(): 20 + +Row 4: +────── +k: 3 +count(): 20 + + Showed first 4. + + +Totals: +─────── +k: 0 +count(): 100 + +Min: +──── +k: 0 +count(): 20 + +Max: +──── +k: 4 +count(): 20 diff --git a/dbms/tests/queries/0_stateless/00460_vertical_and_totals_extremes.sql b/dbms/tests/queries/0_stateless/00460_vertical_and_totals_extremes.sql new file mode 100644 index 00000000000..137304ce713 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00460_vertical_and_totals_extremes.sql @@ -0,0 +1,22 @@ +SELECT k, count() FROM (SELECT number % 5 AS k FROM system.numbers LIMIT 100) GROUP BY k WITH TOTALS ORDER BY k FORMAT Vertical; + +SET extremes = 1; +SELECT k, count() FROM (SELECT number % 5 AS k FROM system.numbers LIMIT 100) GROUP BY k WITH TOTALS ORDER BY k FORMAT Vertical; + +SET output_format_pretty_max_rows = 5; +SELECT k, count() FROM (SELECT number % 5 AS k FROM system.numbers LIMIT 100) GROUP BY k WITH TOTALS ORDER BY k FORMAT Vertical; + +SET output_format_pretty_max_rows = 4; +SELECT k, count() FROM (SELECT number % 5 AS k FROM system.numbers LIMIT 100) GROUP BY k WITH TOTALS ORDER BY k FORMAT Vertical; + + +SELECT k, count() FROM (SELECT number % 5 AS k FROM system.numbers LIMIT 100) GROUP BY k WITH TOTALS ORDER BY k FORMAT VerticalRaw; + +SET extremes = 1; +SELECT k, count() FROM (SELECT number % 5 AS k FROM system.numbers LIMIT 100) GROUP BY k WITH TOTALS ORDER BY k FORMAT VerticalRaw; + +SET output_format_pretty_max_rows = 5; +SELECT k, count() FROM (SELECT number % 5 AS k FROM system.numbers LIMIT 100) GROUP BY k WITH TOTALS ORDER BY k FORMAT VerticalRaw; + +SET output_format_pretty_max_rows = 4; +SELECT k, count() FROM (SELECT number % 5 AS k FROM system.numbers LIMIT 100) GROUP BY k WITH TOTALS ORDER BY k FORMAT VerticalRaw;