-
Notifications
You must be signed in to change notification settings - Fork 198
Expand file tree
/
Copy patharray.h
More file actions
323 lines (256 loc) · 10.2 KB
/
array.h
File metadata and controls
323 lines (256 loc) · 10.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
#pragma once
#include "column.h"
#include "numeric.h"
#include "utils.h"
#include <memory>
namespace clickhouse {
template <typename NestedColumnType>
class ColumnArrayT;
/**
* Represents column of Array(T).
*/
class ColumnArray : public Column {
public:
using ValueType = ColumnRef;
/** Create an array of given type.
*
* `data` is used internally (and modified) by ColumnArray.
* Users are strongly advised against supplying non-empty columns and/or modifying
* contents of `data` afterwards.
*/
explicit ColumnArray(ColumnRef data);
/** Create an array of given type, with actual values and offsets.
*
* Both `data` and `offsets` are used (and modified) internally bye ColumnArray.
* Users are strongly advised against modifying contents of `data` or `offsets` afterwards.
*/
ColumnArray(ColumnRef data, std::shared_ptr<ColumnUInt64> offsets);
/// Converts input column to array and appends as one row to the current column.
void AppendAsColumn(ColumnRef array);
/// Converts array at pos n to column.
/// Type of element of result column same as type of array element.
ColumnRef GetAsColumn(size_t n) const;
/// Shorthand to get a column casted to a proper type.
template <typename T>
auto GetAsColumnTyped(size_t n) const {
return GetAsColumn(n)->AsStrict<T>();
}
public:
/// Appends content of given column to the end of current one.
void Append(ColumnRef column) override;
/// Increase the capacity of the column for large block insertion.
void Reserve(size_t new_cap) override;
size_t Capacity() const override;
/// Loads column prefix from input stream.
bool LoadPrefix(InputStream* input, size_t rows) override;
/// Loads column data from input stream.
bool LoadBody(InputStream* input, size_t rows) override;
/// Saves column prefix to output stream.
void SavePrefix(OutputStream* output) override;
/// Saves column data to output stream.
void SaveBody(OutputStream* output) override;
/// Clear column data .
void Clear() override;
/// Returns count of rows in the column.
size_t Size() const override;
size_t MemoryUsage() const override;
/// Makes slice of the current column.
ColumnRef Slice(size_t, size_t) const override;
ColumnRef CloneEmpty() const override;
void Swap(Column&) override;
void OffsetsIncrease(size_t);
protected:
template<typename T> friend class ColumnArrayT;
ColumnArray(ColumnArray&& array);
size_t GetOffset(size_t n) const;
size_t GetSize(size_t n) const;
ColumnRef GetData();
void AddOffset(size_t n);
void Reset();
private:
ColumnRef data_;
std::shared_ptr<ColumnUInt64> offsets_;
};
template <typename ColumnType>
class ColumnArrayT : public ColumnArray {
public:
class ArrayValueView;
using ValueType = ArrayValueView;
using NestedColumnType = ColumnType;
explicit ColumnArrayT(std::shared_ptr<NestedColumnType> data)
: ColumnArray(data)
, typed_nested_data_(data)
{}
ColumnArrayT(std::shared_ptr<NestedColumnType> data, std::shared_ptr<ColumnUInt64> offsets)
: ColumnArray(data, offsets)
, typed_nested_data_(data)
{}
template <typename ...Args>
explicit ColumnArrayT(Args &&... args)
: ColumnArrayT(std::make_shared<NestedColumnType>(std::forward<Args>(args)...))
{}
/** Create a ColumnArrayT from a ColumnArray, without copying data and offsets, but by 'stealing' those from `col`.
*
* Ownership of column internals is transferred to returned object, original (argument) object
* MUST NOT BE USED IN ANY WAY, it is only safe to dispose it.
*
* Throws an exception if `col` is of wrong type, it is safe to use original col in this case.
* This is a static method to make such conversion verbose.
*/
static auto Wrap(ColumnArray&& col) {
auto nested_data = WrapColumn<NestedColumnType>(col.GetData());
return std::make_shared<ColumnArrayT<NestedColumnType>>(nested_data, col.offsets_);
}
static auto Wrap(Column&& col) {
return Wrap(std::move(dynamic_cast<ColumnArray&&>(col)));
}
// Helper to simplify integration with other APIs
static auto Wrap(ColumnRef&& col) {
return Wrap(std::move(*col->AsStrict<ColumnArray>()));
}
/// A single (row) value of the Array-column, i.e. readonly array of items.
class ArrayValueView {
const std::shared_ptr<NestedColumnType> typed_nested_data_;
const size_t offset_;
const size_t size_;
public:
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)
, offset_(offset)
, size_(std::min(typed_nested_data_->Size() - offset, size))
{}
inline auto operator[](size_t index) const {
return (*typed_nested_data_)[offset_ + index];
}
inline auto At(size_t index) const {
if (index >= size_)
throw ValidationError("ColumnArray value index out of bounds: "
+ std::to_string(index) + ", max is " + std::to_string(size_));
return typed_nested_data_->At(offset_ + index);
}
class Iterator {
const std::shared_ptr<NestedColumnType> typed_nested_data_;
const size_t offset_;
const size_t size_;
size_t index_;
public:
Iterator() = default;
Iterator(std::shared_ptr<NestedColumnType> typed_nested_data, size_t offset, size_t size, size_t index)
: typed_nested_data_(typed_nested_data)
, offset_(offset)
, size_(size)
, index_(index)
{}
using ValueType = typename ArrayValueView::ValueType;
inline auto operator*() const {
return typed_nested_data_->At(offset_ + index_);
}
inline Iterator& operator++() {
++index_;
return *this;
}
inline bool operator==(const Iterator& other) const {
return this->typed_nested_data_ == other.typed_nested_data_
&& this->offset_ == other.offset_
&& this->size_ == other.size_
&& this->index_ == other.index_;
}
inline bool operator!=(const Iterator& other) const {
return !(*this == other);
}
};
// minimalistic stl-like container interface, hence the lowercase
inline Iterator begin() const {
return Iterator{typed_nested_data_, offset_, size_, 0};
}
inline Iterator cbegin() const {
return Iterator{typed_nested_data_, offset_, size_, 0};
}
inline Iterator end() const {
return Iterator{typed_nested_data_, offset_, size_, size_};
}
inline Iterator cend() const {
return Iterator{typed_nested_data_, offset_, size_, size_};
}
inline size_t size() const {
return size_;
}
// It is ugly to have both size() and Size(), but it is for compatitability with both STL and rest of the clickhouse-cpp.
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 {
if (index >= Size())
throw ValidationError("ColumnArray row index out of bounds: "
+ std::to_string(index) + ", max is " + std::to_string(Size()));
return ArrayValueView{typed_nested_data_, GetOffset(index), GetSize(index)};
}
inline auto operator[](size_t index) const {
return ArrayValueView{typed_nested_data_, GetOffset(index), GetSize(index)};
}
using ColumnArray::Append;
template <typename Container>
inline void Append(Container&& container) {
using container_type = decltype(container);
if constexpr (std::is_lvalue_reference_v<container_type> ||
std::is_const_v<std::remove_reference_t<container_type>>) {
Append(std::begin(container), std::end(container));
}
else {
Append(std::make_move_iterator(std::begin(container)),
std::make_move_iterator(std::end(container)));
}
}
template <typename ValueType>
inline void Append(const std::initializer_list<ValueType>& container) {
Append(std::begin(container), std::end(container));
}
template <typename Begin, typename End>
inline void Append(Begin begin, End end) {
auto & nested_data = *typed_nested_data_;
size_t counter = 0;
while (begin != end) {
nested_data.Append(*begin);
++begin;
++counter;
}
// Even if there are 0 items, increase counter, creating empty array item.
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)
: ColumnArray(std::move(array))
, typed_nested_data_(std::move(nested_data))
{}
private:
std::shared_ptr<NestedColumnType> typed_nested_data_;
};
}