2017-04-01 09:19:00 +00:00
|
|
|
#include <Columns/ColumnTuple.h>
|
2018-06-05 19:46:49 +00:00
|
|
|
#include <DataStreams/ColumnGathererStream.h>
|
|
|
|
#include <IO/WriteBufferFromString.h>
|
|
|
|
#include <IO/Operators.h>
|
2017-06-06 17:18:32 +00:00
|
|
|
#include <ext/map.h>
|
|
|
|
#include <ext/range.h>
|
2019-03-14 23:10:51 +00:00
|
|
|
#include <Common/typeid_cast.h>
|
2019-08-21 02:28:04 +00:00
|
|
|
#include <Common/assert_cast.h>
|
2020-03-18 16:03:55 +00:00
|
|
|
#include <Common/WeakHash.h>
|
2019-10-04 17:46:36 +00:00
|
|
|
#include <Core/Field.h>
|
2017-03-12 12:56:59 +00:00
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
2017-12-09 17:32:18 +00:00
|
|
|
extern const int ILLEGAL_COLUMN;
|
2017-04-01 07:20:54 +00:00
|
|
|
extern const int NOT_IMPLEMENTED;
|
|
|
|
extern const int CANNOT_INSERT_VALUE_OF_DIFFERENT_SIZE_INTO_TUPLE;
|
2020-03-19 17:35:08 +00:00
|
|
|
extern const int LOGICAL_ERROR;
|
2017-03-12 12:56:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-07 05:53:23 +00:00
|
|
|
std::string ColumnTuple::getName() const
|
|
|
|
{
|
2018-06-05 19:46:49 +00:00
|
|
|
WriteBufferFromOwnString res;
|
2017-12-07 05:53:23 +00:00
|
|
|
res << "Tuple(";
|
|
|
|
bool is_first = true;
|
|
|
|
for (const auto & column : columns)
|
|
|
|
{
|
|
|
|
if (!is_first)
|
|
|
|
res << ", ";
|
|
|
|
is_first = false;
|
|
|
|
res << column->getName();
|
|
|
|
}
|
|
|
|
res << ")";
|
|
|
|
return res.str();
|
|
|
|
}
|
|
|
|
|
2018-03-20 14:17:09 +00:00
|
|
|
ColumnTuple::ColumnTuple(MutableColumns && mutable_columns)
|
|
|
|
{
|
|
|
|
columns.reserve(mutable_columns.size());
|
|
|
|
for (auto & column : mutable_columns)
|
|
|
|
{
|
2019-06-27 19:28:52 +00:00
|
|
|
if (isColumnConst(*column))
|
2018-03-20 14:17:09 +00:00
|
|
|
throw Exception{"ColumnTuple cannot have ColumnConst as its element", ErrorCodes::ILLEGAL_COLUMN};
|
|
|
|
|
|
|
|
columns.push_back(std::move(column));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-21 19:39:14 +00:00
|
|
|
ColumnTuple::Ptr ColumnTuple::create(const Columns & columns)
|
2017-03-12 12:56:59 +00:00
|
|
|
{
|
2017-12-09 17:32:18 +00:00
|
|
|
for (const auto & column : columns)
|
2019-06-27 19:28:52 +00:00
|
|
|
if (isColumnConst(*column))
|
2017-12-09 17:32:18 +00:00
|
|
|
throw Exception{"ColumnTuple cannot have ColumnConst as its element", ErrorCodes::ILLEGAL_COLUMN};
|
2018-03-20 14:17:09 +00:00
|
|
|
|
|
|
|
auto column_tuple = ColumnTuple::create(MutableColumns());
|
2019-03-25 01:43:54 +00:00
|
|
|
column_tuple->columns.assign(columns.begin(), columns.end());
|
2018-03-20 14:17:09 +00:00
|
|
|
|
Get rid of useless std::move to get NRVO
http://eel.is/c++draft/class.copy.elision#:constructor,copy,elision
Some quote:
> Speaking of RVO, return std::move(w); prohibits it. It means "use move constructor or fail to compile", whereas return w; means "use RVO, and if you can't, use move constructor, and if you can't, use copy constructor, and if you can't, fail to compile."
There is one exception to this rule:
```cpp
Block FilterBlockInputStream::removeFilterIfNeed(Block && block)
{
if (block && remove_filter)
block.erase(static_cast<size_t>(filter_column));
return std::move(block);
}
```
because references are not eligible for NRVO, which is another rule "always move rvalue references and forward universal references" that takes precedence.
2018-08-27 14:04:22 +00:00
|
|
|
return column_tuple;
|
2017-03-12 12:56:59 +00:00
|
|
|
}
|
|
|
|
|
2019-03-25 17:56:18 +00:00
|
|
|
ColumnTuple::Ptr ColumnTuple::create(const TupleColumns & columns)
|
|
|
|
{
|
|
|
|
for (const auto & column : columns)
|
2019-06-27 19:28:52 +00:00
|
|
|
if (isColumnConst(*column))
|
2019-03-25 17:56:18 +00:00
|
|
|
throw Exception{"ColumnTuple cannot have ColumnConst as its element", ErrorCodes::ILLEGAL_COLUMN};
|
|
|
|
|
|
|
|
auto column_tuple = ColumnTuple::create(MutableColumns());
|
|
|
|
column_tuple->columns = columns;
|
|
|
|
|
|
|
|
return column_tuple;
|
|
|
|
}
|
|
|
|
|
2017-12-15 19:46:24 +00:00
|
|
|
MutableColumnPtr ColumnTuple::cloneEmpty() const
|
2017-03-12 13:16:48 +00:00
|
|
|
{
|
2017-12-08 00:50:25 +00:00
|
|
|
const size_t tuple_size = columns.size();
|
2018-03-20 14:17:09 +00:00
|
|
|
MutableColumns new_columns(tuple_size);
|
2017-12-08 00:50:25 +00:00
|
|
|
for (size_t i = 0; i < tuple_size; ++i)
|
|
|
|
new_columns[i] = columns[i]->cloneEmpty();
|
|
|
|
|
2018-03-20 14:17:09 +00:00
|
|
|
return ColumnTuple::create(std::move(new_columns));
|
2017-03-12 13:16:48 +00:00
|
|
|
}
|
|
|
|
|
2019-08-28 15:44:18 +00:00
|
|
|
MutableColumnPtr ColumnTuple::cloneResized(size_t new_size) const
|
|
|
|
{
|
|
|
|
const size_t tuple_size = columns.size();
|
|
|
|
MutableColumns new_columns(tuple_size);
|
|
|
|
for (size_t i = 0; i < tuple_size; ++i)
|
|
|
|
new_columns[i] = columns[i]->cloneResized(new_size);
|
|
|
|
|
|
|
|
return ColumnTuple::create(std::move(new_columns));
|
|
|
|
}
|
|
|
|
|
2017-03-12 12:56:59 +00:00
|
|
|
Field ColumnTuple::operator[](size_t n) const
|
|
|
|
{
|
2019-10-18 15:57:05 +00:00
|
|
|
return ext::map<Tuple>(columns, [n] (const auto & column) { return (*column)[n]; });
|
2017-03-12 12:56:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ColumnTuple::get(size_t n, Field & res) const
|
|
|
|
{
|
2017-12-08 00:50:25 +00:00
|
|
|
const size_t tuple_size = columns.size();
|
2019-10-18 15:57:05 +00:00
|
|
|
Tuple tuple(tuple_size);
|
2017-12-08 00:50:25 +00:00
|
|
|
for (const auto i : ext::range(0, tuple_size))
|
2019-10-18 15:57:05 +00:00
|
|
|
columns[i]->get(n, tuple[i]);
|
|
|
|
|
|
|
|
res = tuple;
|
2017-03-12 12:56:59 +00:00
|
|
|
}
|
|
|
|
|
2017-12-01 21:13:25 +00:00
|
|
|
StringRef ColumnTuple::getDataAt(size_t) const
|
2017-03-12 12:56:59 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
throw Exception("Method getDataAt is not supported for " + getName(), ErrorCodes::NOT_IMPLEMENTED);
|
2017-03-12 12:56:59 +00:00
|
|
|
}
|
|
|
|
|
2017-12-01 21:13:25 +00:00
|
|
|
void ColumnTuple::insertData(const char *, size_t)
|
2017-03-12 12:56:59 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
throw Exception("Method insertData is not supported for " + getName(), ErrorCodes::NOT_IMPLEMENTED);
|
2017-03-12 12:56:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ColumnTuple::insert(const Field & x)
|
|
|
|
{
|
2019-10-18 15:57:05 +00:00
|
|
|
auto & tuple = DB::get<const Tuple &>(x);
|
2017-03-12 12:56:59 +00:00
|
|
|
|
2017-12-08 00:50:25 +00:00
|
|
|
const size_t tuple_size = columns.size();
|
|
|
|
if (tuple.size() != tuple_size)
|
2017-04-01 07:20:54 +00:00
|
|
|
throw Exception("Cannot insert value of different size into tuple", ErrorCodes::CANNOT_INSERT_VALUE_OF_DIFFERENT_SIZE_INTO_TUPLE);
|
2017-03-12 12:56:59 +00:00
|
|
|
|
2017-12-08 00:50:25 +00:00
|
|
|
for (size_t i = 0; i < tuple_size; ++i)
|
2019-03-25 01:43:54 +00:00
|
|
|
columns[i]->insert(tuple[i]);
|
2017-03-12 12:56:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ColumnTuple::insertFrom(const IColumn & src_, size_t n)
|
|
|
|
{
|
2019-08-21 02:28:04 +00:00
|
|
|
const ColumnTuple & src = assert_cast<const ColumnTuple &>(src_);
|
2017-03-12 12:56:59 +00:00
|
|
|
|
2017-12-08 00:50:25 +00:00
|
|
|
const size_t tuple_size = columns.size();
|
|
|
|
if (src.columns.size() != tuple_size)
|
2017-04-01 07:20:54 +00:00
|
|
|
throw Exception("Cannot insert value of different size into tuple", ErrorCodes::CANNOT_INSERT_VALUE_OF_DIFFERENT_SIZE_INTO_TUPLE);
|
2017-03-12 12:56:59 +00:00
|
|
|
|
2017-12-08 00:50:25 +00:00
|
|
|
for (size_t i = 0; i < tuple_size; ++i)
|
2019-03-25 01:43:54 +00:00
|
|
|
columns[i]->insertFrom(*src.columns[i], n);
|
2017-03-12 12:56:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ColumnTuple::insertDefault()
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
for (auto & column : columns)
|
2019-03-25 01:43:54 +00:00
|
|
|
column->insertDefault();
|
2017-03-12 12:56:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ColumnTuple::popBack(size_t n)
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
for (auto & column : columns)
|
2019-03-25 01:43:54 +00:00
|
|
|
column->popBack(n);
|
2017-03-12 12:56:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
StringRef ColumnTuple::serializeValueIntoArena(size_t n, Arena & arena, char const *& begin) const
|
|
|
|
{
|
2019-07-15 16:20:21 +00:00
|
|
|
StringRef res(begin, 0);
|
2017-04-01 07:20:54 +00:00
|
|
|
for (auto & column : columns)
|
2019-07-15 16:20:21 +00:00
|
|
|
{
|
|
|
|
auto value_ref = column->serializeValueIntoArena(n, arena, begin);
|
|
|
|
res.data = value_ref.data - res.size;
|
|
|
|
res.size += value_ref.size;
|
|
|
|
}
|
2017-03-12 12:56:59 +00:00
|
|
|
|
2019-07-15 16:20:21 +00:00
|
|
|
return res;
|
2017-03-12 12:56:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const char * ColumnTuple::deserializeAndInsertFromArena(const char * pos)
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
for (auto & column : columns)
|
2019-03-25 01:43:54 +00:00
|
|
|
pos = column->deserializeAndInsertFromArena(pos);
|
2017-03-12 12:56:59 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
return pos;
|
2017-03-12 12:56:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ColumnTuple::updateHashWithValue(size_t n, SipHash & hash) const
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
for (auto & column : columns)
|
|
|
|
column->updateHashWithValue(n, hash);
|
2017-03-12 12:56:59 +00:00
|
|
|
}
|
|
|
|
|
2020-03-18 16:03:55 +00:00
|
|
|
void ColumnTuple::updateWeakHash32(WeakHash32 & hash) const
|
|
|
|
{
|
|
|
|
auto s = size();
|
|
|
|
|
|
|
|
if (hash.getData().size() != s)
|
|
|
|
throw Exception("Size of WeakHash32 does not match size of column: column size is " + std::to_string(s) +
|
|
|
|
", hash size is " + std::to_string(hash.getData().size()), ErrorCodes::LOGICAL_ERROR);
|
|
|
|
|
|
|
|
for (auto & column : columns)
|
|
|
|
column->updateWeakHash32(hash);
|
|
|
|
}
|
|
|
|
|
2017-03-12 12:56:59 +00:00
|
|
|
void ColumnTuple::insertRangeFrom(const IColumn & src, size_t start, size_t length)
|
|
|
|
{
|
2017-12-08 00:50:25 +00:00
|
|
|
const size_t tuple_size = columns.size();
|
|
|
|
for (size_t i = 0; i < tuple_size; ++i)
|
2019-03-25 01:43:54 +00:00
|
|
|
columns[i]->insertRangeFrom(
|
2019-08-21 02:28:04 +00:00
|
|
|
*assert_cast<const ColumnTuple &>(src).columns[i],
|
2017-04-01 07:20:54 +00:00
|
|
|
start, length);
|
2017-03-12 12:56:59 +00:00
|
|
|
}
|
|
|
|
|
2018-03-20 14:17:09 +00:00
|
|
|
ColumnPtr ColumnTuple::filter(const Filter & filt, ssize_t result_size_hint) const
|
2017-03-12 12:56:59 +00:00
|
|
|
{
|
2017-12-08 00:50:25 +00:00
|
|
|
const size_t tuple_size = columns.size();
|
|
|
|
Columns new_columns(tuple_size);
|
2017-03-12 12:56:59 +00:00
|
|
|
|
2017-12-08 00:50:25 +00:00
|
|
|
for (size_t i = 0; i < tuple_size; ++i)
|
|
|
|
new_columns[i] = columns[i]->filter(filt, result_size_hint);
|
2017-03-12 12:56:59 +00:00
|
|
|
|
2017-12-14 01:43:19 +00:00
|
|
|
return ColumnTuple::create(new_columns);
|
2017-03-12 12:56:59 +00:00
|
|
|
}
|
|
|
|
|
2019-02-18 19:44:26 +00:00
|
|
|
ColumnPtr ColumnTuple::permute(const Permutation & perm, size_t limit) const
|
2017-03-12 12:56:59 +00:00
|
|
|
{
|
2017-12-08 00:50:25 +00:00
|
|
|
const size_t tuple_size = columns.size();
|
|
|
|
Columns new_columns(tuple_size);
|
2017-03-12 12:56:59 +00:00
|
|
|
|
2017-12-08 00:50:25 +00:00
|
|
|
for (size_t i = 0; i < tuple_size; ++i)
|
|
|
|
new_columns[i] = columns[i]->permute(perm, limit);
|
2017-03-12 12:56:59 +00:00
|
|
|
|
2017-12-14 01:43:19 +00:00
|
|
|
return ColumnTuple::create(new_columns);
|
2017-03-12 12:56:59 +00:00
|
|
|
}
|
|
|
|
|
2019-02-18 17:28:53 +00:00
|
|
|
ColumnPtr ColumnTuple::index(const IColumn & indexes, size_t limit) const
|
2018-04-23 16:40:25 +00:00
|
|
|
{
|
|
|
|
const size_t tuple_size = columns.size();
|
|
|
|
Columns new_columns(tuple_size);
|
|
|
|
|
|
|
|
for (size_t i = 0; i < tuple_size; ++i)
|
|
|
|
new_columns[i] = columns[i]->index(indexes, limit);
|
|
|
|
|
|
|
|
return ColumnTuple::create(new_columns);
|
|
|
|
}
|
|
|
|
|
2018-03-20 14:17:09 +00:00
|
|
|
ColumnPtr ColumnTuple::replicate(const Offsets & offsets) const
|
2017-03-12 12:56:59 +00:00
|
|
|
{
|
2017-12-08 00:50:25 +00:00
|
|
|
const size_t tuple_size = columns.size();
|
|
|
|
Columns new_columns(tuple_size);
|
2017-03-12 12:56:59 +00:00
|
|
|
|
2017-12-08 00:50:25 +00:00
|
|
|
for (size_t i = 0; i < tuple_size; ++i)
|
|
|
|
new_columns[i] = columns[i]->replicate(offsets);
|
2017-03-12 12:56:59 +00:00
|
|
|
|
2017-12-14 01:43:19 +00:00
|
|
|
return ColumnTuple::create(new_columns);
|
2017-03-12 12:56:59 +00:00
|
|
|
}
|
|
|
|
|
2017-12-15 01:34:30 +00:00
|
|
|
MutableColumns ColumnTuple::scatter(ColumnIndex num_columns, const Selector & selector) const
|
2017-03-12 12:56:59 +00:00
|
|
|
{
|
2017-12-08 00:50:25 +00:00
|
|
|
const size_t tuple_size = columns.size();
|
2017-12-15 19:46:24 +00:00
|
|
|
std::vector<MutableColumns> scattered_tuple_elements(tuple_size);
|
2017-03-12 12:56:59 +00:00
|
|
|
|
2017-12-08 00:50:25 +00:00
|
|
|
for (size_t tuple_element_idx = 0; tuple_element_idx < tuple_size; ++tuple_element_idx)
|
|
|
|
scattered_tuple_elements[tuple_element_idx] = columns[tuple_element_idx]->scatter(num_columns, selector);
|
2017-03-12 12:56:59 +00:00
|
|
|
|
2017-12-15 01:34:30 +00:00
|
|
|
MutableColumns res(num_columns);
|
2017-03-12 12:56:59 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
for (size_t scattered_idx = 0; scattered_idx < num_columns; ++scattered_idx)
|
|
|
|
{
|
2018-03-20 14:17:09 +00:00
|
|
|
MutableColumns new_columns(tuple_size);
|
2017-12-08 00:50:25 +00:00
|
|
|
for (size_t tuple_element_idx = 0; tuple_element_idx < tuple_size; ++tuple_element_idx)
|
2017-12-15 19:46:24 +00:00
|
|
|
new_columns[tuple_element_idx] = std::move(scattered_tuple_elements[tuple_element_idx][scattered_idx]);
|
2018-03-20 14:17:09 +00:00
|
|
|
res[scattered_idx] = ColumnTuple::create(std::move(new_columns));
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
2017-03-12 12:56:59 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
return res;
|
2017-03-12 12:56:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int ColumnTuple::compareAt(size_t n, size_t m, const IColumn & rhs, int nan_direction_hint) const
|
|
|
|
{
|
2017-12-08 00:50:25 +00:00
|
|
|
const size_t tuple_size = columns.size();
|
|
|
|
for (size_t i = 0; i < tuple_size; ++i)
|
2019-08-21 02:28:04 +00:00
|
|
|
if (int res = columns[i]->compareAt(n, m, *assert_cast<const ColumnTuple &>(rhs).columns[i], nan_direction_hint))
|
2017-04-01 07:20:54 +00:00
|
|
|
return res;
|
2017-03-12 12:56:59 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
return 0;
|
2017-03-12 12:56:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <bool positive>
|
|
|
|
struct ColumnTuple::Less
|
|
|
|
{
|
2019-03-25 01:43:54 +00:00
|
|
|
TupleColumns columns;
|
2017-04-01 07:20:54 +00:00
|
|
|
int nan_direction_hint;
|
|
|
|
|
2019-08-03 11:02:40 +00:00
|
|
|
Less(const TupleColumns & columns_, int nan_direction_hint_)
|
|
|
|
: columns(columns_), nan_direction_hint(nan_direction_hint_)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator() (size_t a, size_t b) const
|
|
|
|
{
|
2019-03-25 01:43:54 +00:00
|
|
|
for (const auto & column : columns)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2019-03-25 01:43:54 +00:00
|
|
|
int res = column->compareAt(a, b, *column, nan_direction_hint);
|
2017-04-01 07:20:54 +00:00
|
|
|
if (res < 0)
|
|
|
|
return positive;
|
|
|
|
else if (res > 0)
|
|
|
|
return !positive;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2017-03-12 12:56:59 +00:00
|
|
|
};
|
|
|
|
|
2019-02-18 19:44:26 +00:00
|
|
|
void ColumnTuple::getPermutation(bool reverse, size_t limit, int nan_direction_hint, Permutation & res) const
|
2017-03-12 12:56:59 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
size_t rows = size();
|
|
|
|
res.resize(rows);
|
|
|
|
for (size_t i = 0; i < rows; ++i)
|
|
|
|
res[i] = i;
|
|
|
|
|
|
|
|
if (limit >= rows)
|
|
|
|
limit = 0;
|
|
|
|
|
|
|
|
if (limit)
|
|
|
|
{
|
|
|
|
if (reverse)
|
|
|
|
std::partial_sort(res.begin(), res.begin() + limit, res.end(), Less<false>(columns, nan_direction_hint));
|
|
|
|
else
|
|
|
|
std::partial_sort(res.begin(), res.begin() + limit, res.end(), Less<true>(columns, nan_direction_hint));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (reverse)
|
|
|
|
std::sort(res.begin(), res.end(), Less<false>(columns, nan_direction_hint));
|
|
|
|
else
|
|
|
|
std::sort(res.begin(), res.end(), Less<true>(columns, nan_direction_hint));
|
|
|
|
}
|
2017-03-12 12:56:59 +00:00
|
|
|
}
|
|
|
|
|
2017-07-06 13:54:55 +00:00
|
|
|
void ColumnTuple::gather(ColumnGathererStream & gatherer)
|
|
|
|
{
|
|
|
|
gatherer.gather(*this);
|
|
|
|
}
|
|
|
|
|
2017-03-12 12:56:59 +00:00
|
|
|
void ColumnTuple::reserve(size_t n)
|
|
|
|
{
|
2017-12-15 19:46:24 +00:00
|
|
|
const size_t tuple_size = columns.size();
|
|
|
|
for (size_t i = 0; i < tuple_size; ++i)
|
2017-12-16 01:21:59 +00:00
|
|
|
getColumn(i).reserve(n);
|
2017-03-12 12:56:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
size_t ColumnTuple::byteSize() const
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
size_t res = 0;
|
|
|
|
for (const auto & column : columns)
|
|
|
|
res += column->byteSize();
|
|
|
|
return res;
|
2017-03-12 12:56:59 +00:00
|
|
|
}
|
|
|
|
|
2017-07-13 16:49:09 +00:00
|
|
|
size_t ColumnTuple::allocatedBytes() const
|
2017-03-12 12:56:59 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
size_t res = 0;
|
|
|
|
for (const auto & column : columns)
|
2017-07-13 16:49:09 +00:00
|
|
|
res += column->allocatedBytes();
|
2017-04-01 07:20:54 +00:00
|
|
|
return res;
|
2017-03-12 12:56:59 +00:00
|
|
|
}
|
|
|
|
|
2019-03-10 03:16:51 +00:00
|
|
|
void ColumnTuple::protect()
|
|
|
|
{
|
|
|
|
for (auto & column : columns)
|
2019-03-25 01:43:54 +00:00
|
|
|
column->protect();
|
2019-03-10 03:16:51 +00:00
|
|
|
}
|
|
|
|
|
2017-03-12 12:56:59 +00:00
|
|
|
void ColumnTuple::getExtremes(Field & min, Field & max) const
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
const size_t tuple_size = columns.size();
|
2017-03-12 12:56:59 +00:00
|
|
|
|
2019-10-18 15:57:05 +00:00
|
|
|
Tuple min_tuple(tuple_size);
|
|
|
|
Tuple max_tuple(tuple_size);
|
2017-03-12 12:56:59 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
for (const auto i : ext::range(0, tuple_size))
|
2019-10-18 15:57:05 +00:00
|
|
|
columns[i]->getExtremes(min_tuple[i], max_tuple[i]);
|
|
|
|
|
|
|
|
min = min_tuple;
|
|
|
|
max = max_tuple;
|
2017-03-12 12:56:59 +00:00
|
|
|
}
|
|
|
|
|
2017-12-07 12:09:55 +00:00
|
|
|
void ColumnTuple::forEachSubcolumn(ColumnCallback callback)
|
|
|
|
{
|
|
|
|
for (auto & column : columns)
|
|
|
|
callback(column);
|
|
|
|
}
|
|
|
|
|
2019-03-14 23:10:51 +00:00
|
|
|
bool ColumnTuple::structureEquals(const IColumn & rhs) const
|
|
|
|
{
|
|
|
|
if (auto rhs_tuple = typeid_cast<const ColumnTuple *>(&rhs))
|
|
|
|
{
|
|
|
|
const size_t tuple_size = columns.size();
|
|
|
|
if (tuple_size != rhs_tuple->columns.size())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (const auto i : ext::range(0, tuple_size))
|
|
|
|
if (!columns[i]->structureEquals(*rhs_tuple->columns[i]))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
2017-12-07 12:09:55 +00:00
|
|
|
|
2017-03-12 12:56:59 +00:00
|
|
|
|
|
|
|
}
|