@@ -336,24 +336,17 @@ impl TableProvider for DataFusionTable {
336336// Create a fake object store URL. Different table paths should produce fake URLs
337337// that differ in the host name, because DF's DefaultObjectStoreRegistry only takes
338338// hostname into account for object store keys
339- fn fake_object_store_url ( table_location_url : & str ) -> Option < ObjectStoreUrl > {
340- let mut u = url:: Url :: parse ( table_location_url) . ok ( ) ?;
341- u. set_host ( Some ( & format ! (
342- "{}-{}" ,
343- u. host_str( ) . unwrap_or( "" ) ,
344- // Hex-encode the path to ensure it produces a valid hostname
345- u. path( )
346- . as_bytes( )
347- . iter( )
348- . map( |b| format!( "{b:02x}" ) )
349- . collect:: <Vec <_>>( )
350- . join( "" )
351- ) ) )
352- . unwrap ( ) ;
353- u. set_path ( "" ) ;
354- u. set_query ( None ) ;
355- u. set_fragment ( None ) ;
356- ObjectStoreUrl :: parse ( & u) . ok ( )
339+ fn fake_object_store_url ( table_location_url : & str ) -> ObjectStoreUrl {
340+ // Use quasi url-encoding to escape the characters not allowed in host names, (i.e. for `/` use
341+ // `-2F` instead of `%2F`)
342+ ObjectStoreUrl :: parse ( format ! (
343+ "iceberg-rust://{}" ,
344+ table_location_url
345+ . replace( '-' , "-2D" )
346+ . replace( '/' , "-2F" )
347+ . replace( ':' , "-3A" )
348+ ) )
349+ . expect ( "Invalid object store url." )
357350}
358351
359352#[ allow( clippy:: too_many_arguments) ]
@@ -374,8 +367,7 @@ async fn table_scan(
374367 . unwrap_or_else ( || table. current_schema ( None ) . unwrap ( ) . clone ( ) ) ;
375368
376369 // Create a unique URI for this particular object store
377- let object_store_url = fake_object_store_url ( & table. metadata ( ) . location )
378- . unwrap_or_else ( ObjectStoreUrl :: local_filesystem) ;
370+ let object_store_url = fake_object_store_url ( & table. metadata ( ) . location ) ;
379371 session
380372 . runtime_env ( )
381373 . register_object_store ( object_store_url. as_ref ( ) , table. object_store ( ) ) ;
@@ -1137,8 +1129,7 @@ async fn write_parquet_files(
11371129
11381130 let bucket = Bucket :: from_path ( & metadata. location ) . map_err ( DataFusionIcebergError :: from) ?;
11391131
1140- let object_store_url =
1141- fake_object_store_url ( & metadata. location ) . unwrap_or ( ObjectStoreUrl :: local_filesystem ( ) ) ;
1132+ let object_store_url = fake_object_store_url ( & metadata. location ) ;
11421133
11431134 context. runtime_env ( ) . register_object_store (
11441135 & object_store_url
@@ -2478,12 +2469,23 @@ mod tests {
24782469 fn test_fake_object_store_url ( ) {
24792470 assert_eq ! (
24802471 fake_object_store_url( "s3://a" ) ,
2481- Some ( ObjectStoreUrl :: parse( "s3 ://a- " ) . unwrap( ) ) ,
2472+ ObjectStoreUrl :: parse( "iceberg-rust ://s3-3A-2F-2Fa " ) . unwrap( ) ,
24822473 ) ;
24832474 assert_eq ! (
24842475 fake_object_store_url( "s3://a/b" ) ,
2485- Some ( ObjectStoreUrl :: parse( "s3://a-2f62" ) . unwrap( ) ) ,
2476+ ObjectStoreUrl :: parse( "iceberg-rust://s3-3A-2F-2Fa-2Fb" ) . unwrap( ) ,
2477+ ) ;
2478+ assert_eq ! (
2479+ fake_object_store_url( "/warehouse/tpch/lineitem" ) ,
2480+ ObjectStoreUrl :: parse( "iceberg-rust://-2Fwarehouse-2Ftpch-2Flineitem" ) . unwrap( )
2481+ ) ;
2482+ assert_ne ! (
2483+ fake_object_store_url( "s3://a/-/--" ) ,
2484+ fake_object_store_url( "s3://a/--/-" ) ,
2485+ ) ;
2486+ assert_ne ! (
2487+ fake_object_store_url( "s3://a/table-2Fpath" ) ,
2488+ fake_object_store_url( "s3://a/table/path" ) ,
24862489 ) ;
2487- assert_eq ! ( fake_object_store_url( "invalid url" ) , None ) ;
24882490 }
24892491}
0 commit comments