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}