diff --git a/Cargo.lock b/Cargo.lock index 8c1ff336a6..57c68ea40a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3604,13 +3604,16 @@ dependencies = [ "home", "iceberg", "iceberg-catalog-rest", + "iceberg-catalog-sql", "iceberg-datafusion", "mimalloc", + "sqlx", "stacker", "tokio", "toml", "tracing", "tracing-subscriber", + "uuid", ] [[package]] diff --git a/crates/integrations/playground/Cargo.toml b/crates/integrations/playground/Cargo.toml index 3f6774be19..28878ae46a 100644 --- a/crates/integrations/playground/Cargo.toml +++ b/crates/integrations/playground/Cargo.toml @@ -36,7 +36,9 @@ fs-err = { workspace = true } home = { workspace = true } iceberg = { workspace = true } iceberg-catalog-rest = { workspace = true } +iceberg-catalog-sql = { workspace = true } iceberg-datafusion = { workspace = true } +sqlx = { workspace = true, features = ["runtime-tokio", "sqlite", "migrate"] } mimalloc = { workspace = true } stacker = { workspace = true } tokio = { workspace = true } @@ -44,6 +46,9 @@ toml = { workspace = true } tracing = { workspace = true } tracing-subscriber = { workspace = true } +[dev-dependencies] +uuid = { workspace = true, features = ["v4"] } + [package.metadata.cargo-machete] # These dependencies are added to ensure minimal dependency version ignored = ["stacker", "mimalloc", "home"] diff --git a/crates/integrations/playground/src/catalog.rs b/crates/integrations/playground/src/catalog.rs index 66742ab893..17ea70d955 100644 --- a/crates/integrations/playground/src/catalog.rs +++ b/crates/integrations/playground/src/catalog.rs @@ -26,6 +26,7 @@ use fs_err::read_to_string; use iceberg::CatalogBuilder; use iceberg::memory::MemoryCatalogBuilder; use iceberg_catalog_rest::RestCatalogBuilder; +use iceberg_catalog_sql::SqlCatalogBuilder; use iceberg_datafusion::IcebergCatalogProvider; use toml::{Table as TomlTable, Value}; @@ -97,10 +98,11 @@ impl IcebergCatalogList { // Create catalog based on type using the appropriate builder let catalog: Arc = match r#type { "rest" => Arc::new(RestCatalogBuilder::default().load(name, props).await?), + "sql" => Arc::new(SqlCatalogBuilder::default().load(name, props).await?), "memory" => Arc::new(MemoryCatalogBuilder::default().load(name, props).await?), _ => { return Err(anyhow::anyhow!( - "Unsupported catalog type: '{type}'. Supported types: rest, memory" + "Unsupported catalog type: '{type}'. Supported types: rest, sql, memory" )); } }; @@ -139,8 +141,45 @@ impl CatalogProviderList for IcebergCatalogList { #[cfg(test)] mod tests { + use sqlx::migrate::MigrateDatabase; + use super::*; + fn temp_path() -> String { + let uuid = uuid::Uuid::new_v4(); + format!("/tmp/iceberg-test-{uuid}") + } + + #[tokio::test] + async fn test_parse_sql_catalog() { + let db_path = temp_path(); + let sql_uri = format!("sqlite:{db_path}"); + + // Create the SQLite database file first + sqlx::Sqlite::create_database(&sql_uri).await.unwrap(); + + let config = format!( + r#" + [[catalogs]] + name = "test_sql" + type = "sql" + [catalogs.config] + uri = "{sql_uri}" + warehouse = "/tmp/sql-warehouse" + "# + ); + + let toml_table: TomlTable = toml::from_str(&config).unwrap(); + let catalog_list = IcebergCatalogList::parse_table(&toml_table).await.unwrap(); + + assert!( + catalog_list + .catalog_names() + .contains(&"test_sql".to_string()) + ); + assert!(catalog_list.catalog("test_sql").is_some()); + } + #[tokio::test] async fn test_parse_memory_catalog() { let config = r#" @@ -179,7 +218,7 @@ mod tests { let err_msg = result.unwrap_err().to_string(); assert!(err_msg.contains("Unsupported catalog type")); assert!(err_msg.contains("hive")); - assert!(err_msg.contains("rest, memory")); + assert!(err_msg.contains("rest, sql, memory")); } #[tokio::test]