|
19 | 19 |
|
20 | 20 | #include "iceberg/snapshot.h" |
21 | 21 |
|
| 22 | +#include <charconv> |
| 23 | + |
22 | 24 | #include "iceberg/file_io.h" |
23 | 25 | #include "iceberg/manifest/manifest_list.h" |
24 | 26 | #include "iceberg/manifest/manifest_reader.h" |
@@ -75,6 +77,39 @@ std::optional<std::string_view> Snapshot::operation() const { |
75 | 77 | return std::nullopt; |
76 | 78 | } |
77 | 79 |
|
| 80 | +std::optional<int64_t> Snapshot::FirstRowId() const { |
| 81 | + auto it = summary.find("first-row-id"); |
| 82 | + if (it == summary.end()) { |
| 83 | + return std::nullopt; |
| 84 | + } |
| 85 | + |
| 86 | + int64_t first_row_id = 0; |
| 87 | + const std::string& first_row_id_str = it->second; |
| 88 | + auto [_, ec] = |
| 89 | + std::from_chars(first_row_id_str.data(), |
| 90 | + first_row_id_str.data() + first_row_id_str.size(), first_row_id); |
| 91 | + if (ec != std::errc()) { |
| 92 | + return std::nullopt; |
| 93 | + } |
| 94 | + return first_row_id; |
| 95 | +} |
| 96 | + |
| 97 | +std::optional<int64_t> Snapshot::AddedRows() const { |
| 98 | + auto it = summary.find("added-rows"); |
| 99 | + if (it == summary.end()) { |
| 100 | + return std::nullopt; |
| 101 | + } |
| 102 | + |
| 103 | + int64_t added_rows = 0; |
| 104 | + const std::string& added_rows_str = it->second; |
| 105 | + auto [_, ec] = std::from_chars( |
| 106 | + added_rows_str.data(), added_rows_str.data() + added_rows_str.size(), added_rows); |
| 107 | + if (ec != std::errc()) { |
| 108 | + return std::nullopt; |
| 109 | + } |
| 110 | + return added_rows; |
| 111 | +} |
| 112 | + |
78 | 113 | bool Snapshot::Equals(const Snapshot& other) const { |
79 | 114 | if (this == &other) { |
80 | 115 | return true; |
@@ -141,4 +176,103 @@ Result<std::span<ManifestFile>> CachedSnapshot::DeleteManifests( |
141 | 176 | return std::span<ManifestFile>(cache.first.data() + delete_start, delete_count); |
142 | 177 | } |
143 | 178 |
|
| 179 | +// SnapshotRef::Builder implementation |
| 180 | + |
| 181 | +SnapshotRef::Builder::Builder(SnapshotRefType type, int64_t snapshot_id) |
| 182 | + : type_(type), snapshot_id_(snapshot_id) {} |
| 183 | + |
| 184 | +SnapshotRef::Builder SnapshotRef::Builder::TagBuilder(int64_t snapshot_id) { |
| 185 | + return Builder(SnapshotRefType::kTag, snapshot_id); |
| 186 | +} |
| 187 | + |
| 188 | +SnapshotRef::Builder SnapshotRef::Builder::BranchBuilder(int64_t snapshot_id) { |
| 189 | + return Builder(SnapshotRefType::kBranch, snapshot_id); |
| 190 | +} |
| 191 | + |
| 192 | +SnapshotRef::Builder SnapshotRef::Builder::BuilderFor(int64_t snapshot_id, |
| 193 | + SnapshotRefType type) { |
| 194 | + return Builder(type, snapshot_id); |
| 195 | +} |
| 196 | + |
| 197 | +SnapshotRef::Builder SnapshotRef::Builder::BuilderFrom(const SnapshotRef& ref) { |
| 198 | + Builder builder(ref.type(), ref.snapshot_id); |
| 199 | + if (ref.type() == SnapshotRefType::kBranch) { |
| 200 | + const auto& branch = std::get<SnapshotRef::Branch>(ref.retention); |
| 201 | + builder.min_snapshots_to_keep_ = branch.min_snapshots_to_keep; |
| 202 | + builder.max_snapshot_age_ms_ = branch.max_snapshot_age_ms; |
| 203 | + builder.max_ref_age_ms_ = branch.max_ref_age_ms; |
| 204 | + } else { |
| 205 | + const auto& tag = std::get<SnapshotRef::Tag>(ref.retention); |
| 206 | + builder.max_ref_age_ms_ = tag.max_ref_age_ms; |
| 207 | + } |
| 208 | + return builder; |
| 209 | +} |
| 210 | + |
| 211 | +SnapshotRef::Builder SnapshotRef::Builder::BuilderFrom(const SnapshotRef& ref, |
| 212 | + int64_t snapshot_id) { |
| 213 | + Builder builder(ref.type(), snapshot_id); |
| 214 | + if (ref.type() == SnapshotRefType::kBranch) { |
| 215 | + const auto& branch = std::get<SnapshotRef::Branch>(ref.retention); |
| 216 | + builder.min_snapshots_to_keep_ = branch.min_snapshots_to_keep; |
| 217 | + builder.max_snapshot_age_ms_ = branch.max_snapshot_age_ms; |
| 218 | + builder.max_ref_age_ms_ = branch.max_ref_age_ms; |
| 219 | + } else { |
| 220 | + const auto& tag = std::get<SnapshotRef::Tag>(ref.retention); |
| 221 | + builder.max_ref_age_ms_ = tag.max_ref_age_ms; |
| 222 | + } |
| 223 | + return builder; |
| 224 | +} |
| 225 | + |
| 226 | +SnapshotRef::Builder& SnapshotRef::Builder::MinSnapshotsToKeep( |
| 227 | + std::optional<int32_t> value) { |
| 228 | + if (type_ == SnapshotRefType::kTag && value.has_value()) { |
| 229 | + return AddError(ErrorKind::kInvalidArgument, |
| 230 | + "Tags do not support setting minSnapshotsToKeep"); |
| 231 | + } |
| 232 | + if (value.has_value() && value.value() <= 0) { |
| 233 | + return AddError(ErrorKind::kInvalidArgument, |
| 234 | + "Min snapshots to keep must be greater than 0"); |
| 235 | + } |
| 236 | + min_snapshots_to_keep_ = value; |
| 237 | + return *this; |
| 238 | +} |
| 239 | + |
| 240 | +SnapshotRef::Builder& SnapshotRef::Builder::MaxSnapshotAgeMs( |
| 241 | + std::optional<int64_t> value) { |
| 242 | + if (type_ == SnapshotRefType::kTag && value.has_value()) { |
| 243 | + return AddError(ErrorKind::kInvalidArgument, |
| 244 | + "Tags do not support setting maxSnapshotAgeMs"); |
| 245 | + } |
| 246 | + if (value.has_value() && value.value() <= 0) { |
| 247 | + return AddError(ErrorKind::kInvalidArgument, |
| 248 | + "Max snapshot age must be greater than 0 ms"); |
| 249 | + } |
| 250 | + max_snapshot_age_ms_ = value; |
| 251 | + return *this; |
| 252 | +} |
| 253 | + |
| 254 | +SnapshotRef::Builder& SnapshotRef::Builder::MaxRefAgeMs(std::optional<int64_t> value) { |
| 255 | + if (value.has_value() && value.value() <= 0) { |
| 256 | + return AddError(ErrorKind::kInvalidArgument, |
| 257 | + "Max reference age must be greater than 0"); |
| 258 | + } |
| 259 | + max_ref_age_ms_ = value; |
| 260 | + return *this; |
| 261 | +} |
| 262 | + |
| 263 | +Result<SnapshotRef> SnapshotRef::Builder::Build() const { |
| 264 | + ICEBERG_RETURN_UNEXPECTED(CheckErrors()); |
| 265 | + |
| 266 | + if (type_ == SnapshotRefType::kBranch) { |
| 267 | + return SnapshotRef{ |
| 268 | + .snapshot_id = snapshot_id_, |
| 269 | + .retention = SnapshotRef::Branch{.min_snapshots_to_keep = min_snapshots_to_keep_, |
| 270 | + .max_snapshot_age_ms = max_snapshot_age_ms_, |
| 271 | + .max_ref_age_ms = max_ref_age_ms_}}; |
| 272 | + } else { |
| 273 | + return SnapshotRef{.snapshot_id = snapshot_id_, |
| 274 | + .retention = SnapshotRef::Tag{.max_ref_age_ms = max_ref_age_ms_}}; |
| 275 | + } |
| 276 | +} |
| 277 | + |
144 | 278 | } // namespace iceberg |
0 commit comments