1pub mod errors;
2pub mod models;
3use errors::DBResult;
4use leetcode_core as api;
5pub use models::{question::DbQuestion, topic::DbTopic};
6use models::{QuestionTopicMap, TopicQuestionMap};
7use native_db::Database;
8use native_db::DatabaseBuilder;
9use native_db::Input;
10use std::path::PathBuf;
11use std::sync::OnceLock;
12
13pub type Db<'a> = Database<'a>;
14
15pub static DB_BUILDER: OnceLock<DatabaseBuilder> = OnceLock::new();
16pub static DB_CLIENT: OnceLock<Db> = OnceLock::new();
17
18pub(crate) fn get_db_client() -> &'static Database<'static> {
19 DB_CLIENT.get().expect("Database client is not initialized")
20}
21
22pub fn define_schema(db_builder: &mut DatabaseBuilder) -> errors::DBResult<&mut DatabaseBuilder> {
23 db_builder.define::<DbQuestion>()?;
24 db_builder.define::<DbTopic>()?;
25 db_builder.define::<QuestionTopicMap>()?;
26 db_builder.define::<TopicQuestionMap>()?;
27 Ok(db_builder)
28}
29
30pub fn init(db_path: Option<&PathBuf>) {
31 let mut database_builder = DatabaseBuilder::new();
32 define_schema(&mut database_builder).expect("DB schema initialization failed.");
33
34 DB_BUILDER.get_or_init(|| database_builder);
35
36 DB_CLIENT.get_or_init(|| {
37 if let Some(path) = db_path {
38 DB_BUILDER
39 .get()
40 .unwrap()
41 .create(path)
42 .expect("Error while creating db conn.")
43 } else {
44 DB_BUILDER
45 .get()
46 .unwrap()
47 .create_in_memory()
48 .expect("Error while creating db conn in memory.")
49 }
50 });
51}
52
53fn save<'a, T: Input + Clone>(item: &T) -> DBResult<()> {
54 let rw = get_db_client().rw_transaction()?;
55 rw.insert(item.clone())?;
56 rw.commit()?;
57 Ok(())
58}
59
60fn save_multiple<'a, T: Input + Clone>(items: &Vec<T>) -> DBResult<()> {
61 let rw = get_db_client().rw_transaction()?;
62 for item in items {
63 rw.insert(item.clone())?;
64 }
65 rw.commit()?;
66 Ok(())
67}