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
37 changes: 27 additions & 10 deletions src/storage/src/sink/iceberg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1548,16 +1548,33 @@ fn write_data_files<'scope, H: EnvelopeHandler + 'static>(
.context("Failed to merge Materialize metadata into Iceberg schema")?,
);

// WORKAROUND: S3 Tables catalog incorrectly sets location to the metadata file path
// instead of the warehouse root. Strip off the /metadata/*.metadata.json suffix.
// No clear way to detect this properly right now, so we use heuristics.
let location = table_metadata.location();
let corrected_location = match location.rsplit_once("/metadata/") {
Some((a, b)) if b.ends_with(".metadata.json") => a,
_ => location,
};

let data_location = format!("{}/data", corrected_location);
// A catalog that manages where data files live advertises it through
// `write.data.path`. Honor it: catalogs backing an Iceberg table with
// their own storage layout reject a commit whose data files sit outside
// that path. Unity Catalog, for one, has to register the files in the
// Delta log that actually backs the table, and answers a commit
// referencing files under `<location>/data` with a 500.
//
// `DefaultLocationGenerator::new` reads these same properties, but its
// fallback misses the S3 Tables correction below, so choose explicitly.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style nit: Can we shorten this a bit? Too verbose for my taste. Not a blocking issue though.

Proposed replacement:

// Unity Catalog required respecting "write.data.path" while AWS does
// not provide "write.data.path" and required a hacky workaround.

let data_location = table_metadata
.properties()
.get("write.data.path")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to confirm this doesn't show up for AWS? What testing/validation did we have covering this

.or_else(|| table_metadata.properties().get("write.folder-storage.path"))
.cloned()
.unwrap_or_else(|| {
// WORKAROUND: S3 Tables catalog incorrectly sets location to the
// metadata file path instead of the warehouse root. Strip off the
// /metadata/*.metadata.json suffix. No clear way to detect this
// properly right now, so we use heuristics.
let location = table_metadata.location();
let corrected_location = match location.rsplit_once("/metadata/") {
Some((a, b)) if b.ends_with(".metadata.json") => a,
_ => location,
};
format!("{}/data", corrected_location)
});
debug!(%data_location, "iceberg sink data file location");
let location_generator =
DefaultLocationGenerator::with_data_location(data_location);

Expand Down
Loading