2016-11-03 12:00:44 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <DB/DataStreams/IProfilingBlockInputStream.h>
|
|
|
|
#include <DB/Storages/IStorage.h>
|
|
|
|
#include <DB/Common/PODArray.h>
|
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
/// Tiny struct, stores number of a Part from which current row was fetched, and insertion flag.
|
|
|
|
struct RowSourcePart
|
|
|
|
{
|
|
|
|
RowSourcePart() = default;
|
|
|
|
|
|
|
|
RowSourcePart(size_t source_num, bool flag = false)
|
|
|
|
{
|
|
|
|
static_assert(sizeof(*this) == 1, "Size of RowSourcePart is too big due to compiler settings");
|
|
|
|
setSourceNum(source_num);
|
|
|
|
setSkipFlag(flag);
|
|
|
|
}
|
|
|
|
|
2016-12-20 14:58:23 +00:00
|
|
|
/// Data is equal to getSourceNum() if flag is false
|
|
|
|
UInt8 getData() const { return data; }
|
2016-11-03 12:00:44 +00:00
|
|
|
|
2016-12-21 19:00:25 +00:00
|
|
|
size_t getSourceNum() const { return data & MASK_NUMBER; }
|
2016-11-03 12:00:44 +00:00
|
|
|
|
|
|
|
/// In CollapsingMergeTree case flag means "skip this rows"
|
|
|
|
bool getSkipFlag() const { return (data & MASK_FLAG) != 0; }
|
|
|
|
|
|
|
|
void setSourceNum(size_t source_num)
|
|
|
|
{
|
|
|
|
data = (data & MASK_FLAG) | (static_cast<UInt8>(source_num) & MASK_NUMBER);
|
|
|
|
}
|
|
|
|
|
|
|
|
void setSkipFlag(bool flag)
|
|
|
|
{
|
|
|
|
data = flag ? data | MASK_FLAG : data & ~MASK_FLAG;
|
|
|
|
}
|
|
|
|
|
|
|
|
static constexpr size_t MAX_PARTS = 0x7F;
|
|
|
|
static constexpr UInt8 MASK_NUMBER = 0x7F;
|
|
|
|
static constexpr UInt8 MASK_FLAG = 0x80;
|
|
|
|
|
|
|
|
private:
|
|
|
|
UInt8 data;
|
|
|
|
};
|
|
|
|
|
|
|
|
using MergedRowSources = PODArray<RowSourcePart>;
|
|
|
|
|
|
|
|
|
|
|
|
/** Gather single stream from multiple streams according to streams mask.
|
|
|
|
* Stream mask maps row number to index of source stream.
|
|
|
|
* Streams should conatin exactly one column.
|
|
|
|
*/
|
|
|
|
class ColumnGathererStream : public IProfilingBlockInputStream
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ColumnGathererStream(const BlockInputStreams & source_streams, const String & column_name_,
|
2016-12-20 14:58:23 +00:00
|
|
|
const MergedRowSources & row_source_, size_t block_preferred_size_ = DEFAULT_MERGE_BLOCK_SIZE);
|
2016-11-03 12:00:44 +00:00
|
|
|
|
|
|
|
String getName() const override { return "ColumnGatherer"; }
|
|
|
|
|
|
|
|
String getID() const override;
|
|
|
|
|
|
|
|
Block readImpl() override;
|
|
|
|
|
2016-12-13 16:19:57 +00:00
|
|
|
void readSuffixImpl() override;
|
|
|
|
|
2016-11-03 12:00:44 +00:00
|
|
|
private:
|
|
|
|
|
|
|
|
String name;
|
|
|
|
ColumnWithTypeAndName column;
|
2016-12-15 20:03:21 +00:00
|
|
|
const MergedRowSources & row_source;
|
2016-11-03 12:00:44 +00:00
|
|
|
|
|
|
|
/// Cache required fileds
|
|
|
|
struct Source
|
|
|
|
{
|
|
|
|
const IColumn * column;
|
|
|
|
size_t pos;
|
|
|
|
size_t size;
|
|
|
|
Block block;
|
|
|
|
|
|
|
|
Source(Block && block_, const String & name) : block(std::move(block_))
|
|
|
|
{
|
|
|
|
update(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
void update(const String & name)
|
|
|
|
{
|
|
|
|
column = block.getByName(name).column.get();
|
|
|
|
size = block.rows();
|
|
|
|
pos = 0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-12-20 14:58:23 +00:00
|
|
|
void fetchNewBlock(Source & source, size_t source_num);
|
|
|
|
|
2016-11-03 12:00:44 +00:00
|
|
|
std::vector<Source> sources;
|
|
|
|
|
2016-12-15 20:03:21 +00:00
|
|
|
size_t pos_global_start = 0;
|
2016-12-20 14:58:23 +00:00
|
|
|
size_t block_preferred_size;
|
2016-11-03 12:00:44 +00:00
|
|
|
|
|
|
|
Logger * log = &Logger::get("ColumnGathererStream");
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|