sqlite_ll/lib.rs
1//! [<img alt="github" src="https://img.shields.io/badge/github-udoprog/sqlite--ll-8da0cb?style=for-the-badge&logo=github" height="20">](https://github.com/udoprog/sqlite-ll)
2//! [<img alt="crates.io" src="https://img.shields.io/crates/v/sqlite-ll.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/sqlite-ll)
3//! [<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-sqlite--ll-66c2a5?style=for-the-badge&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K" height="20">](https://docs.rs/sqlite-ll)
4//!
5//! Low-level interface to the [SQLite] database.
6//!
7//! This is a rewrite of the [sqlite crate], and components used from there have
8//! been copied under the MIT license.
9//!
10//! <br>
11//!
12//! ## Why do we need another sqlite interface?
13//!
14//! It is difficult to set up and use prepared statements with existing crates,
15//! because they are all implemented in a manner which requires the caller to
16//! borrow the connection in use.
17//!
18//! Prepared statements can be expensive to create and *should* be cached and
19//! re-used to achieve the best performance. Statements can also benefit from
20//! using the [`Prepare::PERSISTENT`] option This library uses
21//! `sqlite3_close_v2` when the connection is dropped, causing the closing of
22//! the connection to be delayed until resources associated with it has been
23//! closed.
24//!
25//! We've also designed this library to avoid intermediary allocations. So for
26//! example [calling `execute`] doesn't allocate externally of the sqlite3
27//! bindings. This was achieved by porting the execute implementation from the
28//! sqlite library and works because sqlite actually uses UTF-8 internally but
29//! this is not exposed in the legacy C API that other crates use to execute
30//! statements.
31//!
32//! <br>
33//!
34//! ## Example
35//!
36//! Open an in-memory connection, create a table, and insert some rows:
37//!
38//! ```
39//! use sqlite_ll::Connection;
40//!
41//! let c = Connection::memory()?;
42//!
43//! c.execute(
44//! r#"
45//! CREATE TABLE users (name TEXT, age INTEGER);
46//! INSERT INTO users VALUES ('Alice', 42);
47//! INSERT INTO users VALUES ('Bob', 69);
48//! "#,
49//! )?;
50//! # Ok::<_, sqlite_ll::Error>(())
51//! ```
52//!
53//! Querying data using a parepared statement with bindings:
54//!
55//! ```
56//! use sqlite_ll::State;
57//! # use sqlite_ll::Connection;
58//! # let c = Connection::memory()?;
59//! # c.execute(r#"
60//! # CREATE TABLE users (name TEXT, age INTEGER);
61//! # INSERT INTO users VALUES ('Alice', 42);
62//! # INSERT INTO users VALUES ('Bob', 69);
63//! # "#)?;
64//! let mut stmt = c.prepare("SELECT * FROM users WHERE age > ?")?;
65//!
66//! let mut results = Vec::new();
67//!
68//! for age in [40, 50] {
69//! stmt.reset()?;
70//! stmt.bind(1, age)?;
71//!
72//! while let State::Row = stmt.step()? {
73//! results.push((stmt.read::<String>(0)?, stmt.read::<i64>(1)?));
74//! }
75//! }
76//!
77//! let expected = vec![
78//! (String::from("Alice"), 42),
79//! (String::from("Bob"), 69),
80//! (String::from("Bob"), 69),
81//! ];
82//!
83//! assert_eq!(results, expected);
84//! # Ok::<_, sqlite_ll::Error>(())
85//! ```
86//!
87//! [`Prepare::PERSISTENT`]: enum.Prepare.html#variant.PERSISTENT
88//! [calling `execute`]: struct.Connection.html#method.execute
89//! [sqlite crate]: https://github.com/stainless-steel/sqlite
90//! [SQLite]: https://www.sqlite.org
91
92#![no_std]
93#![allow(clippy::should_implement_trait)]
94
95#[cfg(feature = "std")]
96extern crate std;
97
98#[cfg(feature = "alloc")]
99extern crate alloc;
100
101#[cfg(not(feature = "alloc"))]
102compile_error!("The `alloc` feature must be enabled to use this crate.");
103
104#[cfg(test)]
105mod tests;
106
107mod bindable;
108mod bytes;
109mod connection;
110mod error;
111mod fixed_bytes;
112mod owned;
113mod readable;
114mod statement;
115mod utils;
116mod value;
117mod writable;
118
119#[doc(inline)]
120pub use self::bindable::Bindable;
121#[doc(inline)]
122pub use self::connection::{Connection, OpenOptions, Prepare};
123#[doc(inline)]
124pub use self::error::{Code, Error, Result};
125#[doc(inline)]
126pub use self::fixed_bytes::FixedBytes;
127#[doc(inline)]
128pub use self::readable::Readable;
129#[doc(inline)]
130pub use self::statement::{Null, State, Statement};
131#[doc(inline)]
132pub use self::value::{Type, Value};
133#[doc(inline)]
134pub use self::writable::Writable;
135
136/// Return the version number of SQLite.
137///
138/// For instance, the version `3.8.11.1` corresponds to the integer `3008011`.
139#[inline]
140pub fn version() -> u64 {
141 unsafe { sqlite3_sys::sqlite3_libversion_number() as u64 }
142}