luna_orm/database/
sqlite.rs1use crate::database::lib::Database;
2use crate::database::lib::DatabaseType;
3use crate::database::DB;
4use crate::{error::LunaOrmError, LunaOrmResult};
5
6use luna_orm_trait::LastRowId;
7use sqlx::any::AnyConnectOptions;
8use sqlx::any::AnyPoolOptions;
9use sqlx::sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePool, SqliteSynchronous};
10use sqlx::AnyPool;
11
12use std::fs;
13use std::path::Path;
14use std::str::FromStr;
15
16use crate::command_executor::CommandExecutor;
17use crate::sql_executor::SqlExecutor;
18use crate::sql_generator::DefaultSqlGenerator;
19use crate::sql_generator::SqlGenerator;
20use luna_orm_trait::Entity;
21use luna_orm_trait::SelectedEntity;
22use sqlx::any::AnyArguments;
23use sqlx::any::AnyRow;
24use tracing::debug;
25
26use path_absolutize::*;
27
28pub struct SqliteLocalConfig {
29 pub work_dir: String,
30 pub db_file: String,
31}
32
33impl SqliteLocalConfig {
34 pub fn new<S>(work_dir: S, db_file: S) -> Self
35 where
36 S: Into<String>,
37 {
38 Self {
39 work_dir: work_dir.into(),
40 db_file: db_file.into(),
41 }
42 }
43}
44
45#[derive(Debug, Clone)]
46pub struct SqliteDatabase {
47 database_type: DatabaseType,
48 pool: AnyPool,
49 sql_generator: DefaultSqlGenerator,
50}
51
52impl SqlExecutor for SqliteDatabase {
53 fn get_pool(&self) -> LunaOrmResult<&AnyPool> {
54 Ok(&self.pool)
55 }
56}
57
58impl CommandExecutor for SqliteDatabase {
59 type G = DefaultSqlGenerator;
60
61 fn get_generator(&self) -> &Self::G {
62 &self.sql_generator
63 }
64
65 async fn create<'a>(&mut self, entity: &'a mut dyn Entity) -> LunaOrmResult<bool> {
68 debug!(target: "luna_orm2", command = "create", entity = ?entity);
69 let sql = self.get_generator().get_create_sql(entity);
70 debug!(target: "luna_orm", command = "create", sql = sql);
71 let args = entity.any_arguments_of_insert();
72 if entity.get_auto_increment_field().is_some() {
73 let last_row_id: LastRowId = self.fetch_one(&sql, args).await?;
74 entity.set_auto_increment_field(Some(last_row_id.id));
75 } else {
76 self.execute(&sql, args).await?;
77 }
78 debug!(target: "luna_orm", command = "create", result = ?entity);
79
80 let trx = self.pool.begin().await?;
82 trx.commit().await?;
84 return Ok(true);
85 }
86}
87
88impl Database for SqliteDatabase {
89 fn get_type(&self) -> &DatabaseType {
90 &self.database_type
91 }
92}
93
94impl From<SqliteDatabase> for DB<SqliteDatabase> {
95 fn from(value: SqliteDatabase) -> Self {
96 Self(value)
97 }
98}
99
100impl SqliteDatabase {
101 pub async fn init_local_sqlite(workspace_dir: &str, db_file: &str) -> LunaOrmResult<AnyPool> {
102 let workspace = Path::new(workspace_dir);
103 let workspace_absolute = workspace
104 .absolutize()
105 .map_err(|_e| LunaOrmError::DatabaseInitFail("workdir absolute fail".to_string()))?;
106
107 fs::create_dir_all(&workspace_absolute)
108 .map_err(|_e| LunaOrmError::DatabaseInitFail("create dir fail".to_string()))?;
109 let db_file_path = workspace_absolute.join(db_file);
110 {
111 let options = SqliteConnectOptions::new()
112 .filename(db_file_path.clone())
113 .synchronous(SqliteSynchronous::Full)
114 .journal_mode(SqliteJournalMode::Wal)
115 .create_if_missing(true);
116 let _ = SqlitePool::connect_with(options).await.map_err(|_e| {
117 LunaOrmError::DatabaseInitFail("create is missing fail".to_string())
118 })?;
119 }
120
121 sqlx::any::install_default_drivers();
122 let url = format!("sqlite:{}", db_file_path.to_str().unwrap());
123 let any_options = AnyConnectOptions::from_str(&url).unwrap();
124 let any_pool = AnyPool::connect_with(any_options)
125 .await
126 .map_err(|_e| LunaOrmError::DatabaseInitFail("init pool fail".to_string()))?;
127 return Ok(any_pool);
128 }
129
130 pub async fn build(config: SqliteLocalConfig) -> LunaOrmResult<Self> {
131 let pool = SqliteDatabase::init_local_sqlite(&config.work_dir, &config.db_file).await?;
132 let generator = DefaultSqlGenerator::new();
133 let database = SqliteDatabase {
134 database_type: DatabaseType::SqliteLocal,
135 pool,
136 sql_generator: generator,
137 };
138 return Ok(database);
139 }
140
141 }