drizzle_sqlite/builder/prepared.rs
1use std::borrow::Cow;
2
3use drizzle_core::{
4 OwnedParam, Param,
5 prepared::{
6 PreparedStatement as CorePreparedStatement,
7 owned::OwnedPreparedStatement as CoreOwnedPreparedStatement,
8 },
9};
10
11use crate::{SQLiteValue, values::OwnedSQLiteValue};
12
13/// SQLite-specific prepared statement wrapper.
14///
15/// A prepared statement represents a compiled SQL query with placeholder parameters
16/// that can be executed multiple times with different parameter values. This wrapper
17/// provides SQLite-specific functionality while maintaining compatibility with the
18/// core Drizzle prepared statement infrastructure.
19///
20/// ## Features
21///
22/// - **Parameter Binding**: Safely bind values to SQL placeholders
23/// - **Reusable Execution**: Execute the same query multiple times efficiently
24/// - **Memory Management**: Automatic handling of borrowed/owned lifetimes
25/// - **Type Safety**: Compile-time verification of parameter types
26///
27/// ## Basic Usage
28///
29/// ```rust,ignore
30/// use drizzle_sqlite::builder::QueryBuilder;
31/// use drizzle_macros::{SQLiteTable, SQLiteSchema};
32/// use drizzle_core::{ToSQL, expressions::conditions::eq};
33///
34/// #[SQLiteTable(name = "users")]
35/// struct User {
36/// #[integer(primary)]
37/// id: i32,
38/// #[text]
39/// name: String,
40/// }
41///
42/// #[derive(SQLiteSchema)]
43/// struct Schema {
44/// user: User,
45/// }
46///
47/// let builder = QueryBuilder::new::<Schema>();
48/// let Schema { user } = Schema::new();
49///
50/// // Build query that will become a prepared statement
51/// let query = builder
52/// .select(user.name)
53/// .from(user)
54/// .r#where(eq(user.id, drizzle_core::Placeholder::question()));
55///
56/// // Convert to prepared statement (this would typically be done by the driver)
57/// let sql = query.to_sql();
58/// println!("SQL: {}", sql.sql()); // "SELECT "users"."name" FROM "users" WHERE "users"."id" = ?"
59/// ```
60///
61/// ## Lifetime Management
62///
63/// The prepared statement can be converted between borrowed and owned forms:
64///
65/// - `PreparedStatement<'a>` - Borrows data with lifetime 'a
66/// - `OwnedPreparedStatement` - Owns all data, no lifetime constraints
67///
68/// This allows for flexible usage patterns depending on whether you need to
69/// store the prepared statement long-term or use it immediately.
70#[derive(Debug, Clone)]
71pub struct PreparedStatement<'a> {
72 pub inner: CorePreparedStatement<'a, crate::SQLiteValue<'a>>,
73}
74
75impl<'a> PreparedStatement<'a> {
76 /// Converts this borrowed prepared statement into an owned one.
77 ///
78 /// This method clones all the internal data to create an `OwnedPreparedStatement`
79 /// that doesn't have any lifetime constraints. This is useful when you need to
80 /// store the prepared statement beyond the lifetime of the original query builder.
81 ///
82 /// # Examples
83 ///
84 /// ```rust,ignore
85 /// # use drizzle_sqlite::builder::PreparedStatement;
86 /// # let prepared_statement: PreparedStatement = todo!(); // Would come from driver
87 /// // Convert borrowed to owned for long-term storage
88 /// let owned = prepared_statement.into_owned();
89 ///
90 /// // Now `owned` can be stored without lifetime constraints
91 /// ```
92 pub fn into_owned(&self) -> OwnedPreparedStatement {
93 let owned_params = self.inner.params.iter().map(|p| OwnedParam {
94 placeholder: p.placeholder,
95 value: p
96 .value
97 .clone()
98 .map(|v| OwnedSQLiteValue::from(v.into_owned())),
99 });
100
101 let inner = CoreOwnedPreparedStatement {
102 text_segments: self.inner.text_segments.clone(),
103 params: owned_params.collect::<Box<[_]>>(),
104 };
105
106 OwnedPreparedStatement { inner }
107 }
108}
109
110/// Owned SQLite prepared statement wrapper.
111///
112/// This is the owned counterpart to [`PreparedStatement`] that doesn't have any lifetime
113/// constraints. All data is owned by this struct, making it suitable for long-term storage,
114/// caching, or passing across thread boundaries.
115///
116/// ## Use Cases
117///
118/// - **Caching**: Store prepared statements in a cache for reuse
119/// - **Multi-threading**: Pass prepared statements between threads
120/// - **Long-term storage**: Keep prepared statements in application state
121/// - **Serialization**: Convert to/from persistent storage (when serialization is implemented)
122///
123/// ## Examples
124///
125/// ```rust,ignore
126/// use drizzle_sqlite::builder::{QueryBuilder, PreparedStatement, OwnedPreparedStatement};
127/// use drizzle_macros::{SQLiteTable, SQLiteSchema};
128/// use drizzle_core::ToSQL;
129///
130/// #[SQLiteTable(name = "users")]
131/// struct User {
132/// #[integer(primary)]
133/// id: i32,
134/// #[text]
135/// name: String,
136/// }
137///
138/// #[derive(SQLiteSchema)]
139/// struct Schema {
140/// user: User,
141/// }
142///
143/// let builder = QueryBuilder::new::<Schema>();
144/// let Schema { user } = Schema::new();
145///
146/// // Create a prepared statement and convert to owned
147/// let query = builder.select(user.name).from(user);
148/// let sql = query.to_sql();
149///
150/// // In practice, this conversion would be handled by the database driver
151/// // let prepared: PreparedStatement = driver.prepare(sql)?;
152/// // let owned: OwnedPreparedStatement = prepared.into_owned();
153/// ```
154///
155/// ## Conversion
156///
157/// You can convert between borrowed and owned forms:
158/// - `PreparedStatement::into_owned()` → `OwnedPreparedStatement`
159/// - `OwnedPreparedStatement` → `PreparedStatement` (via `From` trait)
160#[derive(Debug, Clone)]
161pub struct OwnedPreparedStatement {
162 pub inner: CoreOwnedPreparedStatement<crate::values::OwnedSQLiteValue>,
163}
164impl<'a> From<PreparedStatement<'a>> for OwnedPreparedStatement {
165 fn from(value: PreparedStatement<'a>) -> Self {
166 let owned_params = value.inner.params.iter().map(|p| OwnedParam {
167 placeholder: p.placeholder,
168 value: p
169 .value
170 .clone()
171 .map(|v| OwnedSQLiteValue::from(v.into_owned())),
172 });
173 let inner = CoreOwnedPreparedStatement {
174 text_segments: value.inner.text_segments,
175 params: owned_params.collect::<Box<[_]>>(),
176 };
177 Self { inner }
178 }
179}
180
181impl From<OwnedPreparedStatement> for PreparedStatement<'_> {
182 fn from(value: OwnedPreparedStatement) -> Self {
183 let sqlitevalue = value.inner.params.iter().map(|v| {
184 Param::new(
185 v.placeholder,
186 v.value.clone().map(|v| Cow::Owned(SQLiteValue::from(v))),
187 )
188 });
189 let inner = CorePreparedStatement {
190 text_segments: value.inner.text_segments,
191 params: sqlitevalue.collect::<Box<[_]>>(),
192 };
193 PreparedStatement { inner }
194 }
195}
196
197impl OwnedPreparedStatement {}
198
199impl<'a> std::fmt::Display for PreparedStatement<'a> {
200 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
201 write!(f, "{}", self.inner)
202 }
203}
204
205impl std::fmt::Display for OwnedPreparedStatement {
206 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
207 write!(f, "{}", self.inner)
208 }
209}