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>
|
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;
|
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)
|
|
|
|
{
|
|
|
|
if (column->isColumnConst())
|
|
|
|
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)
|
|
|
|
if (column->isColumnConst())
|
|
|
|
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());
|
|
|
|
column_tuple->columns = columns;
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2017-03-12 12:56:59 +00:00
|
|
|
Field ColumnTuple::operator[](size_t n) const
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
return Tuple{ext::map<TupleBackend>(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();
|
|
|
|
res = Tuple(TupleBackend(tuple_size));
|
2018-05-16 00:34:56 +00:00
|
|
|
TupleBackend & res_arr = DB::get<Tuple &>(res).toUnderType();
|
2017-12-08 00:50:25 +00:00
|
|
|
for (const auto i : ext::range(0, tuple_size))
|
2017-04-01 07:20:54 +00:00
|
|
|
columns[i]->get(n, res_arr[i]);
|
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)
|
|
|
|
{
|
2018-05-16 00:34:56 +00:00
|
|
|
const TupleBackend & tuple = DB::get<const Tuple &>(x).toUnderType();
|
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)
|
2018-02-12 18:58:14 +00:00
|
|
|
columns[i]->assumeMutableRef().insert(tuple[i]);
|
2017-03-12 12:56:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ColumnTuple::insertFrom(const IColumn & src_, size_t n)
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
const ColumnTuple & src = static_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)
|
2018-02-12 18:58:14 +00:00
|
|
|
columns[i]->assumeMutableRef().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)
|
2018-02-12 18:58:14 +00:00
|
|
|
column->assumeMutableRef().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)
|
2018-02-12 18:58:14 +00:00
|
|
|
column->assumeMutableRef().popBack(n);
|
2017-03-12 12:56:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
StringRef ColumnTuple::serializeValueIntoArena(size_t n, Arena & arena, char const *& begin) const
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
size_t values_size = 0;
|
|
|
|
for (auto & column : columns)
|
|
|
|
values_size += column->serializeValueIntoArena(n, arena, begin).size;
|
2017-03-12 12:56:59 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
return StringRef(begin, values_size);
|
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)
|
2018-02-12 18:58:14 +00:00
|
|
|
pos = column->assumeMutableRef().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
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
2018-02-12 18:58:14 +00:00
|
|
|
columns[i]->assumeMutableRef().insertRangeFrom(
|
2017-12-08 00:50:25 +00:00
|
|
|
*static_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)
|
2017-04-01 07:20:54 +00:00
|
|
|
if (int res = columns[i]->compareAt(n, m, *static_cast<const ColumnTuple &>(rhs).columns[i], nan_direction_hint))
|
|
|
|
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
|
|
|
|
{
|
2017-12-13 01:27:53 +00:00
|
|
|
ColumnRawPtrs plain_columns;
|
2017-04-01 07:20:54 +00:00
|
|
|
int nan_direction_hint;
|
|
|
|
|
|
|
|
Less(const Columns & columns, int nan_direction_hint_)
|
|
|
|
: nan_direction_hint(nan_direction_hint_)
|
|
|
|
{
|
|
|
|
for (const auto & column : columns)
|
|
|
|
plain_columns.push_back(column.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator() (size_t a, size_t b) const
|
|
|
|
{
|
2017-12-13 01:27:53 +00:00
|
|
|
for (ColumnRawPtrs::const_iterator it = plain_columns.begin(); it != plain_columns.end(); ++it)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
int res = (*it)->compareAt(a, b, **it, nan_direction_hint);
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
min = Tuple(TupleBackend(tuple_size));
|
|
|
|
max = Tuple(TupleBackend(tuple_size));
|
2017-03-12 12:56:59 +00:00
|
|
|
|
2018-05-16 00:34:56 +00:00
|
|
|
auto & min_backend = min.get<Tuple &>().toUnderType();
|
|
|
|
auto & max_backend = max.get<Tuple &>().toUnderType();
|
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))
|
|
|
|
columns[i]->getExtremes(min_backend[i], max_backend[i]);
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-12 12:56:59 +00:00
|
|
|
|
|
|
|
}
|