This is an automated email from the ASF dual-hosted git repository.

github-merge-queue[bot] pushed a commit to branch 
gh-readonly-queue/main/pr-3311-f2409e9f5eaff1c643985013d927e17fdf16e6ec
in repository https://gitbox.apache.org/repos/asf/iceberg-rust.git

commit 78fafa99fa77903545dfd3301c8db716f3482b2a
Author: Yuhao Su <[email protected]>
AuthorDate: Tue Oct 6 23:11:47 2026 +0000

    fix(storage-azdls): drop the leading slash from relative paths (#3311)
    
    ADLS relative paths kept the leading `/` of the URL path, unlike the other
    backends. OpenDAL's Deleter passes paths to the service without normalizing
    them, so FileIO::delete_stream sent `DELETE <filesystem>//dir/file`, which
    ADLS rejects with 400 InvalidUri.
    
    Co-authored-by: Claude Opus 5.5 <[email protected]>
---
 crates/storage/opendal/src/azdls.rs | 28 +++++++++++++++++++++++-----
 crates/storage/opendal/src/lib.rs   |  5 ++---
 2 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/crates/storage/opendal/src/azdls.rs 
b/crates/storage/opendal/src/azdls.rs
index 6d39320df..88a197fea 100644
--- a/crates/storage/opendal/src/azdls.rs
+++ b/crates/storage/opendal/src/azdls.rs
@@ -101,8 +101,7 @@ pub(crate) fn azdls_create_operator<'a>(
     // including their filesystem and account name.
     // OpenDAL's operator methods expect only the relative path, so we split it
     // off and save it for later use.
-    let relative_path_len = path.path.len();
-    let (_, relative_path) = absolute_path.split_at(absolute_path.len() - 
relative_path_len);
+    let relative_path = path.relative_path(absolute_path);
 
     Ok((op, relative_path))
 }
@@ -237,6 +236,13 @@ impl AzureStoragePath {
             self.endpoint_suffix
         )
     }
+
+    /// The part of `absolute_path` below the filesystem, without a leading 
`/`,
+    /// like the relative paths of the other backends.
+    pub(crate) fn relative_path<'a>(&self, absolute_path: &'a str) -> &'a str {
+        let path = &absolute_path[absolute_path.len() - self.path.len()..];
+        path.strip_prefix('/').unwrap_or(path)
+    }
 }
 
 impl FromStr for AzureStoragePath {
@@ -395,7 +401,19 @@ mod tests {
                         ..Default::default()
                     },
                 ),
-                Some(("myfs", "/path/to/file.parquet")),
+                Some(("myfs", "path/to/file.parquet")),
+            ),
+            (
+                "filesystem root",
+                (
+                    "abfss://[email protected]/",
+                    AzdlsConfig {
+                        account_name: Some("myaccount".to_string()),
+                        endpoint: 
Some("https://myaccount.dfs.core.windows.net".to_string()),
+                        ..Default::default()
+                    },
+                ),
+                Some(("myfs", "")),
             ),
             (
                 "different account",
@@ -445,7 +463,7 @@ mod tests {
                         ..Default::default()
                     },
                 ),
-                Some(("myfs", "/path/to/file.parquet")),
+                Some(("myfs", "path/to/file.parquet")),
             ),
             (
                 "scheme differs from a previously-configured one is accepted",
@@ -459,7 +477,7 @@ mod tests {
                         ..Default::default()
                     },
                 ),
-                Some(("myfs", "/path/to/file.parquet")),
+                Some(("myfs", "path/to/file.parquet")),
             ),
         ];
 
diff --git a/crates/storage/opendal/src/lib.rs 
b/crates/storage/opendal/src/lib.rs
index f58d6f534..9e0155201 100644
--- a/crates/storage/opendal/src/lib.rs
+++ b/crates/storage/opendal/src/lib.rs
@@ -603,8 +603,7 @@ impl OpenDalStorage {
             OpenDalStorage::Azdls { config, .. } => {
                 let azure_path = path.parse::<AzureStoragePath>()?;
                 match_path_with_config(&azure_path, config)?;
-                let relative_path_len = azure_path.path.len();
-                Ok(&path[path.len() - relative_path_len..])
+                Ok(azure_path.relative_path(path))
             }
             #[cfg(feature = "opendal-hf")]
             OpenDalStorage::Hf { .. } => {
@@ -1176,7 +1175,7 @@ mod tests {
             storage
                 
.relativize_path("abfss://[email protected]/path/to/file.parquet")
                 .unwrap(),
-            "/path/to/file.parquet"
+            "path/to/file.parquet"
         );
     }
 }

Reply via email to