1use std::sync::OnceLock;
2use std::{any::TypeId, collections::HashMap, sync::Mutex};
3
4use crate::dialect::SqlDialect;
5
6type PlaceholderKey = (TypeId, usize);
7type PlaceholderFromKey = (TypeId, usize, usize);
8type PlaceholderCache = Mutex<HashMap<PlaceholderKey, &'static str>>;
9type PlaceholderFromCache = Mutex<HashMap<PlaceholderFromKey, &'static str>>;
10
11static PLACEHOLDER_CACHE: OnceLock<PlaceholderCache> = OnceLock::new();
12static PLACEHOLDER_FROM_CACHE: OnceLock<PlaceholderFromCache> = OnceLock::new();
13
14pub fn cached_placeholders<DB>(count: usize) -> &'static str
16where
17 DB: SqlDialect + 'static,
18{
19 let key = (TypeId::of::<DB>(), count);
20 let cache = PLACEHOLDER_CACHE.get_or_init(|| Mutex::new(HashMap::new()));
21 let mut guard = cache.lock().expect("placeholder cache poisoned");
22 if let Some(value) = guard.get(&key) {
23 value
24 } else {
25 let placeholders = crate::build_placeholders::<DB>(1, count);
26 let leaked: &'static str = Box::leak(placeholders.into_boxed_str());
27 guard.insert(key, leaked);
28 leaked
29 }
30}
31
32pub fn cached_placeholders_from<DB>(start: usize, count: usize) -> &'static str
34where
35 DB: SqlDialect + 'static,
36{
37 let key = (TypeId::of::<DB>(), start, count);
38 let cache = PLACEHOLDER_FROM_CACHE.get_or_init(|| Mutex::new(HashMap::new()));
39 let mut guard = cache.lock().expect("placeholder cache poisoned");
40 if let Some(value) = guard.get(&key) {
41 value
42 } else {
43 let placeholders = crate::build_placeholders::<DB>(start, count);
44 let leaked: &'static str = Box::leak(placeholders.into_boxed_str());
45 guard.insert(key, leaked);
46 leaked
47 }
48}