Skip to content

Commit fc2cde0

Browse files
authored
feat: implement InMemoryCatalog's UpdateTable (#386)
1 parent 769e2ac commit fc2cde0

18 files changed

+636
-87
lines changed

src/iceberg/catalog/memory/in_memory_catalog.cc

Lines changed: 54 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@
2323
#include <iterator>
2424

2525
#include "iceberg/table.h"
26+
#include "iceberg/table_identifier.h"
2627
#include "iceberg/table_metadata.h"
28+
#include "iceberg/table_requirement.h"
29+
#include "iceberg/table_update.h"
2730
#include "iceberg/util/macros.h"
2831

2932
namespace iceberg {
@@ -120,6 +123,13 @@ class ICEBERG_EXPORT InMemoryNamespace {
120123
/// \return The metadata location if the table exists; error otherwise.
121124
Result<std::string> GetTableMetadataLocation(const TableIdentifier& table_ident) const;
122125

126+
/// \brief Updates the metadata location for the specified table.
127+
///
128+
/// \param table_ident The identifier of the table.
129+
/// \param metadata_location The new metadata location.
130+
Status UpdateTableMetadataLocation(const TableIdentifier& table_ident,
131+
const std::string& metadata_location);
132+
123133
/// \brief Internal utility for retrieving a namespace node pointer from the tree.
124134
///
125135
/// \tparam NamespacePtr The type of the namespace node pointer.
@@ -278,7 +288,7 @@ Result<std::vector<std::string>> InMemoryNamespace::ListTables(
278288
return table_names;
279289
}
280290

281-
Status InMemoryNamespace::RegisterTable(TableIdentifier const& table_ident,
291+
Status InMemoryNamespace::RegisterTable(const TableIdentifier& table_ident,
282292
const std::string& metadata_location) {
283293
const auto ns = GetNamespace(this, table_ident.ns);
284294
ICEBERG_RETURN_UNEXPECTED(ns);
@@ -289,21 +299,21 @@ Status InMemoryNamespace::RegisterTable(TableIdentifier const& table_ident,
289299
return {};
290300
}
291301

292-
Status InMemoryNamespace::UnregisterTable(TableIdentifier const& table_ident) {
302+
Status InMemoryNamespace::UnregisterTable(const TableIdentifier& table_ident) {
293303
const auto ns = GetNamespace(this, table_ident.ns);
294304
ICEBERG_RETURN_UNEXPECTED(ns);
295305
ns.value()->table_metadata_locations_.erase(table_ident.name);
296306
return {};
297307
}
298308

299-
Result<bool> InMemoryNamespace::TableExists(TableIdentifier const& table_ident) const {
309+
Result<bool> InMemoryNamespace::TableExists(const TableIdentifier& table_ident) const {
300310
const auto ns = GetNamespace(this, table_ident.ns);
301311
ICEBERG_RETURN_UNEXPECTED(ns);
302312
return ns.value()->table_metadata_locations_.contains(table_ident.name);
303313
}
304314

305315
Result<std::string> InMemoryNamespace::GetTableMetadataLocation(
306-
TableIdentifier const& table_ident) const {
316+
const TableIdentifier& table_ident) const {
307317
const auto ns = GetNamespace(this, table_ident.ns);
308318
ICEBERG_RETURN_UNEXPECTED(ns);
309319
const auto it = ns.value()->table_metadata_locations_.find(table_ident.name);
@@ -313,17 +323,24 @@ Result<std::string> InMemoryNamespace::GetTableMetadataLocation(
313323
return it->second;
314324
}
315325

326+
Status InMemoryNamespace::UpdateTableMetadataLocation(
327+
const TableIdentifier& table_ident, const std::string& metadata_location) {
328+
ICEBERG_ASSIGN_OR_RAISE(auto ns, GetNamespace(this, table_ident.ns));
329+
ns->table_metadata_locations_[table_ident.name] = metadata_location;
330+
return {};
331+
}
332+
316333
std::shared_ptr<InMemoryCatalog> InMemoryCatalog::Make(
317-
std::string const& name, std::shared_ptr<FileIO> const& file_io,
318-
std::string const& warehouse_location,
319-
std::unordered_map<std::string, std::string> const& properties) {
334+
const std::string& name, const std::shared_ptr<FileIO>& file_io,
335+
const std::string& warehouse_location,
336+
const std::unordered_map<std::string, std::string>& properties) {
320337
return std::make_shared<InMemoryCatalog>(name, file_io, warehouse_location, properties);
321338
}
322339

323340
InMemoryCatalog::InMemoryCatalog(
324-
std::string const& name, std::shared_ptr<FileIO> const& file_io,
325-
std::string const& warehouse_location,
326-
std::unordered_map<std::string, std::string> const& properties)
341+
const std::string& name, const std::shared_ptr<FileIO>& file_io,
342+
const std::string& warehouse_location,
343+
const std::unordered_map<std::string, std::string>& properties)
327344
: catalog_name_(std::move(name)),
328345
properties_(std::move(properties)),
329346
file_io_(std::move(file_io)),
@@ -395,7 +412,31 @@ Result<std::unique_ptr<Table>> InMemoryCatalog::UpdateTable(
395412
const std::vector<std::unique_ptr<TableRequirement>>& requirements,
396413
const std::vector<std::unique_ptr<TableUpdate>>& updates) {
397414
std::unique_lock lock(mutex_);
398-
return NotImplemented("update table");
415+
ICEBERG_ASSIGN_OR_RAISE(auto base_metadata_location,
416+
root_namespace_->GetTableMetadataLocation(identifier));
417+
418+
ICEBERG_ASSIGN_OR_RAISE(auto base,
419+
TableMetadataUtil::Read(*file_io_, base_metadata_location));
420+
421+
for (const auto& requirement : requirements) {
422+
ICEBERG_RETURN_UNEXPECTED(requirement->Validate(base.get()));
423+
}
424+
425+
auto builder = TableMetadataBuilder::BuildFrom(base.get());
426+
for (const auto& update : updates) {
427+
update->ApplyTo(*builder);
428+
}
429+
ICEBERG_ASSIGN_OR_RAISE(auto updated, builder->Build());
430+
ICEBERG_ASSIGN_OR_RAISE(
431+
auto new_metadata_location,
432+
TableMetadataUtil::Write(*file_io_, base.get(), base_metadata_location, *updated));
433+
ICEBERG_RETURN_UNEXPECTED(
434+
root_namespace_->UpdateTableMetadataLocation(identifier, new_metadata_location));
435+
TableMetadataUtil::DeleteRemovedMetadataFiles(*file_io_, base.get(), *updated);
436+
437+
return std::make_unique<Table>(identifier, std::move(updated),
438+
std::move(new_metadata_location), file_io_,
439+
std::static_pointer_cast<Catalog>(shared_from_this()));
399440
}
400441

401442
Result<std::shared_ptr<Transaction>> InMemoryCatalog::StageCreateTable(
@@ -438,9 +479,8 @@ Result<std::unique_ptr<Table>> InMemoryCatalog::LoadTable(
438479

439480
ICEBERG_ASSIGN_OR_RAISE(auto metadata,
440481
TableMetadataUtil::Read(*file_io_, metadata_location));
441-
442-
return std::make_unique<Table>(identifier, std::move(metadata), metadata_location,
443-
file_io_,
482+
return std::make_unique<Table>(identifier, std::move(metadata),
483+
std::move(metadata_location), file_io_,
444484
std::static_pointer_cast<Catalog>(shared_from_this()));
445485
}
446486

src/iceberg/json_internal.cc

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -797,9 +797,7 @@ nlohmann::json ToJson(const TableMetadata& table_metadata) {
797797
json[kSortOrders] = ToJsonList(table_metadata.sort_orders);
798798

799799
// write properties map
800-
if (table_metadata.properties) {
801-
json[kProperties] = table_metadata.properties->configs();
802-
}
800+
json[kProperties] = table_metadata.properties.configs();
803801

804802
if (std::ranges::find_if(table_metadata.snapshots, [&](const auto& snapshot) {
805803
return snapshot->snapshot_id == table_metadata.current_snapshot_id;

src/iceberg/table.cc

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,8 @@ Status Table::Refresh() {
5151
}
5252

5353
ICEBERG_ASSIGN_OR_RAISE(auto refreshed_table, catalog_->LoadTable(identifier_));
54-
if (metadata_location_ != refreshed_table->metadata_location_) {
54+
if (metadata_location_ != refreshed_table->metadata_file_location()) {
5555
metadata_ = std::move(refreshed_table->metadata_);
56-
metadata_location_ = std::move(refreshed_table->metadata_location_);
5756
io_ = std::move(refreshed_table->io_);
5857
metadata_cache_ = std::make_unique<TableMetadataCache>(metadata_.get());
5958
}
@@ -87,12 +86,14 @@ Table::sort_orders() const {
8786
return metadata_cache_->GetSortOrdersById();
8887
}
8988

90-
const std::shared_ptr<TableProperties>& Table::properties() const {
91-
return metadata_->properties;
92-
}
89+
const TableProperties& Table::properties() const { return metadata_->properties; }
90+
91+
const std::string& Table::metadata_file_location() const { return metadata_location_; }
9392

9493
const std::string& Table::location() const { return metadata_->location; }
9594

95+
const TimePointMs& Table::last_updated_ms() const { return metadata_->last_updated_ms; }
96+
9697
Result<std::shared_ptr<Snapshot>> Table::current_snapshot() const {
9798
return metadata_->Snapshot();
9899
}

src/iceberg/table.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "iceberg/snapshot.h"
3030
#include "iceberg/table_identifier.h"
3131
#include "iceberg/type_fwd.h"
32+
#include "iceberg/util/timepoint.h"
3233

3334
namespace iceberg {
3435

@@ -82,11 +83,19 @@ class ICEBERG_EXPORT Table {
8283
sort_orders() const;
8384

8485
/// \brief Return a map of string properties for this table
85-
const std::shared_ptr<TableProperties>& properties() const;
86+
const TableProperties& properties() const;
87+
88+
/// \brief Return the table's metadata file location
89+
const std::string& metadata_file_location() const;
8690

8791
/// \brief Return the table's base location
8892
const std::string& location() const;
8993

94+
/// \brief Get the time when this table was last updated
95+
///
96+
/// \return the time when this table was last updated
97+
const TimePointMs& last_updated_ms() const;
98+
9099
/// \brief Return the table's current snapshot, return NotFoundError if not found
91100
Result<std::shared_ptr<Snapshot>> current_snapshot() const;
92101

0 commit comments

Comments
 (0)