ClickHouse/dbms/src/DataStreams/PrettyBlockOutputStream.cpp

266 lines
6.2 KiB
C++
Raw Normal View History

2011-11-07 04:51:37 +00:00
#include <sys/ioctl.h>
#include <unistd.h>
#include <DB/Functions/FunctionFactory.h>
Squashed commit of the following: commit e712f469a55ff34ad34b482b15cc4153b7ad7233 Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:59:13 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit 2a002823084e3a79bffcc17d479620a68eb0644b Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:58:30 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit 9e06f407c8ee781ed8ddf98bdfcc31846bf2a0fe Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:55:14 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit 9581620f1e839f456fa7894aa1f996d5162ac6cd Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:54:22 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit 2a8564c68cb6cc3649fafaf401256d43c9a2e777 Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:47:34 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit cf60632d78ec656be3304ef4565e859bb6ce80ba Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:40:09 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit ee3d1dc6e0c4ca60e3ac1e0c30d4b3ed1e66eca0 Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:22:49 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit 65592ef7116a90104fcd524b53ef8b7cf22640f2 Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:18:17 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit 37972c257320d3b7e7b294e0fdeffff218647bfd Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:17:06 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit dd909d149974ce5bed2456de1261aa5a368fd3ff Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:16:28 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit 3cf43266ca7e30adf01212b1a739ba5fe43639fd Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:15:42 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit 6731a3df96d1609286e2536b6432916af7743f0f Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:13:35 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit 1b5727e0d56415b7add4cb76110105358663602c Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:11:18 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit bbcf726a55685b8e72f5b40ba0bf1904bd1c0407 Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:09:04 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit c03b477d5e2e65014e8906ecfa2efb67ee295af1 Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:06:30 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit 2986e2fb0466bc18d73693dcdded28fccc0dc66b Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:05:44 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit 5d6cdef13d2e02bd5c4954983334e9162ab2635b Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:04:53 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit f2b819b25ce8b2ccdcb201eefb03e1e6f5aab590 Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:01:47 2017 +0300 Less dependencies [#CLICKHOUSE-2]
2017-01-14 09:00:19 +00:00
#include <DB/Functions/IFunction.h>
#include <DB/DataTypes/DataTypesNumber.h>
#include <DB/DataTypes/DataTypeString.h>
2011-11-07 01:15:37 +00:00
#include <DB/DataStreams/PrettyBlockOutputStream.h>
#include <DB/Columns/ColumnConst.h>
#include <DB/Columns/ColumnsNumber.h>
#include <DB/IO/WriteBuffer.h>
#include <DB/IO/WriteHelpers.h>
2011-11-07 01:15:37 +00:00
namespace DB
{
PrettyBlockOutputStream::PrettyBlockOutputStream(WriteBuffer & ostr_, bool no_escapes_, size_t max_rows_, const Context & context_)
: ostr(ostr_), max_rows(max_rows_), no_escapes(no_escapes_), context(context_)
2011-11-07 04:51:37 +00:00
{
struct winsize w;
2011-11-28 04:05:53 +00:00
if (0 == ioctl(STDOUT_FILENO, TIOCGWINSZ, &w))
2011-11-07 04:51:37 +00:00
terminal_width = w.ws_col;
}
2016-08-13 01:57:35 +00:00
void PrettyBlockOutputStream::flush()
{
ostr.next();
}
2011-11-28 04:05:53 +00:00
void PrettyBlockOutputStream::calculateWidths(Block & block, Widths_t & max_widths, Widths_t & name_widths)
2011-11-07 01:15:37 +00:00
{
size_t rows = block.rows();
size_t columns = block.columns();
2011-11-28 04:05:53 +00:00
max_widths.resize(columns);
name_widths.resize(columns);
2011-11-07 01:15:37 +00:00
FunctionPtr visible_width_func = FunctionFactory::instance().get("visibleWidth", context);
2011-11-07 01:15:37 +00:00
/// Calculate widths of all values.
2011-11-07 01:15:37 +00:00
for (size_t i = 0; i < columns; ++i)
{
ColumnWithTypeAndName column;
column.type = std::make_shared<DataTypeUInt64>();
column.name = "visibleWidth(" + block.getByPosition(i).name + ")";
2011-11-07 01:15:37 +00:00
size_t result_number = block.columns();
block.insert(column);
visible_width_func->execute(block, {i}, result_number);
column.column = block.safeGetByPosition(result_number).column;
2011-11-07 01:15:37 +00:00
2016-08-17 13:38:33 +00:00
if (const ColumnUInt64 * col = typeid_cast<const ColumnUInt64 *>(&*column.column))
2011-11-07 01:15:37 +00:00
{
const ColumnUInt64::Container_t & res = col->getData();
2011-11-07 01:15:37 +00:00
for (size_t j = 0; j < rows; ++j)
{
2016-08-17 13:38:33 +00:00
if (res[j] > max_widths[i])
max_widths[i] = res[j];
}
2011-11-07 01:15:37 +00:00
}
2016-08-17 13:38:33 +00:00
else if (const ColumnConstUInt64 * col = typeid_cast<const ColumnConstUInt64 *>(&*column.column))
2011-11-07 01:15:37 +00:00
{
UInt64 res = col->getData();
max_widths[i] = res;
}
else
2016-08-17 13:38:33 +00:00
throw Exception("Illegal column " + column.column->getName()
+ " of result of function " + visible_width_func->getName(),
2011-11-07 01:15:37 +00:00
ErrorCodes::ILLEGAL_COLUMN);
/// And also calculate widths for names of columns.
{
const String & name = block.getByPosition(i).name;
Block block_with_name
{
{ std::make_shared<ColumnConstString>(1, name), std::make_shared<DataTypeString>(), "name" },
{ nullptr, std::make_shared<DataTypeUInt64>(), "width" }
};
visible_width_func->execute(block_with_name, {0}, 1);
name_widths[i] = typeid_cast<const ColumnConstUInt64 &>(*block_with_name.getByPosition(1).column).getData();
if (name_widths[i] > max_widths[i])
max_widths[i] = name_widths[i];
}
2011-11-07 01:15:37 +00:00
}
2011-11-28 04:05:53 +00:00
}
void PrettyBlockOutputStream::write(const Block & block_)
{
if (total_rows >= max_rows)
2012-05-08 11:19:00 +00:00
{
total_rows += block_.rows();
2011-11-28 04:05:53 +00:00
return;
2012-05-08 11:19:00 +00:00
}
/// We will insert here columns with the calculated values of visible lengths.
2011-11-28 04:05:53 +00:00
Block block = block_;
2011-11-28 04:05:53 +00:00
size_t rows = block.rows();
size_t columns = block.columns();
Widths_t max_widths;
Widths_t name_widths;
calculateWidths(block, max_widths, name_widths);
2011-11-07 01:15:37 +00:00
2017-03-25 20:12:56 +00:00
/// Create separators
2011-11-07 01:15:37 +00:00
std::stringstream top_separator;
std::stringstream middle_names_separator;
std::stringstream middle_values_separator;
std::stringstream bottom_separator;
top_separator << "";
middle_names_separator << "";
middle_values_separator << "";
bottom_separator << "";
for (size_t i = 0; i < columns; ++i)
{
if (i != 0)
{
top_separator << "";
middle_names_separator << "";
middle_values_separator << "";
bottom_separator << "";
}
for (size_t j = 0; j < max_widths[i] + 2; ++j)
{
top_separator << "";
middle_names_separator << "";
middle_values_separator << "";
bottom_separator << "";
}
}
top_separator << "\n";
middle_names_separator << "\n";
middle_values_separator << "\n";
bottom_separator << "\n";
std::string top_separator_s = top_separator.str();
std::string middle_names_separator_s = middle_names_separator.str();
std::string middle_values_separator_s = middle_values_separator.str();
std::string bottom_separator_s = bottom_separator.str();
2017-03-25 20:12:56 +00:00
/// Output the block
2011-11-07 01:15:37 +00:00
writeString(top_separator_s, ostr);
2017-03-25 20:12:56 +00:00
/// Names
writeCString("", ostr);
2011-11-07 01:15:37 +00:00
for (size_t i = 0; i < columns; ++i)
{
if (i != 0)
writeCString("", ostr);
2011-11-07 01:15:37 +00:00
const ColumnWithTypeAndName & col = block.safeGetByPosition(i);
2011-11-07 01:15:37 +00:00
2012-06-25 05:07:34 +00:00
if (!no_escapes)
writeCString("\033[1m", ostr);
2011-11-07 01:15:37 +00:00
if (col.type->isNumeric())
{
for (size_t k = 0; k < max_widths[i] - name_widths[i]; ++k)
writeChar(' ', ostr);
writeEscapedString(col.name, ostr);
}
else
{
writeEscapedString(col.name, ostr);
for (size_t k = 0; k < max_widths[i] - name_widths[i]; ++k)
writeChar(' ', ostr);
}
2012-06-25 05:07:34 +00:00
if (!no_escapes)
writeCString("\033[0m", ostr);
2011-11-07 01:15:37 +00:00
}
writeCString("\n", ostr);
2011-11-07 01:15:37 +00:00
writeString(middle_names_separator_s, ostr);
2011-11-07 04:51:37 +00:00
for (size_t i = 0; i < rows && total_rows + i < max_rows; ++i)
2011-11-07 01:15:37 +00:00
{
if (i != 0)
writeString(middle_values_separator_s, ostr);
writeCString("", ostr);
2011-11-07 01:15:37 +00:00
for (size_t j = 0; j < columns; ++j)
{
if (j != 0)
writeCString("", ostr);
2011-11-07 01:15:37 +00:00
const ColumnWithTypeAndName & col = block.safeGetByPosition(j);
2011-11-07 01:15:37 +00:00
if (col.type->isNumeric())
{
size_t width = get<UInt64>((*block.safeGetByPosition(columns + j).column)[i]);
2011-11-07 01:15:37 +00:00
for (size_t k = 0; k < max_widths[j] - width; ++k)
writeChar(' ', ostr);
col.type->serializeTextEscaped(*col.column.get(), i, ostr);
2011-11-07 01:15:37 +00:00
}
else
{
col.type->serializeTextEscaped(*col.column.get(), i, ostr);
2011-11-07 01:15:37 +00:00
size_t width = get<UInt64>((*block.safeGetByPosition(columns + j).column)[i]);
2011-11-07 01:15:37 +00:00
for (size_t k = 0; k < max_widths[j] - width; ++k)
writeChar(' ', ostr);
}
}
writeCString("\n", ostr);
2011-11-07 01:15:37 +00:00
}
2011-11-07 01:15:37 +00:00
writeString(bottom_separator_s, ostr);
2011-11-07 04:51:37 +00:00
total_rows += rows;
}
void PrettyBlockOutputStream::writeSuffix()
{
if (total_rows >= max_rows)
{
writeCString(" Showed first ", ostr);
2011-11-07 04:51:37 +00:00
writeIntText(max_rows, ostr);
writeCString(".\n", ostr);
2011-11-07 04:51:37 +00:00
}
total_rows = 0;
writeTotals();
writeExtremes();
}
void PrettyBlockOutputStream::writeTotals()
{
if (totals)
{
writeCString("\nTotals:\n", ostr);
write(totals);
}
}
void PrettyBlockOutputStream::writeExtremes()
{
if (extremes)
{
writeCString("\nExtremes:\n", ostr);
write(extremes);
}
2011-11-07 01:15:37 +00:00
}
2011-11-07 04:51:37 +00:00
2011-11-07 01:15:37 +00:00
}