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, Default)]
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 QueryCompilerRegistry {
27 #[must_use]
29 pub fn with_enabled_features() -> Self {
30 let mut registry = Self::default();
31 registry.register_builtins();
32 registry
33 }
34
35 fn register_builtins(&mut self) {
36 #[cfg(feature = "compiler-sql")]
37 {
38 let sql: Arc<dyn QueryCompiler> = Arc::new(crate::backend::SqlQueryCompiler);
39 self.register(KnownEngines::SQLITE, Arc::clone(&sql));
40 self.register(KnownEngines::POSTGRES, Arc::clone(&sql));
41 self.register(KnownEngines::INMEMORY_MEM, sql);
42 }
43 #[cfg(feature = "compiler-surreal")]
44 {
45 self.register(
46 KnownEngines::SURREALDB,
47 Arc::new(crate::backend::SurrealQueryCompiler) as Arc<dyn QueryCompiler>,
48 );
49 }
50 #[cfg(feature = "compiler-mongodb")]
51 {
52 self.register(
53 KnownEngines::MONGODB,
54 Arc::new(crate::backend::MongoQueryCompiler) as Arc<dyn QueryCompiler>,
55 );
56 }
57 #[cfg(feature = "compiler-redis")]
58 {
59 self.register(
60 KnownEngines::REDIS,
61 Arc::new(crate::backend::RedisQueryCompiler) as Arc<dyn QueryCompiler>,
62 );
63 }
64 #[cfg(feature = "compiler-indradb")]
65 {
66 self.register(
67 KnownEngines::INDRADB,
68 Arc::new(crate::backend::IndraQueryCompiler) as Arc<dyn QueryCompiler>,
69 );
70 }
71 #[cfg(feature = "compiler-hybrid")]
72 {
73 self.register(
74 KnownEngines::HYBRID_INDRA_SQL,
75 Arc::new(crate::backend::HybridQueryCompiler) as Arc<dyn QueryCompiler>,
76 );
77 }
78 }
79
80 pub fn register(&mut self, engine_id: &'static str, compiler: Arc<dyn QueryCompiler>) {
82 self.compilers.insert(engine_id, compiler);
83 }
84
85 pub fn get(&self, engine_id: &str) -> Option<&Arc<dyn QueryCompiler>> {
87 self.compilers.get(engine_id)
88 }
89
90 pub fn compile(&self, engine_id: &str, core: &QueryCore) -> Result<CompiledQuery> {
95 let compiler = self.get(engine_id).ok_or_else(|| {
96 Error::Internal(format!(
97 "no query compiler registered for engine `{engine_id}` — enable the matching \
98 valence-core `compiler-*` / valence public crate feature"
99 ))
100 })?;
101 compiler.compile(core)
102 }
103}
104
105static GLOBAL_REGISTRY: OnceLock<QueryCompilerRegistry> = OnceLock::new();
106
107pub fn global_compiler_registry() -> &'static QueryCompilerRegistry {
109 GLOBAL_REGISTRY.get_or_init(QueryCompilerRegistry::with_enabled_features)
110}
111
112pub fn compile_for_engine(engine_id: &str, core: &QueryCore) -> Result<CompiledQuery> {
117 global_compiler_registry().compile(engine_id, core)
118}