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