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::open_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::open_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`]: https://docs.rs/sqlite-ll/latest/sqlite_ll/struct.Prepare.html#associatedconstant.PERSISTENT
88//! [calling `execute`]: https://docs.rs/sqlite-ll/latest/sqlite_ll/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#![cfg_attr(docsrs, feature(doc_cfg))]
95
96#[cfg(feature = "std")]
97extern crate std;
98
99#[cfg(feature = "alloc")]
100extern crate alloc;
101
102#[cfg(not(feature = "alloc"))]
103compile_error!("The `alloc` feature must be enabled to use this crate.");
104
105#[cfg(test)]
106mod tests;
107
108mod bindable;
109mod bytes;
110mod connection;
111mod error;
112mod fixed_bytes;
113mod owned;
114mod readable;
115mod statement;
116mod utils;
117mod value;
118mod writable;
119
120#[doc(inline)]
121pub use self::bindable::Bindable;
122#[doc(inline)]
123pub use self::connection::{Connection, OpenOptions, Prepare};
124#[doc(inline)]
125pub use self::error::{Code, Error, Result};
126#[doc(inline)]
127pub use self::fixed_bytes::FixedBytes;
128#[doc(inline)]
129pub use self::readable::Readable;
130#[doc(inline)]
131pub use self::statement::{Null, State, Statement};
132#[doc(inline)]
133pub use self::value::{Type, Value};
134#[doc(inline)]
135pub use self::writable::Writable;
136
137/// Return the version number of SQLite.
138///
139/// For instance, the version `3.8.11.1` corresponds to the integer `3008011`.
140#[inline]
141pub fn version() -> u64 {
142    unsafe { sqlite3_sys::sqlite3_libversion_number() as u64 }
143}