Skip to content

Commit c2f9b00

Browse files
committed
fix: Improve absolute file path handling in PyArrow integration
1 parent 8820046 commit c2f9b00

8 files changed

Lines changed: 209 additions & 549 deletions

File tree

crates/core/src/logstore/mod.rs

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -538,34 +538,64 @@ pub(crate) fn object_store_path(table_root: &Url) -> DeltaResult<Path> {
538538

539539
/// TODO
540540
pub fn to_uri(root: &Url, location: &Path) -> String {
541+
let location_str = location.as_ref();
542+
543+
// Handle absolute URIs in location (e.g., s3://, gcs://, abfss://) regardless of root scheme
544+
if location_str.contains("://") {
545+
return location_str.to_string();
546+
}
547+
541548
match root.scheme() {
542549
"file" => {
543-
#[cfg(windows)]
544-
let uri = format!(
545-
"{}/{}",
546-
root.as_ref().trim_end_matches('/'),
547-
location.as_ref()
548-
)
549-
.replace("file:///", "");
550-
#[cfg(unix)]
551-
let uri = format!(
552-
"{}/{}",
553-
root.as_ref().trim_end_matches('/'),
554-
location.as_ref()
555-
)
556-
.replace("file://", "");
557-
uri
550+
// Handle file URIs by stripping the scheme prefix
551+
if let Some(path) = strip_file_uri_scheme(location_str) {
552+
return ensure_absolute_path(path);
553+
}
554+
555+
// Handle relative paths by making them absolute with respect to the table root
556+
let uri_intermediate = format!("{}/{}", root.as_ref().trim_end_matches('/'), location_str);
557+
let os_abs_path = strip_file_uri_scheme(&uri_intermediate)
558+
.map(ensure_absolute_path)
559+
.unwrap_or_else(|| {
560+
// Fallback: strip file:// prefix manually
561+
#[cfg(windows)]
562+
let stripped = uri_intermediate.replace("file:///", "");
563+
#[cfg(unix)]
564+
let stripped = uri_intermediate.replace("file://", "");
565+
stripped
566+
});
567+
568+
os_abs_path
558569
}
559570
_ => {
560-
if location.as_ref().is_empty() || location.as_ref() == "/" {
571+
if location_str.is_empty() || location_str == "/" {
561572
root.as_ref().to_string()
562573
} else {
563-
format!("{}/{}", root.as_ref(), location.as_ref())
574+
format!("{}/{}", root.as_ref(), location_str)
564575
}
565576
}
566577
}
567578
}
568579

580+
/// Strip file URI scheme prefixes and return the path portion
581+
fn strip_file_uri_scheme(uri: &str) -> Option<String> {
582+
if uri.starts_with("file:///") {
583+
Some(uri.strip_prefix("file:///")?.to_string())
584+
} else if uri.starts_with("file:/") && !uri.starts_with("file://") {
585+
Some(uri.strip_prefix("file:/")?.to_string())
586+
} else {
587+
None
588+
}
589+
}
590+
591+
/// Ensure the path starts with '/' to make it a valid OS absolute path
592+
fn ensure_absolute_path(mut path: String) -> String {
593+
if !path.starts_with('/') && !path.is_empty() {
594+
path.insert(0, '/');
595+
}
596+
path
597+
}
598+
569599
/// Reads a commit and gets list of actions
570600
pub async fn get_actions(
571601
version: i64,

0 commit comments

Comments
 (0)