2017-04-01 09:19:00 +00:00
|
|
|
#include <Columns/ColumnTuple.h>
|
2020-11-13 11:28:18 +00:00
|
|
|
|
2020-06-01 12:10:32 +00:00
|
|
|
#include <Columns/IColumnImpl.h>
|
2021-02-17 23:09:46 +00:00
|
|
|
#include <Columns/ColumnCompressed.h>
|
2020-11-13 11:28:18 +00:00
|
|
|
#include <Core/Field.h>
|
2018-06-05 19:46:49 +00:00
|
|
|
#include <DataStreams/ColumnGathererStream.h>
|
|
|
|
#include <IO/Operators.h>
|
2020-11-13 11:28:18 +00:00
|
|
|
#include <IO/WriteBufferFromString.h>
|
|
|
|
#include <Common/WeakHash.h>
|
|
|
|
#include <Common/assert_cast.h>
|
|
|
|
#include <Common/typeid_cast.h>
|
|
|
|
#include <common/sort.h>
|
2017-06-06 17:18:32 +00:00
|
|
|
#include <ext/map.h>
|
|
|
|
#include <ext/range.h>
|
2020-11-10 20:25:29 +00:00
|
|
|
|
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)
|
|
|
|
{
|
2020-04-22 06:22:14 +00:00
|
|
|
const 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);
|
2020-04-22 06:22:14 +00:00
|
|
|
for (const 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
|
|
|
}
|
|
|
|
|
2021-02-16 21:26:06 +00:00
|
|
|
const char * ColumnTuple::skipSerializedInArena(const char * pos) const
|
|
|
|
{
|
2021-02-21 12:50:55 +00:00
|
|
|
for (const auto & column : columns)
|
2021-02-16 21:26:06 +00:00
|
|
|
pos = column->skipSerializedInArena(pos);
|
|
|
|
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
|
2017-03-12 12:56:59 +00:00
|
|
|
void ColumnTuple::updateHashWithValue(size_t n, SipHash & hash) const
|
|
|
|
{
|
2020-04-22 06:22:14 +00:00
|
|
|
for (const auto & column : columns)
|
2017-04-01 07:20:54 +00:00
|
|
|
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);
|
|
|
|
|
2020-04-22 06:22:14 +00:00
|
|
|
for (const auto & column : columns)
|
2020-03-18 16:03:55 +00:00
|
|
|
column->updateWeakHash32(hash);
|
|
|
|
}
|
|
|
|
|
2020-05-20 22:16:08 +00:00
|
|
|
void ColumnTuple::updateHashFast(SipHash & hash) const
|
|
|
|
{
|
|
|
|
for (const auto & column : columns)
|
|
|
|
column->updateHashFast(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
|
|
|
}
|
|
|
|
|
2020-10-29 11:24:01 +00:00
|
|
|
int ColumnTuple::compareAtImpl(size_t n, size_t m, const IColumn & rhs, int nan_direction_hint, const Collator * collator) const
|
2017-03-12 12:56:59 +00:00
|
|
|
{
|
2017-12-08 00:50:25 +00:00
|
|
|
const size_t tuple_size = columns.size();
|
|
|
|
for (size_t i = 0; i < tuple_size; ++i)
|
2020-10-29 11:24:01 +00:00
|
|
|
{
|
|
|
|
int res;
|
|
|
|
if (collator && columns[i]->isCollationSupported())
|
|
|
|
res = columns[i]->compareAtWithCollation(n, m, *assert_cast<const ColumnTuple &>(rhs).columns[i], nan_direction_hint, *collator);
|
|
|
|
else
|
|
|
|
res = columns[i]->compareAt(n, m, *assert_cast<const ColumnTuple &>(rhs).columns[i], nan_direction_hint);
|
|
|
|
if (res)
|
2017-04-01 07:20:54 +00:00
|
|
|
return res;
|
2020-10-29 11:24:01 +00:00
|
|
|
}
|
2017-04-01 07:20:54 +00:00
|
|
|
return 0;
|
2017-03-12 12:56:59 +00:00
|
|
|
}
|
|
|
|
|
2020-10-29 11:24:01 +00:00
|
|
|
int ColumnTuple::compareAt(size_t n, size_t m, const IColumn & rhs, int nan_direction_hint) const
|
|
|
|
{
|
|
|
|
return compareAtImpl(n, m, rhs, nan_direction_hint);
|
|
|
|
}
|
|
|
|
|
2020-06-02 00:23:41 +00:00
|
|
|
void ColumnTuple::compareColumn(const IColumn & rhs, size_t rhs_row_num,
|
2020-06-17 11:43:55 +00:00
|
|
|
PaddedPODArray<UInt64> * row_indexes, PaddedPODArray<Int8> & compare_results,
|
2020-06-02 00:23:41 +00:00
|
|
|
int direction, int nan_direction_hint) const
|
2020-06-01 12:10:32 +00:00
|
|
|
{
|
2020-06-17 11:43:55 +00:00
|
|
|
return doCompareColumn<ColumnTuple>(assert_cast<const ColumnTuple &>(rhs), rhs_row_num, row_indexes,
|
|
|
|
compare_results, direction, nan_direction_hint);
|
2020-06-01 12:10:32 +00:00
|
|
|
}
|
|
|
|
|
2020-10-29 11:24:01 +00:00
|
|
|
int ColumnTuple::compareAtWithCollation(size_t n, size_t m, const IColumn & rhs, int nan_direction_hint, const Collator & collator) const
|
|
|
|
{
|
|
|
|
return compareAtImpl(n, m, rhs, nan_direction_hint, &collator);
|
|
|
|
}
|
|
|
|
|
2021-02-26 04:50:04 +00:00
|
|
|
bool ColumnTuple::hasEqualValues() const
|
|
|
|
{
|
|
|
|
return hasEqualValuesImpl<ColumnTuple>();
|
|
|
|
}
|
|
|
|
|
2020-11-03 14:25:52 +00:00
|
|
|
template <bool positive>
|
2017-03-12 12:56:59 +00:00
|
|
|
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;
|
2020-10-29 11:24:01 +00:00
|
|
|
const Collator * collator;
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2020-11-03 14:25:52 +00:00
|
|
|
Less(const TupleColumns & columns_, int nan_direction_hint_, const Collator * collator_=nullptr)
|
|
|
|
: columns(columns_), nan_direction_hint(nan_direction_hint_), collator(collator_)
|
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
|
|
|
{
|
2020-10-29 11:24:01 +00:00
|
|
|
int res;
|
|
|
|
if (collator && column->isCollationSupported())
|
|
|
|
res = column->compareAtWithCollation(a, b, *column, nan_direction_hint, *collator);
|
|
|
|
else
|
|
|
|
res = column->compareAt(a, b, *column, nan_direction_hint);
|
2017-04-01 07:20:54 +00:00
|
|
|
if (res < 0)
|
2020-11-03 14:25:52 +00:00
|
|
|
return positive;
|
2017-04-01 07:20:54 +00:00
|
|
|
else if (res > 0)
|
2020-11-03 14:25:52 +00:00
|
|
|
return !positive;
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2017-03-12 12:56:59 +00:00
|
|
|
};
|
|
|
|
|
2020-10-29 11:24:01 +00:00
|
|
|
template <typename LessOperator>
|
|
|
|
void ColumnTuple::getPermutationImpl(size_t limit, Permutation & res, LessOperator less) 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)
|
2020-11-13 11:28:18 +00:00
|
|
|
partial_sort(res.begin(), res.begin() + limit, res.end(), less);
|
2017-04-01 07:20:54 +00:00
|
|
|
else
|
2020-10-29 11:24:01 +00:00
|
|
|
std::sort(res.begin(), res.end(), less);
|
2017-03-12 12:56:59 +00:00
|
|
|
}
|
|
|
|
|
2020-10-29 11:24:01 +00:00
|
|
|
void ColumnTuple::updatePermutationImpl(bool reverse, size_t limit, int nan_direction_hint, IColumn::Permutation & res, EqualRanges & equal_ranges, const Collator * collator) const
|
2020-05-14 21:00:56 +00:00
|
|
|
{
|
2020-09-09 12:27:05 +00:00
|
|
|
if (equal_ranges.empty())
|
2020-09-04 18:05:06 +00:00
|
|
|
return;
|
|
|
|
|
2020-09-09 12:27:05 +00:00
|
|
|
for (const auto & column : columns)
|
2020-05-14 21:00:56 +00:00
|
|
|
{
|
2020-10-29 11:24:01 +00:00
|
|
|
if (collator && column->isCollationSupported())
|
|
|
|
column->updatePermutationWithCollation(*collator, reverse, limit, nan_direction_hint, res, equal_ranges);
|
|
|
|
else
|
|
|
|
column->updatePermutation(reverse, limit, nan_direction_hint, res, equal_ranges);
|
2020-09-09 12:27:05 +00:00
|
|
|
|
|
|
|
while (limit && !equal_ranges.empty() && limit <= equal_ranges.back().first)
|
|
|
|
equal_ranges.pop_back();
|
2020-05-25 14:33:31 +00:00
|
|
|
|
2020-09-09 12:27:05 +00:00
|
|
|
if (equal_ranges.empty())
|
2020-05-12 00:58:58 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-29 11:24:01 +00:00
|
|
|
void ColumnTuple::getPermutation(bool reverse, size_t limit, int nan_direction_hint, Permutation & res) const
|
|
|
|
{
|
2020-11-03 14:25:52 +00:00
|
|
|
if (reverse)
|
|
|
|
getPermutationImpl(limit, res, Less<false>(columns, nan_direction_hint));
|
|
|
|
else
|
|
|
|
getPermutationImpl(limit, res, Less<true>(columns, nan_direction_hint));
|
2020-10-29 11:24:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ColumnTuple::updatePermutation(bool reverse, size_t limit, int nan_direction_hint, IColumn::Permutation & res, EqualRanges & equal_ranges) const
|
|
|
|
{
|
|
|
|
updatePermutationImpl(reverse, limit, nan_direction_hint, res, equal_ranges);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ColumnTuple::getPermutationWithCollation(const Collator & collator, bool reverse, size_t limit, int nan_direction_hint, Permutation & res) const
|
|
|
|
{
|
2020-11-03 14:25:52 +00:00
|
|
|
if (reverse)
|
|
|
|
getPermutationImpl(limit, res, Less<false>(columns, nan_direction_hint, &collator));
|
|
|
|
else
|
|
|
|
getPermutationImpl(limit, res, Less<true>(columns, nan_direction_hint, &collator));
|
2020-10-29 11:24:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ColumnTuple::updatePermutationWithCollation(const Collator & collator, bool reverse, size_t limit, int nan_direction_hint, Permutation & res, EqualRanges & equal_ranges) const
|
|
|
|
{
|
|
|
|
updatePermutationImpl(reverse, limit, nan_direction_hint, res, equal_ranges, &collator);
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2021-01-02 22:58:10 +00:00
|
|
|
size_t ColumnTuple::byteSizeAt(size_t n) const
|
|
|
|
{
|
|
|
|
size_t res = 0;
|
|
|
|
for (const auto & column : columns)
|
|
|
|
res += column->byteSizeAt(n);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
{
|
2020-04-22 06:22:14 +00:00
|
|
|
if (const auto * rhs_tuple = typeid_cast<const ColumnTuple *>(&rhs))
|
2019-03-14 23:10:51 +00:00
|
|
|
{
|
|
|
|
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
|
|
|
|
2020-10-29 11:24:01 +00:00
|
|
|
bool ColumnTuple::isCollationSupported() const
|
|
|
|
{
|
2021-02-17 23:09:46 +00:00
|
|
|
for (const auto & column : columns)
|
2020-10-29 11:24:01 +00:00
|
|
|
{
|
|
|
|
if (column->isCollationSupported())
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-03-12 12:56:59 +00:00
|
|
|
|
2021-02-17 23:09:46 +00:00
|
|
|
ColumnPtr ColumnTuple::compress() const
|
|
|
|
{
|
|
|
|
size_t byte_size = 0;
|
|
|
|
Columns compressed;
|
|
|
|
compressed.reserve(columns.size());
|
|
|
|
for (const auto & column : columns)
|
|
|
|
{
|
|
|
|
auto compressed_column = column->compress();
|
|
|
|
byte_size += compressed_column->byteSize();
|
|
|
|
compressed.emplace_back(std::move(compressed_column));
|
|
|
|
}
|
|
|
|
|
|
|
|
return ColumnCompressed::create(size(), byte_size,
|
2021-02-17 23:52:07 +00:00
|
|
|
[compressed = std::move(compressed)]() mutable
|
2021-02-17 23:09:46 +00:00
|
|
|
{
|
|
|
|
for (auto & column : compressed)
|
|
|
|
column = column->decompress();
|
|
|
|
return ColumnTuple::create(compressed);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-03-12 12:56:59 +00:00
|
|
|
}
|