-
Notifications
You must be signed in to change notification settings - Fork 173
/
Copy pathnullable.h
154 lines (117 loc) · 4.77 KB
/
nullable.h
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
#pragma once
#include "column.h"
#include "numeric.h"
#include <optional>
namespace clickhouse {
/**
* Represents column of Nullable(T).
*/
class ColumnNullable : public Column {
public:
ColumnNullable(ColumnRef nested, ColumnRef nulls);
/// Appends one null flag to the end of the column
void Append(bool isnull);
/// Returns null flag at given row number.
bool IsNull(size_t n) const;
/// Returns nested column.
ColumnRef Nested() const;
/// Returns nulls column.
ColumnRef Nulls() const;
public:
/// Increase the capacity of the column for large block insertion.
void Reserve(size_t new_cap) override;
/// Appends content of given column to the end of current one.
void Append(ColumnRef column) 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;
/// Makes slice of the current column.
ColumnRef Slice(size_t begin, size_t len) const override;
ColumnRef CloneEmpty() const override;
void Swap(Column&) override;
ItemView GetItem(size_t) const override;
private:
ColumnRef nested_;
std::shared_ptr<ColumnUInt8> nulls_;
};
template <typename ColumnType>
class ColumnNullableT : public ColumnNullable {
public:
using NestedColumnType = ColumnType;
using ValueType = std::optional<std::decay_t<decltype(std::declval<NestedColumnType>().At(0))>>;
ColumnNullableT(std::shared_ptr<NestedColumnType> data, std::shared_ptr<ColumnUInt8> nulls)
: ColumnNullable(data, nulls)
, typed_nested_data_(data)
{}
explicit ColumnNullableT(std::shared_ptr<NestedColumnType> data)
: ColumnNullableT(data, FillNulls(data->Size()))
{}
template <typename ...Args>
explicit ColumnNullableT(Args &&... args)
: ColumnNullableT(std::make_shared<NestedColumnType>(std::forward<Args>(args)...))
{}
inline ValueType At(size_t index) const {
return IsNull(index) ? ValueType{} : ValueType{typed_nested_data_->At(index)};
}
inline ValueType operator[](size_t index) const { return At(index); }
/// Appends content of given column to the end of current one.
void Append(ColumnRef column) override {
ColumnNullable::Append(std::move(column));
}
inline void Append(ValueType value) {
if (value.has_value()) {
typed_nested_data_->Append(std::move(*value));
} else {
typed_nested_data_->Append(typename ValueType::value_type{});
}
// Must be called after Append to nested column because it might fail
ColumnNullable::Append(!value.has_value());
}
/** Create a ColumnNullableT from a ColumnNullable, 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(ColumnNullable&& col) {
return std::make_shared<ColumnNullableT<NestedColumnType>>(
col.Nested()->AsStrict<NestedColumnType>(),
col.Nulls()->AsStrict<ColumnUInt8>()) ;
}
static auto Wrap(Column&& col) { return Wrap(std::move(dynamic_cast<ColumnNullable&&>(col))); }
// Helper to simplify integration with other APIs
static auto Wrap(ColumnRef&& col) { return Wrap(std::move(*col->AsStrict<ColumnNullable>())); }
ColumnRef Slice(size_t begin, size_t size) const override {
return Wrap(ColumnNullable::Slice(begin, size));
}
ColumnRef CloneEmpty() const override { return Wrap(ColumnNullable::CloneEmpty()); }
void Swap(Column& other) override {
auto& col = dynamic_cast<ColumnNullableT<NestedColumnType>&>(other);
typed_nested_data_.swap(col.typed_nested_data_);
ColumnNullable::Swap(other);
}
private:
static inline auto FillNulls(size_t n){
auto result = std::make_shared<ColumnUInt8>();
for (size_t i = 0; i < n; ++i) {
result->Append(0);
}
return result;
}
std::shared_ptr<NestedColumnType> typed_nested_data_;
};
template <typename T>
constexpr bool IsNullable = std::is_base_of_v<ColumnNullable, T>;
}