Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ C++ client for [ClickHouse](https://clickhouse.com/).
* UInt8, UInt16, UInt32, UInt64, Int8, Int16, Int32, Int64
* Int128
* UUID
* Map

## Building

Expand Down Expand Up @@ -87,7 +88,7 @@ int main()

## Retries
If you wish to implement some retry logic atop of `clickhouse::Client` there are few simple rules to make you life easier:
- If previous attempt threw an exception, then make sure to call `clickhouse::Client::ResetConnection()` before the next try.
- If previous attempt threw an exception, then make sure to call `clickhouse::Client::ResetConnection()` before the next try.
- For `clickhouse::Client::Insert()` you can reuse a block from previous try, no need to rebuild it from scratch.

See https://github.com/ClickHouse/clickhouse-cpp/issues/184 for details.
2 changes: 2 additions & 0 deletions clickhouse/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ SET ( clickhouse-cpp-lib-src
columns/lowcardinalityadaptor.h
columns/nullable.cpp
columns/numeric.cpp
columns/map.cpp
columns/string.cpp
columns/tuple.cpp
columns/uuid.cpp
Expand Down Expand Up @@ -121,6 +122,7 @@ INSTALL(FILES columns/itemview.h DESTINATION include/clickhouse/columns/)
INSTALL(FILES columns/lowcardinality.h DESTINATION include/clickhouse/columns/)
INSTALL(FILES columns/nullable.h DESTINATION include/clickhouse/columns/)
INSTALL(FILES columns/numeric.h DESTINATION include/clickhouse/columns/)
INSTALL(FILES columns/map.h DESTINATION include/clickhouse/columns/)
INSTALL(FILES columns/string.h DESTINATION include/clickhouse/columns/)
INSTALL(FILES columns/tuple.h DESTINATION include/clickhouse/columns/)
INSTALL(FILES columns/utils.h DESTINATION include/clickhouse/columns/)
Expand Down
1 change: 1 addition & 0 deletions clickhouse/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "columns/lowcardinality.h"
#include "columns/nullable.h"
#include "columns/numeric.h"
#include "columns/map.h"
#include "columns/string.h"
#include "columns/tuple.h"
#include "columns/uuid.h"
Expand Down
44 changes: 35 additions & 9 deletions clickhouse/columns/array.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "column.h"
#include "numeric.h"
#include "utils.h"

#include <memory>

Expand Down Expand Up @@ -121,13 +122,8 @@ class ColumnArrayT : public ColumnArray {
* This is a static method to make such conversion verbose.
*/
static auto Wrap(ColumnArray&& col) {
if constexpr (std::is_base_of_v<ColumnArray, NestedColumnType> && !std::is_same_v<ColumnArray, NestedColumnType>) {
// assuming NestedColumnType is ArrayT specialization
return std::make_shared<ColumnArrayT<NestedColumnType>>(NestedColumnType::Wrap(col.GetData()), col.offsets_);
} else {
auto nested_data = col.GetData()->template AsStrict<NestedColumnType>();
return std::make_shared<ColumnArrayT<NestedColumnType>>(nested_data, col.offsets_);
}
auto nested_data = WrapColumn<NestedColumnType>(col.GetData());
return std::make_shared<ColumnArrayT<NestedColumnType>>(nested_data, col.offsets_);
}

static auto Wrap(Column&& col) {
Expand All @@ -146,7 +142,7 @@ class ColumnArrayT : public ColumnArray {
const size_t size_;

public:
using ValueType = typename NestedColumnType::ValueType;
using ValueType = std::decay_t<decltype(std::declval<NestedColumnType>().At(0))>;

ArrayValueView(std::shared_ptr<NestedColumnType> data, size_t offset = 0, size_t size = std::numeric_limits<size_t>::max())
: typed_nested_data_(data)
Expand Down Expand Up @@ -178,7 +174,7 @@ class ColumnArrayT : public ColumnArray {
, index_(index)
{}

using ValueType = typename NestedColumnType::ValueType;
using ValueType = typename ArrayValueView::ValueType;

inline auto operator*() const {
return typed_nested_data_->At(offset_ + index_);
Expand Down Expand Up @@ -226,6 +222,22 @@ class ColumnArrayT : public ColumnArray {
inline size_t Size() const {
return size_;
}

inline bool operator==(const ArrayValueView& other) const {
if (size() != other.size()) {
return false;
}
for (size_t i = 0; i < size_; ++i) {
if ((*this)[i] != other[i]) {
return false;
}
}
return true;
}

inline bool operator!=(const ArrayValueView& other) const {
return !(*this == other);
}
};

inline auto At(size_t index) const {
Expand Down Expand Up @@ -267,6 +279,20 @@ class ColumnArrayT : public ColumnArray {
AddOffset(counter);
}

ColumnRef Slice(size_t begin, size_t size) const override {
return Wrap(ColumnArray::Slice(begin, size));
}

ColumnRef CloneEmpty() const override {
return Wrap(ColumnArray::CloneEmpty());
}

void Swap(Column& other) override {
auto & col = dynamic_cast<ColumnArrayT<NestedColumnType> &>(other);
typed_nested_data_.swap(col.typed_nested_data_);
ColumnArray::Swap(other);
}

private:
/// Helper to allow wrapping a "typeless" ColumnArray
ColumnArrayT(ColumnArray&& array, std::shared_ptr<NestedColumnType> nested_data)
Expand Down
24 changes: 23 additions & 1 deletion clickhouse/columns/factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "string.h"
#include "tuple.h"
#include "uuid.h"
#include "map.h"

#include "../types/type_parser.h"

Expand Down Expand Up @@ -86,7 +87,7 @@ static ColumnRef CreateTerminalColumn(const TypeAst& ast) {
case Type::Date:
return std::make_shared<ColumnDate>();
case Type::Date32:
return std::make_shared<ColumnDate32>();
return std::make_shared<ColumnDate32>();

case Type::IPv4:
return std::make_shared<ColumnIPv4>();
Expand Down Expand Up @@ -198,6 +199,27 @@ static ColumnRef CreateColumnFromAst(const TypeAst& ast, CreateColumnByTypeSetti
return CreateTerminalColumn(ast.elements.back());
}

case TypeAst::Map: {
if (ast.elements.size() != 2) {
throw ValidationError(ast.name + " content is not correct");
}

std::vector<ColumnRef> columns;

columns.reserve(ast.elements.size());
for (const auto& elem : ast.elements) {
if (auto col = CreateColumnFromAst(elem, settings)) {
columns.push_back(col);
} else {
return nullptr;
}
}

return std::make_shared<ColumnMap>(
std::make_shared<ColumnArray>(
std::make_shared<ColumnTuple>(columns)));
}

case TypeAst::Assign:
case TypeAst::Null:
case TypeAst::Number:
Expand Down
1 change: 1 addition & 0 deletions clickhouse/columns/itemview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ void ItemView::ValidateData(Type::Code type, DataType data) {
case Type::Code::Nullable:
case Type::Code::Tuple:
case Type::Code::LowCardinality:
case Type::Code::Map:
throw AssertionError("Unsupported type in ItemView: " + std::string(Type::TypeName(type)));

case Type::Code::IPv6:
Expand Down
83 changes: 83 additions & 0 deletions clickhouse/columns/map.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#include "map.h"

#include <stdexcept>

#include "../exceptions.h"
#include "utils.h"

namespace {

using namespace clickhouse;

TypeRef GetMapType(const Type& data_type) {
auto array = data_type.As<ArrayType>();
if (!array) {
throw ValidationError("Wrong type " + data_type.GetName() + " of data for map");
}
auto tuple = array->GetItemType()->As<TupleType>();
if (!tuple) {
throw ValidationError("Wrong type " + data_type.GetName() + " of data for map");
}
auto types = tuple->GetTupleType();
if (types.size() != 2) {
throw ValidationError("Wrong type " + data_type.GetName() + " of data for map");
}
return Type::CreateMap(types[0], types[1]);
}

} // namespace

namespace clickhouse {

ColumnMap::ColumnMap(ColumnRef data)
: Column(GetMapType(data->GetType())), data_(data->As<ColumnArray>()) {
}

void ColumnMap::Clear() {
data_->Clear();
}

void ColumnMap::Append(ColumnRef column) {
if (auto col = column->As<ColumnMap>()) {
data_->Append(col->data_);
}
}

bool ColumnMap::LoadPrefix(InputStream* input, size_t rows) {
return data_->LoadPrefix(input, rows);
}

bool ColumnMap::LoadBody(InputStream* input, size_t rows) {
return data_->LoadBody(input, rows);
}

void ColumnMap::SavePrefix(OutputStream* output) {
data_->SavePrefix(output);
}

void ColumnMap::SaveBody(OutputStream* output) {
data_->SaveBody(output);
}

size_t ColumnMap::Size() const {
return data_->Size();
}

ColumnRef ColumnMap::Slice(size_t begin, size_t len) const {
return std::make_shared<ColumnMap>(data_->Slice(begin, len));
}

ColumnRef ColumnMap::CloneEmpty() const {
return std::make_shared<ColumnMap>(data_->CloneEmpty());
}

void ColumnMap::Swap(Column& other) {
auto& col = dynamic_cast<ColumnMap&>(other);
data_.swap(col.data_);
}

ColumnRef ColumnMap::GetAsColumn(size_t n) const {
return data_->GetAsColumn(n);
}

} // namespace clickhouse
Loading