2011-09-19 01:42:16 +00:00
|
|
|
#pragma once
|
2010-03-12 18:25:35 +00:00
|
|
|
|
2016-05-27 20:18:34 +00:00
|
|
|
#include <cmath>
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <Columns/IColumn.h>
|
2019-10-07 18:56:03 +00:00
|
|
|
#include <Columns/IColumnImpl.h>
|
2018-12-27 00:34:49 +00:00
|
|
|
#include <Columns/ColumnVectorHelper.h>
|
2018-12-14 17:50:10 +00:00
|
|
|
#include <common/unaligned.h>
|
2019-09-27 13:44:33 +00:00
|
|
|
#include <Core/Field.h>
|
2018-12-14 17:50:10 +00:00
|
|
|
|
2010-03-12 18:25:35 +00:00
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2017-03-09 00:56:38 +00:00
|
|
|
/** Stuff for comparing numbers.
|
2017-03-09 04:18:41 +00:00
|
|
|
* Integer values are compared as usual.
|
2017-03-09 00:56:38 +00:00
|
|
|
* Floating-point numbers are compared this way that NaNs always end up at the end
|
|
|
|
* (if you don't do this, the sort would not work at all).
|
2013-11-01 20:10:43 +00:00
|
|
|
*/
|
|
|
|
template <typename T>
|
|
|
|
struct CompareHelper
|
|
|
|
{
|
2017-12-01 17:49:12 +00:00
|
|
|
static bool less(T a, T b, int /*nan_direction_hint*/) { return a < b; }
|
|
|
|
static bool greater(T a, T b, int /*nan_direction_hint*/) { return a > b; }
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
/** Compares two numbers. Returns a number less than zero, equal to zero, or greater than zero if a < b, a == b, a > b, respectively.
|
|
|
|
* If one of the values is NaN, then
|
|
|
|
* - if nan_direction_hint == -1 - NaN are considered less than all numbers;
|
|
|
|
* - if nan_direction_hint == 1 - NaN are considered to be larger than all numbers;
|
|
|
|
* Essentially: nan_direction_hint == -1 says that the comparison is for sorting in descending order.
|
|
|
|
*/
|
2017-12-01 17:49:12 +00:00
|
|
|
static int compare(T a, T b, int /*nan_direction_hint*/)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
return a > b ? 1 : (a < b ? -1 : 0);
|
|
|
|
}
|
2013-11-01 20:10:43 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
struct FloatCompareHelper
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
static bool less(T a, T b, int nan_direction_hint)
|
|
|
|
{
|
|
|
|
bool isnan_a = std::isnan(a);
|
|
|
|
bool isnan_b = std::isnan(b);
|
|
|
|
|
|
|
|
if (isnan_a && isnan_b)
|
|
|
|
return false;
|
|
|
|
if (isnan_a)
|
|
|
|
return nan_direction_hint < 0;
|
|
|
|
if (isnan_b)
|
|
|
|
return nan_direction_hint > 0;
|
|
|
|
|
|
|
|
return a < b;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool greater(T a, T b, int nan_direction_hint)
|
|
|
|
{
|
|
|
|
bool isnan_a = std::isnan(a);
|
|
|
|
bool isnan_b = std::isnan(b);
|
|
|
|
|
|
|
|
if (isnan_a && isnan_b)
|
|
|
|
return false;
|
|
|
|
if (isnan_a)
|
|
|
|
return nan_direction_hint > 0;
|
|
|
|
if (isnan_b)
|
|
|
|
return nan_direction_hint < 0;
|
|
|
|
|
|
|
|
return a > b;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int compare(T a, T b, int nan_direction_hint)
|
|
|
|
{
|
|
|
|
bool isnan_a = std::isnan(a);
|
|
|
|
bool isnan_b = std::isnan(b);
|
|
|
|
if (unlikely(isnan_a || isnan_b))
|
|
|
|
{
|
|
|
|
if (isnan_a && isnan_b)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return isnan_a
|
|
|
|
? nan_direction_hint
|
|
|
|
: -nan_direction_hint;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (T(0) < (a - b)) - ((a - b) < T(0));
|
|
|
|
}
|
2013-11-01 20:10:43 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template <> struct CompareHelper<Float32> : public FloatCompareHelper<Float32> {};
|
|
|
|
template <> struct CompareHelper<Float64> : public FloatCompareHelper<Float64> {};
|
|
|
|
|
|
|
|
|
2017-03-11 01:12:51 +00:00
|
|
|
/** A template for columns that use a simple array to store.
|
2018-07-25 19:38:21 +00:00
|
|
|
*/
|
2018-08-07 13:57:28 +00:00
|
|
|
template <typename T>
|
2019-04-19 20:21:17 +00:00
|
|
|
class ColumnVector final : public COWHelper<ColumnVectorHelper, ColumnVector<T>>
|
2010-03-12 18:25:35 +00:00
|
|
|
{
|
2018-09-12 17:50:51 +00:00
|
|
|
static_assert(!IsDecimalNumber<T>);
|
|
|
|
|
2013-05-03 05:23:14 +00:00
|
|
|
private:
|
2018-09-13 14:59:03 +00:00
|
|
|
using Self = ColumnVector;
|
2019-04-19 20:21:17 +00:00
|
|
|
friend class COWHelper<ColumnVectorHelper, Self>;
|
2017-03-11 01:12:51 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
struct less;
|
|
|
|
struct greater;
|
2017-03-11 01:12:51 +00:00
|
|
|
|
2010-03-12 18:25:35 +00:00
|
|
|
public:
|
2019-11-20 08:57:19 +00:00
|
|
|
using ValueType = T;
|
|
|
|
using Container = PaddedPODArray<ValueType>;
|
2010-03-12 18:25:35 +00:00
|
|
|
|
2017-12-14 03:56:56 +00:00
|
|
|
private:
|
2017-04-01 07:20:54 +00:00
|
|
|
ColumnVector() {}
|
2017-12-15 21:32:25 +00:00
|
|
|
ColumnVector(const size_t n) : data(n) {}
|
2019-11-20 08:57:19 +00:00
|
|
|
ColumnVector(const size_t n, const ValueType x) : data(n, x) {}
|
2018-06-03 16:51:31 +00:00
|
|
|
ColumnVector(const ColumnVector & src) : data(src.data.begin(), src.data.end()) {}
|
2011-08-28 00:31:30 +00:00
|
|
|
|
2017-12-15 21:32:25 +00:00
|
|
|
/// Sugar constructor.
|
2020-02-28 19:14:13 +00:00
|
|
|
ColumnVector(std::initializer_list<T> il) : data{il} {}
|
2017-12-15 21:32:25 +00:00
|
|
|
|
2017-12-14 03:56:56 +00:00
|
|
|
public:
|
2018-08-07 13:57:28 +00:00
|
|
|
bool isNumeric() const override { return IsNumber<T>; }
|
2011-09-26 12:50:50 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
size_t size() const override
|
|
|
|
{
|
|
|
|
return data.size();
|
|
|
|
}
|
2013-01-07 06:47:15 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
StringRef getDataAt(size_t n) const override
|
|
|
|
{
|
|
|
|
return StringRef(reinterpret_cast<const char *>(&data[n]), sizeof(data[n]));
|
|
|
|
}
|
2014-05-01 00:17:02 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
void insertFrom(const IColumn & src, size_t n) override
|
|
|
|
{
|
|
|
|
data.push_back(static_cast<const Self &>(src).getData()[n]);
|
|
|
|
}
|
2012-12-16 00:52:06 +00:00
|
|
|
|
2017-12-01 17:49:12 +00:00
|
|
|
void insertData(const char * pos, size_t /*length*/) override
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2018-09-02 20:14:47 +00:00
|
|
|
data.push_back(unalignedLoad<T>(pos));
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
2013-02-16 20:15:45 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
void insertDefault() override
|
|
|
|
{
|
|
|
|
data.push_back(T());
|
|
|
|
}
|
2010-05-20 19:29:04 +00:00
|
|
|
|
2019-11-08 11:15:20 +00:00
|
|
|
virtual void insertManyDefaults(size_t length) override
|
|
|
|
{
|
|
|
|
data.resize_fill(data.size() + length, T());
|
|
|
|
}
|
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
void popBack(size_t n) override
|
|
|
|
{
|
|
|
|
data.resize_assume_reserved(data.size() - n);
|
|
|
|
}
|
2016-02-16 16:39:39 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
StringRef serializeValueIntoArena(size_t n, Arena & arena, char const *& begin) const override;
|
2015-10-04 03:17:36 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
const char * deserializeAndInsertFromArena(const char * pos) override;
|
2015-10-04 03:17:36 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
void updateHashWithValue(size_t n, SipHash & hash) const override;
|
2016-07-10 15:58:58 +00:00
|
|
|
|
2020-03-13 17:31:50 +00:00
|
|
|
void updateWeakHash32(WeakHash32 & hash) const override;
|
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
size_t byteSize() const override
|
|
|
|
{
|
|
|
|
return data.size() * sizeof(data[0]);
|
|
|
|
}
|
2011-08-27 22:43:31 +00:00
|
|
|
|
2017-07-13 16:49:09 +00:00
|
|
|
size_t allocatedBytes() const override
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2017-07-13 16:49:09 +00:00
|
|
|
return data.allocated_bytes();
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
2017-01-17 20:54:32 +00:00
|
|
|
|
2019-03-10 03:16:51 +00:00
|
|
|
void protect() override
|
|
|
|
{
|
|
|
|
data.protect();
|
|
|
|
}
|
|
|
|
|
2018-10-22 08:54:54 +00:00
|
|
|
void insertValue(const T value)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
data.push_back(value);
|
|
|
|
}
|
2015-03-23 13:29:32 +00:00
|
|
|
|
2017-07-05 17:18:52 +00:00
|
|
|
/// This method implemented in header because it could be possibly devirtualized.
|
2017-04-01 07:20:54 +00:00
|
|
|
int compareAt(size_t n, size_t m, const IColumn & rhs_, int nan_direction_hint) const override
|
|
|
|
{
|
|
|
|
return CompareHelper<T>::compare(data[n], static_cast<const Self &>(rhs_).data[m], nan_direction_hint);
|
|
|
|
}
|
2011-09-04 00:22:19 +00:00
|
|
|
|
2019-02-18 19:44:26 +00:00
|
|
|
void getPermutation(bool reverse, size_t limit, int nan_direction_hint, IColumn::Permutation & res) const override;
|
2011-09-26 11:05:38 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
void reserve(size_t n) override
|
|
|
|
{
|
|
|
|
data.reserve(n);
|
|
|
|
}
|
2013-02-03 18:39:09 +00:00
|
|
|
|
2017-12-07 22:11:51 +00:00
|
|
|
const char * getFamilyName() const override;
|
2013-02-08 23:41:05 +00:00
|
|
|
|
2017-12-14 03:56:56 +00:00
|
|
|
MutableColumnPtr cloneResized(size_t size) const override;
|
2013-02-08 23:41:05 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
Field operator[](size_t n) const override
|
|
|
|
{
|
2018-10-22 08:54:54 +00:00
|
|
|
return data[n];
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
2013-02-08 23:41:05 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
void get(size_t n, Field & res) const override
|
|
|
|
{
|
2018-08-10 14:57:55 +00:00
|
|
|
res = (*this)[n];
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
2013-02-08 23:41:05 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
UInt64 get64(size_t n) const override;
|
2014-05-01 00:17:02 +00:00
|
|
|
|
2019-05-30 21:59:40 +00:00
|
|
|
Float64 getFloat64(size_t n) const override;
|
2019-12-03 01:55:46 +00:00
|
|
|
Float32 getFloat32(size_t n) const override;
|
2019-05-30 21:59:40 +00:00
|
|
|
|
2019-12-30 20:04:10 +00:00
|
|
|
/// Out of range conversion is permitted.
|
|
|
|
UInt64 NO_SANITIZE_UNDEFINED getUInt(size_t n) const override
|
2017-07-24 07:48:26 +00:00
|
|
|
{
|
|
|
|
return UInt64(data[n]);
|
|
|
|
}
|
|
|
|
|
2019-12-30 20:04:10 +00:00
|
|
|
/// Out of range conversion is permitted.
|
|
|
|
Int64 NO_SANITIZE_UNDEFINED getInt(size_t n) const override
|
2018-04-24 07:16:39 +00:00
|
|
|
{
|
2019-12-30 20:04:10 +00:00
|
|
|
return Int64(data[n]);
|
2018-04-24 07:16:39 +00:00
|
|
|
}
|
|
|
|
|
2019-12-30 20:04:10 +00:00
|
|
|
bool getBool(size_t n) const override
|
2017-07-24 06:32:02 +00:00
|
|
|
{
|
2019-12-30 20:04:10 +00:00
|
|
|
return bool(data[n]);
|
2017-07-24 06:32:02 +00:00
|
|
|
}
|
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
void insert(const Field & x) override
|
|
|
|
{
|
2018-11-20 20:09:20 +00:00
|
|
|
data.push_back(DB::get<NearestFieldType<T>>(x));
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
2013-05-03 05:23:14 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
void insertRangeFrom(const IColumn & src, size_t start, size_t length) override;
|
2014-08-17 07:39:28 +00:00
|
|
|
|
2018-03-20 14:17:09 +00:00
|
|
|
ColumnPtr filter(const IColumn::Filter & filt, ssize_t result_size_hint) const override;
|
2013-05-03 05:23:14 +00:00
|
|
|
|
2019-02-18 19:44:26 +00:00
|
|
|
ColumnPtr permute(const IColumn::Permutation & perm, size_t limit) const override;
|
2013-05-03 05:23:14 +00:00
|
|
|
|
2019-02-18 17:28:53 +00:00
|
|
|
ColumnPtr index(const IColumn & indexes, size_t limit) const override;
|
2018-04-18 21:00:47 +00:00
|
|
|
|
|
|
|
template <typename Type>
|
2019-02-18 17:28:53 +00:00
|
|
|
ColumnPtr indexImpl(const PaddedPODArray<Type> & indexes, size_t limit) const;
|
2018-04-18 21:00:47 +00:00
|
|
|
|
2018-03-20 14:17:09 +00:00
|
|
|
ColumnPtr replicate(const IColumn::Offsets & offsets) const override;
|
2016-08-10 19:12:29 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
void getExtremes(Field & min, Field & max) const override;
|
2016-08-10 19:12:29 +00:00
|
|
|
|
2017-12-14 04:25:22 +00:00
|
|
|
MutableColumns scatter(IColumn::ColumnIndex num_columns, const IColumn::Selector & selector) const override
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2017-12-14 04:25:22 +00:00
|
|
|
return this->template scatterImpl<Self>(num_columns, selector);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
2017-02-11 20:20:57 +00:00
|
|
|
|
2017-07-06 13:54:55 +00:00
|
|
|
void gather(ColumnGathererStream & gatherer_stream) override;
|
2017-02-11 20:20:57 +00:00
|
|
|
|
2017-12-09 10:14:45 +00:00
|
|
|
|
|
|
|
bool canBeInsideNullable() const override { return true; }
|
|
|
|
|
|
|
|
bool isFixedAndContiguous() const override { return true; }
|
|
|
|
size_t sizeOfValueIfFixed() const override { return sizeof(T); }
|
2018-04-25 15:16:48 +00:00
|
|
|
StringRef getRawData() const override { return StringRef(reinterpret_cast<const char*>(data.data()), data.size()); }
|
2017-12-09 10:14:45 +00:00
|
|
|
|
2019-03-14 23:10:51 +00:00
|
|
|
|
|
|
|
bool structureEquals(const IColumn & rhs) const override
|
|
|
|
{
|
|
|
|
return typeid(rhs) == typeid(ColumnVector<T>);
|
|
|
|
}
|
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
/** More efficient methods of manipulation - to manipulate with data directly. */
|
2017-12-15 21:32:25 +00:00
|
|
|
Container & getData()
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
return data;
|
|
|
|
}
|
2016-08-10 19:12:29 +00:00
|
|
|
|
2017-12-15 21:32:25 +00:00
|
|
|
const Container & getData() const
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
return data;
|
|
|
|
}
|
2016-08-10 19:12:29 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
const T & getElement(size_t n) const
|
|
|
|
{
|
|
|
|
return data[n];
|
|
|
|
}
|
2017-03-11 05:23:01 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
T & getElement(size_t n)
|
|
|
|
{
|
|
|
|
return data[n];
|
|
|
|
}
|
2017-03-11 05:23:01 +00:00
|
|
|
|
2016-08-10 19:12:29 +00:00
|
|
|
protected:
|
2017-12-15 21:32:25 +00:00
|
|
|
Container data;
|
2013-02-08 23:41:05 +00:00
|
|
|
};
|
|
|
|
|
2018-04-23 17:19:24 +00:00
|
|
|
template <typename T>
|
|
|
|
template <typename Type>
|
2019-02-18 17:28:53 +00:00
|
|
|
ColumnPtr ColumnVector<T>::indexImpl(const PaddedPODArray<Type> & indexes, size_t limit) const
|
2018-04-23 17:19:24 +00:00
|
|
|
{
|
2019-02-18 17:31:18 +00:00
|
|
|
size_t size = indexes.size();
|
2018-04-23 17:19:24 +00:00
|
|
|
|
|
|
|
if (limit == 0)
|
|
|
|
limit = size;
|
|
|
|
else
|
|
|
|
limit = std::min(size, limit);
|
|
|
|
|
|
|
|
auto res = this->create(limit);
|
|
|
|
typename Self::Container & res_data = res->getData();
|
|
|
|
for (size_t i = 0; i < limit; ++i)
|
|
|
|
res_data[i] = data[indexes[i]];
|
|
|
|
|
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 res;
|
2018-04-23 17:19:24 +00:00
|
|
|
}
|
2013-02-08 23:41:05 +00:00
|
|
|
|
2010-03-12 18:25:35 +00:00
|
|
|
}
|