camel_component_sql/
bundle.rs1use std::sync::Arc;
2
3use camel_component_api::{CamelError, ComponentBundle, ComponentRegistrar};
4
5use crate::{SqlComponent, config::SqlGlobalConfig};
6
7pub struct SqlBundle {
8 config: SqlGlobalConfig,
9 catalog: Option<Arc<dyn camel_api::datasource::DatasourceCatalog>>,
10}
11
12impl ComponentBundle for SqlBundle {
13 fn config_key() -> &'static str {
14 "sql"
15 }
16
17 fn from_toml(value: toml::Value) -> Result<Self, CamelError> {
18 let config: SqlGlobalConfig = value
19 .try_into()
20 .map_err(|e: toml::de::Error| CamelError::Config(e.to_string()))?;
21 Ok(Self {
22 config,
23 catalog: None,
24 })
25 }
26
27 fn register_all(self, ctx: &mut dyn ComponentRegistrar) {
28 let component = match self.catalog {
29 Some(catalog) => SqlComponent::with_config_and_catalog(self.config, catalog),
30 None => SqlComponent::with_config(self.config),
31 };
32 ctx.register_component_dyn(Arc::new(component));
33 }
34}
35
36impl SqlBundle {
37 pub fn with_catalog(
38 mut self,
39 catalog: Arc<dyn camel_api::datasource::DatasourceCatalog>,
40 ) -> Self {
41 if let Err(e) =
42 catalog.register_factory("sqlx", Arc::new(crate::pool_factory::SqlPoolFactory))
43 {
44 tracing::warn!("failed to register sqlx pool factory: {}", e);
46 }
47 self.catalog = Some(catalog);
48 self
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55 use camel_component_api::ComponentBundle;
56
57 struct TestRegistrar {
58 schemes: Vec<String>,
59 }
60
61 impl camel_component_api::ComponentRegistrar for TestRegistrar {
62 fn register_component_dyn(
63 &mut self,
64 component: std::sync::Arc<dyn camel_component_api::Component>,
65 ) {
66 self.schemes.push(component.scheme().to_string());
67 }
68 }
69
70 #[test]
71 fn sql_bundle_from_toml_empty_uses_defaults() {
72 let value: toml::Value = toml::from_str("").unwrap();
73 let result = SqlBundle::from_toml(value);
74 assert!(
75 result.is_ok(),
76 "empty TOML must use defaults: {:?}",
77 result.err()
78 );
79 }
80
81 #[test]
82 fn sql_bundle_registers_expected_schemes() {
83 let bundle = SqlBundle::from_toml(toml::Value::Table(toml::map::Map::new())).unwrap();
84 let mut registrar = TestRegistrar { schemes: vec![] };
85
86 bundle.register_all(&mut registrar);
87
88 assert_eq!(registrar.schemes, vec!["sql"]);
89 }
90
91 #[test]
92 fn sql_bundle_from_toml_returns_error_on_invalid_config() {
93 let mut table = toml::map::Map::new();
94 table.insert(
95 "max_connections".to_string(),
96 toml::Value::String("not-a-number".to_string()),
97 );
98
99 let result = SqlBundle::from_toml(toml::Value::Table(table));
100 assert!(result.is_err(), "expected Err on malformed config");
101 let err_msg = match result {
102 Err(err) => err.to_string(),
103 Ok(_) => panic!("expected Err on malformed config"),
104 };
105 assert!(
106 err_msg.contains("Configuration error"),
107 "expected CamelError::Config, got: {err_msg}"
108 );
109 }
110}