Skip to content

Commit 66e4742

Browse files
authored
Merge pull request #254 from den818/MapColumn
Support column type: map
2 parents 122c2af + 8c8c7a6 commit 66e4742

21 files changed

+769
-18
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ C++ client for [ClickHouse](https://clickhouse.com/).
2121
* UInt8, UInt16, UInt32, UInt64, Int8, Int16, Int32, Int64
2222
* Int128
2323
* UUID
24+
* Map
2425

2526
## Building
2627

@@ -87,7 +88,7 @@ int main()
8788

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

9394
See https://github.com/ClickHouse/clickhouse-cpp/issues/184 for details.

clickhouse/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ SET ( clickhouse-cpp-lib-src
1818
columns/lowcardinalityadaptor.h
1919
columns/nullable.cpp
2020
columns/numeric.cpp
21+
columns/map.cpp
2122
columns/string.cpp
2223
columns/tuple.cpp
2324
columns/uuid.cpp
@@ -121,6 +122,7 @@ INSTALL(FILES columns/itemview.h DESTINATION include/clickhouse/columns/)
121122
INSTALL(FILES columns/lowcardinality.h DESTINATION include/clickhouse/columns/)
122123
INSTALL(FILES columns/nullable.h DESTINATION include/clickhouse/columns/)
123124
INSTALL(FILES columns/numeric.h DESTINATION include/clickhouse/columns/)
125+
INSTALL(FILES columns/map.h DESTINATION include/clickhouse/columns/)
124126
INSTALL(FILES columns/string.h DESTINATION include/clickhouse/columns/)
125127
INSTALL(FILES columns/tuple.h DESTINATION include/clickhouse/columns/)
126128
INSTALL(FILES columns/utils.h DESTINATION include/clickhouse/columns/)

clickhouse/client.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "columns/lowcardinality.h"
1313
#include "columns/nullable.h"
1414
#include "columns/numeric.h"
15+
#include "columns/map.h"
1516
#include "columns/string.h"
1617
#include "columns/tuple.h"
1718
#include "columns/uuid.h"

clickhouse/columns/array.h

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "column.h"
44
#include "numeric.h"
5+
#include "utils.h"
56

67
#include <memory>
78

@@ -121,13 +122,8 @@ class ColumnArrayT : public ColumnArray {
121122
* This is a static method to make such conversion verbose.
122123
*/
123124
static auto Wrap(ColumnArray&& col) {
124-
if constexpr (std::is_base_of_v<ColumnArray, NestedColumnType> && !std::is_same_v<ColumnArray, NestedColumnType>) {
125-
// assuming NestedColumnType is ArrayT specialization
126-
return std::make_shared<ColumnArrayT<NestedColumnType>>(NestedColumnType::Wrap(col.GetData()), col.offsets_);
127-
} else {
128-
auto nested_data = col.GetData()->template AsStrict<NestedColumnType>();
129-
return std::make_shared<ColumnArrayT<NestedColumnType>>(nested_data, col.offsets_);
130-
}
125+
auto nested_data = WrapColumn<NestedColumnType>(col.GetData());
126+
return std::make_shared<ColumnArrayT<NestedColumnType>>(nested_data, col.offsets_);
131127
}
132128

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

148144
public:
149-
using ValueType = typename NestedColumnType::ValueType;
145+
using ValueType = std::decay_t<decltype(std::declval<NestedColumnType>().At(0))>;
150146

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

181-
using ValueType = typename NestedColumnType::ValueType;
177+
using ValueType = typename ArrayValueView::ValueType;
182178

183179
inline auto operator*() const {
184180
return typed_nested_data_->At(offset_ + index_);
@@ -226,6 +222,22 @@ class ColumnArrayT : public ColumnArray {
226222
inline size_t Size() const {
227223
return size_;
228224
}
225+
226+
inline bool operator==(const ArrayValueView& other) const {
227+
if (size() != other.size()) {
228+
return false;
229+
}
230+
for (size_t i = 0; i < size_; ++i) {
231+
if ((*this)[i] != other[i]) {
232+
return false;
233+
}
234+
}
235+
return true;
236+
}
237+
238+
inline bool operator!=(const ArrayValueView& other) const {
239+
return !(*this == other);
240+
}
229241
};
230242

231243
inline auto At(size_t index) const {
@@ -267,6 +279,20 @@ class ColumnArrayT : public ColumnArray {
267279
AddOffset(counter);
268280
}
269281

282+
ColumnRef Slice(size_t begin, size_t size) const override {
283+
return Wrap(ColumnArray::Slice(begin, size));
284+
}
285+
286+
ColumnRef CloneEmpty() const override {
287+
return Wrap(ColumnArray::CloneEmpty());
288+
}
289+
290+
void Swap(Column& other) override {
291+
auto & col = dynamic_cast<ColumnArrayT<NestedColumnType> &>(other);
292+
typed_nested_data_.swap(col.typed_nested_data_);
293+
ColumnArray::Swap(other);
294+
}
295+
270296
private:
271297
/// Helper to allow wrapping a "typeless" ColumnArray
272298
ColumnArrayT(ColumnArray&& array, std::shared_ptr<NestedColumnType> nested_data)

clickhouse/columns/factory.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "string.h"
1515
#include "tuple.h"
1616
#include "uuid.h"
17+
#include "map.h"
1718

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

@@ -86,7 +87,7 @@ static ColumnRef CreateTerminalColumn(const TypeAst& ast) {
8687
case Type::Date:
8788
return std::make_shared<ColumnDate>();
8889
case Type::Date32:
89-
return std::make_shared<ColumnDate32>();
90+
return std::make_shared<ColumnDate32>();
9091

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

202+
case TypeAst::Map: {
203+
if (ast.elements.size() != 2) {
204+
throw ValidationError(ast.name + " content is not correct");
205+
}
206+
207+
std::vector<ColumnRef> columns;
208+
209+
columns.reserve(ast.elements.size());
210+
for (const auto& elem : ast.elements) {
211+
if (auto col = CreateColumnFromAst(elem, settings)) {
212+
columns.push_back(col);
213+
} else {
214+
return nullptr;
215+
}
216+
}
217+
218+
return std::make_shared<ColumnMap>(
219+
std::make_shared<ColumnArray>(
220+
std::make_shared<ColumnTuple>(columns)));
221+
}
222+
201223
case TypeAst::Assign:
202224
case TypeAst::Null:
203225
case TypeAst::Number:

clickhouse/columns/itemview.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ void ItemView::ValidateData(Type::Code type, DataType data) {
7777
case Type::Code::Nullable:
7878
case Type::Code::Tuple:
7979
case Type::Code::LowCardinality:
80+
case Type::Code::Map:
8081
throw AssertionError("Unsupported type in ItemView: " + std::string(Type::TypeName(type)));
8182

8283
case Type::Code::IPv6:

clickhouse/columns/map.cpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#include "map.h"
2+
3+
#include <stdexcept>
4+
5+
#include "../exceptions.h"
6+
#include "utils.h"
7+
8+
namespace {
9+
10+
using namespace clickhouse;
11+
12+
TypeRef GetMapType(const Type& data_type) {
13+
auto array = data_type.As<ArrayType>();
14+
if (!array) {
15+
throw ValidationError("Wrong type " + data_type.GetName() + " of data for map");
16+
}
17+
auto tuple = array->GetItemType()->As<TupleType>();
18+
if (!tuple) {
19+
throw ValidationError("Wrong type " + data_type.GetName() + " of data for map");
20+
}
21+
auto types = tuple->GetTupleType();
22+
if (types.size() != 2) {
23+
throw ValidationError("Wrong type " + data_type.GetName() + " of data for map");
24+
}
25+
return Type::CreateMap(types[0], types[1]);
26+
}
27+
28+
} // namespace
29+
30+
namespace clickhouse {
31+
32+
ColumnMap::ColumnMap(ColumnRef data)
33+
: Column(GetMapType(data->GetType())), data_(data->As<ColumnArray>()) {
34+
}
35+
36+
void ColumnMap::Clear() {
37+
data_->Clear();
38+
}
39+
40+
void ColumnMap::Append(ColumnRef column) {
41+
if (auto col = column->As<ColumnMap>()) {
42+
data_->Append(col->data_);
43+
}
44+
}
45+
46+
bool ColumnMap::LoadPrefix(InputStream* input, size_t rows) {
47+
return data_->LoadPrefix(input, rows);
48+
}
49+
50+
bool ColumnMap::LoadBody(InputStream* input, size_t rows) {
51+
return data_->LoadBody(input, rows);
52+
}
53+
54+
void ColumnMap::SavePrefix(OutputStream* output) {
55+
data_->SavePrefix(output);
56+
}
57+
58+
void ColumnMap::SaveBody(OutputStream* output) {
59+
data_->SaveBody(output);
60+
}
61+
62+
size_t ColumnMap::Size() const {
63+
return data_->Size();
64+
}
65+
66+
ColumnRef ColumnMap::Slice(size_t begin, size_t len) const {
67+
return std::make_shared<ColumnMap>(data_->Slice(begin, len));
68+
}
69+
70+
ColumnRef ColumnMap::CloneEmpty() const {
71+
return std::make_shared<ColumnMap>(data_->CloneEmpty());
72+
}
73+
74+
void ColumnMap::Swap(Column& other) {
75+
auto& col = dynamic_cast<ColumnMap&>(other);
76+
data_.swap(col.data_);
77+
}
78+
79+
ColumnRef ColumnMap::GetAsColumn(size_t n) const {
80+
return data_->GetAsColumn(n);
81+
}
82+
83+
} // namespace clickhouse

0 commit comments

Comments
 (0)