tree: c7228b861b7d9f5f2341fa39ca4c201af9169d9a
  1. src/
  2. tests/
  3. Cargo.toml
  4. DEPENDENCIES.rust.tsv
  5. public-api.txt
  6. README.md
crates/storage/opendal/README.md

iceberg-storage-opendal

OpenDAL-based storage backend implementations for Apache Iceberg Rust.

Supported Storage Backends

Storage BackendFeature FlagStatusDescription
Memoryopendal-memory✅ StableIn-memory storage for testing and development
Local Filesystemopendal-fs✅ StableLocal filesystem storage
Amazon S3opendal-s3✅ StableAmazon S3 storage
Google Cloud Storageopendal-gcs✅ StableGoogle Cloud Storage
Hugging Faceopendal-hf✅ StableHugging Face buckets and repositories
Alibaba Cloud OSSopendal-oss🧪 ExperimentalAlibaba Cloud Object Storage Service
Azure Datalakeopendal-azdls🧪 ExperimentalAzure Datalake Storage v2

You can enable all stable storage backends at once using the opendal-all feature flag.

Note that opendal-oss and opendal-azdls are currently experimental and not included in opendal-all.

Usage

Add the crate to your Cargo.toml with the feature flags for the backends you need:

[dependencies]
iceberg = { version = "x.y.z" }
iceberg-storage-opendal = { version = "x.y.z", features = ["opendal-s3"] }
iceberg-catalog-rest = { version = "x.y.z" }

Then pass an OpenDalStorageFactory to your catalog builder:

use std::collections::HashMap;
use std::sync::Arc;

use iceberg::{Catalog, CatalogBuilder, TableIdent};
use iceberg_catalog_rest::{RestCatalogBuilder, REST_CATALOG_PROP_URI};
use iceberg_storage_opendal::OpenDalStorageFactory;

#[tokio::main]
async fn main() -> iceberg::Result<()> {
    let catalog = RestCatalogBuilder::default()
        .with_storage_factory(Arc::new(OpenDalStorageFactory::S3 {
            customized_credential_load: None,
        }))
        .load(
            "my_catalog",
            HashMap::from([
                (REST_CATALOG_PROP_URI.to_string(), "http://localhost:8181".to_string()),
            ]),
        )
        .await?;

    let table = catalog
        .load_table(&TableIdent::from_strs(["my_namespace", "my_table"])?)
        .await?;

    let scan = table.scan().select_all().build()?;
    let stream = scan.to_arrow().await?;

    Ok(())
}