br_db/
config.rs

1use json::{object, JsonValue};
2use serde::{Deserialize, Serialize};
3use std::collections::BTreeMap;
4use std::fs;
5use std::path::PathBuf;
6
7#[derive(Clone, Debug, Deserialize, Serialize)]
8pub struct Config {
9    pub default: String,
10    pub connections: BTreeMap<String, Connection>,
11}
12
13impl Default for Config {
14    fn default() -> Self {
15        Self::new()
16    }
17}
18
19impl Config {
20    pub fn new() -> Config {
21        let mut connections = BTreeMap::new();
22        connections.insert("sqlite".to_string(), Connection::new("sqlite"));
23        connections.insert("mysql".to_string(), Connection::new("mysql"));
24        connections.insert("pgsql".to_string(), Connection::new("pgsql"));
25        connections.insert("mssql".to_string(), Connection::new("mssql"));
26        Self {
27            default: "sqlite".to_string(),
28            connections,
29        }
30    }
31    pub fn from(data: JsonValue) -> Config {
32        let default = data["default"].to_string();
33        let mut connections = BTreeMap::new();
34        for (key, value) in data["connections"].entries() {
35            let connection = Connection::from(value.clone()).clone();
36            connections.insert(key.to_string(), connection.clone());
37        }
38
39        Self {
40            default,
41            connections,
42        }
43    }
44    pub fn create(config_file: PathBuf, pkg_name: bool) -> Config {
45        #[derive(Clone, Debug, Deserialize, Serialize)]
46        pub struct ConfigPkg {
47            pub br_db: Config,
48        }
49        impl ConfigPkg {
50            pub fn new() -> ConfigPkg {
51                let mut connections = BTreeMap::new();
52                connections.insert("sqlite".to_string(), Connection::new("sqlite"));
53                connections.insert("mysql".to_string(), Connection::new("mysql"));
54                connections.insert("pgsql".to_string(), Connection::new("pgsql"));
55                connections.insert("mssql".to_string(), Connection::new("mssql"));
56                Self {
57                    br_db: Config {
58                        default: "sqlite".to_string(),
59                        connections,
60                    }
61                }
62            }
63        }
64        match fs::read_to_string(config_file.clone()) {
65            Ok(e) => {
66                if pkg_name {
67                    toml::from_str::<ConfigPkg>(&e).unwrap_or_else(|_| {
68                        let data = ConfigPkg::new();
69                        let toml = toml::to_string(&data).unwrap();
70                        let toml = format!("{}\r\n{}", e, toml);
71                        let _ = fs::write(config_file.to_str().unwrap(), toml);
72                        data
73                    }).br_db
74                } else {
75                    toml::from_str::<Config>(&e).unwrap_or_else(|_| {
76                        let data = Config::new();
77                        let toml = toml::to_string(&data).unwrap();
78                        let toml = format!("{}\r\n{}", e, toml);
79                        let _ = fs::write(config_file.to_str().unwrap(), toml);
80                        data
81                    })
82                }
83            }
84            Err(_) => {
85                if pkg_name {
86                    let data = ConfigPkg::new();
87                    fs::create_dir_all(config_file.parent().unwrap()).unwrap();
88                    let toml = toml::to_string(&data).unwrap();
89                    let _ = fs::write(config_file.to_str().unwrap(), toml);
90                    data.br_db
91                } else {
92                    let data = Config::new();
93                    fs::create_dir_all(config_file.parent().unwrap()).unwrap();
94                    let toml = toml::to_string(&data).unwrap();
95                    let _ = fs::write(config_file.to_str().unwrap(), toml);
96                    data
97                }
98            }
99        }
100    }
101    /// 设置新的连接配置
102    pub fn set_connection(&mut self, name: &str, connection: JsonValue) {
103        let connection = Connection::from(connection);
104        self.connections.insert(name.to_string(), connection);
105    }
106    /// 设置当前运行配置
107    pub fn set_default(&mut self, name: &str) {
108        self.default = name.to_string();
109    }
110}
111/// 数据库模式
112#[derive(Clone, Debug, Deserialize, Serialize)]
113pub enum Mode {
114    Mysql,
115    Mssql,
116    Sqlite,
117    Pgsql,
118    None,
119}
120
121impl Mode {
122    pub fn str(&mut self) -> String {
123        match self {
124            Mode::Mysql => "mysql",
125            Mode::Sqlite => "sqlite",
126            Mode::Mssql => "mssql",
127            Mode::Pgsql => "pgsql",
128            Mode::None => "",
129        }.to_string()
130    }
131    pub fn from(name: &str) -> Self {
132        match name.to_lowercase().as_str() {
133            "mysql" => Mode::Mysql,
134            "sqlite" => Mode::Sqlite,
135            "mssql" => Mode::Mssql,
136            "pgsql" => Mode::Pgsql,
137            _ => Mode::None,
138        }
139    }
140}
141
142
143/// 数据库连接
144#[derive(Clone, Debug, Deserialize, Serialize)]
145pub struct Connection {
146    pub mode: Mode,
147    /// 连接地址
148    pub hostname: String,
149    /// 连接端口
150    pub hostport: String,
151    /// 数据库名称
152    pub database: String,
153    /// 账号
154    pub username: String,
155    /// 密码
156    pub userpass: String,
157    pub params: Vec<String>,
158    /// 数据库语言
159    pub charset: Charset,
160    /// 表前缀
161    pub prefix: String,
162    /// 调试开关
163    pub debug: bool,
164}
165
166impl Default for Connection {
167    fn default() -> Self {
168        Self::new("sqlite")
169    }
170}
171
172impl Connection {
173    pub fn new(mode: &str) -> Connection {
174        let mut that = Self {
175            mode: Mode::from(mode),
176            hostname: "".to_string(),
177            hostport: "".to_string(),
178            database: "".to_string(),
179            username: "".to_string(),
180            userpass: "".to_string(),
181            params: vec![],
182            charset: Charset::Utf8mb4,
183            prefix: "".to_string(),
184            debug: false,
185        };
186        match Mode::from(mode) {
187            Mode::Mysql => {
188                that.hostname = "127.0.0.1".to_string();
189                that.hostport = "3306".to_string();
190                that.database = "test".to_string();
191                that.username = "test".to_string();
192                that.userpass = "test".to_string();
193            }
194            Mode::Mssql => {}
195            Mode::Sqlite => {
196                that.database = "db/app.db".to_string();
197            }
198            Mode::Pgsql => {
199                that.hostname = "127.0.0.1".to_string();
200                that.hostport = "5432".to_string();
201                that.username = "test".to_string();
202                that.userpass = "test".to_string();
203            }
204            Mode::None => {}
205        }
206
207        that
208    }
209    pub fn json(&mut self) -> JsonValue {
210        object! {
211            mode: self.mode.str(),
212            hostname: self.hostname.clone(),
213            hostport: self.hostport.clone(),
214            database: self.database.clone(),
215            username: self.username.clone(),
216            userpass:self.userpass.clone(),
217            params: self.params.clone(),
218            charset: self.charset.str(),
219            prefix: self.prefix.clone(),
220            debug: self.debug
221        }
222    }
223    pub fn from(data: JsonValue) -> Connection {
224        Self {
225            mode: Mode::from(data["mode"].as_str().unwrap()),
226            hostname: data["hostname"].to_string(),
227            hostport: data["hostport"].to_string(),
228            database: data["database"].to_string(),
229            username: data["username"].to_string(),
230            userpass: data["userpass"].to_string(),
231            params: data["params"].members().map(|x| x.to_string()).collect(),
232            charset: Charset::from(data["charset"].as_str().unwrap_or("utf8mb4")),
233            prefix: data["prefix"].as_str().unwrap_or("").to_string(),
234            debug: data["debug"].to_string().parse::<bool>().unwrap_or(false),
235        }
236    }
237    pub fn get_dsn(self) -> String {
238        match self.mode {
239            Mode::Mysql => {
240                format!(
241                    "mysql://{}:{}@{}:{}/{}",
242                    self.username, self.userpass, self.hostname, self.hostport, self.database
243                )
244            }
245            Mode::Sqlite => {
246                let db_path = self.database.as_str();
247                let path_buf = PathBuf::from(db_path);
248                if !path_buf.is_file() && path_buf.file_name().is_some() {
249                    fs::create_dir_all(
250                        db_path.trim_end_matches(path_buf.file_name().unwrap().to_str().unwrap()),
251                    ).unwrap();
252                }
253                path_buf.to_str().unwrap().to_string()
254            }
255            Mode::Mssql => format!(
256                "sqlsrv://{}:{}@{}:{}/{}",
257                self.username, self.userpass, self.hostname, self.hostport, self.database
258            ),
259            Mode::Pgsql => format!(
260                "host={} user={} password={} dbname={}",
261                self.hostname, self.username, self.userpass, self.database
262            ),
263            Mode::None => "".to_string(),
264        }
265    }
266}
267
268#[derive(Clone, Debug, Deserialize, Serialize)]
269pub enum Charset {
270    Utf8mb4,
271    Utf8,
272    None,
273}
274
275impl Charset {
276    pub fn from(str: &str) -> Charset {
277        match str.to_lowercase().as_str() {
278            "utf8" => Charset::Utf8,
279            "utf8mb4" => Charset::Utf8mb4,
280            _ => Charset::None,
281        }
282    }
283    pub fn str(&self) -> String {
284        match self {
285            Charset::Utf8 => "utf8",
286            Charset::Utf8mb4 => "utf8mb4",
287            Charset::None => "",
288        }.to_string()
289    }
290}