Skip to content

Commit 38dd15d

Browse files
authored
Merge pull request #428 from IyeOnline/master
Introduce validation to the ColumnArray constructor
2 parents 85437b5 + a842ab8 commit 38dd15d

File tree

1 file changed

+33
-7
lines changed

1 file changed

+33
-7
lines changed

clickhouse/columns/array.cpp

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,38 @@
55

66
namespace clickhouse {
77

8-
ColumnArray::ColumnArray(ColumnRef data)
9-
: ColumnArray(data, std::make_shared<ColumnUInt64>())
10-
{
8+
namespace {
9+
std::shared_ptr<ColumnUInt64> make_single_offset(size_t value) {
10+
auto res = std::make_shared<ColumnUInt64>();
11+
if (value != 0) {
12+
res->Append(value);
13+
}
14+
return res;
15+
}
16+
} // namespace
17+
18+
ColumnArray::ColumnArray(ColumnRef data) : ColumnArray(data, make_single_offset(data->Size())) {
1119
}
1220

1321
ColumnArray::ColumnArray(ColumnRef data, std::shared_ptr<ColumnUInt64> offsets)
1422
: Column(Type::CreateArray(data->Type()))
1523
, data_(data)
1624
, offsets_(offsets)
1725
{
26+
const auto rows = offsets_->Size();
27+
const auto expected_values = rows > 0 ? offsets_->At(rows - 1) : 0;
28+
std::uint64_t prev = 0;
29+
// Ensure the offset array is internally consistent
30+
for (const auto& o : offsets_->GetWritableData()) {
31+
if (o < prev) {
32+
throw ValidationError("offsets must be monotonically increasing");
33+
}
34+
prev = o;
35+
}
36+
if (data_->Size() != expected_values) {
37+
throw ValidationError("Mismatch between data and offsets: Expected " + std::to_string(expected_values) +
38+
" values in data, but got " + std::to_string(data_->Size()));
39+
}
1840
}
1941

2042
ColumnArray::ColumnArray(ColumnArray&& other)
@@ -41,11 +63,15 @@ ColumnRef ColumnArray::Slice(size_t begin, size_t size) const {
4163
if (size && begin + size > Size())
4264
throw ValidationError("Slice indexes are out of bounds");
4365

44-
auto result = std::make_shared<ColumnArray>(data_->Slice(GetOffset(begin), GetOffset(begin + size) - GetOffset(begin)));
45-
for (size_t i = 0; i < size; i++)
46-
result->AddOffset(GetSize(begin + i));
66+
auto sliced_data = data_->Slice(GetOffset(begin), GetOffset(begin + size) - GetOffset(begin));
67+
auto offsets = std::make_shared<ColumnUInt64>();
68+
auto offset = uint64_t{0};
69+
for (size_t i = 0; i < size; i++) {
70+
offset += GetSize(begin + i);
71+
offsets->Append(offset);
72+
}
4773

48-
return result;
74+
return std::make_shared<ColumnArray>(std::move(sliced_data), std::move(offsets));
4975
}
5076

5177
ColumnRef ColumnArray::CloneEmpty() const {

0 commit comments

Comments
 (0)