Skip to content

Commit d27c8f4

Browse files
committed
1
1 parent b1901e7 commit d27c8f4

File tree

6 files changed

+480
-76
lines changed

6 files changed

+480
-76
lines changed

src/iceberg/snapshot.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ ICEBERG_EXPORT constexpr Result<SnapshotRefType> SnapshotRefTypeFromString(
6262

6363
/// \brief A reference to a snapshot, either a branch or a tag.
6464
struct ICEBERG_EXPORT SnapshotRef {
65+
static constexpr std::string_view kMainBranch = "main";
66+
6567
struct ICEBERG_EXPORT Branch {
6668
/// A positive number for the minimum number of snapshots to keep in a branch while
6769
/// expiring snapshots. Defaults to table property

src/iceberg/table_requirements.cc

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include <memory>
2323

24+
#include "iceberg/snapshot.h"
2425
#include "iceberg/table_metadata.h"
2526
#include "iceberg/table_requirement.h"
2627
#include "iceberg/table_update.h"
@@ -36,12 +37,73 @@ Result<std::vector<std::unique_ptr<TableRequirement>>> TableUpdateContext::Build
3637
return std::move(requirements_);
3738
}
3839

40+
void TableUpdateContext::RequireLastAssignedFieldIdUnchanged() {
41+
if (!added_last_assigned_field_id_) {
42+
if (base_ != nullptr) {
43+
AddRequirement(
44+
std::make_unique<table::AssertLastAssignedFieldId>(base_->last_column_id));
45+
}
46+
added_last_assigned_field_id_ = true;
47+
}
48+
}
49+
50+
void TableUpdateContext::RequireCurrentSchemaIdUnchanged() {
51+
if (!added_current_schema_id_) {
52+
if (base_ != nullptr && !is_replace_) {
53+
AddRequirement(std::make_unique<table::AssertCurrentSchemaID>(
54+
base_->current_schema_id.value()));
55+
}
56+
added_current_schema_id_ = true;
57+
}
58+
}
59+
60+
void TableUpdateContext::RequireLastAssignedPartitionIdUnchanged() {
61+
if (!added_last_assigned_partition_id_) {
62+
if (base_ != nullptr) {
63+
AddRequirement(std::make_unique<table::AssertLastAssignedPartitionId>(
64+
base_->last_partition_id));
65+
}
66+
added_last_assigned_partition_id_ = true;
67+
}
68+
}
69+
70+
void TableUpdateContext::RequireDefaultSpecIdUnchanged() {
71+
if (!added_default_spec_id_) {
72+
if (base_ != nullptr && !is_replace_) {
73+
AddRequirement(
74+
std::make_unique<table::AssertDefaultSpecID>(base_->default_spec_id));
75+
}
76+
added_default_spec_id_ = true;
77+
}
78+
}
79+
80+
void TableUpdateContext::RequireDefaultSortOrderIdUnchanged() {
81+
if (!added_default_sort_order_id_) {
82+
if (base_ != nullptr && !is_replace_) {
83+
AddRequirement(std::make_unique<table::AssertDefaultSortOrderID>(
84+
base_->default_sort_order_id));
85+
}
86+
added_default_sort_order_id_ = true;
87+
}
88+
}
89+
90+
void TableUpdateContext::RequireNoBranchesChanged() {
91+
if (base_ != nullptr && !is_replace_) {
92+
for (const auto& [name, ref] : base_->refs) {
93+
if (ref->type() == SnapshotRefType::kBranch && name != SnapshotRef::kMainBranch) {
94+
AddRequirement(
95+
std::make_unique<table::AssertRefSnapshotID>(name, ref->snapshot_id));
96+
}
97+
}
98+
}
99+
}
100+
39101
Result<std::vector<std::unique_ptr<TableRequirement>>> TableRequirements::ForCreateTable(
40102
const std::vector<std::unique_ptr<TableUpdate>>& table_updates) {
41103
TableUpdateContext context(nullptr, false);
42104
context.AddRequirement(std::make_unique<table::AssertDoesNotExist>());
43105
for (const auto& update : table_updates) {
44-
ICEBERG_RETURN_UNEXPECTED(update->GenerateRequirements(context));
106+
update->GenerateRequirements(context);
45107
}
46108
return context.Build();
47109
}
@@ -52,7 +114,7 @@ Result<std::vector<std::unique_ptr<TableRequirement>>> TableRequirements::ForRep
52114
TableUpdateContext context(&base, true);
53115
context.AddRequirement(std::make_unique<table::AssertUUID>(base.table_uuid));
54116
for (const auto& update : table_updates) {
55-
ICEBERG_RETURN_UNEXPECTED(update->GenerateRequirements(context));
117+
update->GenerateRequirements(context);
56118
}
57119
return context.Build();
58120
}
@@ -63,7 +125,7 @@ Result<std::vector<std::unique_ptr<TableRequirement>>> TableRequirements::ForUpd
63125
TableUpdateContext context(&base, false);
64126
context.AddRequirement(std::make_unique<table::AssertUUID>(base.table_uuid));
65127
for (const auto& update : table_updates) {
66-
ICEBERG_RETURN_UNEXPECTED(update->GenerateRequirements(context));
128+
update->GenerateRequirements(context);
67129
}
68130
return context.Build();
69131
}

