#pragma once #include #include #include #include #include #include #include namespace DB { using Poco::SharedPtr; class IColumnConst : public IColumn { public: bool isConst() const { return true; } virtual ColumnPtr convertToFullColumn() const = 0; }; /** шаблон для столбцов-констант (столбцов одинаковых значений). */ template class ColumnConst : public IColumnConst { public: typedef T Type; /// Для ColumnConst data_type_ должен быть ненулевым. /// Для ColumnConst data_type_ должен быть ненулевым, если тип данных FixedString. ColumnConst(size_t s_, const T & data_, DataTypePtr data_type_ = DataTypePtr()) : s(s_), data(data_), data_type(data_type_) {} std::string getName() const { return "ColumnConst<" + TypeName::get() + ">"; } bool isNumeric() const { return IsNumber::value; } size_t sizeOfField() const { return sizeof(T); } ColumnPtr cloneResized(size_t s_) const { return new ColumnConst(s_, data); } size_t size() const { return s; } Field operator[](size_t n) const { return typename NearestFieldType::Type(data); } void get(size_t n, Field & res) const { res = typename NearestFieldType::Type(data); } ColumnPtr cut(size_t start, size_t length) const { return new ColumnConst(length, data, data_type); } void insert(const Field & x) { throw Exception("Cannot insert element into constant column " + getName(), ErrorCodes::CANNOT_INSERT_ELEMENT_INTO_CONSTANT_COLUMN); } void insertData(const char * pos, size_t length) { throw Exception("Cannot insert element into constant column " + getName(), ErrorCodes::NOT_IMPLEMENTED); } void insertDefault() { ++s; } ColumnPtr filter(const Filter & filt) const { if (s != filt.size()) throw Exception("Size of filter doesn't match size of column.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH); size_t new_size = 0; for (Filter::const_iterator it = filt.begin(); it != filt.end(); ++it) if (*it) ++new_size; return new ColumnConst(new_size, data, data_type); } ColumnPtr replicate(const Offsets_t & offsets) const { if (s != offsets.size()) throw Exception("Size of offsets doesn't match size of column.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH); return new ColumnConst(offsets.back(), data, data_type); } size_t byteSize() const { return sizeof(data) + sizeof(s); } ColumnPtr permute(const Permutation & perm) const { if (s != perm.size()) throw Exception("Size of permutation doesn't match size of column.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH); return new ColumnConst(s, data, data_type); } int compareAt(size_t n, size_t m, const IColumn & rhs_) const { const ColumnConst & rhs = static_cast &>(rhs_); return data < rhs.data ? -1 : (data == rhs.data ? 0 : 1); } Permutation getPermutation() const { Permutation res(s); for (size_t i = 0; i < s; ++i) res[i] = i; return res; } StringRef getDataAt(size_t n) const; StringRef getDataAtWithTerminatingZero(size_t n) const; /** Более эффективные методы манипуляции */ T & getData() { return data; } const T & getData() const { return data; } /** Преобразование из константы в полноценный столбец */ ColumnPtr convertToFullColumn() const; private: size_t s; T data; DataTypePtr data_type; }; typedef ColumnConst ColumnConstString; typedef ColumnConst ColumnConstArray; template ColumnPtr ColumnConst::convertToFullColumn() const { ColumnVector * res = new ColumnVector; res->getData().assign(s, data); return res; } template <> ColumnPtr ColumnConst::convertToFullColumn() const; template <> ColumnPtr ColumnConst::convertToFullColumn() const; template StringRef ColumnConst::getDataAt(size_t n) const { throw Exception("Method getDataAt is not supported for " + getName(), ErrorCodes::NOT_IMPLEMENTED); } template <> inline StringRef ColumnConst::getDataAt(size_t n) const { return StringRef(data); } /// Для элементарных типов. template StringRef getDataAtImpl(size_t n, const T & data) { return StringRef(reinterpret_cast(&data), sizeof(data)); } template <> inline StringRef ColumnConst::getDataAt(size_t n) const { return getDataAtImpl(n, data); } template <> inline StringRef ColumnConst::getDataAt(size_t n) const { return getDataAtImpl(n, data); } template <> inline StringRef ColumnConst::getDataAt(size_t n) const { return getDataAtImpl(n, data); } template <> inline StringRef ColumnConst::getDataAt(size_t n) const { return getDataAtImpl(n, data); } template <> inline StringRef ColumnConst::getDataAt(size_t n) const { return getDataAtImpl(n, data); } template <> inline StringRef ColumnConst::getDataAt(size_t n) const { return getDataAtImpl(n, data); } template <> inline StringRef ColumnConst::getDataAt(size_t n) const { return getDataAtImpl(n, data); } template <> inline StringRef ColumnConst::getDataAt(size_t n) const { return getDataAtImpl(n, data); } template <> inline StringRef ColumnConst::getDataAt(size_t n) const { return getDataAtImpl(n, data); } template <> inline StringRef ColumnConst::getDataAt(size_t n) const { return getDataAtImpl(n, data); } template StringRef ColumnConst::getDataAtWithTerminatingZero(size_t n) const { return getDataAt(n); } template <> inline StringRef ColumnConst::getDataAtWithTerminatingZero(size_t n) const { return StringRef(data.data(), data.size() + 1); } }