Skip to content

Commit 31e9943

Browse files
committed
keep a single API shape for ErrorCollector and SnapshotUpdate
1 parent bd71e84 commit 31e9943

4 files changed

Lines changed: 32 additions & 165 deletions

File tree

‎src/iceberg/update/snapshot_update.h‎

Lines changed: 14 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -62,112 +62,10 @@ class ICEBERG_EXPORT SnapshotUpdate : public PendingUpdate {
6262
bool IsRetryable() const override { return true; }
6363
Status Commit() override;
6464

65-
// C++23 uses deducing `this` so chaining keeps returning the derived update type.
66-
// C++20 exposes the same operations but returns SnapshotUpdate&, because preserving
67-
// the derived type would require making the update hierarchy CRTP. Keyed on the
68-
// language version rather than __cpp_explicit_this_parameter, which Apple clang does
69-
// not define, and compared with "> 202002L" because MSVC's /std:c++latest only
70-
// promises a value above 202002L.
71-
#if __cplusplus > 202002L || (defined(_MSVC_LANG) && _MSVC_LANG > 202002L)
7265
/// \brief Set the metrics reporter for this snapshot update.
7366
///
7467
/// \param reporter The metrics reporter to use.
7568
/// \return Reference to this for method chaining.
76-
auto& ReportWith(this auto& self, std::shared_ptr<MetricsReporter> reporter) {
77-
static_cast<SnapshotUpdate&>(self).reporter_ = std::move(reporter);
78-
return self;
79-
}
80-
81-
/// \brief Set a callback to delete files instead of the table's default.
82-
///
83-
/// \param delete_func A function used to delete file locations.
84-
/// \return This update for method chaining.
85-
/// \note Cannot be called more than once.
86-
auto& DeleteWith(this auto& self,
87-
std::function<Status(const std::string&)> delete_func) {
88-
if (self.delete_func_) {
89-
return self.AddError(ErrorKind::kInvalidArgument,
90-
"Cannot set delete callback more than once");
91-
}
92-
self.delete_func_ = std::move(delete_func);
93-
return self;
94-
}
95-
96-
/// \brief Stage a snapshot in table metadata, but do not make it current.
97-
///
98-
/// The snapshot is assigned an ID and added to table metadata. The table's
99-
/// current snapshot ID is not updated.
100-
///
101-
/// \return This update for method chaining.
102-
auto& StageOnly(this auto& self) {
103-
self.stage_only_ = true;
104-
return self;
105-
}
106-
107-
/// \brief Configure an executor for manifest planning work.
108-
///
109-
/// \param executor Executor to use while planning manifests.
110-
/// \return Reference to this for method chaining.
111-
auto& ScanManifestsWith(this auto& self, Executor& executor) {
112-
self.plan_executor_ = std::ref(executor);
113-
return self;
114-
}
115-
116-
/// \brief Perform operations on a particular branch.
117-
///
118-
/// \param branch The name of a SnapshotRef of type branch.
119-
/// \return This update for method chaining.
120-
auto& ToBranch(this auto& self, const std::string& branch) {
121-
if (branch.empty()) [[unlikely]] {
122-
return self.AddError(ErrorKind::kInvalidArgument, "Branch name cannot be empty");
123-
}
124-
125-
if (auto ref_it = self.base().refs.find(branch); ref_it != self.base().refs.end()) {
126-
if (ref_it->second->type() != SnapshotRefType::kBranch) {
127-
return self.AddError(ErrorKind::kInvalidArgument,
128-
"{} is a tag, not a branch. Tags cannot be targets for "
129-
"producing snapshots",
130-
branch);
131-
}
132-
}
133-
134-
self.target_branch_ = branch;
135-
return self;
136-
}
137-
138-
/// \brief Set a summary property in the snapshot produced by this update.
139-
///
140-
/// \param property A String property name.
141-
/// \param value A String property value.
142-
/// \return This update for method chaining.
143-
auto& Set(this auto& self, const std::string& property, const std::string& value) {
144-
static_cast<SnapshotUpdate&>(self).SetSummaryProperty(property, value);
145-
return self;
146-
}
147-
148-
/// \brief Configure an executor and max writer count for writing new manifests.
149-
///
150-
/// If this method is not called, manifest writes remain serial. When configured,
151-
/// files may be split into independent rolling-writer groups.
152-
///
153-
/// \note Custom FileIO implementations and registered writer factories used for
154-
/// manifest writes must support concurrent calls when an executor is configured.
155-
auto& WriteManifestsWith(this auto& self, Executor& executor, int32_t parallelism) {
156-
if (parallelism <= 0) [[unlikely]] {
157-
return self.AddError(
158-
ErrorKind::kInvalidArgument,
159-
"Manifest write parallelism must be greater than 0, but was: {}", parallelism);
160-
}
161-
162-
self.write_manifest_executor_ = std::ref(executor);
163-
self.write_manifest_parallelism_ = parallelism;
164-
return self;
165-
}
166-
#else
167-
/// \brief Set the metrics reporter for this snapshot update.
168-
///
169-
/// \param reporter The metrics reporter to use.
170-
/// \return This snapshot update for method chaining.
17169
SnapshotUpdate& ReportWith(std::shared_ptr<MetricsReporter> reporter) {
17270
reporter_ = std::move(reporter);
17371
return *this;
@@ -176,7 +74,7 @@ class ICEBERG_EXPORT SnapshotUpdate : public PendingUpdate {
17674
/// \brief Set a callback to delete files instead of the table's default.
17775
///
17876
/// \param delete_func A function used to delete file locations.
179-
/// \return This snapshot update for method chaining.
77+
/// \return This update for method chaining.
18078
/// \note Cannot be called more than once.
18179
SnapshotUpdate& DeleteWith(std::function<Status(const std::string&)> delete_func) {
18280
if (delete_func_) {
@@ -189,7 +87,10 @@ class ICEBERG_EXPORT SnapshotUpdate : public PendingUpdate {
18987

19088
/// \brief Stage a snapshot in table metadata, but do not make it current.
19189
///
192-
/// \return This snapshot update for method chaining.
90+
/// The snapshot is assigned an ID and added to table metadata. The table's
91+
/// current snapshot ID is not updated.
92+
///
93+
/// \return This update for method chaining.
19394
SnapshotUpdate& StageOnly() {
19495
stage_only_ = true;
19596
return *this;
@@ -198,7 +99,7 @@ class ICEBERG_EXPORT SnapshotUpdate : public PendingUpdate {
19899
/// \brief Configure an executor for manifest planning work.
199100
///
200101
/// \param executor Executor to use while planning manifests.
201-
/// \return This snapshot update for method chaining.
102+
/// \return Reference to this for method chaining.
202103
SnapshotUpdate& ScanManifestsWith(Executor& executor) {
203104
plan_executor_ = std::ref(executor);
204105
return *this;
@@ -207,7 +108,7 @@ class ICEBERG_EXPORT SnapshotUpdate : public PendingUpdate {
207108
/// \brief Perform operations on a particular branch.
208109
///
209110
/// \param branch The name of a SnapshotRef of type branch.
210-
/// \return This snapshot update for method chaining.
111+
/// \return This update for method chaining.
211112
SnapshotUpdate& ToBranch(const std::string& branch) {
212113
if (branch.empty()) [[unlikely]] {
213114
AddError(ErrorKind::kInvalidArgument, "Branch name cannot be empty");
@@ -232,17 +133,22 @@ class ICEBERG_EXPORT SnapshotUpdate : public PendingUpdate {
232133
///
233134
/// \param property A String property name.
234135
/// \param value A String property value.
235-
/// \return This snapshot update for method chaining.
136+
/// \return This update for method chaining.
236137
SnapshotUpdate& Set(const std::string& property, const std::string& value) {
237138
SetSummaryProperty(property, value);
238139
return *this;
239140
}
240141

241142
/// \brief Configure an executor and max writer count for writing new manifests.
242143
///
144+
/// If this method is not called, manifest writes remain serial. When configured,
145+
/// files may be split into independent rolling-writer groups.
146+
///
243147
/// \param executor Executor to use while writing manifests.
244148
/// \param parallelism Maximum number of concurrent manifest writers.
245-
/// \return This snapshot update for method chaining.
149+
/// \return This update for method chaining.
150+
/// \note Custom FileIO implementations and registered writer factories used for
151+
/// manifest writes must support concurrent calls when an executor is configured.
246152
SnapshotUpdate& WriteManifestsWith(Executor& executor, int32_t parallelism) {
247153
if (parallelism <= 0) [[unlikely]] {
248154
AddError(ErrorKind::kInvalidArgument,
@@ -255,7 +161,6 @@ class ICEBERG_EXPORT SnapshotUpdate : public PendingUpdate {
255161
write_manifest_parallelism_ = parallelism;
256162
return *this;
257163
}
258-
#endif // C++23
259164

260165
protected:
261166
friend class Transaction;

‎src/iceberg/update/update_partition_spec.cc‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,8 @@ UpdatePartitionSpec& UpdatePartitionSpec::AddField(const std::shared_ptr<Term>&
123123
return AddFieldInternal(part_name, source_id, bound_transform->transform());
124124
}
125125

126-
return AddError(
127-
InvalidArgument("Cannot add {} term to partition spec", term->ToString()));
126+
AddError(InvalidArgument("Cannot add {} term to partition spec", term->ToString()));
127+
return *this;
128128
}
129129

130130
UpdatePartitionSpec& UpdatePartitionSpec::AddFieldInternal(
@@ -195,8 +195,9 @@ UpdatePartitionSpec& UpdatePartitionSpec::AddFieldInternal(
195195
// Rename the old deleted field
196196
RenameField(existing_field->name(), std::move(renamed));
197197
} else {
198-
return AddError(
198+
AddError(
199199
InvalidArgument("Cannot add duplicate partition field name: {}", field_name));
200+
return *this;
200201
}
201202
} else {
202203
// Field is being deleted, rename it to avoid conflict
@@ -257,8 +258,9 @@ UpdatePartitionSpec& UpdatePartitionSpec::RemoveField(const std::shared_ptr<Term
257258
return RemoveFieldByTransform(key, term->ToString());
258259
}
259260

260-
return AddError(
261+
AddError(
261262
InvalidArgument("Cannot remove {} term from partition spec", term->ToString()));
263+
return *this;
262264
}
263265

264266
UpdatePartitionSpec& UpdatePartitionSpec::RemoveFieldByTransform(

‎src/iceberg/update/update_sort_order.cc‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,9 @@ UpdateSortOrder& UpdateSortOrder::AddSortField(const std::shared_ptr<Term>& term
6565
sort_fields_.emplace_back(bound_term->reference()->field_id(),
6666
unbound_transform->transform(), direction, null_order);
6767
} else {
68-
return AddError(ErrorKind::kNotSupported, "Not supported unbound term: {}",
69-
static_cast<int>(term->kind()));
68+
AddError(ErrorKind::kNotSupported, "Not supported unbound term: {}",
69+
static_cast<int>(term->kind()));
70+
return *this;
7071
}
7172

7273
return *this;

‎src/iceberg/util/error_collector.h‎

Lines changed: 9 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -104,55 +104,6 @@ class ICEBERG_EXPORT ErrorCollector {
104104
ErrorCollector(const ErrorCollector&) = default;
105105
ErrorCollector& operator=(const ErrorCollector&) = default;
106106

107-
// C++23 uses deducing `this` so that `return AddError(...)` keeps returning the
108-
// derived builder type. C++20 exposes the same overloads returning ErrorCollector&,
109-
// because preserving the derived type would require making the builders CRTP. Keyed
110-
// on the language version rather than __cpp_explicit_this_parameter, which Apple
111-
// clang does not define, and compared with "> 202002L" because MSVC's
112-
// /std:c++latest only promises a value above 202002L.
113-
#if __cplusplus > 202002L || (defined(_MSVC_LANG) && _MSVC_LANG > 202002L)
114-
/// \brief Add a specific error and return reference to derived class
115-
///
116-
/// \param self Deduced reference to the derived class instance
117-
/// \param kind The kind of error
118-
/// \param fmt The format string
119-
/// \param args The arguments to format the message
120-
/// \return Reference to the derived class for method chaining
121-
template <typename... Args>
122-
auto& AddError(this auto& self, ErrorKind kind, const std::format_string<Args...> fmt,
123-
Args&&... args) {
124-
self.errors_.emplace_back(kind, std::format(fmt, std::forward<Args>(args)...));
125-
return self;
126-
}
127-
128-
/// \brief Add an existing error object and return reference to derived class
129-
///
130-
/// Useful when propagating errors from other components or reusing
131-
/// error objects without deconstructing and reconstructing them.
132-
///
133-
/// \param self Deduced reference to the derived class instance
134-
/// \param err The error to add
135-
/// \return Reference to the derived class for method chaining
136-
auto& AddError(this auto& self, Error err) {
137-
self.errors_.push_back(std::move(err));
138-
return self;
139-
}
140-
141-
/// \brief Add an unexpected result's error and return reference to derived class
142-
///
143-
/// Useful for cases like below:
144-
/// \code
145-
/// return AddError(InvalidArgument("Invalid value: {}", value));
146-
/// \endcode
147-
///
148-
/// \param self Deduced reference to the derived class instance
149-
/// \param err The unexpected result containing the error to add
150-
/// \return Reference to the derived class for method chaining
151-
auto& AddError(this auto& self, unexpected<Error> err) {
152-
self.errors_.push_back(std::move(err.error()));
153-
return self;
154-
}
155-
#else
156107
/// \brief Add a specific error
157108
///
158109
/// \param kind The kind of error
@@ -168,6 +119,9 @@ class ICEBERG_EXPORT ErrorCollector {
168119

169120
/// \brief Add an existing error object
170121
///
122+
/// Useful when propagating errors from other components or reusing
123+
/// error objects without deconstructing and reconstructing them.
124+
///
171125
/// \param err The error to add
172126
/// \return This error collector for method chaining
173127
ErrorCollector& AddError(Error err) {
@@ -177,13 +131,18 @@ class ICEBERG_EXPORT ErrorCollector {
177131

178132
/// \brief Add an unexpected result's error
179133
///
134+
/// Useful for cases like below:
135+
/// \code
136+
/// AddError(InvalidArgument("Invalid value: {}", value));
137+
/// return *this;
138+
/// \endcode
139+
///
180140
/// \param err The unexpected result containing the error to add
181141
/// \return This error collector for method chaining
182142
ErrorCollector& AddError(unexpected<Error> err) {
183143
errors_.push_back(std::move(err.error()));
184144
return *this;
185145
}
186-
#endif // C++23
187146

188147
/// \brief Check if any errors have been collected
189148
///

0 commit comments

Comments
 (0)