src/iceberg/table_requirements.h

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -68,27 +68,19 @@ class ICEBERG_EXPORT TableUpdateContext {
6868
/// \brief Build and return the list of requirements
6969
Result<std::vector<std::unique_ptr<TableRequirement>>> Build();
7070

71-
// Getters for deduplication flags
72-
bool added_last_assigned_field_id() const { return added_last_assigned_field_id_; }
73-
bool added_current_schema_id() const { return added_current_schema_id_; }
74-
bool added_last_assigned_partition_id() const {
75-
return added_last_assigned_partition_id_;
76-
}
77-
bool added_default_spec_id() const { return added_default_spec_id_; }
78-
bool added_default_sort_order_id() const { return added_default_sort_order_id_; }
79-
80-
// Setters for deduplication flags
81-
void set_added_last_assigned_field_id(bool value) {
82-
added_last_assigned_field_id_ = value;
83-
}
84-
void set_added_current_schema_id(bool value) { added_current_schema_id_ = value; }
85-
void set_added_last_assigned_partition_id(bool value) {
86-
added_last_assigned_partition_id_ = value;
87-
}
88-
void set_added_default_spec_id(bool value) { added_default_spec_id_ = value; }
89-
void set_added_default_sort_order_id(bool value) {
90-
added_default_sort_order_id_ = value;
91-
}
71+
// Helper methods to deduplicate requirements to add.
72+
/// \brief Require that the last assigned field ID remains unchanged
73+
void RequireLastAssignedFieldIdUnchanged();
74+
/// \brief Require that the current schema ID remains unchanged
75+
void RequireCurrentSchemaIdUnchanged();
76+
/// \brief Require that the last assigned partition ID remains unchanged
77+
void RequireLastAssignedPartitionIdUnchanged();
78+
/// \brief Require that the default spec ID remains unchanged
79+
void RequireDefaultSpecIdUnchanged();
80+
/// \brief Require that the default sort order ID remains unchanged
81+
void RequireDefaultSortOrderIdUnchanged();
82+
/// \brief Require that no branches have been changed
83+
void RequireNoBranchesChanged();
9284

9385
private:
9486
const TableMetadata* base_;

src/iceberg/table_update.cc

Lines changed: 37 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121

2222
#include "iceberg/exception.h"
2323
#include "iceberg/table_metadata.h"
24-
#include "iceberg/table_requirement.h"
2524
#include "iceberg/table_requirements.h"
2625

2726
namespace iceberg::table {
@@ -32,9 +31,8 @@ void AssignUUID::ApplyTo(TableMetadataBuilder& builder) const {
3231
builder.AssignUUID(uuid_);
3332
}
3433

35-
Status AssignUUID::GenerateRequirements(TableUpdateContext& context) const {
34+
void AssignUUID::GenerateRequirements(TableUpdateContext& context) const {
3635
// AssignUUID does not generate additional requirements.
37-
return {};
3836
}
3937

4038
// UpgradeFormatVersion
@@ -43,8 +41,8 @@ void UpgradeFormatVersion::ApplyTo(TableMetadataBuilder& builder) const {
4341
throw IcebergError(std::format("{} not implemented", __FUNCTION__));
4442
}
4543

46-
Status UpgradeFormatVersion::GenerateRequirements(TableUpdateContext& context) const {
47-
return NotImplemented("UpgradeFormatVersion::GenerateRequirements not implemented");
44+
void UpgradeFormatVersion::GenerateRequirements(TableUpdateContext& context) const {
45+
// UpgradeFormatVersion doesn't generate any requirements
4846
}
4947

5048
// AddSchema
@@ -53,8 +51,8 @@ void AddSchema::ApplyTo(TableMetadataBuilder& builder) const {
5351
throw IcebergError(std::format("{} not implemented", __FUNCTION__));
5452
}
5553

56-
Status AddSchema::GenerateRequirements(TableUpdateContext& context) const {
57-
return NotImplemented("AddTableSchema::GenerateRequirements not implemented");
54+
void AddSchema::GenerateRequirements(TableUpdateContext& context) const {
55+
context.RequireLastAssignedFieldIdUnchanged();
5856
}
5957

6058
// SetCurrentSchema
@@ -63,8 +61,8 @@ void SetCurrentSchema::ApplyTo(TableMetadataBuilder& builder) const {
6361
throw IcebergError(std::format("{} not implemented", __FUNCTION__));
6462
}
6563

66-
Status SetCurrentSchema::GenerateRequirements(TableUpdateContext& context) const {
67-
return NotImplemented("SetCurrentTableSchema::GenerateRequirements not implemented");
64+
void SetCurrentSchema::GenerateRequirements(TableUpdateContext& context) const {
65+
context.RequireCurrentSchemaIdUnchanged();
6866
}
6967

7068
// AddPartitionSpec
@@ -73,8 +71,8 @@ void AddPartitionSpec::ApplyTo(TableMetadataBuilder& builder) const {
7371
throw IcebergError(std::format("{} not implemented", __FUNCTION__));
7472
}
7573

76-
Status AddPartitionSpec::GenerateRequirements(TableUpdateContext& context) const {
77-
return NotImplemented("AddTablePartitionSpec::GenerateRequirements not implemented");
74+
void AddPartitionSpec::GenerateRequirements(TableUpdateContext& context) const {
75+
context.RequireLastAssignedPartitionIdUnchanged();
7876
}
7977

8078
// SetDefaultPartitionSpec
@@ -83,9 +81,8 @@ void SetDefaultPartitionSpec::ApplyTo(TableMetadataBuilder& builder) const {
8381
throw IcebergError(std::format("{} not implemented", __FUNCTION__));
8482
}
8583

86-
Status SetDefaultPartitionSpec::GenerateRequirements(TableUpdateContext& context) const {
87-
return NotImplemented(
88-
"SetDefaultTablePartitionSpec::GenerateRequirements not implemented");
84+
void SetDefaultPartitionSpec::GenerateRequirements(TableUpdateContext& context) const {
85+
context.RequireDefaultSpecIdUnchanged();
8986
}
9087

9188
// RemovePartitionSpecs
@@ -94,9 +91,9 @@ void RemovePartitionSpecs::ApplyTo(TableMetadataBuilder& builder) const {
9491
throw IcebergError(std::format("{} not implemented", __FUNCTION__));
9592
}
9693

97-
Status RemovePartitionSpecs::GenerateRequirements(TableUpdateContext& context) const {
98-
return NotImplemented(
99-
"RemoveTablePartitionSpecs::GenerateRequirements not implemented");
94+
void RemovePartitionSpecs::GenerateRequirements(TableUpdateContext& context) const {
95+
context.RequireDefaultSpecIdUnchanged();
96+
context.RequireNoBranchesChanged();
10097
}
10198

10299
// RemoveSchemas
@@ -105,28 +102,29 @@ void RemoveSchemas::ApplyTo(TableMetadataBuilder& builder) const {
105102
throw IcebergError(std::format("{} not implemented", __FUNCTION__));
106103
}
107104

108-
Status RemoveSchemas::GenerateRequirements(TableUpdateContext& context) const {
109-
return NotImplemented("RemoveTableSchemas::GenerateRequirements not implemented");
105+
void RemoveSchemas::GenerateRequirements(TableUpdateContext& context) const {
106+
context.RequireCurrentSchemaIdUnchanged();
107+
context.RequireNoBranchesChanged();
110108
}
111109

112110
// AddSortOrder
113111

114112
void AddSortOrder::ApplyTo(TableMetadataBuilder& builder) const {
115-
throw IcebergError(std::format("{} not implemented", __FUNCTION__));
113+
builder.AddSortOrder(sort_order_);
116114
}
117115

118-
Status AddSortOrder::GenerateRequirements(TableUpdateContext& context) const {
119-
return NotImplemented("AddTableSortOrder::GenerateRequirements not implemented");
116+
void AddSortOrder::GenerateRequirements(TableUpdateContext& context) const {
117+
// AddSortOrder doesn't generate any requirements
120118
}
121119

122120
// SetDefaultSortOrder
123121

124122
void SetDefaultSortOrder::ApplyTo(TableMetadataBuilder& builder) const {
125-
throw IcebergError(std::format("{} not implemented", __FUNCTION__));
123+
builder.SetDefaultSortOrder(sort_order_id_);
126124
}
127125

128-
Status SetDefaultSortOrder::GenerateRequirements(TableUpdateContext& context) const {
129-
return NotImplemented("SetDefaultTableSortOrder::GenerateRequirements not implemented");
126+
void SetDefaultSortOrder::GenerateRequirements(TableUpdateContext& context) const {
127+
context.RequireDefaultSortOrderIdUnchanged();
130128
}
131129

132130
// AddSnapshot
@@ -135,16 +133,16 @@ void AddSnapshot::ApplyTo(TableMetadataBuilder& builder) const {
135133
throw IcebergError(std::format("{} not implemented", __FUNCTION__));
136134
}
137135

138-
Status AddSnapshot::GenerateRequirements(TableUpdateContext& context) const {
139-
return NotImplemented("AddTableSnapshot::GenerateRequirements not implemented");
136+
void AddSnapshot::GenerateRequirements(TableUpdateContext& context) const {
137+
// AddSnapshot doesn't generate any requirements
140138
}
141139

142140
// RemoveSnapshots
143141

144142
void RemoveSnapshots::ApplyTo(TableMetadataBuilder& builder) const {}
145143

146-
Status RemoveSnapshots::GenerateRequirements(TableUpdateContext& context) const {
147-
return NotImplemented("RemoveTableSnapshots::GenerateRequirements not implemented");
144+
void RemoveSnapshots::GenerateRequirements(TableUpdateContext& context) const {
145+
throw IcebergError("RemoveTableSnapshots::GenerateRequirements not implemented");
148146
}
149147

150148
// RemoveSnapshotRef
@@ -153,8 +151,8 @@ void RemoveSnapshotRef::ApplyTo(TableMetadataBuilder& builder) const {
153151
throw IcebergError(std::format("{} not implemented", __FUNCTION__));
154152
}
155153

156-
Status RemoveSnapshotRef::GenerateRequirements(TableUpdateContext& context) const {
157-
return NotImplemented("RemoveTableSnapshotRef::GenerateRequirements not implemented");
154+
void RemoveSnapshotRef::GenerateRequirements(TableUpdateContext& context) const {
155+
// RemoveSnapshotRef doesn't generate any requirements
158156
}
159157

160158
// SetSnapshotRef
@@ -163,8 +161,8 @@ void SetSnapshotRef::ApplyTo(TableMetadataBuilder& builder) const {
163161
throw IcebergError(std::format("{} not implemented", __FUNCTION__));
164162
}
165163

166-
Status SetSnapshotRef::GenerateRequirements(TableUpdateContext& context) const {
167-
return NotImplemented("SetTableSnapshotRef::GenerateRequirements not implemented");
164+
void SetSnapshotRef::GenerateRequirements(TableUpdateContext& context) const {
165+
throw NotImplemented("SetTableSnapshotRef::GenerateRequirements not implemented");
168166
}
169167

170168
// SetProperties
@@ -173,9 +171,8 @@ void SetProperties::ApplyTo(TableMetadataBuilder& builder) const {
173171
builder.SetProperties(updated_);
174172
}
175173

176-
Status SetProperties::GenerateRequirements(TableUpdateContext& context) const {
177-
// No requirements
178-
return {};
174+
void SetProperties::GenerateRequirements(TableUpdateContext& context) const {
175+
// SetProperties doesn't generate any requirements
179176
}
180177

181178
// RemoveProperties
@@ -184,9 +181,8 @@ void RemoveProperties::ApplyTo(TableMetadataBuilder& builder) const {
184181
builder.RemoveProperties(removed_);
185182
}
186183

187-
Status RemoveProperties::GenerateRequirements(TableUpdateContext& context) const {
188-
// No requirements
189-
return {};
184+
void RemoveProperties::GenerateRequirements(TableUpdateContext& context) const {
185+
// RemoveProperties doesn't generate any requirements
190186
}
191187

192188
// SetLocation
@@ -195,8 +191,8 @@ void SetLocation::ApplyTo(TableMetadataBuilder& builder) const {
195191
throw IcebergError(std::format("{} not implemented", __FUNCTION__));
196192
}
197193

198-
Status SetLocation::GenerateRequirements(TableUpdateContext& context) const {
199-
return NotImplemented("SetTableLocation::GenerateRequirements not implemented");
194+
void SetLocation::GenerateRequirements(TableUpdateContext& context) const {
195+
// SetLocation doesn't generate any requirements
200196
}
201197

202198
} // namespace iceberg::table

0 commit comments

Comments
 (0)