ClickHouse/dbms/src/DataStreams/IBlockInputStream.cpp

140 lines
3.3 KiB
C++
Raw Normal View History

2011-09-26 01:50:32 +00:00
#include <math.h>
2011-09-04 21:23:19 +00:00
#include <DB/DataStreams/IProfilingBlockInputStream.h>
#include <DB/DataStreams/IBlockInputStream.h>
namespace DB
{
namespace ErrorCodes
{
extern const int TOO_DEEP_PIPELINE;
}
2012-03-05 02:34:20 +00:00
2012-06-25 03:42:08 +00:00
String IBlockInputStream::getTreeID() const
{
std::stringstream s;
s << getName();
if (!children.empty())
{
s << "(";
for (BlockInputStreams::const_iterator it = children.begin(); it != children.end(); ++it)
{
if (it != children.begin())
s << ", ";
s << (*it)->getTreeID();
}
s << ")";
}
return s.str();
}
size_t IBlockInputStream::checkDepth(size_t max_depth) const
{
return checkDepthImpl(max_depth, max_depth);
}
size_t IBlockInputStream::checkDepthImpl(size_t max_depth, size_t level) const
{
if (children.empty())
return 0;
if (level > max_depth)
2013-06-21 20:34:19 +00:00
throw Exception("Query pipeline is too deep. Maximum: " + toString(max_depth), ErrorCodes::TOO_DEEP_PIPELINE);
size_t res = 0;
for (BlockInputStreams::const_iterator it = children.begin(); it != children.end(); ++it)
{
size_t child_depth = (*it)->checkDepth(level + 1);
if (child_depth > res)
res = child_depth;
}
return res + 1;
}
2012-06-25 03:42:08 +00:00
void IBlockInputStream::dumpTree(std::ostream & ostr, size_t indent, size_t multiplier)
2011-09-04 21:23:19 +00:00
{
2012-03-09 05:10:34 +00:00
/// Не будем отображать в дереве обёртку потока блоков в AsynchronousBlockInputStream.
if (getName() != "Asynchronous")
2012-03-09 05:10:34 +00:00
{
ostr << String(indent, ' ') << getName();
2012-06-25 03:42:08 +00:00
if (multiplier > 1)
ostr << " × " << multiplier;
ostr << std::endl;
2012-03-09 05:10:34 +00:00
++indent;
2012-03-05 02:34:20 +00:00
2012-06-25 03:42:08 +00:00
/// Если поддерево повторяется несколько раз, то будем выводить его один раз с множителем.
using Multipliers = std::map<String, size_t>;
2012-06-25 03:42:08 +00:00
Multipliers multipliers;
for (BlockInputStreams::const_iterator it = children.begin(); it != children.end(); ++it)
++multipliers[(*it)->getTreeID()];
for (BlockInputStreams::iterator it = children.begin(); it != children.end(); ++it)
{
String id = (*it)->getTreeID();
size_t & subtree_multiplier = multipliers[id];
if (subtree_multiplier != 0) /// Уже выведенные поддеревья помечаем нулём в массиве множителей.
{
(*it)->dumpTree(ostr, indent, subtree_multiplier);
subtree_multiplier = 0;
}
}
}
else
{
for (BlockInputStreams::iterator it = children.begin(); it != children.end(); ++it)
(*it)->dumpTree(ostr, indent, multiplier);
}
2012-03-05 02:34:20 +00:00
}
2012-03-09 04:45:27 +00:00
BlockInputStreams IBlockInputStream::getLeaves()
{
BlockInputStreams res;
getLeavesImpl(res);
return res;
}
2012-08-23 23:49:28 +00:00
void IBlockInputStream::getLeafRowsBytes(size_t & rows, size_t & bytes)
{
BlockInputStreams leaves = getLeaves();
rows = 0;
bytes = 0;
for (BlockInputStreams::const_iterator it = leaves.begin(); it != leaves.end(); ++it)
{
if (const IProfilingBlockInputStream * profiling = dynamic_cast<const IProfilingBlockInputStream *>(&**it))
{
const BlockStreamProfileInfo & info = profiling->getInfo();
rows += info.rows;
bytes += info.bytes;
}
}
}
2012-03-09 04:45:27 +00:00
void IBlockInputStream::getLeavesImpl(BlockInputStreams & res, BlockInputStreamPtr this_shared_ptr)
{
if (children.empty())
{
if (this_shared_ptr)
res.push_back(this_shared_ptr);
}
else
for (BlockInputStreams::iterator it = children.begin(); it != children.end(); ++it)
(*it)->getLeavesImpl(res, *it);
}
2011-09-04 21:23:19 +00:00
}