Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/iceberg/catalog/memory/in_memory_catalog.cc
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,11 @@ Result<std::shared_ptr<Table>> InMemoryCatalog::CreateTable(
const std::string& location,
const std::unordered_map<std::string, std::string>& properties) {
std::unique_lock lock(mutex_);
ICEBERG_ASSIGN_OR_RAISE(auto namespace_exists,
root_namespace_->NamespaceExists(identifier.ns));
if (!namespace_exists) {
return NoSuchNamespace("Table namespace does not exist: {}", identifier.ns);
}
if (root_namespace_->TableExists(identifier).value_or(false)) {
return AlreadyExists("Table already exists: {}", identifier);
}
Expand Down Expand Up @@ -609,7 +614,9 @@ Result<std::shared_ptr<Table>> InMemoryCatalog::RegisterTable(
TableMetadataUtil::Read(*file_io_, metadata_file_location));

std::unique_lock lock(mutex_);
if (!root_namespace_->NamespaceExists(identifier.ns)) {
ICEBERG_ASSIGN_OR_RAISE(auto namespace_exists,
root_namespace_->NamespaceExists(identifier.ns));
if (!namespace_exists) {
return NoSuchNamespace("Table namespace does not exist: {}", identifier.ns);
}
if (!root_namespace_->RegisterTable(identifier, metadata_file_location)) {
Expand Down
47 changes: 47 additions & 0 deletions src/iceberg/test/in_memory_catalog_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,53 @@ TEST_F(InMemoryCatalogTest, RegisterTable) {
ASSERT_EQ(table.value()->location(), "s3://bucket/test/location");
}

TEST_F(InMemoryCatalogTest, CreateTableNonexistentNamespace) {
TableIdentifier table_ident{.ns = Namespace{.levels = {"missing"}}, .name = "t1"};
auto schema = std::make_shared<Schema>(
std::vector<SchemaField>{SchemaField::MakeRequired(1, "id", int64())},
/*schema_id=*/1);
auto spec = PartitionSpec::Unpartitioned();
auto sort_order = SortOrder::Unsorted();

// Use an explicit location whose metadata directory already exists (the local
// FileIO does not create parent dirs). A write-before-validate bug would land a
// detectable orphan there. GenerateTestTableLocation is unique per test and
// auto-cleaned via created_temp_paths_.
auto table_location = GenerateTestTableLocation(table_ident.name);

auto table =
catalog_->CreateTable(table_ident, schema, spec, sort_order, table_location, {});
EXPECT_THAT(table, IsError(ErrorKind::kNoSuchNamespace));

// The namespace check must run before any metadata file is written, so a
// failed create must leave no orphaned metadata file behind.
std::error_code ec;
size_t metadata_files = 0;
for (auto it = std::filesystem::recursive_directory_iterator(table_location, ec);
it != std::filesystem::recursive_directory_iterator(); it.increment(ec)) {
if (it->path().extension() == ".json") {
++metadata_files;
}
}
EXPECT_EQ(metadata_files, 0);
}

TEST_F(InMemoryCatalogTest, RegisterTableNonexistentNamespace) {
TableIdentifier table_ident{.ns = Namespace{.levels = {"missing"}}, .name = "t1"};

ICEBERG_UNWRAP_OR_FAIL(auto metadata,
ReadTableMetadataFromResource("TableMetadataV2Valid.json"));
auto table_location = GenerateTestTableLocation(table_ident.name);
auto metadata_location = std::format("{}v1.metadata.json", table_location);
ASSERT_THAT(TableMetadataUtil::Write(*file_io_, metadata_location, *metadata), IsOk());
Comment on lines +195 to +199

// Registering into a nonexistent namespace reports NoSuchNamespace. The dead
// if (!NamespaceExists(...)) check tested the Result<bool>'s has_value() rather
// than the contained bool, so this previously fell through to kUnknownError.
auto table = catalog_->RegisterTable(table_ident, metadata_location);
EXPECT_THAT(table, IsError(ErrorKind::kNoSuchNamespace));
}

TEST_F(InMemoryCatalogTest, RefreshTable) {
TableIdentifier table_ident{.ns = {}, .name = "t1"};
auto schema = std::make_shared<Schema>(
Expand Down
Loading