Skip to content

Commit f09e5e7

Browse files
committed
refactor(sqllogictest): use tagged enum for EngineConfig with CatalogConfig
- Replace EngineConfig struct with tagged enum for better type safety - Add CatalogConfig struct with catalog_type and props fields - Remove unused _name parameter from DataFusionEngine::new() - Prepare structure for future catalog loader integration
1 parent 50f4295 commit f09e5e7

File tree

3 files changed

+89
-52
lines changed

3 files changed

+89
-52
lines changed

crates/sqllogictest/src/engine/datafusion.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use iceberg::{Catalog, CatalogBuilder, NamespaceIdent, TableCreation};
2828
use iceberg_datafusion::IcebergCatalogProvider;
2929
use indicatif::ProgressBar;
3030

31-
use crate::engine::{EngineConfig, EngineRunner, run_slt_with_runner};
31+
use crate::engine::{CatalogConfig, EngineRunner, run_slt_with_runner};
3232
use crate::error::Result;
3333

3434
pub struct DataFusionEngine {
@@ -58,12 +58,15 @@ impl EngineRunner for DataFusionEngine {
5858
}
5959

6060
impl DataFusionEngine {
61-
pub async fn new(_name: &str, config: &EngineConfig) -> Result<Self> {
61+
pub async fn new(catalog_config: Option<CatalogConfig>) -> Result<Self> {
6262
let session_config = SessionConfig::new()
6363
.with_target_partitions(4)
6464
.with_information_schema(true);
6565
let ctx = SessionContext::new_with_config(session_config);
66-
ctx.register_catalog("default", Self::create_catalog(&config.extra).await?);
66+
ctx.register_catalog(
67+
"default",
68+
Self::create_catalog(catalog_config.as_ref()).await?,
69+
);
6770

6871
Ok(Self {
6972
test_data_path: PathBuf::from("testdata"),
@@ -72,10 +75,10 @@ impl DataFusionEngine {
7275
}
7376

7477
async fn create_catalog(
75-
_extra: &HashMap<String, toml::Value>,
78+
_catalog_config: Option<&CatalogConfig>,
7679
) -> anyhow::Result<Arc<dyn CatalogProvider>> {
77-
// TODO: support dynamic catalog configuration
78-
// See: https://github.com/apache/iceberg-rust/issues/1780
80+
// TODO: Use catalog_config to load different catalog types via iceberg-catalog-loader
81+
// See: https://github.com/apache/iceberg-rust/issues/1780
7982
let catalog = MemoryCatalogBuilder::default()
8083
.load(
8184
"memory",

crates/sqllogictest/src/engine/mod.rs

Lines changed: 56 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -27,34 +27,35 @@ use sqllogictest::{AsyncDB, MakeConnection, Runner, parse_file};
2727
use crate::engine::datafusion::DataFusionEngine;
2828
use crate::error::{Error, Result};
2929

30-
/// Supported engine types for sqllogictest
31-
#[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
32-
#[serde(rename_all = "lowercase")]
33-
pub enum EngineType {
34-
Datafusion,
35-
}
36-
37-
/// Configuration for a single engine instance
30+
/// Configuration for the catalog used by an engine
3831
#[derive(Debug, Clone, Deserialize)]
39-
pub struct EngineConfig {
40-
/// The type of engine
32+
pub struct CatalogConfig {
33+
/// Catalog type: "memory", "rest", "glue", "hms", "s3tables", "sql"
4134
#[serde(rename = "type")]
42-
pub engine_type: EngineType,
35+
pub catalog_type: String,
36+
/// Catalog properties passed to the catalog loader
37+
#[serde(default)]
38+
pub props: HashMap<String, String>,
39+
}
4340

44-
/// Additional configuration fields for extensibility
45-
/// This allows forward-compatibility with future fields like catalog_type, catalog_properties
46-
#[serde(flatten)]
47-
pub extra: HashMap<String, toml::Value>,
41+
/// Engine configuration as a tagged enum
42+
#[derive(Debug, Clone, Deserialize)]
43+
#[serde(tag = "type", rename_all = "lowercase")]
44+
pub enum EngineConfig {
45+
Datafusion {
46+
#[serde(default)]
47+
catalog: Option<CatalogConfig>,
48+
},
4849
}
4950

5051
#[async_trait::async_trait]
5152
pub trait EngineRunner: Send {
5253
async fn run_slt_file(&mut self, path: &Path) -> Result<()>;
5354
}
5455

55-
pub async fn load_engine_runner(name: &str, config: EngineConfig) -> Result<Box<dyn EngineRunner>> {
56-
match config.engine_type {
57-
EngineType::Datafusion => Ok(Box::new(DataFusionEngine::new(name, &config).await?)),
56+
pub async fn load_engine_runner(config: EngineConfig) -> Result<Box<dyn EngineRunner>> {
57+
match config {
58+
EngineConfig::Datafusion { catalog } => Ok(Box::new(DataFusionEngine::new(catalog).await?)),
5859
}
5960
}
6061

@@ -80,45 +81,63 @@ where
8081

8182
#[cfg(test)]
8283
mod tests {
83-
use std::collections::HashMap;
84-
85-
use crate::engine::{EngineConfig, EngineType, load_engine_runner};
84+
use crate::engine::{CatalogConfig, EngineConfig, load_engine_runner};
8685

8786
#[test]
8887
fn test_deserialize_engine_config() {
89-
let input = r#"
90-
type = "datafusion"
91-
"#;
88+
let input = r#"type = "datafusion""#;
9289

9390
let config: EngineConfig = toml::from_str(input).unwrap();
94-
assert_eq!(config.engine_type, EngineType::Datafusion);
95-
assert!(config.extra.is_empty());
91+
assert!(matches!(config, EngineConfig::Datafusion { catalog: None }));
9692
}
9793

9894
#[test]
99-
fn test_deserialize_engine_config_with_extras() {
95+
fn test_deserialize_engine_config_with_catalog() {
10096
let input = r#"
10197
type = "datafusion"
102-
catalog_type = "rest"
10398
104-
[catalog_properties]
99+
[catalog]
100+
type = "rest"
101+
102+
[catalog.props]
105103
uri = "http://localhost:8181"
106104
"#;
107105

108106
let config: EngineConfig = toml::from_str(input).unwrap();
109-
assert_eq!(config.engine_type, EngineType::Datafusion);
110-
assert!(config.extra.contains_key("catalog_type"));
111-
assert!(config.extra.contains_key("catalog_properties"));
107+
match config {
108+
EngineConfig::Datafusion { catalog: Some(cat) } => {
109+
assert_eq!(cat.catalog_type, "rest");
110+
assert_eq!(
111+
cat.props.get("uri"),
112+
Some(&"http://localhost:8181".to_string())
113+
);
114+
}
115+
_ => panic!("Expected Datafusion with catalog"),
116+
}
117+
}
118+
119+
#[test]
120+
fn test_deserialize_catalog_config() {
121+
let input = r#"
122+
type = "memory"
123+
124+
[props]
125+
warehouse = "file:///tmp/warehouse"
126+
"#;
127+
128+
let config: CatalogConfig = toml::from_str(input).unwrap();
129+
assert_eq!(config.catalog_type, "memory");
130+
assert_eq!(
131+
config.props.get("warehouse"),
132+
Some(&"file:///tmp/warehouse".to_string())
133+
);
112134
}
113135

114136
#[tokio::test]
115137
async fn test_load_datafusion() {
116-
let config = EngineConfig {
117-
engine_type: EngineType::Datafusion,
118-
extra: HashMap::new(),
119-
};
138+
let config = EngineConfig::Datafusion { catalog: None };
120139

121-
let result = load_engine_runner("df", config).await;
140+
let result = load_engine_runner(config).await;
122141
assert!(result.is_ok());
123142
}
124143
}

crates/sqllogictest/src/schedule.rs

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ impl Schedule {
8383
let mut engines = HashMap::new();
8484

8585
for (name, config) in configs {
86-
let engine = load_engine_runner(&name, config).await?;
86+
let engine = load_engine_runner(config).await?;
8787
engines.insert(name, engine);
8888
}
8989

@@ -129,7 +129,7 @@ impl Schedule {
129129

130130
#[cfg(test)]
131131
mod tests {
132-
use crate::engine::EngineType;
132+
use crate::engine::EngineConfig;
133133
use crate::schedule::ScheduleConfig;
134134

135135
#[test]
@@ -147,7 +147,9 @@ mod tests {
147147

148148
assert_eq!(config.engines.len(), 1);
149149
assert!(config.engines.contains_key("df"));
150-
assert_eq!(config.engines["df"].engine_type, EngineType::Datafusion);
150+
assert!(matches!(config.engines["df"], EngineConfig::Datafusion {
151+
catalog: None
152+
}));
151153
assert_eq!(config.steps.len(), 1);
152154
assert_eq!(config.steps[0].engine, "df");
153155
assert_eq!(config.steps[0].slt, "test.slt");
@@ -178,11 +180,16 @@ mod tests {
178180
}
179181

180182
#[test]
181-
fn test_deserialize_with_extra_fields() {
182-
// Test forward-compatibility with extra fields (for PR #1943)
183+
fn test_deserialize_with_catalog_config() {
183184
let input = r#"
184-
[engines]
185-
df = { type = "datafusion", catalog_type = "rest", some_future_field = "value" }
185+
[engines.df]
186+
type = "datafusion"
187+
188+
[engines.df.catalog]
189+
type = "rest"
190+
191+
[engines.df.catalog.props]
192+
uri = "http://localhost:8181"
186193
187194
[[steps]]
188195
engine = "df"
@@ -191,8 +198,16 @@ mod tests {
191198

192199
let config: ScheduleConfig = toml::from_str(input).unwrap();
193200

194-
assert!(config.engines["df"].extra.contains_key("catalog_type"));
195-
assert!(config.engines["df"].extra.contains_key("some_future_field"));
201+
match &config.engines["df"] {
202+
EngineConfig::Datafusion { catalog: Some(cat) } => {
203+
assert_eq!(cat.catalog_type, "rest");
204+
assert_eq!(
205+
cat.props.get("uri"),
206+
Some(&"http://localhost:8181".to_string())
207+
);
208+
}
209+
_ => panic!("Expected Datafusion with catalog config"),
210+
}
196211
}
197212

198213
#[test]

0 commit comments

Comments
 (0)