#pragma once #include "../types/types.h" #include "../exceptions.h" #include #include #include namespace clickhouse { /** ItemView is a view on a data stored in Column, safe-ish interface for reading values from Column. * * Data is not owned (hence the name View) and will be invalidated on column update, load * or destruction (basically on calling any non-const method of Column). * `type` reflects what is stored in `data` and can be almost any value-type * (except Nullable, Array, Tuple, LowCardinality). * */ struct ItemView { using DataType = std::string_view; const Type::Code type; const DataType data; private: template inline auto ConvertToStorageValue(const T& t) { if constexpr (std::is_same_v || std::is_same_v) { return std::string_view{t}; } else if constexpr (std::is_fundamental_v || std::is_same_v> || std::is_same_v>) { return std::string_view{reinterpret_cast(&t), sizeof(T)}; } else { static_assert(!std::is_same_v, "Unknown type, which can't be stored in ItemView"); return; } } public: ItemView(Type::Code type, DataType data) : type(type), data(data) { ValidateData(type, data); } ItemView(Type::Code type, ItemView other) : type(type), data(other.data) { ValidateData(type, data); } explicit ItemView() : ItemView(Type::Void, std::string_view{}) {} template explicit ItemView(Type::Code type, const T & value) : ItemView(type, ConvertToStorageValue(value)) {} template auto get() const { using ValueType = std::remove_cv_t>; if constexpr (std::is_same_v || std::is_same_v) { return data; } else if constexpr (std::is_fundamental_v || std::is_same_v || std::is_same_v) { if (sizeof(ValueType) == data.size()) { return *reinterpret_cast(data.data()); } else { throw AssertionError("Incompatitable value type and size. Requested size: " + std::to_string(sizeof(ValueType)) + " stored size: " + std::to_string(data.size())); } } } inline std::string_view AsBinaryData() const { return data; } // Validate that value matches type, will throw an exception if validation fails. static void ValidateData(Type::Code type, DataType data); }; }