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>
|
2018-12-27 00:34:49 +00:00
|
|
|
#include <Columns/ColumnVectorHelper.h>
|
2018-12-14 17:50:10 +00:00
|
|
|
#include <common/unaligned.h>
|
|
|
|
|
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>
|
2018-12-26 02:06:54 +00:00
|
|
|
class ColumnVector final : public COWPtrHelper<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;
|
2018-12-26 02:06:54 +00:00
|
|
|
friend class COWPtrHelper<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:
|
2017-04-01 07:20:54 +00:00
|
|
|
using value_type = T;
|
2018-08-27 16:16:16 +00:00
|
|
|
using Container = PaddedPODArray<value_type>;
|
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) {}
|
|
|
|
ColumnVector(const size_t n, const value_type 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.
|
|
|
|
ColumnVector(std::initializer_list<T> il) : data{il} {}
|
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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-10 15:17:45 +00:00
|
|
|
void getPermutation(bool reverse, UInt64 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
|
|
|
|
2017-07-24 07:48:26 +00:00
|
|
|
UInt64 getUInt(size_t n) const override
|
|
|
|
{
|
|
|
|
return UInt64(data[n]);
|
|
|
|
}
|
|
|
|
|
2018-05-06 11:29:17 +00:00
|
|
|
bool getBool(size_t n) const override
|
2018-04-24 07:16:39 +00:00
|
|
|
{
|
2018-05-06 11:33:03 +00:00
|
|
|
return bool(data[n]);
|
2018-04-24 07:16:39 +00:00
|
|
|
}
|
|
|
|
|
2017-07-24 06:32:02 +00:00
|
|
|
Int64 getInt(size_t n) const override
|
|
|
|
{
|
|
|
|
return Int64(data[n]);
|
|
|
|
}
|
|
|
|
|
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-10 15:17:45 +00:00
|
|
|
ColumnPtr permute(const IColumn::Permutation & perm, UInt64 limit) const override;
|
2013-05-03 05:23:14 +00:00
|
|
|
|
2019-02-10 15:17:45 +00:00
|
|
|
ColumnPtr index(const IColumn & indexes, UInt64 limit) const override;
|
2018-04-18 21:00:47 +00:00
|
|
|
|
|
|
|
template <typename Type>
|
2019-02-10 15:17:45 +00:00
|
|
|
ColumnPtr indexImpl(const PaddedPODArray<Type> & indexes, UInt64 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
|
|
|
|
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-10 15:17:45 +00:00
|
|
|
ColumnPtr ColumnVector<T>::indexImpl(const PaddedPODArray<Type> & indexes, UInt64 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
|
|
|
}
|