gluesql_composite_storage/
lib.rs

1#![deny(clippy::str_to_string)]
2
3mod store;
4mod store_mut;
5mod transaction;
6
7use {
8    gluesql_core::{
9        data::Schema,
10        error::{Error, Result},
11        store::{GStore, GStoreMut, Metadata, Planner, Store},
12    },
13    std::collections::HashMap,
14};
15
16pub trait IStorage: GStore + GStoreMut {}
17
18impl<T: GStore + GStoreMut> IStorage for T {}
19
20#[derive(Default)]
21pub struct CompositeStorage {
22    pub storages: HashMap<String, Box<dyn IStorage>>,
23    pub default_engine: Option<String>,
24}
25
26impl CompositeStorage {
27    pub fn new() -> Self {
28        CompositeStorage::default()
29    }
30
31    pub fn set_default<T: Into<String>>(&mut self, default_engine: T) {
32        self.default_engine = Some(default_engine.into());
33    }
34
35    pub fn remove_default(&mut self) {
36        self.default_engine = None;
37    }
38
39    pub fn push<T: Into<String>, U: IStorage + 'static>(&mut self, engine: T, storage: U) {
40        self.storages.insert(engine.into(), Box::new(storage));
41    }
42
43    pub fn remove<T: AsRef<str>>(&mut self, engine: T) -> Option<Box<dyn IStorage>> {
44        let engine = engine.as_ref();
45
46        if self.default_engine.as_deref() == Some(engine) {
47            self.default_engine = None;
48        }
49
50        self.storages.remove(engine)
51    }
52
53    pub fn clear(&mut self) {
54        self.storages.clear();
55        self.default_engine = None;
56    }
57
58    async fn fetch_engine(&self, table_name: &str) -> Result<String> {
59        self.fetch_schema(table_name)
60            .await?
61            .and_then(|Schema { engine, .. }| engine)
62            .or_else(|| self.default_engine.clone())
63            .ok_or_else(|| Error::StorageMsg(format!("engine not found for table: {table_name}")))
64    }
65
66    async fn fetch_storage(&self, table_name: &str) -> Result<&Box<dyn IStorage>> {
67        self.fetch_engine(table_name)
68            .await
69            .map(|engine| self.storages.get(&engine))?
70            .ok_or_else(|| {
71                Error::StorageMsg(format!(
72                    "[fetch_storage] storage not found for table: {table_name}"
73                ))
74            })
75    }
76
77    async fn fetch_storage_mut(&mut self, table_name: &str) -> Result<&mut Box<dyn IStorage>> {
78        self.fetch_engine(table_name)
79            .await
80            .map(|engine| self.storages.get_mut(&engine))?
81            .ok_or_else(|| {
82                Error::StorageMsg(format!(
83                    "[fetch_storage_mut] storage not found for table: {table_name}"
84                ))
85            })
86    }
87}
88
89impl gluesql_core::store::AlterTable for CompositeStorage {}
90impl gluesql_core::store::Index for CompositeStorage {}
91impl gluesql_core::store::IndexMut for CompositeStorage {}
92impl Metadata for CompositeStorage {}
93impl gluesql_core::store::CustomFunction for CompositeStorage {}
94impl gluesql_core::store::CustomFunctionMut for CompositeStorage {}
95impl Planner for CompositeStorage {}