Skip to content

Commit 1106659

Browse files
authored
Merge pull request #535 from ClickHouse/fix-nullable-append-exception-safety
Fix NullableT append exception guarantee
2 parents 1eb55fa + f11e78a commit 1106659

3 files changed

Lines changed: 29 additions & 9 deletions

File tree

clickhouse/columns/json.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,15 @@ class ColumnJSON : public Column {
7272
template <>
7373
inline void ColumnNullableT<ColumnJSON>::Append(std::optional<std::string_view> value) {
7474
ColumnNullable::Append(!value.has_value());
75-
if (value.has_value()) {
76-
typed_nested_data_->Append(*value);
77-
} else {
78-
typed_nested_data_->Append(std::string_view("{}"));
75+
try {
76+
if (value.has_value()) {
77+
typed_nested_data_->Append(*value);
78+
} else {
79+
typed_nested_data_->Append(std::string_view("{}"));
80+
}
81+
} catch (...) {
82+
Nulls()->AsStrict<ColumnUInt8>()->Erase(Size() - 1);
83+
throw;
7984
}
8085
}
8186

clickhouse/columns/nullable.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,15 @@ class ColumnNullableT : public ColumnNullable {
9696

9797
inline void Append(ValueType value) {
9898
ColumnNullable::Append(!value.has_value());
99-
if (value.has_value()) {
100-
typed_nested_data_->Append(std::move(*value));
101-
} else {
102-
typed_nested_data_->Append(typename ValueType::value_type{});
99+
try {
100+
if (value.has_value()) {
101+
typed_nested_data_->Append(std::move(*value));
102+
} else {
103+
typed_nested_data_->Append(typename ValueType::value_type{});
104+
}
105+
} catch (...) {
106+
Nulls()->template As<ColumnUInt8>()->Erase(Size() - 1);
107+
throw;
103108
}
104109
}
105110

ut/Column_ut.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,17 @@ std::ostream& operator<<(std::ostream& ostr, const Type::Code& type_code) {
4141

4242
}
4343

44+
TEST(ColumnNullableT, AppendRollsBackNullFlagWhenNestedAppendThrows) {
45+
auto nested = std::make_shared<ColumnFixedString>(1);
46+
auto column = std::make_shared<ColumnNullableT<ColumnFixedString>>(nested);
47+
48+
EXPECT_THROW(column->Append(std::string_view("too long")), ValidationError);
49+
50+
EXPECT_EQ(0u, column->Size());
51+
EXPECT_EQ(0u, column->Nulls()->Size());
52+
EXPECT_EQ(0u, column->Nested()->Size());
53+
}
54+
4455

4556
// Generic tests for a Column subclass against basic API:
4657
// 1. Constructor: Create, ensure that it is empty
@@ -515,4 +526,3 @@ TYPED_TEST(GenericColumnTest, ArrayT_RoundTrip) {
515526

516527
this->TestColumnRoundtrip(column, LocalHostEndpoint, AllCompressionMethods);
517528
}
518-

0 commit comments

Comments
 (0)