Cut dependendy (code must depend on Functions only via FunctionFactory) [#METR-2944].

This commit is contained in:
Alexey Milovidov 2016-12-30 03:15:50 +03:00
parent 0eb5d53133
commit b4e18e2222
9 changed files with 93 additions and 75 deletions

View File

@ -7,6 +7,7 @@ namespace DB
{
class WriteBuffer;
class Context;
/** Выводит результат в виде красивых таблиц.
@ -15,7 +16,7 @@ class PrettyBlockOutputStream : public IBlockOutputStream
{
public:
/// no_escapes - не использовать ANSI escape sequences - для отображения в браузере, а не в консоли.
PrettyBlockOutputStream(WriteBuffer & ostr_, bool no_escapes_, size_t max_rows_);
PrettyBlockOutputStream(WriteBuffer & ostr_, bool no_escapes_, size_t max_rows_, const Context & context_);
void write(const Block & block) override;
void writeSuffix() override;
@ -36,13 +37,15 @@ protected:
WriteBuffer & ostr;
size_t max_rows;
size_t total_rows;
size_t terminal_width;
size_t total_rows = 0;
size_t terminal_width = 0;
bool no_escapes;
Block totals;
Block extremes;
const Context & context;
};
}

View File

@ -11,8 +11,8 @@ namespace DB
class PrettyCompactBlockOutputStream : public PrettyBlockOutputStream
{
public:
PrettyCompactBlockOutputStream(WriteBuffer & ostr_, bool no_escapes_, size_t max_rows_)
: PrettyBlockOutputStream(ostr_, no_escapes_, max_rows_) {}
PrettyCompactBlockOutputStream(WriteBuffer & ostr_, bool no_escapes_, size_t max_rows_, const Context & context_)
: PrettyBlockOutputStream(ostr_, no_escapes_, max_rows_, context_) {}
void write(const Block & block) override;

View File

@ -12,8 +12,8 @@ namespace DB
class PrettyCompactMonoBlockOutputStream : public PrettyCompactBlockOutputStream
{
public:
PrettyCompactMonoBlockOutputStream(WriteBuffer & ostr_, bool no_escapes_, size_t max_rows_)
: PrettyCompactBlockOutputStream(ostr_, no_escapes_, max_rows_) {}
PrettyCompactMonoBlockOutputStream(WriteBuffer & ostr_, bool no_escapes_, size_t max_rows_, const Context & context_)
: PrettyCompactBlockOutputStream(ostr_, no_escapes_, max_rows_, context_) {}
void write(const Block & block) override;
void writeSuffix() override;

View File

@ -11,8 +11,8 @@ namespace DB
class PrettySpaceBlockOutputStream : public PrettyBlockOutputStream
{
public:
PrettySpaceBlockOutputStream(WriteBuffer & ostr_, bool no_escapes_, size_t max_rows_)
: PrettyBlockOutputStream(ostr_, no_escapes_, max_rows_) {}
PrettySpaceBlockOutputStream(WriteBuffer & ostr_, bool no_escapes_, size_t max_rows_, const Context & context_)
: PrettyBlockOutputStream(ostr_, no_escapes_, max_rows_, context_) {}
void write(const Block & block) override;
void writeSuffix() override;

View File

@ -9,14 +9,16 @@ namespace DB
{
class WriteBuffer;
class Context;
/** Поток для вывода данных в формате "каждое значение на своей строке".
/** Stream to output data in format "each value in separate row".
* Usable to show few rows with many columns.
*/
class VerticalRowOutputStream : public IRowOutputStream
{
public:
VerticalRowOutputStream(WriteBuffer & ostr_, const Block & sample_);
VerticalRowOutputStream(WriteBuffer & ostr_, const Block & sample_, const Context & context);
void writeField(const IColumn & column, const IDataType & type, size_t row_num) override;
void writeRowStartDelimiter() override;
@ -29,22 +31,21 @@ protected:
WriteBuffer & ostr;
const Block sample;
Names names;
size_t field_number;
size_t row_number;
size_t field_number = 0;
size_t row_number = 0;
using Pads_t = std::vector<String>;
Pads_t pads;
using NamesAndPaddings = std::vector<String>;
NamesAndPaddings names_and_paddings;
};
/** То же самое, но строки выводятся без экранирования.
/** Same but values are printed without escaping.
*/
class VerticalRawRowOutputStream : public VerticalRowOutputStream
class VerticalRawRowOutputStream final : public VerticalRowOutputStream
{
public:
VerticalRawRowOutputStream(WriteBuffer & ostr_, const Block & sample_)
: VerticalRowOutputStream(ostr_, sample_) {}
VerticalRawRowOutputStream(WriteBuffer & ostr_, const Block & sample_, const Context & context)
: VerticalRowOutputStream(ostr_, sample_, context) {}
protected:
void writeValue(const IColumn & column, const IDataType & type, size_t row_num) const override;

View File

@ -75,24 +75,6 @@ namespace ErrorCodes
*/
static inline UInt64 stringWidth(const UInt8 * pos, const UInt8 * end)
{
UInt64 res = 0;
for (; pos < end; ++pos)
{
if (*pos == '\b' || *pos == '\f' || *pos == '\n' || *pos == '\r' || *pos == '\t' || *pos == '\0' || *pos == '\'' || *pos == '\\')
++res;
if (*pos <= 0x7F || *pos >= 0xC0)
++res;
}
return res;
}
static inline void stringWidthConstant(const String & data, UInt64 & res)
{
res = stringWidth(reinterpret_cast<const UInt8 *>(data.data()), reinterpret_cast<const UInt8 *>(data.data()) + data.size());
}
class FunctionCurrentDatabase : public IFunction
{
const String db_name;

View File

@ -120,23 +120,23 @@ static BlockOutputStreamPtr getOutputImpl(const String & name, WriteBuffer & buf
else if (name == "CSVWithNames")
return std::make_shared<BlockOutputStreamFromRowOutputStream>(std::make_shared<CSVRowOutputStream>(buf, sample, true));
else if (name == "Pretty")
return std::make_shared<PrettyBlockOutputStream>(buf, false, settings.output_format_pretty_max_rows);
return std::make_shared<PrettyBlockOutputStream>(buf, false, settings.output_format_pretty_max_rows, context);
else if (name == "PrettyCompact")
return std::make_shared<PrettyCompactBlockOutputStream>(buf, false, settings.output_format_pretty_max_rows);
return std::make_shared<PrettyCompactBlockOutputStream>(buf, false, settings.output_format_pretty_max_rows, context);
else if (name == "PrettyCompactMonoBlock")
return std::make_shared<PrettyCompactMonoBlockOutputStream>(buf, false, settings.output_format_pretty_max_rows);
return std::make_shared<PrettyCompactMonoBlockOutputStream>(buf, false, settings.output_format_pretty_max_rows, context);
else if (name == "PrettySpace")
return std::make_shared<PrettySpaceBlockOutputStream>(buf, false, settings.output_format_pretty_max_rows);
return std::make_shared<PrettySpaceBlockOutputStream>(buf, false, settings.output_format_pretty_max_rows, context);
else if (name == "PrettyNoEscapes")
return std::make_shared<PrettyBlockOutputStream>(buf, true, settings.output_format_pretty_max_rows);
return std::make_shared<PrettyBlockOutputStream>(buf, true, settings.output_format_pretty_max_rows, context);
else if (name == "PrettyCompactNoEscapes")
return std::make_shared<PrettyCompactBlockOutputStream>(buf, true, settings.output_format_pretty_max_rows);
return std::make_shared<PrettyCompactBlockOutputStream>(buf, true, settings.output_format_pretty_max_rows, context);
else if (name == "PrettySpaceNoEscapes")
return std::make_shared<PrettySpaceBlockOutputStream>(buf, true, settings.output_format_pretty_max_rows);
return std::make_shared<PrettySpaceBlockOutputStream>(buf, true, settings.output_format_pretty_max_rows, context);
else if (name == "Vertical")
return std::make_shared<BlockOutputStreamFromRowOutputStream>(std::make_shared<VerticalRowOutputStream>(buf, sample));
return std::make_shared<BlockOutputStreamFromRowOutputStream>(std::make_shared<VerticalRowOutputStream>(buf, sample, context));
else if (name == "VerticalRaw")
return std::make_shared<BlockOutputStreamFromRowOutputStream>(std::make_shared<VerticalRawRowOutputStream>(buf, sample));
return std::make_shared<BlockOutputStreamFromRowOutputStream>(std::make_shared<VerticalRawRowOutputStream>(buf, sample, context));
else if (name == "Values")
return std::make_shared<BlockOutputStreamFromRowOutputStream>(std::make_shared<ValuesRowOutputStream>(buf));
else if (name == "JSON")

View File

@ -1,15 +1,18 @@
#include <sys/ioctl.h>
#include <unistd.h>
#include <DB/Functions/FunctionsMiscellaneous.h>
#include <DB/Functions/FunctionFactory.h>
#include <DB/DataTypes/DataTypesNumberFixed.h>
#include <DB/DataTypes/DataTypeString.h>
#include <DB/DataStreams/PrettyBlockOutputStream.h>
#include <DB/Columns/ColumnConst.h>
namespace DB
{
PrettyBlockOutputStream::PrettyBlockOutputStream(WriteBuffer & ostr_, bool no_escapes_, size_t max_rows_)
: ostr(ostr_), max_rows(max_rows_), total_rows(0), terminal_width(0), no_escapes(no_escapes_)
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_)
{
struct winsize w;
if (0 == ioctl(STDOUT_FILENO, TIOCGWINSZ, &w))
@ -31,20 +34,19 @@ void PrettyBlockOutputStream::calculateWidths(Block & block, Widths_t & max_widt
max_widths.resize(columns);
name_widths.resize(columns);
FunctionVisibleWidth visible_width_func;
DataTypePtr visible_width_type = std::make_shared<DataTypeUInt64>();
FunctionPtr visible_width_func = FunctionFactory::instance().get("visibleWidth", context);
/// Вычислим ширину всех значений
/// Calculate widths of all values.
for (size_t i = 0; i < columns; ++i)
{
ColumnWithTypeAndName column;
column.type = visible_width_type;
column.name = "visibleWidth(" + block.getByPosition(i).name + ")";
column.type = std::make_shared<DataTypeUInt64>();
column.name = "visibleWidth(" + block.unsafeGetByPosition(i).name + ")";
size_t result_number = block.columns();
block.insert(column);
visible_width_func.execute(block, {i}, result_number);
visible_width_func->execute(block, {i}, result_number);
column.column = block.getByPosition(result_number).column;
if (const ColumnUInt64 * col = typeid_cast<const ColumnUInt64 *>(&*column.column))
@ -63,15 +65,28 @@ void PrettyBlockOutputStream::calculateWidths(Block & block, Widths_t & max_widt
}
else
throw Exception("Illegal column " + column.column->getName()
+ " of result of function " + visible_width_func.getName(),
+ " of result of function " + visible_width_func->getName(),
ErrorCodes::ILLEGAL_COLUMN);
/// И не только значений, но и их имён
stringWidthConstant(block.getByPosition(i).name, name_widths[i]);
/// And also calculate widths for names of columns.
{
const String & name = block.unsafeGetByPosition(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.unsafeGetByPosition(1).column).getData();
if (name_widths[i] > max_widths[i])
max_widths[i] = name_widths[i];
}
}
}
void PrettyBlockOutputStream::write(const Block & block_)

View File

@ -1,33 +1,53 @@
#include <DB/Functions/FunctionsMiscellaneous.h>
#include <DB/Functions/FunctionFactory.h>
#include <DB/Columns/ColumnConst.h>
#include <DB/DataTypes/DataTypeString.h>
#include <DB/DataTypes/DataTypesNumberFixed.h>
#include <DB/IO/WriteHelpers.h>
#include <DB/DataStreams/VerticalRowOutputStream.h>
namespace DB
{
VerticalRowOutputStream::VerticalRowOutputStream(WriteBuffer & ostr_, const Block & sample_)
: ostr(ostr_), sample(sample_), field_number(0), row_number(0)
VerticalRowOutputStream::VerticalRowOutputStream(WriteBuffer & ostr_, const Block & sample_, const Context & context)
: ostr(ostr_), sample(sample_)
{
size_t columns = sample.columns();
names.resize(columns);
using Widths_t = std::vector<size_t>;
Widths_t name_widths(columns);
size_t max_name_width = 0;
FunctionPtr visible_width_func = FunctionFactory::instance().get("visibleWidth", context);
for (size_t i = 0; i < columns; ++i)
{
names[i] = sample.getByPosition(i).name;
stringWidthConstant(names[i], name_widths[i]);
{
Block block_with_name
{
{ std::make_shared<ColumnConstString>(1, sample.unsafeGetByPosition(i).name), std::make_shared<DataTypeString>(), "name" },
{ nullptr, std::make_shared<DataTypeUInt64>(), "width" }
};
visible_width_func->execute(block_with_name, {0}, 1);
name_widths[i] = (*block_with_name.unsafeGetByPosition(1).column)[0].get<UInt64>();
}
if (name_widths[i] > max_name_width)
max_name_width = name_widths[i];
}
pads.resize(columns);
names_and_paddings.resize(columns);
for (size_t i = 0; i < columns; ++i)
pads[i] = String(max_name_width - name_widths[i], ' ');
{
WriteBufferFromString out(names_and_paddings[i]);
writeEscapedString(sample.unsafeGetByPosition(i).name, out);
writeCString(": ", out);
}
for (size_t i = 0; i < columns; ++i)
names_and_paddings[i].resize(max_name_width + strlen(": "), ' ');
}
@ -39,13 +59,10 @@ void VerticalRowOutputStream::flush()
void VerticalRowOutputStream::writeField(const IColumn & column, const IDataType & type, size_t row_num)
{
writeEscapedString(names[field_number], ostr);
writeCString(": ", ostr);
writeString(pads[field_number], ostr);
writeString(names_and_paddings[field_number], ostr);
writeValue(column, type, row_num);
writeChar('\n', ostr);
++field_number;
}