Rusqlite
Rusqlite is an ergonomic wrapper for using SQLite from Rust.
Historically, the API was based on the one from rust-postgres
. However, the two have diverged in many ways, and no compatibility between the two is intended.
Usage
In your Cargo.toml:
[dependencies]
# `bundled` causes us to automatically compile and link in an up to date
# version of SQLite for you. This avoids many common build issues, and
# avoids depending on the version of SQLite on the users system (or your
# system), which may be old or missing. It's the right choice for most
# programs that control their own SQLite databases.
#
# That said, it's not ideal for all scenarios and in particular, generic
# libraries built around `rusqlite` should probably not enable it, which
# is why it is not a default feature -- it could become hard to disable.
rusqlite = { version = "0.29.0", features = ["bundled"] }
Simple example usage:
use rusqlite::{Connection, Result};
#[derive(Debug)]
struct Person {
id: i32,
name: String,
data: Option<Vec<u8>>,
}
fn main() -> Result<()> {
let conn = Connection::open_in_memory()?;
conn.execute(
"CREATE TABLE person (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
data BLOB
)",
(), // empty list of parameters.
)?;
let me = Person {
id: 0,
name: "Steven".to_string(),
data: None,
};
conn.execute(
"INSERT INTO person (name, data) VALUES (?1, ?2)",
(&me.name, &me.data),
)?;
let mut stmt = conn.prepare("SELECT id, name, data FROM person")?;
let person_iter = stmt.query_map([], |row| {
Ok(Person {
id: row.get(0)?,
name: row.get(1)?,
data: row.get(2)?,
})
})?;
for person in person_iter {
println!("Found person {:?}", person.unwrap());
}
Ok(())
}
Supported SQLite Versions
The base rusqlite
package supports SQLite version 3.14.0 or newer. If you need
support for older versions, please file an issue. Some cargo features require a
newer SQLite version; see details below.
Optional Features
Rusqlite provides several features that are behind Cargo features. They are:
load_extension
allows loading dynamic library-based SQLite extensions.backup
allows use of SQLite's online backup API. Note: This feature requires SQLite 3.6.11 or later.functions
allows you to load Rust closures into SQLite connections for use in queries. Note: This feature requires SQLite 3.7.3 or later.window
for window function support (fun(...) OVER ...
). (Impliesfunctions
.)trace
allows hooks into SQLite's tracing and profiling APIs. Note: This feature requires SQLite 3.6.23 or later.blob
givesstd::io::{Read, Write, Seek}
access to SQL BLOBs. Note: This feature requires SQLite 3.7.4 or later.limits
allows you to set and retrieve SQLite's per connection limits.chrono
implementsFromSql
andToSql
for various types from thechrono
crate.serde_json
implementsFromSql
andToSql
for theValue
type from theserde_json
crate.time
implementsFromSql
andToSql
for thetime::OffsetDateTime
type from thetime
crate.url
implementsFromSql
andToSql
for theUrl
type from theurl
crate.bundled
uses a bundled version of SQLite. This is a good option for cases where linking to SQLite is complicated, such as Windows.sqlcipher
looks for the SQLCipher library to link against instead of SQLite. This feature overridesbundled
.bundled-sqlcipher
uses a bundled version of SQLCipher. This searches for and links against a system-installed crypto library to provide the crypto implementation.bundled-sqlcipher-vendored-openssl
allows using bundled-sqlcipher with a vendored version of OpenSSL (via theopenssl-sys
crate) as the crypto provider.- As the name implies this depends on the
bundled-sqlcipher
feature, and automatically turns it on. - If turned on, this uses the
openssl-sys
crate, with thevendored
feature enabled in order to build and bundle the OpenSSL crypto library.
- As the name implies this depends on the
hooks
for Commit, Rollback and Data Change notification callbacks.unlock_notify
for Unlock notification.vtab
for virtual table support (allows you to write virtual table implementations in Rust). Currently, only read-only virtual tables are supported.series
exposesgenerate_series(...)
Table-Valued Function. (Impliesvtab
.)csvtab
, CSV virtual table written in Rust. (Impliesvtab
.)array
, Therarray()
Table-Valued Function. (Impliesvtab
.)i128_blob
allows storing values of typei128
type in SQLite databases. Internally, the data is stored as a 16 byte big-endian blob, with the most significant bit flipped, which allows ordering and comparison between different blobs storing i128s to work as expected.uuid
allows storing and retrievingUuid
values from theuuid
crate using blobs.session
, Session module extension. Requiresbuildtime_bindgen
feature. (Implieshooks
.)extra_check
fail when a query passed to execute is readonly or has a column count > 0.column_decltype
providescolumns()
method for Statements and Rows; omit if linking to a version of SQLite/SQLCipher compiled with-DSQLITE_OMIT_DECLTYPE
.collation
exposessqlite3_create_collation_v2
.winsqlite3
allows linking against the SQLite present in newer versions of Windows
Notes on building rusqlite and libsqlite3-sys
libsqlite3-sys
is a separate crate from rusqlite
that provides the Rust
declarations for SQLite's C API. By default, libsqlite3-sys
attempts to find a SQLite library that already exists on your system using pkg-config, or a
Vcpkg installation for MSVC ABI builds.
You can adjust this behavior in a number of ways:
-
If you use the
bundled
,bundled-sqlcipher
, orbundled-sqlcipher-vendored-openssl
features,libsqlite3-sys
will use the cc crate to compile SQLite or SQLCipher from source and link against that. This source is embedded in thelibsqlite3-sys
crate and is currently SQLite 3.41.2 (as ofrusqlite
0.29.0 /libsqlite3-sys
0.26.0). This is probably the simplest solution to any build problems. You can enable this by adding the following in yourCargo.toml
file:[dependencies.rusqlite] version = "0.29.0" features = ["bundled"]
-
When using any of the
bundled
features, the build script will honorSQLITE_MAX_VARIABLE_NUMBER
andSQLITE_MAX_EXPR_DEPTH
variables. It will also honor aLIBSQLITE3_FLAGS
variable, which can have a format like"-USQLITE_ALPHA -DSQLITE_BETA SQLITE_GAMMA ..."
. That would disable theSQLITE_ALPHA
flag, and set theSQLITE_BETA
andSQLITE_GAMMA
flags. (The initial-D
can be omitted, as on the last one.) -
When using
bundled-sqlcipher
(and not also usingbundled-sqlcipher-vendored-openssl
),libsqlite3-sys
will need to link against crypto libraries on the system. If the build script can find alibcrypto
from OpenSSL or LibreSSL (it will consultOPENSSL_LIB_DIR
/OPENSSL_INCLUDE_DIR
andOPENSSL_DIR
environment variables), it will use that. If building on and for Macs, and none of those variables are set, it will use the system's SecurityFramework instead. -
When linking against a SQLite (or SQLCipher) library already on the system (so not using any of the
bundled
features), you can set theSQLITE3_LIB_DIR
(orSQLCIPHER_LIB_DIR
) environment variable to point to a directory containing the library. You can also set theSQLITE3_INCLUDE_DIR
(orSQLCIPHER_INCLUDE_DIR
) variable to point to the directory containingsqlite3.h
. -
Installing the sqlite3 development packages will usually be all that is required, but the build helpers for pkg-config and vcpkg have some additional configuration options. The default when using vcpkg is to dynamically link, which must be enabled by setting
VCPKGRS_DYNAMIC=1
environment variable before build.vcpkg install sqlite3:x64-windows
will install the required library. -
When linking against a SQLite (or SQLCipher) library already on the system, you can set the
SQLITE3_STATIC
(orSQLCIPHER_STATIC
) environment variable to 1 to request that the library be statically instead of dynamically linked.
Binding generation
We use bindgen to generate the Rust
declarations from SQLite's C header file. bindgen
recommends
running this as part of the build process of libraries that used this. We tried
this briefly (rusqlite
0.10.0, specifically), but it had some annoyances:
- The build time for
libsqlite3-sys
(and thereforerusqlite
) increased dramatically. - Running
bindgen
requires a relatively-recent version of Clang, which many systems do not have installed by default. - Running
bindgen
also requires the SQLite header file to be present.
As of rusqlite
0.10.1, we avoid running bindgen
at build-time by shipping
pregenerated bindings for several versions of SQLite. When compiling
rusqlite
, we use your selected Cargo features to pick the bindings for the
minimum SQLite version that supports your chosen features. If you are using
libsqlite3-sys
directly, you can use the same features to choose which
pregenerated bindings are chosen:
min_sqlite_version_3_14_0
- SQLite 3.14.0 bindings (this is the default)
If you use any of the bundled
features, you will get pregenerated bindings for the
bundled version of SQLite/SQLCipher. If you need other specific pregenerated binding
versions, please file an issue. If you want to run bindgen
at buildtime to
produce your own bindings, use the buildtime_bindgen
Cargo feature.
If you enable the modern_sqlite
feature, we'll use the bindings we would have
included with the bundled build. You generally should have buildtime_bindgen
enabled if you turn this on, as otherwise you'll need to keep the version of
SQLite you link with in sync with what rusqlite would have bundled, (usually the
most recent release of SQLite). Failing to do this will cause a runtime error.
Contributing
Rusqlite has many features, and many of them impact the build configuration in incompatible ways. This is unfortunate, and makes testing changes hard.
To help here: you generally should ensure that you run tests/lint for
--features bundled
, and --features "bundled-full session buildtime_bindgen"
.
If running bindgen is problematic for you, --features bundled-full
enables
bundled and all features which don't require binding generation, and can be used
instead.
Checklist
- Run
cargo fmt
to ensure your Rust code is correctly formatted. - Ensure
cargo clippy --workspace --features bundled
passes without warnings. - Ensure
cargo clippy --workspace --features "bundled-full session buildtime_bindgen"
passes without warnings. - Ensure
cargo test --workspace --features bundled
reports no failures. - Ensure
cargo test --workspace --features "bundled-full session buildtime_bindgen"
reports no failures.
Author
Rusqlite is the product of hard work by a number of people. A list is available here: https://github.com/rusqlite/rusqlite/graphs/contributors
Community
Feel free to join the Rusqlite Discord Server to discuss or get help with rusqlite
or libsqlite3-sys
.
License
Rusqlite and libsqlite3-sys are available under the MIT license. See the LICENSE file for more info.
Licenses of Bundled Software
Depending on the set of enabled cargo features
, rusqlite and libsqlite3-sys will also bundle other libraries, which have their own licensing terms:
-
If
--features=bundled-sqlcipher
is enabled, the vendored source of SQLcipher will be compiled and statically linked in. SQLcipher is distributed under a BSD-style license, as described here. -
If
--features=bundled
is enabled, the vendored source of SQLite will be compiled and linked in. SQLite is in the public domain, as described here.
Both of these are quite permissive, have no bearing on the license of the code in rusqlite
or libsqlite3-sys
themselves, and can be entirely ignored if you do not use the feature in question.