parsql_sqlite/
lib.rs

1//! # parsql-sqlite
2//! 
3//! SQLite integration for parsql.
4//! This crate provides synchronous APIs for working with SQLite databases.
5//! 
6//! ## Features
7//! 
8//! - Synchronous SQLite operations
9//! - Automatic SQL query generation
10//! - Secure parameter management
11//! - Generic CRUD operations
12//! - Transaction support
13//! - Extension methods for the Connection object
14//! 
15//! ## Usage
16//! 
17//! ```rust,no_run
18//! use rusqlite::{Connection, Result};
19//! use parsql::sqlite::{fetch, insert};
20//! 
21//! #[derive(Insertable, SqlParams)]
22//! #[table("users")]
23//! pub struct InsertUser {
24//!     pub name: String,
25//!     pub email: String,
26//! }
27//! 
28//! #[derive(Queryable, SqlParams, FromRow)]
29//! #[table("users")]
30//! #[where_clause("id = ?")]
31//! pub struct GetUser {
32//!     pub id: i32,
33//!     pub name: String,
34//!     pub email: String,
35//! }
36//! 
37//! fn main() -> Result<()> {
38//!     let conn = Connection::open("test.db")?;
39//!     
40//!     // Insert a new user
41//!     let insert_user = InsertUser {
42//!         name: "John".to_string(),
43//!         email: "john@example.com".to_string(),
44//!     };
45//!     
46//!     let id = insert(&conn, insert_user)?;
47//!     
48//!     // Get the user back
49//!     let get_user = GetUser::new(id as i32);
50//!     let user = fetch(&conn, &get_user)?;
51//!     
52//!     println!("User: {:?}", user);
53//!     Ok(())
54//! }
55//! ```
56//!
57//! ## Using Extension Methods
58//!
59//! You can also use the extension methods directly on the Connection object:
60//!
61//! ```rust,no_run
62//! use rusqlite::{Connection, Result};
63//! use parsql::sqlite::CrudOps;  // Import the trait
64//! use parsql::sqlite::macros::{Insertable, SqlParams, Queryable, FromRow};
65//!
66//! #[derive(Insertable, SqlParams)]
67//! #[table("users")]
68//! pub struct InsertUser {
69//!     pub name: String,
70//!     pub email: String,
71//! }
72//!
73//! #[derive(Queryable, FromRow, SqlParams)]
74//! #[table("users")]
75//! #[where_clause("id = ?")]
76//! pub struct GetUser {
77//!     pub id: i32,
78//!     pub name: String,
79//!     pub email: String,
80//! }
81//!
82//! fn main() -> Result<()> {
83//!     let conn = Connection::open("test.db")?;
84//!     
85//!     // Insert a new user using extension method
86//!     let insert_user = InsertUser {
87//!         name: "John".to_string(),
88//!         email: "john@example.com".to_string(),
89//!     };
90//!     
91//!     let rows_affected = conn.insert(insert_user)?;
92//!     
93//!     // Get the user back using extension method
94//!     let get_user = GetUser {
95//!         id: 1,
96//!         name: String::new(),
97//!         email: String::new(),
98//!     };
99//!     let user = conn.fetch(&get_user)?;
100//!     
101//!     println!("User: {:?}", user);
102//!     Ok(())
103//! }
104//! ```
105//!
106//! ## Using Transactions
107//! 
108//! You can perform database operations within a transaction to ensure atomicity:
109//! 
110//! ```rust,no_run
111//! use rusqlite::{Connection, Result};
112//! use parsql::sqlite::transactional;
113//! use parsql::macros::{Insertable, SqlParams, Updateable, UpdateParams};
114//! 
115//! #[derive(Insertable, SqlParams)]
116//! #[table("users")]
117//! struct InsertUser {
118//!     name: String,
119//!     email: String,
120//! }
121//! 
122//! #[derive(Updateable, UpdateParams)]
123//! #[table("users")]
124//! #[update("email")]
125//! #[where_clause("id = ?")]
126//! struct UpdateUser {
127//!     id: i64,
128//!     email: String,
129//! }
130//! 
131//! fn main() -> Result<()> {
132//!     let conn = Connection::open("test.db")?;
133//!     
134//!     // Begin a transaction
135//!     let tx = transactional::begin(&conn)?;
136//!     
137//!     // Insert a user within the transaction
138//!     let insert_user = InsertUser {
139//!         name: "John".to_string(),
140//!         email: "john@example.com".to_string(),
141//!     };
142//!     let (tx, _) = transactional::tx_insert(tx, insert_user)?;
143//!     
144//!     // Update the user within the same transaction
145//!     let update_user = UpdateUser {
146//!         id: 1,
147//!         email: "john.updated@example.com".to_string(),
148//!     };
149//!     let (tx, _) = transactional::tx_update(tx, update_user)?;
150//!     
151//!     // Commit the transaction - both operations succeed or fail together
152//!     tx.commit()?;
153//!     
154//!     Ok(())
155//! }
156//! ```
157//!
158//! ## Installation
159//!
160//! Add to your Cargo.toml file as follows:
161//!
162//! ```toml
163//! [dependencies]
164//! parsql = { version = "0.3.7", features = ["sqlite"] }
165//! ```
166//!
167//! or if you want to use this package directly:
168//!
169//! ```toml
170//! [dependencies]
171//! parsql-sqlite = "0.3.7"
172//! parsql-macros = "0.3.7"
173//! ```
174
175pub mod crud_ops;
176pub mod transactional_ops;
177
178// Re-export sqlite types that might be needed
179pub use rusqlite::{Connection, Error, Row};
180pub use rusqlite::types::ToSql;
181
182// Re-export crud operations
183pub use crud_ops::{
184    insert, 
185    select, 
186    select_all, 
187    update, 
188    delete, 
189    fetch, 
190    fetch_all,
191    CrudOps,
192};
193
194// Re-export transaction operations
195pub use transactional_ops as transactional;
196
197pub use parsql_macros as macros;
198
199/// Trait for generating SQL queries.
200/// This trait is implemented by the derive macro `Queryable`, `Insertable`, `Updateable`, and `Deletable`.
201pub trait SqlQuery {
202    /// Returns the SQL query string.
203    fn query() -> String;
204}
205
206/// Trait for providing SQL parameters.
207/// This trait is implemented by the derive macro `SqlParams`.
208pub trait SqlParams {
209    /// Returns a vector of references to SQL parameters.
210    fn params(&self) -> Vec<&(dyn ToSql + Sync)>;
211}
212
213/// Trait for providing UPDATE parameters.
214/// This trait is implemented by the derive macro `UpdateParams`.
215pub trait UpdateParams {
216    /// Returns a vector of references to SQL parameters for UPDATE operations.
217    fn params(&self) -> Vec<&(dyn ToSql + Sync)>;
218}
219
220/// Trait for converting database rows to Rust structs.
221/// This trait is implemented by the derive macro `FromRow`.
222pub trait FromRow {
223    /// Converts a database row to a Rust struct.
224    /// 
225    /// # Arguments
226    /// * `row` - A reference to a database row
227    /// 
228    /// # Returns
229    /// * `Result<Self, Error>` - The converted struct or an error
230    fn from_row(row: &Row) -> Result<Self, Error>
231    where
232        Self: Sized;
233}