sqlx_core_oldapi/sqlite/connection/
mod.rs1use std::cmp::Ordering;
2use std::fmt::{self, Debug, Formatter};
3use std::ptr::NonNull;
4
5use futures_core::future::BoxFuture;
6use futures_intrusive::sync::MutexGuard;
7use futures_util::future;
8use libsqlite3_sys::sqlite3;
9
10pub(crate) use handle::{ConnectionHandle, ConnectionHandleRaw};
11
12use crate::common::StatementCache;
13use crate::connection::{Connection, LogSettings};
14use crate::error::Error;
15use crate::sqlite::connection::establish::EstablishParams;
16use crate::sqlite::connection::worker::ConnectionWorker;
17use crate::sqlite::statement::VirtualStatement;
18use crate::sqlite::{Sqlite, SqliteConnectOptions};
19use crate::transaction::Transaction;
20
21pub(crate) mod collation;
22pub(crate) mod describe;
23pub(crate) mod establish;
24pub(crate) mod execute;
25mod executor;
26mod explain;
27pub(crate) mod function;
28mod handle;
29
30mod worker;
31
32pub struct SqliteConnection {
43 pub(crate) worker: ConnectionWorker,
44 pub(crate) row_channel_size: usize,
45}
46
47pub struct LockedSqliteHandle<'a> {
48 pub(crate) guard: MutexGuard<'a, ConnectionState>,
49}
50
51pub(crate) struct ConnectionState {
52 pub(crate) handle: ConnectionHandle,
53
54 pub(crate) transaction_depth: usize,
56
57 pub(crate) statements: Statements,
58
59 log_settings: LogSettings,
60}
61
62pub(crate) struct Statements {
63 cached: StatementCache<VirtualStatement>,
65 temp: Option<VirtualStatement>,
67}
68
69impl SqliteConnection {
70 pub(crate) async fn establish(options: &SqliteConnectOptions) -> Result<Self, Error> {
71 let params = EstablishParams::from_options(options)?;
72 let worker = ConnectionWorker::establish(params).await?;
73 Ok(Self {
74 worker,
75 row_channel_size: options.row_channel_size,
76 })
77 }
78
79 #[deprecated = "Unsynchronized access is unsafe. See documentation for details."]
88 pub fn as_raw_handle(&mut self) -> *mut sqlite3 {
89 self.worker.handle_raw.as_ptr()
90 }
91
92 #[deprecated = "Completes asynchronously. See documentation for details."]
115 pub fn create_collation(
116 &mut self,
117 name: &str,
118 compare: impl Fn(&str, &str) -> Ordering + Send + Sync + 'static,
119 ) -> Result<(), Error> {
120 self.worker.create_collation(name, compare)
121 }
122
123 pub async fn lock_handle(&mut self) -> Result<LockedSqliteHandle<'_>, Error> {
128 let guard = self.worker.unlock_db().await?;
129
130 Ok(LockedSqliteHandle { guard })
131 }
132}
133
134impl Debug for SqliteConnection {
135 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
136 f.debug_struct("SqliteConnection")
137 .field("row_channel_size", &self.row_channel_size)
138 .field("cached_statements_size", &self.cached_statements_size())
139 .finish()
140 }
141}
142
143impl Connection for SqliteConnection {
144 type Database = Sqlite;
145
146 type Options = SqliteConnectOptions;
147
148 fn close(mut self) -> BoxFuture<'static, Result<(), Error>> {
149 Box::pin(async move {
150 let shutdown = self.worker.shutdown();
151 drop(self);
154 shutdown.await
156 })
157 }
158
159 fn close_hard(self) -> BoxFuture<'static, Result<(), Error>> {
160 Box::pin(async move {
161 drop(self);
162 Ok(())
163 })
164 }
165
166 fn ping(&mut self) -> BoxFuture<'_, Result<(), Error>> {
168 Box::pin(self.worker.ping())
169 }
170
171 fn begin(&mut self) -> BoxFuture<'_, Result<Transaction<'_, Self::Database>, Error>>
172 where
173 Self: Sized,
174 {
175 Transaction::begin(self)
176 }
177
178 fn cached_statements_size(&self) -> usize {
179 self.worker
180 .shared
181 .cached_statements_size
182 .load(std::sync::atomic::Ordering::Acquire)
183 }
184
185 fn clear_cached_statements(&mut self) -> BoxFuture<'_, Result<(), Error>> {
186 Box::pin(async move {
187 self.worker.clear_cache().await?;
188 Ok(())
189 })
190 }
191
192 #[doc(hidden)]
193 fn flush(&mut self) -> BoxFuture<'_, Result<(), Error>> {
194 Box::pin(future::ok(()))
199 }
200
201 #[doc(hidden)]
202 fn should_flush(&self) -> bool {
203 false
204 }
205
206 fn dbms_name(&mut self) -> BoxFuture<'_, Result<String, Error>> {
207 Box::pin(async move { Ok("SQLite".to_string()) })
208 }
209}
210
211impl LockedSqliteHandle<'_> {
212 pub fn as_raw_handle(&mut self) -> NonNull<sqlite3> {
217 self.guard.handle.as_non_null_ptr()
218 }
219
220 pub fn create_collation(
224 &mut self,
225 name: &str,
226 compare: impl Fn(&str, &str) -> Ordering + Send + Sync + 'static,
227 ) -> Result<(), Error> {
228 collation::create_collation(&mut self.guard.handle, name, compare)
229 }
230
231 pub fn create_function(&mut self, function: function::Function) -> Result<(), Error> {
234 function.create(&mut self.guard.handle)
235 }
236}
237
238impl Drop for ConnectionState {
239 fn drop(&mut self) {
240 self.statements.clear();
242 }
243}
244
245impl Statements {
246 fn new(capacity: usize) -> Self {
247 Statements {
248 cached: StatementCache::new(capacity),
249 temp: None,
250 }
251 }
252
253 fn get(&mut self, query: &str, persistent: bool) -> Result<&mut VirtualStatement, Error> {
254 if !persistent || !self.cached.is_enabled() {
255 return Ok(self.temp.insert(VirtualStatement::new(query, false)?));
256 }
257
258 let exists = self.cached.contains_key(query);
259
260 if !exists {
261 let statement = VirtualStatement::new(query, true)?;
262 self.cached.insert(query, statement);
263 }
264
265 let statement = self.cached.get_mut(query).unwrap();
266
267 if exists {
268 statement.reset()?;
270 }
271
272 Ok(statement)
273 }
274
275 fn len(&self) -> usize {
276 self.cached.len()
277 }
278
279 fn clear(&mut self) {
280 self.cached.clear();
281 self.temp = None;
282 }
283}