2626#include " iceberg/table_identifier.h"
2727#include " iceberg/table_metadata.h"
2828#include " iceberg/table_requirement.h"
29+ #include " iceberg/table_requirements.h"
2930#include " iceberg/table_update.h"
31+ #include " iceberg/transaction.h"
32+ #include " iceberg/util/checked_cast.h"
3033#include " iceberg/util/macros.h"
3134
3235namespace iceberg {
@@ -318,7 +321,7 @@ Result<std::string> InMemoryNamespace::GetTableMetadataLocation(
318321 ICEBERG_RETURN_UNEXPECTED (ns);
319322 const auto it = ns.value ()->table_metadata_locations_ .find (table_ident.name );
320323 if (it == ns.value ()->table_metadata_locations_ .end ()) {
321- return NotFound (" {} does not exist" , table_ident. name );
324+ return NotFound (" Table does not exist: {} " , table_ident);
322325 }
323326 return it->second ;
324327}
@@ -405,32 +408,68 @@ Result<std::shared_ptr<Table>> InMemoryCatalog::CreateTable(
405408 const std::string& location,
406409 const std::unordered_map<std::string, std::string>& properties) {
407410 std::unique_lock lock (mutex_);
408- return NotImplemented (" create table" );
411+ if (root_namespace_->TableExists (identifier).value_or (false )) {
412+ return AlreadyExists (" Table already exists: {}" , identifier);
413+ }
414+
415+ std::string base_location =
416+ location.empty () ? warehouse_location_ + " /" + identifier.ToString () : location;
417+
418+ ICEBERG_ASSIGN_OR_RAISE (auto table_metadata, TableMetadata::Make (*schema, *spec, *order,
419+ location, properties));
420+
421+ ICEBERG_ASSIGN_OR_RAISE (
422+ auto metadata_file_location,
423+ TableMetadataUtil::Write (*file_io_, nullptr , " " , *table_metadata));
424+ ICEBERG_RETURN_UNEXPECTED (
425+ root_namespace_->UpdateTableMetadataLocation (identifier, metadata_file_location));
426+ return Table::Make (identifier, std::move (table_metadata),
427+ std::move (metadata_file_location), file_io_, shared_from_this ());
409428}
410429
411430Result<std::shared_ptr<Table>> InMemoryCatalog::UpdateTable (
412431 const TableIdentifier& identifier,
413432 const std::vector<std::unique_ptr<TableRequirement>>& requirements,
414433 const std::vector<std::unique_ptr<TableUpdate>>& updates) {
415434 std::unique_lock lock (mutex_);
416- ICEBERG_ASSIGN_OR_RAISE (auto base_metadata_location,
417- root_namespace_->GetTableMetadataLocation (identifier));
418-
419- ICEBERG_ASSIGN_OR_RAISE (auto base,
420- TableMetadataUtil::Read (*file_io_, base_metadata_location));
435+ auto base_metadata_location = root_namespace_->GetTableMetadataLocation (identifier);
436+ std::unique_ptr<TableMetadata> base;
437+ std::unique_ptr<TableMetadataBuilder> builder;
438+ ICEBERG_ASSIGN_OR_RAISE (auto is_create, TableRequirements::IsCreate (requirements));
439+ if (is_create) {
440+ if (base_metadata_location.has_value ()) {
441+ return AlreadyExists (" Table already exists: {}" , identifier);
442+ }
443+ int8_t format_version = TableMetadata::kDefaultTableFormatVersion ;
444+ for (const auto & update : updates) {
445+ if (update->kind () == TableUpdate::Kind::kUpgradeFormatVersion ) {
446+ format_version =
447+ internal::checked_cast<const table::UpgradeFormatVersion&>(*update)
448+ .format_version ();
449+ }
450+ }
451+ builder = TableMetadataBuilder::BuildFromEmpty (format_version);
452+ } else {
453+ ICEBERG_RETURN_UNEXPECTED (base_metadata_location);
454+ ICEBERG_ASSIGN_OR_RAISE (
455+ base, TableMetadataUtil::Read (*file_io_, base_metadata_location.value ()));
456+ builder = TableMetadataBuilder::BuildFrom (base.get ());
457+ }
421458
422459 for (const auto & requirement : requirements) {
423460 ICEBERG_RETURN_UNEXPECTED (requirement->Validate (base.get ()));
424461 }
425462
426- auto builder = TableMetadataBuilder::BuildFrom (base.get ());
427463 for (const auto & update : updates) {
428464 update->ApplyTo (*builder);
429465 }
430466 ICEBERG_ASSIGN_OR_RAISE (auto updated, builder->Build ());
431467 ICEBERG_ASSIGN_OR_RAISE (
432468 auto new_metadata_location,
433- TableMetadataUtil::Write (*file_io_, base.get (), base_metadata_location, *updated));
469+ TableMetadataUtil::Write (
470+ *file_io_, base.get (),
471+ base_metadata_location.has_value () ? base_metadata_location.value () : " " ,
472+ *updated));
434473 ICEBERG_RETURN_UNEXPECTED (
435474 root_namespace_->UpdateTableMetadataLocation (identifier, new_metadata_location));
436475 TableMetadataUtil::DeleteRemovedMetadataFiles (*file_io_, base.get (), *updated);
@@ -445,7 +484,21 @@ Result<std::shared_ptr<Transaction>> InMemoryCatalog::StageCreateTable(
445484 const std::string& location,
446485 const std::unordered_map<std::string, std::string>& properties) {
447486 std::unique_lock lock (mutex_);
448- return NotImplemented (" stage create table" );
487+ if (root_namespace_->TableExists (identifier).value_or (false )) {
488+ return AlreadyExists (" Table already exists: {}" , identifier);
489+ }
490+
491+ std::string base_location =
492+ location.empty () ? warehouse_location_ + " /" + identifier.ToString () : location;
493+
494+ ICEBERG_ASSIGN_OR_RAISE (
495+ auto table_metadata,
496+ TableMetadata::Make (*schema, *spec, *order, base_location, properties));
497+ ICEBERG_ASSIGN_OR_RAISE (
498+ auto table, StagedTable::Make (identifier, std::move (table_metadata), " " , file_io_,
499+ shared_from_this ()));
500+ return Transaction::Make (std::move (table), Transaction::Kind::kCreate ,
501+ /* auto_commit */ false );
449502}
450503
451504Result<bool > InMemoryCatalog::TableExists (const TableIdentifier& identifier) const {
@@ -495,7 +548,7 @@ Result<std::shared_ptr<Table>> InMemoryCatalog::RegisterTable(
495548
496549 std::unique_lock lock (mutex_);
497550 if (!root_namespace_->NamespaceExists (identifier.ns )) {
498- return NoSuchNamespace (" table namespace does not exist. " );
551+ return NoSuchNamespace (" Table namespace does not exist: {} " , identifier. ns );
499552 }
500553 if (!root_namespace_->RegisterTable (identifier, metadata_file_location)) {
501554 return UnknownError (" The registry failed." );
0 commit comments