Skip to content

Commit e8867c8

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 e8867c8

File tree

3 files changed

+89
-52
lines changed

3 files changed

+89
-52
lines changed

crates/sqllogictest/src/engine/datafusion.rs

Lines changed: 6 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,12 @@ 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("default", Self::create_catalog(catalog_config.as_ref()).await?);
6767

6868
Ok(Self {
6969
test_data_path: PathBuf::from("testdata"),
@@ -72,10 +72,10 @@ impl DataFusionEngine {
7272
}
7373

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

crates/sqllogictest/src/engine/mod.rs

Lines changed: 58 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -27,34 +27,37 @@ 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 } => {
59+
Ok(Box::new(DataFusionEngine::new(catalog).await?))
60+
}
5861
}
5962
}
6063

@@ -80,45 +83,63 @@ where
8083

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

8788
#[test]
8889
fn test_deserialize_engine_config() {
89-
let input = r#"
90-
type = "datafusion"
91-
"#;
90+
let input = r#"type = "datafusion""#;
9291

9392
let config: EngineConfig = toml::from_str(input).unwrap();
94-
assert_eq!(config.engine_type, EngineType::Datafusion);
95-
assert!(config.extra.is_empty());
93+
assert!(matches!(config, EngineConfig::Datafusion { catalog: None }));
9694
}
9795

9896
#[test]
99-
fn test_deserialize_engine_config_with_extras() {
97+
fn test_deserialize_engine_config_with_catalog() {
10098
let input = r#"
10199
type = "datafusion"
102-
catalog_type = "rest"
103100
104-
[catalog_properties]
101+
[catalog]
102+
type = "rest"
103+
104+
[catalog.props]
105105
uri = "http://localhost:8181"
106106
"#;
107107

108108
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"));
109+
match config {
110+
EngineConfig::Datafusion { catalog: Some(cat) } => {
111+
assert_eq!(cat.catalog_type, "rest");
112+
assert_eq!(
113+
cat.props.get("uri"),
114+
Some(&"http://localhost:8181".to_string())
115+
);
116+
}
117+
_ => panic!("Expected Datafusion with catalog"),
118+
}
119+
}
120+
121+
#[test]
122+
fn test_deserialize_catalog_config() {
123+
let input = r#"
124+
type = "memory"
125+
126+
[props]
127+
warehouse = "file:///tmp/warehouse"
128+
"#;
129+
130+
let config: CatalogConfig = toml::from_str(input).unwrap();
131+
assert_eq!(config.catalog_type, "memory");
132+
assert_eq!(
133+
config.props.get("warehouse"),
134+
Some(&"file:///tmp/warehouse".to_string())
135+
);
112136
}
113137

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

121-
let result = load_engine_runner("df", config).await;
142+
let result = load_engine_runner(config).await;
122143
assert!(result.is_ok());
123144
}
124145
}

crates/sqllogictest/src/schedule.rs

Lines changed: 25 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,10 @@ 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!(
151+
config.engines["df"],
152+
EngineConfig::Datafusion { catalog: None }
153+
));
151154
assert_eq!(config.steps.len(), 1);
152155
assert_eq!(config.steps[0].engine, "df");
153156
assert_eq!(config.steps[0].slt, "test.slt");
@@ -178,11 +181,16 @@ mod tests {
178181
}
179182

180183
#[test]
181-
fn test_deserialize_with_extra_fields() {
182-
// Test forward-compatibility with extra fields (for PR #1943)
184+
fn test_deserialize_with_catalog_config() {
183185
let input = r#"
184-
[engines]
185-
df = { type = "datafusion", catalog_type = "rest", some_future_field = "value" }
186+
[engines.df]
187+
type = "datafusion"
188+
189+
[engines.df.catalog]
190+
type = "rest"
191+
192+
[engines.df.catalog.props]
193+
uri = "http://localhost:8181"
186194
187195
[[steps]]
188196
engine = "df"
@@ -191,8 +199,16 @@ mod tests {
191199

192200
let config: ScheduleConfig = toml::from_str(input).unwrap();
193201

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

198214
#[test]

0 commit comments

Comments
 (0)