dev_tool/
sqlite_util.rs

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