sqll/connection.rs
1use core::ffi::CStr;
2#[cfg(feature = "alloc")]
3use core::ffi::c_void;
4use core::ffi::{c_int, c_uint};
5use core::fmt;
6use core::mem::{ManuallyDrop, MaybeUninit};
7use core::ops::{BitOr, Deref, DerefMut};
8use core::ptr::{NonNull, null_mut};
9use core::slice;
10
11#[cfg(feature = "std")]
12use std::path::Path;
13
14use crate::ffi;
15#[cfg(feature = "alloc")]
16use crate::owned::Owned;
17use crate::utils::{c_to_error_text, sqlite3_try};
18use crate::{
19 Code, DatabaseNotFound, Error, NotThreadSafe, OpenOptions, OwnedBytes, Result, Statement, Text,
20};
21
22/// A collection of flags use to prepare a statement.
23pub struct Prepare(c_uint);
24
25impl Prepare {
26 /// No flags.
27 ///
28 /// This provides the default behavior when preparing a statement.
29 pub const EMPTY: Self = Self(0);
30
31 /// The PERSISTENT flag is a hint to the query planner that the prepared
32 /// statement will be retained for a long time and probably reused many
33 /// times. Without this flag, [`Connection::prepare`] assume that the
34 /// prepared statement will be used just once or at most a few times and
35 /// then destroyed relatively soon.
36 ///
37 /// The current implementation acts on this hint by avoiding the use of
38 /// lookaside memory so as not to deplete the limited store of lookaside
39 /// memory. Future versions of SQLite may act on this hint differently.
40 pub const PERSISTENT: Self = Self(ffi::SQLITE_PREPARE_PERSISTENT as c_uint);
41
42 /// The NORMALIZE flag is a no-op. This flag used to be required for any
43 /// prepared statement that wanted to use the normalized sql interface.
44 /// However, the normalized sql interface is now available to all prepared
45 /// statements, regardless of whether or not they use this flag.
46 pub const NORMALIZE: Self = Self(ffi::SQLITE_PREPARE_NORMALIZE as c_uint);
47
48 /// The NO_VTAB flag causes the SQL compiler to return an error if the
49 /// statement uses any virtual tables.
50 pub const NO_VTAB: Self = Self(ffi::SQLITE_PREPARE_NO_VTAB as c_uint);
51}
52
53impl BitOr for Prepare {
54 type Output = Self;
55
56 fn bitor(self, rhs: Self) -> Self::Output {
57 Self(self.0 | rhs.0)
58 }
59}
60
61/// A SQLite database connection.
62///
63/// For detailed information on how to safetly use a connection, including
64/// complex topics such as *Thread Safety* and asynchronous use, see
65/// [`OpenOptions`].
66///
67/// # Examples
68///
69/// Opening a connection to a filesystem path:
70///
71/// ```no_run
72/// use sqll::Connection;
73///
74/// let c = Connection::open("database.db")?;
75///
76/// c.execute(r#"
77/// CREATE TABLE test (id INTEGER);
78/// "#)?;
79/// # Ok::<_, sqll::Error>(())
80/// ```
81///
82/// Opening an in-memory database:
83///
84/// ```
85/// use sqll::Connection;
86///
87/// let c = Connection::open_in_memory()?;
88///
89/// c.execute(r#"
90/// CREATE TABLE test (id INTEGER);
91/// "#)?;
92/// # Ok::<_, sqll::Error>(())
93/// ```
94pub struct Connection {
95 raw: NonNull<ffi::sqlite3>,
96 #[cfg(feature = "alloc")]
97 busy_callback: Option<Owned>,
98 is_thread_safe: bool,
99}
100
101/// Connection is `Send`.
102#[cfg(feature = "threadsafe")]
103unsafe impl Send for Connection {}
104
105impl Connection {
106 /// Construct a connection from a raw pointer.
107 #[inline]
108 pub(crate) fn from_raw(raw: NonNull<ffi::sqlite3>, is_thread_safe: bool) -> Self {
109 Self {
110 raw,
111 #[cfg(feature = "alloc")]
112 busy_callback: None,
113 is_thread_safe,
114 }
115 }
116
117 /// Coerce this statement into a [`SendConnection`] which can be sent across
118 /// threads.
119 ///
120 /// # Errors
121 ///
122 /// This return an error if neither [`full_mutex`] or [`no_mutex`] are set,
123 /// or if the sqlite library is not configured to be thread safe.
124 ///
125 /// ```
126 /// use sqll::OpenOptions;
127 ///
128 /// let mut c = OpenOptions::new()
129 /// .create()
130 /// .read_write()
131 /// .open_in_memory()?;
132 ///
133 /// let e = unsafe { c.into_send().unwrap_err() };
134 /// assert!(matches!(e, sqll::NotThreadSafe { .. }));
135 /// # Ok::<_, sqll::Error>(())
136 /// ```
137 ///
138 /// [`full_mutex`]: crate::OpenOptions::full_mutex
139 /// [`no_mutex`]: crate::OpenOptions::no_mutex
140 ///
141 /// # Safety
142 ///
143 /// This is unsafe because it required that the caller ensures that any
144 /// database objects are synchronized. The exact level of synchronization
145 /// depends on how the connection was opened:
146 /// * If [`full_mutex`] was set and [`no_mutex`] was not set, no external
147 /// synchronization is necessary, but calls to the statement might block
148 /// if it's busy.
149 /// * If [`no_mutex`] was set, the caller must ensure that the [`Statement`]
150 /// is fully synchronized with respect to the connection that constructed
151 /// it. One way to achieve this is to wrap all the statements behind a
152 /// single mutex.
153 ///
154 /// [`full_mutex`]: crate::OpenOptions::full_mutex
155 /// [`no_mutex`]: crate::OpenOptions::no_mutex
156 ///
157 /// # Examples
158 ///
159 /// The following example showcases how you can share a single connection in
160 /// a multi-threaded asynchronous application.
161 ///
162 /// > In this example, statements are compiled and executed on-the-fly. See
163 /// > [`Statement::into_send`] for an example which is more idiomatic and
164 /// > uses prepared statement.
165 ///
166 /// ```
167 /// use std::sync::Arc;
168 /// use sqll::{OpenOptions, SendConnection};
169 /// use anyhow::Result;
170 /// use tokio::task;
171 /// use tokio::sync::Mutex;
172 ///
173 /// #[derive(Clone)]
174 /// struct Database {
175 /// c: Arc<Mutex<SendConnection>>,
176 /// }
177 ///
178 /// fn setup_database() -> Result<Database> {
179 /// let c = OpenOptions::new()
180 /// .create()
181 /// .read_write()
182 /// .no_mutex()
183 /// .open_in_memory()?;
184 ///
185 /// c.execute(
186 /// r#"
187 /// CREATE TABLE users (name TEXT PRIMARY KEY NOT NULL, age INTEGER);
188 ///
189 /// INSERT INTO users VALUES ('Alice', 60), ('Bob', 70), ('Charlie', 20);
190 /// "#,
191 /// )?;
192 ///
193 /// // SAFETY: We serialize all accesses to the connection behind a mutex.
194 /// let c = unsafe {
195 /// c.into_send()?
196 /// };
197 ///
198 /// Ok(Database {
199 /// c: Arc::new(Mutex::new(c)),
200 /// })
201 /// }
202 ///
203 /// #[tokio::main]
204 /// async fn main() -> Result<()> {
205 /// let db = setup_database()?;
206 ///
207 /// let mut tasks = Vec::new();
208 ///
209 /// for _ in 0..10 {
210 /// _ = task::spawn({
211 /// let db = db.clone();
212 ///
213 /// async move {
214 /// let mut c = db.c.lock_owned().await;
215 ///
216 /// let task = task::spawn_blocking(move || {
217 /// let mut update = c.prepare("UPDATE users SET age = age + ?")?;
218 /// update.execute(2)
219 /// });
220 ///
221 /// Ok::<_, anyhow::Error>(task.await??)
222 /// }
223 /// });
224 ///
225 /// let t = task::spawn({
226 /// let db = db.clone();
227 ///
228 /// async move {
229 /// let mut c = db.c.lock_owned().await;
230 ///
231 /// let task = task::spawn_blocking(move || -> Result<Option<i64>> {
232 /// let mut select = c.prepare("SELECT age FROM users ORDER BY age")?;
233 /// Ok(select.next::<i64>()?)
234 /// });
235 ///
236 /// task.await?
237 /// }
238 /// });
239 ///
240 /// tasks.push(t);
241 /// }
242 ///
243 /// for t in tasks {
244 /// let first = t.await??;
245 /// assert!(matches!(first, Some(20..=40)));
246 /// }
247 ///
248 /// Ok(())
249 /// }
250 /// ```
251 pub unsafe fn into_send(self) -> Result<SendConnection, NotThreadSafe> {
252 if !self.is_thread_safe {
253 return Err(NotThreadSafe::connection());
254 }
255
256 Ok(SendConnection { inner: self })
257 }
258
259 /// Open a database to the given path.
260 ///
261 /// Note that it is possible to open an in-memory database by passing
262 /// `":memory:"` here, this call might require allocating depending on the
263 /// platform, so it should be avoided in favor of using [`open_in_memory`]. To avoid
264 /// allocating for regular paths, you can use [`open_c_str`], however you
265 /// are responsible for ensuring the c-string is a valid path.
266 ///
267 /// This is the same as calling:
268 ///
269 /// ```
270 /// use sqll::OpenOptions;
271 /// # let path = ":memory:";
272 ///
273 /// let c = OpenOptions::new()
274 /// .extended_result_codes()
275 /// .read_write()
276 /// .create()
277 /// .open(path)?;
278 ///
279 /// # Ok::<_, sqll::Error>(())
280 /// ```
281 ///
282 /// [`open_in_memory`]: Self::open_in_memory
283 /// [`open_c_str`]: Self::open_c_str
284 #[cfg(feature = "std")]
285 #[cfg_attr(docsrs, cfg(feature = "std"))]
286 #[inline]
287 pub fn open(path: impl AsRef<Path>) -> Result<Connection> {
288 OpenOptions::new()
289 .extended_result_codes()
290 .read_write()
291 .create()
292 .open(path)
293 }
294
295 /// Open a database connection with a raw c-string.
296 ///
297 /// This can be used to open in-memory databases by passing `c":memory:"` or
298 /// a regular open call with a filesystem path like
299 /// `c"/path/to/database.sql"`.
300 ///
301 /// This is the same as calling:
302 ///
303 /// ```
304 /// use sqll::OpenOptions;
305 /// # let name = c":memory:";
306 ///
307 /// let c = OpenOptions::new()
308 /// .extended_result_codes()
309 /// .read_write()
310 /// .create()
311 /// .open_c_str(name)?;
312 ///
313 /// # Ok::<_, sqll::Error>(())
314 /// ```
315 #[inline]
316 pub fn open_c_str(name: &CStr) -> Result<Connection> {
317 OpenOptions::new()
318 .extended_result_codes()
319 .read_write()
320 .create()
321 .open_c_str(name)
322 }
323
324 /// Open an in-memory database.
325 ///
326 /// This is the same as calling
327 ///
328 /// This is the same as calling:
329 ///
330 /// ```
331 /// use sqll::OpenOptions;
332 ///
333 /// let c = OpenOptions::new()
334 /// .extended_result_codes()
335 /// .read_write()
336 /// .create()
337 /// .open_in_memory()?;
338 ///
339 /// # Ok::<_, sqll::Error>(())
340 /// ```
341 #[inline]
342 pub fn open_in_memory() -> Result<Connection> {
343 OpenOptions::new()
344 .extended_result_codes()
345 .read_write()
346 .create()
347 .open_in_memory()
348 }
349
350 /// Check if the database connection is read-only.
351 ///
352 /// # Examples
353 ///
354 /// ```
355 /// use sqll::{Connection, Code, OpenOptions, DatabaseNotFound};
356 ///
357 /// let c = OpenOptions::new().read_write().open_in_memory()?;
358 ///
359 /// assert!(!c.database_read_only(c"main")?);
360 /// let e = c.database_read_only(c"not a db").unwrap_err();
361 /// assert!(matches!(e, DatabaseNotFound { .. }));
362 ///
363 /// let c = OpenOptions::new().read_only().open_in_memory()?;
364 ///
365 /// assert!(c.database_read_only(c"main")?);
366 /// let e = c.database_read_only(c"not a db").unwrap_err();
367 /// assert!(matches!(e, DatabaseNotFound { .. }));
368 /// # Ok::<_, Box<dyn std::error::Error>>(())
369 /// ```
370 pub fn database_read_only(&self, name: &CStr) -> Result<bool, DatabaseNotFound> {
371 unsafe {
372 match ffi::sqlite3_db_readonly(self.raw.as_ptr(), name.as_ptr()) {
373 1 => Ok(true),
374 0 => Ok(false),
375 _ => Err(DatabaseNotFound),
376 }
377 }
378 }
379
380 /// Execute a batch of statements.
381 ///
382 /// Unlike [`prepare`], this can be used to execute multiple statements
383 /// separated by a semi-colon `;` and is internally optimized for one-off
384 /// queries.
385 ///
386 /// [`prepare`]: Self::prepare
387 ///
388 /// # Errors
389 ///
390 /// If any of the statements fail, an error is returned.
391 ///
392 /// ```
393 /// use sqll::{Code, Connection};
394 ///
395 /// let c = Connection::open_in_memory()?;
396 ///
397 /// let e = c.execute(":)").unwrap_err();
398 /// assert_eq!(e.code(), Code::ERROR);
399 /// # Ok::<_, sqll::Error>(())
400 /// ```
401 ///
402 /// # Examples
403 ///
404 /// ```
405 /// use sqll::{Connection, Result};
406 ///
407 /// let c = Connection::open_in_memory()?;
408 ///
409 /// c.execute(r#"
410 /// CREATE TABLE users (name TEXT, age INTEGER);
411 ///
412 /// INSERT INTO users VALUES ('Alice', 42);
413 /// INSERT INTO users VALUES ('Bob', 72);
414 /// "#)?;
415 ///
416 /// let results = c.prepare("SELECT name, age FROM users")?
417 /// .iter::<(String, u32)>()
418 /// .collect::<Result<Vec<_>>>()?;
419 ///
420 /// assert_eq!(results, [("Alice".to_string(), 42), ("Bob".to_string(), 72)]);
421 /// # Ok::<_, sqll::Error>(())
422 /// ```
423 #[inline]
424 pub fn execute(&self, stmt: impl AsRef<[u8]>) -> Result<()> {
425 self.execute_raw(stmt.as_ref())
426 }
427
428 fn execute_raw(&self, stmt: &[u8]) -> Result<()> {
429 unsafe {
430 let mut ptr = stmt.as_ptr().cast();
431 let mut len = stmt.len();
432
433 while len > 0 {
434 let mut raw = MaybeUninit::uninit();
435 let mut rest = MaybeUninit::uninit();
436
437 let l = i32::try_from(len).unwrap_or(i32::MAX);
438
439 sqlite3_try!(
440 self,
441 ffi::sqlite3_prepare_v3(
442 self.raw.as_ptr(),
443 ptr,
444 l,
445 0,
446 raw.as_mut_ptr(),
447 rest.as_mut_ptr(),
448 )
449 );
450
451 let rest = rest.assume_init();
452
453 // If statement is null then it's simply empty, so we can safely
454 // skip it, otherwise iterate over all rows.
455 if let Some(raw) = NonNull::new(raw.assume_init()) {
456 let mut statement = Statement::from_raw(raw, self.is_thread_safe);
457 while statement.step()?.is_row() {}
458 }
459
460 // Skip over empty statements.
461 let o = rest.offset_from_unsigned(ptr);
462 len -= o;
463 ptr = rest;
464 }
465
466 Ok(())
467 }
468 }
469
470 /// Enable or disable extended result codes.
471 ///
472 /// This can also be set during construction with
473 /// [`OpenOptions::extended_result_codes`].
474 ///
475 /// # Examples
476 ///
477 /// ```
478 /// use sqll::{OpenOptions, Code};
479 ///
480 /// let mut c = OpenOptions::new().create().read_write().open_in_memory()?;
481 ///
482 /// let e = c.execute("
483 /// CREATE TABLE users (name TEXT);
484 /// CREATE UNIQUE INDEX idx_users_name ON users (name);
485 ///
486 /// INSERT INTO users VALUES ('Bob');
487 /// ");
488 ///
489 /// let e = c.execute("INSERT INTO users VALUES ('Bob')").unwrap_err();
490 /// assert_eq!(e.code(), Code::CONSTRAINT_UNIQUE);
491 /// assert_eq!(c.error_message(), "UNIQUE constraint failed: users.name");
492 ///
493 /// c.extended_result_codes(false)?;
494 /// let e = c.execute("INSERT INTO users VALUES ('Bob')").unwrap_err();
495 /// assert_eq!(e.code(), Code::CONSTRAINT);
496 /// assert_eq!(c.error_message(), "UNIQUE constraint failed: users.name");
497 /// # Ok::<_, sqll::Error>(())
498 /// ```
499 pub fn extended_result_codes(&mut self, enabled: bool) -> Result<()> {
500 unsafe {
501 let onoff = i32::from(enabled);
502 sqlite3_try!(
503 self,
504 ffi::sqlite3_extended_result_codes(self.raw.as_ptr(), onoff)
505 );
506 }
507
508 Ok(())
509 }
510
511 /// Get the last error message for this connection.
512 ///
513 /// When operating in multi-threaded environment, the error message seen
514 /// here might not correspond to the query that failed unless some kind of
515 /// external synchronization is in use which is the recommended way to use
516 /// sqlite.
517 ///
518 /// This is only meaningful if an error has occured. If no errors have
519 /// occured, this returns a non-erronous message like `"not an error"`
520 /// (default for sqlite3).
521 ///
522 /// # Examples
523 ///
524 /// ```
525 /// use sqll::{Connection, Code};
526 ///
527 /// let c = Connection::open_in_memory()?;
528 ///
529 /// let e = c.execute("
530 /// CREATE TABLE users (name TEXT);
531 /// CREATE UNIQUE INDEX idx_users_name ON users (name);
532 ///
533 /// INSERT INTO users VALUES ('Bob');
534 /// ");
535 ///
536 /// let e = c.execute("INSERT INTO users VALUES ('Bob')").unwrap_err();
537 /// assert_eq!(e.code(), Code::CONSTRAINT_UNIQUE);
538 /// assert_eq!(c.error_message(), "UNIQUE constraint failed: users.name");
539 /// # Ok::<_, sqll::Error>(())
540 /// ```
541 pub fn error_message(&self) -> &Text {
542 unsafe { c_to_error_text(ffi::sqlite3_errmsg(self.raw.as_ptr())) }
543 }
544
545 /// Build a prepared statement with default options.
546 ///
547 /// This is the same as calling `prepare_with` with without setting any
548 /// options.
549 ///
550 /// The database connection will be kept open for the lifetime of this
551 /// statement.
552 ///
553 /// # Errors
554 ///
555 /// If the prepare call contains multiple statements, it will error. To
556 /// execute multiple statements, use [`execute`] instead.
557 ///
558 /// ```
559 /// use sqll::{Connection, Code};
560 ///
561 /// let c = Connection::open_in_memory()?;
562 ///
563 /// let e = c.prepare("CREATE TABLE test (id INTEGER) /* test */; INSERT INTO test (id) VALUES (1);").unwrap_err();
564 ///
565 /// assert_eq!(e.code(), Code::MISUSE);
566 /// # Ok::<_, sqll::Error>(())
567 /// ```
568 ///
569 /// [`execute`]: Self::execute
570 ///
571 /// # Examples
572 ///
573 /// ```
574 /// use sqll::Connection;
575 ///
576 /// let c = Connection::open_in_memory()?;
577 ///
578 /// c.execute(r#"
579 /// CREATE TABLE test (id INTEGER);
580 /// "#)?;
581 ///
582 /// let mut insert_stmt = c.prepare("INSERT INTO test (id) VALUES (?);")?;
583 /// let mut query_stmt = c.prepare("SELECT id FROM test;")?;
584 ///
585 /// drop(c);
586 ///
587 /// insert_stmt.execute(42)?;
588 ///
589 /// query_stmt.bind(())?;
590 /// assert_eq!(query_stmt.iter::<i64>().collect::<Vec<_>>(), [Ok(42)]);
591 /// # Ok::<_, sqll::Error>(())
592 /// ```
593 #[inline]
594 pub fn prepare(&self, stmt: impl AsRef<[u8]>) -> Result<Statement> {
595 self.prepare_raw(stmt.as_ref(), Prepare::EMPTY)
596 }
597
598 /// Build a prepared statement with custom flags.
599 ///
600 /// For long-running statements it is recommended that they have the
601 /// [`Prepare::PERSISTENT`] flag set.
602 ///
603 /// The database connection will be kept open for the lifetime of this
604 /// statement.
605 ///
606 /// # Errors
607 ///
608 /// If the prepare call contains multiple statements, it will error. To
609 /// execute multiple statements, use [`execute`] instead.
610 ///
611 /// ```
612 /// use sqll::{Connection, Code};
613 ///
614 /// let c = Connection::open_in_memory()?;
615 ///
616 /// let e = c.prepare_with("CREATE TABLE test (id INTEGER); INSERT INTO test (id) VALUES (1);")
617 /// .persistent()
618 /// .build()
619 /// .unwrap_err();
620 ///
621 /// assert_eq!(e.code(), Code::MISUSE);
622 /// # Ok::<_, sqll::Error>(())
623 /// ```
624 ///
625 /// [`execute`]: Self::execute
626 ///
627 /// # Examples
628 ///
629 /// ```
630 /// use sqll::Connection;
631 ///
632 /// let c = Connection::open_in_memory()?;
633 ///
634 /// c.execute(r#"
635 /// CREATE TABLE test (id INTEGER);
636 /// "#)?;
637 ///
638 /// let mut insert_stmt = c.prepare_with("INSERT INTO test (id) VALUES (?)")
639 /// .persistent()
640 /// .build()?;
641 ///
642 /// let mut query_stmt = c.prepare_with("SELECT id FROM test")
643 /// .persistent()
644 /// .build()?;
645 ///
646 /// drop(c);
647 ///
648 /// /* .. */
649 ///
650 /// insert_stmt.bind(42)?;
651 /// assert!(insert_stmt.step()?.is_done());
652 ///
653 /// query_stmt.bind(())?;
654 /// assert_eq!(query_stmt.iter::<i64>().collect::<Vec<_>>(), [Ok(42)]);
655 /// # Ok::<_, sqll::Error>(())
656 /// ```
657 pub fn prepare_with<S>(&self, stmt: S) -> PrepareWith<'_, S>
658 where
659 S: AsRef<[u8]>,
660 {
661 PrepareWith {
662 conn: self,
663 stmt,
664 flags: Prepare::EMPTY,
665 }
666 }
667
668 fn prepare_raw(&self, stmt: &[u8], flags: Prepare) -> Result<Statement> {
669 unsafe {
670 let mut raw = MaybeUninit::uninit();
671 let mut rest = MaybeUninit::uninit();
672
673 let ptr = stmt.as_ptr().cast();
674 let len = i32::try_from(stmt.len()).unwrap_or(i32::MAX);
675
676 sqlite3_try! {
677 self,
678 ffi::sqlite3_prepare_v3(
679 self.raw.as_ptr(),
680 ptr,
681 len,
682 flags.0,
683 raw.as_mut_ptr(),
684 rest.as_mut_ptr(),
685 )
686 };
687
688 let rest = rest.assume_init();
689
690 let o = rest.offset_from_unsigned(ptr);
691
692 if o != stmt.len() {
693 return Err(Error::new(
694 Code::MISUSE,
695 "multiple statements in a single prepare are not allowed",
696 ));
697 }
698
699 let raw = NonNull::new_unchecked(raw.assume_init());
700 Ok(Statement::from_raw(raw, self.is_thread_safe))
701 }
702 }
703
704 /// Return the number of rows inserted, updated, or deleted by the most
705 /// recent INSERT, UPDATE, or DELETE statement.
706 ///
707 /// # Examples
708 ///
709 /// ```
710 /// use sqll::Connection;
711 ///
712 /// let c = Connection::open_in_memory()?;
713 ///
714 /// c.execute(r#"
715 /// CREATE TABLE users (name TEXT, age INTEGER);
716 ///
717 /// INSERT INTO users VALUES ('Alice', 42);
718 /// INSERT INTO users VALUES ('Bob', 72);
719 /// "#)?;
720 ///
721 /// assert_eq!(c.changes(), 1);
722 /// # Ok::<_, sqll::Error>(())
723 /// ```
724 #[inline]
725 pub fn changes(&self) -> usize {
726 unsafe { ffi::sqlite3_changes(self.raw.as_ptr()) as usize }
727 }
728
729 /// Return the total number of rows inserted, updated, and deleted by all
730 /// INSERT, UPDATE, and DELETE statements since the connection was opened.
731 ///
732 /// # Examples
733 ///
734 /// ```
735 /// use sqll::Connection;
736 ///
737 /// let c = Connection::open_in_memory()?;
738 ///
739 /// c.execute(r#"
740 /// CREATE TABLE users (name TEXT, age INTEGER);
741 ///
742 /// INSERT INTO users VALUES ('Alice', 42);
743 /// INSERT INTO users VALUES ('Bob', 72);
744 /// "#)?;
745 ///
746 /// assert_eq!(c.total_changes(), 2);
747 /// # Ok::<_, sqll::Error>(())
748 /// ```
749 #[inline]
750 pub fn total_changes(&self) -> usize {
751 unsafe { ffi::sqlite3_total_changes(self.raw.as_ptr()) as usize }
752 }
753
754 /// Return the rowid of the most recent successful INSERT into a rowid table
755 /// or virtual table.
756 ///
757 /// # Examples
758 ///
759 /// If there is no primary key, the last inserted row id is an internal
760 /// identifier for the row:
761 ///
762 /// ```
763 /// use sqll::Connection;
764 ///
765 /// let c = Connection::open_in_memory()?;
766 ///
767 /// c.execute(r#"
768 /// CREATE TABLE users (name TEXT);
769 ///
770 /// INSERT INTO users VALUES ('Alice');
771 /// INSERT INTO users VALUES ('Bob');
772 /// "#)?;
773 /// assert_eq!(c.last_insert_rowid(), 2);
774 ///
775 /// c.execute(r#"
776 /// INSERT INTO users VALUES ('Charlie');
777 /// "#)?;
778 /// assert_eq!(c.last_insert_rowid(), 3);
779 ///
780 /// let mut stmt = c.prepare("INSERT INTO users VALUES (?)")?;
781 /// stmt.execute("Dave")?;
782 ///
783 /// assert_eq!(c.last_insert_rowid(), 4);
784 /// # Ok::<_, sqll::Error>(())
785 /// ```
786 ///
787 /// If there is a primary key, the last inserted row id corresponds to it:
788 ///
789 /// ```
790 /// use sqll::Connection;
791 ///
792 /// let c = Connection::open_in_memory()?;
793 ///
794 /// c.execute(r#"
795 /// CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT);
796 ///
797 /// INSERT INTO users (name) VALUES ('Alice');
798 /// INSERT INTO users (name) VALUES ('Bob');
799 /// "#)?;
800 /// assert_eq!(c.last_insert_rowid(), 2);
801 ///
802 /// c.execute("INSERT INTO users (name) VALUES ('Charlie')")?;
803 /// assert_eq!(c.last_insert_rowid(), 3);
804 ///
805 /// c.execute("INSERT INTO users (name) VALUES ('Dave')")?;
806 /// assert_eq!(c.last_insert_rowid(), 4);
807 ///
808 /// let mut select = c.prepare("SELECT id FROM users WHERE name = ?")?;
809 /// select.bind("Dave")?;
810 ///
811 /// for id in select.iter::<i64>() {
812 /// assert_eq!(id?, 4);
813 /// }
814 ///
815 /// c.execute("DELETE FROM users WHERE id = 3")?;
816 /// assert_eq!(c.last_insert_rowid(), 4);
817 ///
818 /// c.execute("INSERT INTO users (name) VALUES ('Charlie')")?;
819 /// assert_eq!(c.last_insert_rowid(), 5);
820 ///
821 /// select.bind("Charlie")?;
822 ///
823 /// while let Some(id) = select.next::<i64>()? {
824 /// assert_eq!(id, 5);
825 /// }
826 /// # Ok::<_, sqll::Error>(())
827 /// ```
828 #[inline]
829 pub fn last_insert_rowid(&self) -> i64 {
830 unsafe { ffi::sqlite3_last_insert_rowid(self.raw.as_ptr()) }
831 }
832
833 /// Set a callback for handling busy events.
834 ///
835 /// The callback is triggered when the database cannot perform an operation
836 /// due to processing of some other request. If the callback returns `true`,
837 /// the operation will be repeated.
838 ///
839 /// The busy callback should not take any actions which modify the database
840 /// connection that invoked the busy handler. In other words, the busy
841 /// handler is not reentrant. Any such actions result in undefined behavior.
842 ///
843 /// Since this needs to allocate space to store the closure the `alloc`
844 /// feature has to be enabled.
845 ///
846 /// # Examples
847 ///
848 /// ```
849 /// use sqll::Connection;
850 ///
851 /// let mut c = Connection::open_in_memory()?;
852 ///
853 /// c.busy_handler(|attempts| {
854 /// println!("busy attempt: {attempts}");
855 /// attempts < 5
856 /// })?;
857 /// # Ok::<_, sqll::Error>(())
858 /// ```
859 #[cfg(feature = "alloc")]
860 #[cfg_attr(docsrs, cfg(feature = "alloc"))]
861 pub fn busy_handler<F>(&mut self, callback: F) -> Result<()>
862 where
863 F: FnMut(usize) -> bool + Send + 'static,
864 {
865 extern "C" fn glue<F>(callback: *mut c_void, attempts: c_int) -> c_int
866 where
867 F: FnMut(usize) -> bool,
868 {
869 unsafe {
870 if (*(callback as *mut F))(attempts as usize) {
871 1
872 } else {
873 0
874 }
875 }
876 }
877
878 unsafe {
879 let callback = Owned::new(callback)?;
880
881 let result = ffi::sqlite3_busy_handler(
882 self.raw.as_ptr(),
883 Some(glue::<F>),
884 callback.as_ptr().cast(),
885 );
886
887 // NB: Old callback will be dropped and freed when we set the new
888 // one here.
889 self.busy_callback = Some(callback);
890 sqlite3_try!(self, result);
891 }
892
893 Ok(())
894 }
895
896 /// Clear any previously registered busy handler.
897 ///
898 /// # Examples
899 ///
900 /// ```
901 /// use sqll::Connection;
902 ///
903 /// let mut c = Connection::open_in_memory()?;
904 ///
905 /// c.busy_handler(|attempts| {
906 /// println!("busy attempt: {attempts}");
907 /// attempts < 5
908 /// })?;
909 ///
910 /// c.clear_busy_handler()?;
911 /// # Ok::<_, sqll::Error>(())
912 /// ```
913 #[inline]
914 pub fn clear_busy_handler(&mut self) -> Result<()> {
915 unsafe {
916 sqlite3_try! {
917 self,
918 ffi::sqlite3_busy_handler(
919 self.raw.as_ptr(),
920 None,
921 null_mut()
922 )
923 };
924 }
925
926 #[cfg(feature = "alloc")]
927 {
928 self.busy_callback = None;
929 }
930
931 Ok(())
932 }
933
934 /// Set an implicit callback for handling busy events that tries to repeat
935 /// rejected operations until a timeout expires.
936 ///
937 /// # Examples
938 ///
939 /// ```
940 /// use sqll::Connection;
941 ///
942 /// let mut c = Connection::open_in_memory()?;
943 ///
944 /// c.busy_timeout(5000)?;
945 /// # Ok::<_, sqll::Error>(())
946 /// ```
947 #[inline]
948 pub fn busy_timeout(&mut self, ms: c_int) -> Result<()> {
949 unsafe {
950 sqlite3_try! {
951 self,
952 ffi::sqlite3_busy_timeout(
953 self.raw.as_ptr(),
954 ms
955 )
956 };
957 }
958
959 Ok(())
960 }
961
962 /// Serialize the database to a byte buffer.
963 ///
964 /// The returned buffer is allocated by sqlite and will be freed when
965 /// dropped.
966 ///
967 /// The `name` parameter specifies the name of the database to serialize,
968 /// which is typically `c"main"` for the main database.
969 ///
970 /// # Examples
971 ///
972 /// ```
973 /// use sqll::{Connection, Result};
974 ///
975 /// let c = Connection::open_in_memory()?;
976 ///
977 /// c.execute(r#"
978 /// CREATE TABLE users (name TEXT, age INTEGER);
979 /// INSERT INTO users VALUES ('Alice', 42);
980 /// INSERT INTO users VALUES ('Bob', 72);
981 /// "#)?;
982 ///
983 /// let data = c.serialize(c"main")?;
984 /// assert!(!data.is_empty());
985 ///
986 /// let c2 = Connection::open_in_memory()?;
987 /// c2.deserialize(c"main", data)?;
988 ///
989 /// let results = c2.prepare("SELECT name, age FROM users")?
990 /// .iter::<(String, u32)>()
991 /// .collect::<Result<Vec<_>>>()?;
992 ///
993 /// assert_eq!(results, [("Alice".to_string(), 42), ("Bob".to_string(), 72)]);
994 /// # Ok::<_, sqll::Error>(())
995 /// ```
996 pub fn serialize(&self, name: &CStr) -> Result<OwnedBytes, Error> {
997 unsafe {
998 let mut len = MaybeUninit::uninit();
999
1000 match ffi::sqlite3_serialize(self.raw.as_ptr(), name.as_ptr(), len.as_mut_ptr(), 0) {
1001 ptr if ptr.is_null() => {
1002 Err(Error::new(Code::NOMEM, "failed to serialize database"))
1003 }
1004 ptr => {
1005 let ptr = NonNull::new_unchecked(ptr);
1006 let len = len.assume_init();
1007
1008 let Ok(len) = usize::try_from(len) else {
1009 ffi::sqlite3_free(ptr.as_ptr().cast());
1010
1011 return Err(Error::new(
1012 Code::ERROR,
1013 format_args!(
1014 "failed to serialize database, returned size {len} is non-sensical"
1015 ),
1016 ));
1017 };
1018
1019 Ok(OwnedBytes::from_raw(ptr, len))
1020 }
1021 }
1022 }
1023 }
1024
1025 /// Serialize the database to a byte buffer without copying.
1026 ///
1027 /// This requires that database storage is contiguous in memory which might
1028 /// be difficult to satisfy. One way to do so is if the current database is
1029 /// [`deserialize`] from a previously serialized database (without having
1030 /// been modified).
1031 ///
1032 /// The `name` parameter specifies the name of the database to serialize,
1033 /// which is typically `c"main"` for the main database.
1034 ///
1035 /// [`deserialize`]: Self::deserialize
1036 ///
1037 /// # Safety
1038 ///
1039 /// The returned buffer is valid until the next call to `serialize` or
1040 /// `deserialize`, or until the connection is dropped. Modifying the
1041 /// database in any way might invalidate the returned buffer, so it should
1042 /// be used with care.
1043 ///
1044 /// For a safe variant of this method, see [`serialize`].
1045 ///
1046 /// [`serialize`]: Self::serialize
1047 ///
1048 /// # Examples
1049 ///
1050 /// ```
1051 /// use sqll::{Connection, Result};
1052 ///
1053 /// let c = Connection::open_in_memory()?;
1054 ///
1055 /// c.execute(r#"
1056 /// CREATE TABLE users (name TEXT, age INTEGER);
1057 /// INSERT INTO users VALUES ('Alice', 42);
1058 /// INSERT INTO users VALUES ('Bob', 72);
1059 /// "#)?;
1060 ///
1061 /// let data = c.serialize(c"main")?;
1062 /// assert!(!data.is_empty());
1063 ///
1064 /// let c2 = Connection::open_in_memory()?;
1065 /// c2.deserialize(c"main", data.clone())?;
1066 ///
1067 /// let results = c2.prepare("SELECT name, age FROM users")?
1068 /// .iter::<(String, u32)>()
1069 /// .collect::<Result<Vec<_>>>()?;
1070 ///
1071 /// assert_eq!(results, [("Alice".to_string(), 42), ("Bob".to_string(), 72)]);
1072 ///
1073 /// let data2 = unsafe { c2.serialize_no_copy(c"main")? };
1074 /// assert_eq!(data, *data2);
1075 /// # Ok::<_, sqll::Error>(())
1076 /// ```
1077 pub unsafe fn serialize_no_copy(&self, name: &CStr) -> Result<&[u8], Error> {
1078 unsafe {
1079 let mut len = MaybeUninit::uninit();
1080
1081 match ffi::sqlite3_serialize(
1082 self.raw.as_ptr(),
1083 name.as_ptr(),
1084 len.as_mut_ptr(),
1085 ffi::SQLITE_SERIALIZE_NOCOPY as u32,
1086 ) {
1087 ptr if ptr.is_null() => Err(Error::new(
1088 Code::MISUSE,
1089 "database is not contiguous and cannot be serialized without copying",
1090 )),
1091 ptr => {
1092 let len = len.assume_init();
1093
1094 let Ok(len) = usize::try_from(len) else {
1095 return Err(Error::new(
1096 Code::ERROR,
1097 format_args!(
1098 "failed to serialize database, returned size {len} is non-sensical"
1099 ),
1100 ));
1101 };
1102
1103 Ok(slice::from_raw_parts(ptr.cast(), len))
1104 }
1105 }
1106 }
1107 }
1108
1109 /// Deserialize and take ownership of the specified byte buffer into the
1110 /// database.
1111 ///
1112 /// The `name` parameter specifies the name of the database to deserialize
1113 /// into, which is typically `c"main"` for the main database.
1114 ///
1115 /// The `data` parameter is the byte buffer containing the serialized
1116 /// database, which should be obtained from a previous call to `serialize`
1117 /// or read from a file.
1118 ///
1119 /// # Examples
1120 ///
1121 /// ```
1122 /// use sqll::{Connection, Result};
1123 ///
1124 /// let c = Connection::open_in_memory()?;
1125 ///
1126 /// c.execute(r#"
1127 /// CREATE TABLE users (name TEXT, age INTEGER);
1128 /// INSERT INTO users VALUES ('Alice', 42);
1129 /// INSERT INTO users VALUES ('Bob', 72);
1130 /// "#)?;
1131 ///
1132 /// let data = c.serialize(c"main")?;
1133 /// assert!(!data.is_empty());
1134 ///
1135 /// let c2 = Connection::open_in_memory()?;
1136 /// c2.deserialize(c"main", data)?;
1137 ///
1138 /// let results = c2.prepare("SELECT name, age FROM users")?
1139 /// .iter::<(String, u32)>()
1140 /// .collect::<Result<Vec<_>>>()?;
1141 ///
1142 /// assert_eq!(results, [("Alice".to_string(), 42), ("Bob".to_string(), 72)]);
1143 /// # Ok::<_, sqll::Error>(())
1144 /// ```
1145 pub fn deserialize(&self, name: &CStr, data: OwnedBytes) -> Result<()> {
1146 let data = ManuallyDrop::new(data);
1147
1148 let Ok(len) = i64::try_from(data.len()) else {
1149 return Err(Error::new(
1150 Code::MISUSE,
1151 "length of owned buffer is too large",
1152 ));
1153 };
1154
1155 let Ok(capacity) = i64::try_from(data.capacity()) else {
1156 return Err(Error::new(
1157 Code::MISUSE,
1158 "capacity of owned buffer is too large",
1159 ));
1160 };
1161
1162 unsafe {
1163 sqlite3_try! {
1164 self,
1165 ffi::sqlite3_deserialize(
1166 self.raw.as_ptr(),
1167 name.as_ptr(),
1168 data.as_ptr().cast_mut(),
1169 len,
1170 capacity,
1171 (ffi::SQLITE_DESERIALIZE_FREEONCLOSE | ffi::SQLITE_DESERIALIZE_RESIZEABLE) as u32,
1172 )
1173 };
1174 }
1175
1176 Ok(())
1177 }
1178}
1179
1180impl fmt::Debug for Connection {
1181 #[inline]
1182 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1183 f.debug_struct("Connection")
1184 .field("is_thread_safe", &self.is_thread_safe)
1185 .finish_non_exhaustive()
1186 }
1187}
1188
1189impl Drop for Connection {
1190 #[inline]
1191 #[allow(unused_must_use)]
1192 fn drop(&mut self) {
1193 self.clear_busy_handler();
1194
1195 // Will close the connection unconditionally. The database will stay
1196 // alive until all associated prepared statements have been closed since
1197 // we're using v2.
1198 let code = unsafe { ffi::sqlite3_close_v2(self.raw.as_ptr()) };
1199 debug_assert_eq!(code, ffi::SQLITE_OK);
1200 }
1201}
1202
1203/// A [`Connection`] that can be sent between threads.
1204///
1205/// Constructed using [`Connection::into_send`].
1206pub struct SendConnection {
1207 inner: Connection,
1208}
1209
1210unsafe impl Send for SendConnection {}
1211
1212impl Deref for SendConnection {
1213 type Target = Connection;
1214
1215 #[inline]
1216 fn deref(&self) -> &Self::Target {
1217 &self.inner
1218 }
1219}
1220
1221impl DerefMut for SendConnection {
1222 #[inline]
1223 fn deref_mut(&mut self) -> &mut Self::Target {
1224 &mut self.inner
1225 }
1226}
1227
1228impl fmt::Debug for SendConnection {
1229 #[inline]
1230 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1231 self.inner.fmt(f)
1232 }
1233}
1234
1235/// A builder for customizing a prepared [`Statement`].
1236///
1237/// See [`Connection::prepare_with`] for more details.
1238pub struct PrepareWith<'a, S>
1239where
1240 S: AsRef<[u8]>,
1241{
1242 conn: &'a Connection,
1243 stmt: S,
1244 flags: Prepare,
1245}
1246
1247impl<S> PrepareWith<'_, S>
1248where
1249 S: AsRef<[u8]>,
1250{
1251 /// Set custom flags for the prepared statement.
1252 ///
1253 /// When setting [`Prepare::PERSISTENT`] it is recommended to use
1254 /// [`PrepareWith::persistent`] instead for improved readability.
1255 ///
1256 /// # Examples
1257 ///
1258 /// ```
1259 /// use sqll::{Connection, Prepare};
1260 ///
1261 /// let c = Connection::open_in_memory()?;
1262 ///
1263 /// c.execute(r#"
1264 /// CREATE TABLE test (id INTEGER);
1265 /// "#)?;
1266 ///
1267 /// let mut stmt = c.prepare_with("SELECT id FROM test")
1268 /// .with_flags(Prepare::PERSISTENT | Prepare::NO_VTAB)
1269 /// .build()?;
1270 ///
1271 /// stmt.bind(())?;
1272 /// assert_eq!(stmt.iter::<i64>().collect::<Vec<_>>(), []);
1273 /// # Ok::<_, sqll::Error>(())
1274 /// ```
1275 #[inline]
1276 pub fn with_flags(mut self, flags: Prepare) -> Self {
1277 self.flags = flags;
1278 self
1279 }
1280
1281 /// Set the [`Prepare::PERSISTENT`] flag for the built prepared
1282 /// [`Statement`].
1283 ///
1284 /// # Examples
1285 ///
1286 /// ```
1287 /// use sqll::Connection;
1288 ///
1289 /// let c = Connection::open_in_memory()?;
1290 ///
1291 /// c.execute(r#"
1292 /// CREATE TABLE test (id INTEGER);
1293 /// "#)?;
1294 ///
1295 /// let mut insert_stmt = c.prepare_with("INSERT INTO test (id) VALUES (?)")
1296 /// .persistent()
1297 /// .build()?;
1298 ///
1299 /// let mut query_stmt = c.prepare_with("SELECT id FROM test")
1300 /// .persistent()
1301 /// .build()?;
1302 ///
1303 /// drop(c);
1304 ///
1305 /// /* .. */
1306 ///
1307 /// insert_stmt.bind(42)?;
1308 /// assert!(insert_stmt.step()?.is_done());
1309 ///
1310 /// query_stmt.bind(())?;
1311 /// assert_eq!(query_stmt.iter::<i64>().collect::<Vec<_>>(), [Ok(42)]);
1312 /// # Ok::<_, sqll::Error>(())
1313 /// ```
1314 #[inline]
1315 pub fn persistent(self) -> Self {
1316 self.with_flags(Prepare::PERSISTENT)
1317 }
1318
1319 /// Build the prepared statement.
1320 #[inline]
1321 pub fn build(self) -> Result<Statement> {
1322 self.conn.prepare_raw(self.stmt.as_ref(), self.flags)
1323 }
1324}