valence_core/
query_compiler_registry.rs1use std::collections::HashMap;
4use std::sync::{Arc, OnceLock};
5
6use crate::error::{Error, Result};
7use crate::known_engines::KnownEngines;
8use crate::query::QueryCore;
9use crate::query_compiler::QueryCompiler;
10use crate::CompiledQuery;
11
12#[derive(Clone)]
14pub struct QueryCompilerRegistry {
15 compilers: HashMap<&'static str, Arc<dyn QueryCompiler>>,
16}
17
18impl std::fmt::Debug for QueryCompilerRegistry {
19 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20 f.debug_struct("QueryCompilerRegistry")
21 .field("engines", &self.compilers.keys().collect::<Vec<_>>())
22 .finish()
23 }
24}
25
26impl Default for QueryCompilerRegistry {
27 fn default() -> Self {
28 Self {
29 compilers: HashMap::new(),
30 }
31 }
32}
33
34impl QueryCompilerRegistry {
35 #[must_use]
37 pub fn with_enabled_features() -> Self {
38 let mut registry = Self::default();
39 registry.register_builtins();
40 registry
41 }
42
43 fn register_builtins(&mut self) {
44 #[cfg(feature = "compiler-sql")]
45 {
46 let sql: Arc<dyn QueryCompiler> = Arc::new(crate::backend::SqlQueryCompiler);
47 self.register(KnownEngines::SQLITE, Arc::clone(&sql));
48 self.register(KnownEngines::POSTGRES, Arc::clone(&sql));
49 self.register(KnownEngines::INMEMORY_MEM, sql);
50 }
51 #[cfg(feature = "compiler-surreal")]
52 {
53 self.register(
54 KnownEngines::SURREALDB,
55 Arc::new(crate::backend::SurrealQueryCompiler) as Arc<dyn QueryCompiler>,
56 );
57 }
58 #[cfg(feature = "compiler-mongodb")]
59 {
60 self.register(
61 KnownEngines::MONGODB,
62 Arc::new(crate::backend::MongoQueryCompiler) as Arc<dyn QueryCompiler>,
63 );
64 }
65 #[cfg(feature = "compiler-redis")]
66 {
67 self.register(
68 KnownEngines::REDIS,
69 Arc::new(crate::backend::RedisQueryCompiler) as Arc<dyn QueryCompiler>,
70 );
71 }
72 #[cfg(feature = "compiler-indradb")]
73 {
74 self.register(
75 KnownEngines::INDRADB,
76 Arc::new(crate::backend::IndraQueryCompiler) as Arc<dyn QueryCompiler>,
77 );
78 }
79 }
80
81 pub fn register(&mut self, engine_id: &'static str, compiler: Arc<dyn QueryCompiler>) {
83 self.compilers.insert(engine_id, compiler);
84 }
85
86 pub fn get(&self, engine_id: &str) -> Option<&Arc<dyn QueryCompiler>> {
88 self.compilers.get(engine_id)
89 }
90
91 pub fn compile(&self, engine_id: &str, core: &QueryCore) -> Result<CompiledQuery> {
93 let compiler = self.get(engine_id).ok_or_else(|| {
94 Error::Internal(format!(
95 "no query compiler registered for engine `{engine_id}` — enable the matching \
96 valence-core `compiler-*` / valence facade feature"
97 ))
98 })?;
99 compiler.compile(core)
100 }
101}
102
103static GLOBAL_REGISTRY: OnceLock<QueryCompilerRegistry> = OnceLock::new();
104
105pub fn global_compiler_registry() -> &'static QueryCompilerRegistry {
107 GLOBAL_REGISTRY.get_or_init(QueryCompilerRegistry::with_enabled_features)
108}
109
110pub fn compile_for_engine(engine_id: &str, core: &QueryCore) -> Result<CompiledQuery> {
112 global_compiler_registry().compile(engine_id, core)
113}