Skip to content

Commit f162400

Browse files
committed
Experiment implementation for catalog builder
1 parent e1e3ba4 commit f162400

File tree

3 files changed

+105
-4
lines changed

3 files changed

+105
-4
lines changed

crates/catalog/rest/src/catalog.rs

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@
1818
//! This module contains the iceberg REST catalog implementation.
1919
2020
use std::collections::HashMap;
21+
use std::future::Future;
2122
use std::str::FromStr;
2223

2324
use async_trait::async_trait;
2425
use iceberg::io::FileIO;
2526
use iceberg::table::Table;
2627
use iceberg::{
27-
Catalog, Error, ErrorKind, Namespace, NamespaceIdent, Result, TableCommit, TableCreation,
28-
TableIdent,
28+
Catalog, CatalogBuilder, Error, ErrorKind, Namespace, NamespaceIdent, Result, TableCommit,
29+
TableCreation, TableIdent,
2930
};
3031
use itertools::Itertools;
3132
use reqwest::header::{
@@ -51,6 +52,8 @@ const PATH_V1: &str = "v1";
5152
/// Rest catalog configuration.
5253
#[derive(Clone, Debug, TypedBuilder)]
5354
pub struct RestCatalogConfig {
55+
#[builder(default, setter(strip_option))]
56+
name: Option<String>,
5457
uri: String,
5558

5659
#[builder(default, setter(strip_option(fallback = warehouse_opt)))]
@@ -223,6 +226,74 @@ impl RestCatalogConfig {
223226
}
224227
}
225228

229+
/// Builder for [`RestCatalog`].
230+
#[derive(Debug)]
231+
pub struct RestCatalogBuilder(RestCatalogConfig);
232+
233+
impl Default for RestCatalogBuilder {
234+
fn default() -> Self {
235+
Self(RestCatalogConfig {
236+
name: None,
237+
uri: "".to_string(),
238+
warehouse: None,
239+
props: HashMap::new(),
240+
client: None,
241+
})
242+
}
243+
}
244+
245+
impl CatalogBuilder for RestCatalogBuilder {
246+
type C = RestCatalog;
247+
248+
fn name(mut self, name: impl Into<String>) -> Self {
249+
self.0.name = Some(name.into());
250+
self
251+
}
252+
253+
fn uri(mut self, uri: impl Into<String>) -> Self {
254+
self.0.uri = uri.into();
255+
self
256+
}
257+
258+
fn warehouse(mut self, warehouse: impl Into<String>) -> Self {
259+
self.0.warehouse = Some(warehouse.into());
260+
self
261+
}
262+
263+
fn with_prop(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
264+
self.0.props.insert(key.into(), value.into());
265+
self
266+
}
267+
268+
fn build(self) -> impl Future<Output = Result<Self::C>> {
269+
let result = {
270+
if self.0.name.is_none() {
271+
Err(Error::new(
272+
ErrorKind::DataInvalid,
273+
"Catalog name is required",
274+
))
275+
} else if self.0.uri.is_empty() {
276+
Err(Error::new(
277+
ErrorKind::DataInvalid,
278+
"Catalog uri is required",
279+
))
280+
} else {
281+
Ok(RestCatalog::new(self.0))
282+
}
283+
};
284+
285+
std::future::ready(result)
286+
}
287+
}
288+
289+
impl RestCatalogBuilder {
290+
/// Configures the catalog with a custom HTTP client.
291+
pub fn with_client(mut self, client: Client) -> Self {
292+
self.0.client = Some(client);
293+
self
294+
}
295+
}
296+
226297
#[derive(Debug)]
227298
struct RestContext {
228299
client: HttpClient,
@@ -2257,4 +2328,17 @@ mod tests {
22572328
config_mock.assert_async().await;
22582329
update_table_mock.assert_async().await;
22592330
}
2331+
2332+
#[tokio::test]
2333+
async fn test_create_rest_catalog() {
2334+
let catalog = RestCatalogBuilder::default()
2335+
.name("test")
2336+
.uri("http://localhost:8080")
2337+
.with_client(Client::new())
2338+
.with_prop("a", "b")
2339+
.build()
2340+
.await;
2341+
2342+
assert!(catalog.is_ok());
2343+
}
22602344
}

crates/iceberg/src/catalog/mod.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
2020
use std::collections::HashMap;
2121
use std::fmt::{Debug, Display};
22+
use std::future::Future;
2223
use std::mem::take;
2324
use std::ops::Deref;
2425

@@ -96,6 +97,22 @@ pub trait Catalog: Debug + Sync + Send {
9697
async fn update_table(&self, commit: TableCommit) -> Result<Table>;
9798
}
9899

100+
/// Common interface for all catalog builders.
101+
pub trait CatalogBuilder: Default + Debug + Send + Sync {
102+
/// The catalog type that this builder creates.
103+
type C: Catalog;
104+
/// Configure name of the catalog.
105+
fn name(self, name: impl Into<String>) -> Self;
106+
/// Configure uri of the catalog.
107+
fn uri(self, uri: impl Into<String>) -> Self;
108+
/// Configure warehouse location of the catalog.
109+
fn warehouse(self, warehouse: impl Into<String>) -> Self;
110+
/// Configure properties of the catalog.
111+
fn with_prop(self, key: impl Into<String>, value: impl Into<String>) -> Self;
112+
/// Create the catalog
113+
fn build(self) -> impl Future<Output = Result<Self::C>>;
114+
}
115+
99116
/// NamespaceIdent represents the identifier of a namespace in the catalog.
100117
///
101118
/// The namespace identifier is a list of strings, where each string is a

crates/iceberg/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ pub use error::{Error, ErrorKind, Result};
6363
mod catalog;
6464

6565
pub use catalog::{
66-
Catalog, Namespace, NamespaceIdent, TableCommit, TableCreation, TableIdent, TableRequirement,
67-
TableUpdate, ViewCreation,
66+
Catalog, CatalogBuilder, Namespace, NamespaceIdent, TableCommit, TableCreation, TableIdent,
67+
TableRequirement, TableUpdate, ViewCreation,
6868
};
6969

7070
pub mod table;

0 commit comments

Comments
 (0)