diff --git a/crates/catalog/sql/src/catalog.rs b/crates/catalog/sql/src/catalog.rs index c7bf9d0cfd..3633d8cd1a 100644 --- a/crates/catalog/sql/src/catalog.rs +++ b/crates/catalog/sql/src/catalog.rs @@ -257,7 +257,11 @@ impl SqlCatalog { "StorageFactory must be provided for SqlCatalog. Use `with_storage_factory` to configure it.", ) })?; - let fileio = FileIOBuilder::new(factory).build(); + // Forward catalog props so storage-backend keys reach the FileIO. + // Unrecognized keys are ignored by backends. + let fileio = FileIOBuilder::new(factory) + .with_props(config.props.clone()) + .build(); install_default_drivers(); let max_connections: u32 = config @@ -1185,6 +1189,33 @@ mod tests { new_sql_catalog(warehouse_loc.clone(), Some("iceberg")).await; } + /// Regression test: storage-backend props set on the catalog must reach + /// the FileIO; otherwise authenticated backends fail with 401s on writes. + #[tokio::test] + async fn test_storage_props_propagate_to_file_io() { + let sql_lite_uri = format!("sqlite:{}", temp_path()); + sqlx::Sqlite::create_database(&sql_lite_uri).await.unwrap(); + let warehouse_location = temp_path(); + + let catalog = SqlCatalogBuilder::default() + .with_storage_factory(Arc::new(LocalFsStorageFactory)) + .load( + "iceberg", + HashMap::from_iter([ + (SQL_CATALOG_PROP_URI.to_string(), sql_lite_uri), + (SQL_CATALOG_PROP_WAREHOUSE.to_string(), warehouse_location), + ("s3.region".to_string(), "us-east-1".to_string()), + ("hf.token".to_string(), "hf_test_token".to_string()), + ]), + ) + .await + .unwrap(); + + let props = catalog.fileio.config().props(); + assert_eq!(props.get("s3.region"), Some(&"us-east-1".to_string())); + assert_eq!(props.get("hf.token"), Some(&"hf_test_token".to_string())); + } + #[tokio::test] async fn test_builder_method() { let sql_lite_uri = format!("sqlite:{}", temp_path());