Skip to content

Commit fe6bd93

Browse files
committed
feat: add ManageSnapshots interface
Add the ManageSnapshots interface for managing snapshots, branches, and tags in tables. This interface extends PendingUpdate directly and provides methods for: Snapshot operations: - SetCurrentSnapshot: Roll back to specific snapshot - RollbackToTime: Roll back to snapshot before timestamp - RollbackTo: Roll back to ancestor snapshot - Cherrypick: Apply changes from orphan snapshot Branch operations: - CreateBranch: Create new branch - RemoveBranch: Remove branch - RenameBranch: Rename branch - ReplaceBranch: Replace branch pointer - FastForwardBranch: Fast-forward branch Tag operations: - CreateTag: Create new tag - RemoveTag: Remove tag - ReplaceTag: Replace tag pointer Retention policies: - SetMinSnapshotsToKeep: Set minimum snapshots to retain - SetMaxSnapshotAgeMs: Set maximum snapshot age - SetMaxRefAgeMs: Set maximum reference age The implementation includes comprehensive tests that verify behavior through the public API and follows the Java Iceberg API design.
1 parent 3855012 commit fe6bd93

File tree

4 files changed

+646
-0
lines changed

4 files changed

+646
-0
lines changed

src/iceberg/manage_snapshots.h

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
#pragma once
21+
22+
/// \file iceberg/manage_snapshots.h
23+
/// API for managing snapshots, branches, and tags in a table
24+
25+
#include <cstdint>
26+
#include <string_view>
27+
28+
#include "iceberg/iceberg_export.h"
29+
#include "iceberg/pending_update.h"
30+
#include "iceberg/type_fwd.h"
31+
32+
namespace iceberg {
33+
34+
/// \brief API for managing snapshots, branches, and tags in a table
35+
///
36+
/// ManageSnapshots provides operations for:
37+
/// - Rolling table data back to a state at an older snapshot
38+
/// - Cherry-picking orphan snapshots in audit workflows
39+
/// - Creating, updating, and managing branches and tags
40+
/// - Setting retention policies for snapshots and references
41+
///
42+
/// Behavioral notes:
43+
/// - Does NOT allow conflicting calls to SetCurrentSnapshot() and
44+
/// RollbackToTime() in the same operation
45+
/// - Commit conflicts will NOT be resolved automatically and will result in
46+
/// CommitFailed error
47+
/// - Changes are applied to current table metadata when committed
48+
///
49+
/// Example usage:
50+
/// \code
51+
/// table.ManageSnapshots()
52+
/// .CreateBranch("experiment", snapshot_id)
53+
/// .SetMinSnapshotsToKeep("experiment", 5)
54+
/// .Commit();
55+
/// \endcode
56+
class ICEBERG_EXPORT ManageSnapshots : public PendingUpdateTyped<Snapshot> {
57+
public:
58+
~ManageSnapshots() override = default;
59+
60+
// ========================================================================
61+
// SNAPSHOT ROLLBACK OPERATIONS
62+
// ========================================================================
63+
64+
/// \brief Roll table's data back to a specific snapshot
65+
///
66+
/// This will be set as the current snapshot. Unlike RollbackTo(), the
67+
/// snapshot is NOT required to be an ancestor of the current table state.
68+
///
69+
/// \param snapshot_id ID of the snapshot to roll back table data to
70+
/// \return Reference to this for method chaining
71+
virtual ManageSnapshots& SetCurrentSnapshot(int64_t snapshot_id) = 0;
72+
73+
/// \brief Roll table's data back to the last snapshot before given timestamp
74+
///
75+
/// Cannot be used in the same operation as SetCurrentSnapshot().
76+
///
77+
/// \param timestamp_millis Timestamp in milliseconds since epoch
78+
/// \return Reference to this for method chaining
79+
virtual ManageSnapshots& RollbackToTime(int64_t timestamp_millis) = 0;
80+
81+
/// \brief Rollback table's state to a specific snapshot (must be ancestor)
82+
///
83+
/// The snapshot MUST be an ancestor of the current snapshot.
84+
///
85+
/// \param snapshot_id ID of snapshot to roll back to (must be ancestor)
86+
/// \return Reference to this for method chaining
87+
virtual ManageSnapshots& RollbackTo(int64_t snapshot_id) = 0;
88+
89+
/// \brief Apply changes from a snapshot and create new current snapshot
90+
///
91+
/// Used in audit workflows where data is written to an orphan snapshot,
92+
/// audited, and then applied to the current state.
93+
///
94+
/// \param snapshot_id Snapshot ID whose changes to apply
95+
/// \return Reference to this for method chaining
96+
virtual ManageSnapshots& Cherrypick(int64_t snapshot_id) = 0;
97+
98+
// ========================================================================
99+
// BRANCH OPERATIONS
100+
// ========================================================================
101+
102+
/// \brief Create a new branch pointing to the current snapshot
103+
///
104+
/// The branch will point to the current snapshot if it exists.
105+
///
106+
/// \param name Branch name
107+
/// \return Reference to this for method chaining
108+
virtual ManageSnapshots& CreateBranch(std::string_view name) = 0;
109+
110+
/// \brief Create a new branch pointing to a specific snapshot
111+
///
112+
/// \param name Branch name
113+
/// \param snapshot_id Snapshot ID to be the branch head
114+
/// \return Reference to this for method chaining
115+
virtual ManageSnapshots& CreateBranch(std::string_view name, int64_t snapshot_id) = 0;
116+
117+
/// \brief Remove a branch by name
118+
///
119+
/// \param name Branch name to remove
120+
/// \return Reference to this for method chaining
121+
virtual ManageSnapshots& RemoveBranch(std::string_view name) = 0;
122+
123+
/// \brief Rename an existing branch
124+
///
125+
/// \param name Current branch name
126+
/// \param new_name Desired new branch name
127+
/// \return Reference to this for method chaining
128+
virtual ManageSnapshots& RenameBranch(std::string_view name,
129+
std::string_view new_name) = 0;
130+
131+
/// \brief Replace a branch to point to a specified snapshot
132+
///
133+
/// \param name Branch to replace
134+
/// \param snapshot_id New snapshot ID for the branch
135+
/// \return Reference to this for method chaining
136+
virtual ManageSnapshots& ReplaceBranch(std::string_view name, int64_t snapshot_id) = 0;
137+
138+
/// \brief Replace one branch with another branch's snapshot
139+
///
140+
/// The `to` branch remains unchanged. The `from` branch retains its
141+
/// retention properties. If `from` doesn't exist, it's created with
142+
/// default properties.
143+
///
144+
/// \param from Branch to replace
145+
/// \param to Branch to replace with
146+
/// \return Reference to this for method chaining
147+
virtual ManageSnapshots& ReplaceBranch(std::string_view from, std::string_view to) = 0;
148+
149+
/// \brief Fast-forward one branch to another if from is ancestor of to
150+
///
151+
/// Moves the `from` branch to the `to` branch's snapshot. The `to` branch
152+
/// remains unchanged. The `from` branch retains its retention properties.
153+
/// Creates `from` with default properties if it doesn't exist. Only works
154+
/// if `from` is an ancestor of `to`.
155+
///
156+
/// \param from Branch to fast-forward
157+
/// \param to Reference branch to fast-forward to
158+
/// \return Reference to this for method chaining
159+
virtual ManageSnapshots& FastForwardBranch(std::string_view from,
160+
std::string_view to) = 0;
161+
162+
// ========================================================================
163+
// TAG OPERATIONS
164+
// ========================================================================
165+
166+
/// \brief Create a new tag pointing to a snapshot
167+
///
168+
/// \param name Tag name
169+
/// \param snapshot_id Snapshot ID for the tag head
170+
/// \return Reference to this for method chaining
171+
virtual ManageSnapshots& CreateTag(std::string_view name, int64_t snapshot_id) = 0;
172+
173+
/// \brief Remove a tag by name
174+
///
175+
/// \param name Tag name to remove
176+
/// \return Reference to this for method chaining
177+
virtual ManageSnapshots& RemoveTag(std::string_view name) = 0;
178+
179+
/// \brief Replace an existing tag to point to a new snapshot
180+
///
181+
/// \param name Tag to replace
182+
/// \param snapshot_id New snapshot ID for the tag
183+
/// \return Reference to this for method chaining
184+
virtual ManageSnapshots& ReplaceTag(std::string_view name, int64_t snapshot_id) = 0;
185+
186+
// ========================================================================
187+
// RETENTION POLICY OPERATIONS
188+
// ========================================================================
189+
190+
/// \brief Update minimum number of snapshots to keep for a branch
191+
///
192+
/// \param branch_name Name of the branch
193+
/// \param min_snapshots_to_keep Minimum number of snapshots to retain
194+
/// \return Reference to this for method chaining
195+
virtual ManageSnapshots& SetMinSnapshotsToKeep(std::string_view branch_name,
196+
int min_snapshots_to_keep) = 0;
197+
198+
/// \brief Update maximum snapshot age for a branch
199+
///
200+
/// \param branch_name Name of the branch
201+
/// \param max_snapshot_age_ms Maximum snapshot age in milliseconds
202+
/// \return Reference to this for method chaining
203+
virtual ManageSnapshots& SetMaxSnapshotAgeMs(std::string_view branch_name,
204+
int64_t max_snapshot_age_ms) = 0;
205+
206+
/// \brief Update retention policy for a reference (branch or tag)
207+
///
208+
/// \param name Branch or tag name
209+
/// \param max_ref_age_ms Retention age in milliseconds of the reference
210+
/// \return Reference to this for method chaining
211+
virtual ManageSnapshots& SetMaxRefAgeMs(std::string_view name,
212+
int64_t max_ref_age_ms) = 0;
213+
214+
// Non-copyable, movable (inherited from PendingUpdate)
215+
ManageSnapshots(const ManageSnapshots&) = delete;
216+
ManageSnapshots& operator=(const ManageSnapshots&) = delete;
217+
218+
protected:
219+
ManageSnapshots() = default;
220+
};
221+
222+
} // namespace iceberg

src/iceberg/test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ add_iceberg_test(schema_test
8080
add_iceberg_test(table_test
8181
SOURCES
8282
json_internal_test.cc
83+
manage_snapshots_test.cc
8384
pending_update_test.cc
8485
schema_json_test.cc
8586
table_test.cc

0 commit comments

Comments
 (0)