Skip to content
Open
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
24 changes: 22 additions & 2 deletions src/Databases/Iceberg/RestCatalog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,24 @@ std::string correctAPIURI(const std::string & uri)
return std::filesystem::path(uri) / "v1";
}

/// Encode namespace for use in URL path.
/// According to the Iceberg REST Catalog spec, multi-level namespaces
/// should be joined with the unit separator character (0x1F) which is
/// URL-encoded as %1F.
/// https://github.com/apache/iceberg/blob/main/open-api/rest-catalog-open-api.yaml
String encodeNamespaceForURI(const String & namespace_name)
{
String encoded;
for (const auto & ch : namespace_name)
{
if (ch == '.')
encoded += "%1F";
else
encoded.push_back(ch);
}
return encoded;
}

}

std::string RestCatalog::Config::toString() const
Expand Down Expand Up @@ -468,7 +486,8 @@ RestCatalog::Namespaces RestCatalog::parseNamespaces(DB::ReadBuffer & buf, const

DB::Names RestCatalog::getTables(const std::string & base_namespace, size_t limit) const
{
const std::string endpoint = std::filesystem::path(NAMESPACES_ENDPOINT) / base_namespace / "tables";
auto encoded_namespace = encodeNamespaceForURI(base_namespace);
const std::string endpoint = std::filesystem::path(NAMESPACES_ENDPOINT) / encoded_namespace / "tables";

auto buf = createReadBuffer(config.prefix / endpoint);
return parseTables(*buf, base_namespace, limit);
Expand Down Expand Up @@ -562,7 +581,8 @@ bool RestCatalog::getTableMetadataImpl(
headers.emplace_back("X-Iceberg-Access-Delegation", "vended-credentials");
}

const std::string endpoint = std::filesystem::path(NAMESPACES_ENDPOINT) / namespace_name / "tables" / table_name;
auto encoded_namespace = encodeNamespaceForURI(namespace_name);
const std::string endpoint = std::filesystem::path(NAMESPACES_ENDPOINT) / encoded_namespace / "tables" / table_name;
auto buf = createReadBuffer(config.prefix / endpoint, /* params */{}, headers);

if (buf->eof())
Expand Down