dev_tool/sqlite_util.rs
1//! 使用示例见单元测试
2//!
3//! 使用navicat可以创建sqlite数据库文件,以及查看表数据情况
4//!
5use sqlite::{Connection, State};
6
7pub trait FromSqliteRow {
8 fn from_row(row: &sqlite::Row) -> Self;
9}
10
11pub struct SqliteClient {
12 conn: Connection,
13}
14
15impl SqliteClient {
16 /// 创建一个新的 SQLite 客户端实例
17 ///
18 /// 该函数会打开指定路径的 SQLite 数据库文件,如果文件不存在则会自动创建
19 ///
20 /// # 参数
21 /// * `db_path` - 数据库文件的路径字符串引用
22 ///
23 /// # 返回值
24 /// * `Ok(SqliteClient)` - 成功创建的 SQLite 客户端实例
25 /// * `Err(sqlite::Error)` - 数据库连接过程中发生的错误
26 ///
27 /// # 示例
28 /// ```
29 /// let client = SqliteClient::new("database.db");
30 /// ```
31 pub fn new(db_path: &str) -> Result<Self, sqlite::Error> {
32 let conn = Connection::open(db_path)?;
33 Ok(SqliteClient { conn })
34 }
35
36 /// 执行SQL语句
37 ///
38 /// 该函数用于执行不返回结果集的SQL语句(如INSERT、UPDATE、DELETE等)。
39 /// 如果SQL语句返回了结果集,则会返回错误。
40 ///
41 /// # 参数
42 /// * `sql` - 要执行的SQL语句字符串
43 ///
44 /// # 返回值
45 /// * `Ok(())` - SQL语句执行成功
46 /// * `Err(sqlite::Error)` - SQL语句执行失败或返回了结果集
47 ///
48 /// # 错误
49 /// 当SQL语句返回结果集时,会返回ExecuteReturnedResults错误,
50 /// 此时应该使用query系列函数来处理
51 pub fn execute(&self, sql: &str) -> Result<(), sqlite::Error> {
52 // 准备SQL语句
53 let mut stmt = self.conn.prepare(sql)?;
54 // 执行SQL语句并检查执行状态
55 match stmt.next()? {
56 State::Done => Ok(()),
57 _ => Err(sqlite::Error {
58 code: None,
59 message: Some("ExecuteReturnedResults, please use query...".to_string()),
60 }),
61 }
62 }
63
64 /// 执行SQL查询并返回结果集
65 ///
66 /// 该函数用于执行给定的SQL查询语句,并将查询结果转换为指定类型的向量。
67 /// 结果类型T必须实现FromSqliteRow trait,以便能够从数据库行中创建实例。
68 ///
69 /// # 参数
70 /// * `sql` - 要执行的SQL查询语句字符串引用
71 ///
72 /// # 返回值
73 /// 返回包含查询结果的Vec<T>,其中T是实现了FromSqliteRow trait的类型
74 ///
75 /// # 泛型约束
76 /// T: FromSqliteRow - 结果类型必须实现从SQLite行数据转换的trait
77 pub fn query<T: FromSqliteRow>(&self, sql: &str) -> Vec<T> {
78 // 准备SQL语句
79 let stmt = self.conn.prepare(sql).unwrap();
80 let mut results = Vec::new();
81 // 遍历查询结果,将每一行转换为指定类型并添加到结果集中
82 for row in stmt.into_iter().map(|row| row.unwrap()) {
83 results.push(T::from_row(&row));
84 }
85 results
86 }
87}
88
89#[cfg(test)]
90mod tests {
91
92 use super::*;
93
94 // 假设存在一个 users 表,定义对应的结构体
95 #[derive(Debug)]
96 struct User {
97 id: i64, // 不要使用i32(其没有实现对应的trait)
98 name: String,
99 }
100
101 // 为 User 结构体实现 FromSqliteRow trait
102 impl FromSqliteRow for User {
103 fn from_row(row: &sqlite::Row) -> Self {
104 User {
105 id: row.read::<i64, _>("id"),
106 name: row.read::<&str, _>("name").to_string(),
107 }
108 }
109 }
110
111 #[test]
112 fn it_works() {
113 let util = SqliteClient::new("test.db").expect("Failed to create SqliteUtil");
114 let user_results = util.query::<User>("SELECT id, name FROM users");
115 println!("User results: {:?}", user_results);
116 for item in user_results {
117 println!("id = {}, name = {}", item.id, item.name);
118 }
119 }
120}