Expand description
Efficient interface to SQLite that doesn’t get in your way.
§Usage
The two primary methods to interact with an SQLite database through this
crate is through execute and prepare.
The execute function is used for batch statements, and allows for
multiple queries to be specified. prepare only allows for a single
statement to be specified, but in turn permits reading rows and binding
query parameters.
Special consideration needs to be taken about the thread safety of
connections. You can read more about that in the Connection
documentation.
You can find simple examples of this below.
§Examples
examples/persons.rs- A simple table with users, a primary key, inserting and querying.examples/axum.rs- Create an in-memory database connection and serve it usingaxum. This showcases how to properly handle external synchronization for the best performance in a real-world scenario.examples/tokio_async.rs- Usingsqllin an asynchronous context withtokio.
§Connecting and querying
Here is a simple example of setting up an in-memory connection, creating a table, inserting and querying back some rows:
use sqll::{Connection, Result};
let c = Connection::open_in_memory()?;
c.execute(r#"
CREATE TABLE users (name TEXT, age INTEGER);
INSERT INTO users VALUES ('Alice', 42);
INSERT INTO users VALUES ('Bob', 52);
"#)?;
let results = c.prepare("SELECT name, age FROM users ORDER BY age")?
.iter::<(String, u32)>()
.collect::<Result<Vec<_>>>()?;
assert_eq!(results, [("Alice".to_string(), 42), ("Bob".to_string(), 52)]);§The Row trait.
The Row trait can be used to conveniently read rows from a statement
using next. It can be conveniently implemented using the Row
derive.
use sqll::{Connection, Row};
#[derive(Row)]
struct Person<'stmt> {
name: &'stmt str,
age: u32,
}
let mut c = Connection::open_in_memory()?;
c.execute(r#"
CREATE TABLE users (name TEXT, age INTEGER);
INSERT INTO users VALUES ('Alice', 42);
INSERT INTO users VALUES ('Bob', 52);
"#)?;
let mut results = c.prepare("SELECT name, age FROM users ORDER BY age")?;
while let Some(person) = results.next::<Person<'_>>()? {
println!("{} is {} years old", person.name, person.age);
}§The Bind trait.
The Bind trait can be used to conveniently bind parameters to
prepared statements, and it can conveniently be implemented for structs
using the Bind derive.
use sqll::{Bind, Connection, Row};
#[derive(Bind, Row, PartialEq, Debug)]
#[sql(named)]
struct Person<'stmt> {
name: &'stmt str,
age: u32,
}
let c = Connection::open_in_memory()?;
c.execute(r#"
CREATE TABLE persons (name TEXT, age INTEGER);
"#)?;
let mut stmt = c.prepare("INSERT INTO persons (name, age) VALUES (:name, :age)")?;
stmt.execute(Person { name: "Alice", age: 30 })?;
stmt.execute(Person { name: "Bob", age: 40 })?;
let mut query = c.prepare("SELECT name, age FROM persons ORDER BY age")?;
let p = query.next::<Person<'_>>()?;
assert_eq!(p, Some(Person { name: "Alice", age: 30 }));
let p = query.next::<Person<'_>>()?;
assert_eq!(p, Some(Person { name: "Bob", age: 40 }));§Efficient use of prepared Statements
Correct handling of prepared statements are crucial to get good performance out of sqlite. They contain all the state associated with a query and are expensive to construct so they should be re-used.
Using a Prepare::PERSISTENT prepared statement to perform multiple
queries:
use sqll::{Connection, Prepare};
let c = Connection::open_in_memory()?;
c.execute(r#"
CREATE TABLE users (name TEXT, age INTEGER);
INSERT INTO users VALUES ('Alice', 42);
INSERT INTO users VALUES ('Bob', 52);
"#)?;
let mut stmt = c.prepare_with("SELECT * FROM users WHERE age > ?", Prepare::PERSISTENT)?;
let mut rows = Vec::new();
for age in [40, 50] {
stmt.bind(age)?;
while let Some(row) = stmt.next::<(String, i64)>()? {
rows.push(row);
}
}
let expected = vec![
(String::from("Alice"), 42),
(String::from("Bob"), 52),
(String::from("Bob"), 52),
];
assert_eq!(rows, expected);§Use in asynchronous contexts
In order for sqlite to be used in asynchronous contexts, the Statement
object usually needs to be Send and external synchronization necessary.
Since sqlite is a synchronous library we have to defer any work done to a
thread pool such as the one provided by tokio::task::spawn_blocking. To
make a Statement Send you can use Statement::into_send, but using
it is unsafe since correct behavior depends on the build and runtime
configuration of the sqlite library in use.
See the tokio_async example for a complete example.
§Features
std- Enable usage of the Rust standard library. Enabled by default.alloc- Enable usage of the Rust alloc library. This is required and is enabled by default. Disabling this option will currently cause a compile error.derive- Add a dependency to and re-export of theRowderive macro.bundled- Use a bundled version of sqlite. The bundle is provided by thesqll-syscrate and the sqlite version used is part of the build metadata of that crate1.threadsafe- Enable usage of sqlite with the threadsafe option set. We assume any system level libraries have this build option enabled. If this is disabled thebundledfeature has to be enabled. Ifthreadsafeis disabled,ConnectionandStatementdoes not implementSend. But it is also important to understand that if this option is not set, sqlite may not be used by multiple threads at all even if threads have distinct connections. To disable mutexes which allows for efficient one connection per thread theOpenOptions::no_mutexoption should be used instead1.strict- Enable usage of sqlite with the strict compiler options enabled1.
§License
This is a rewrite of the sqlite crate, and components used from there
have been copied under the MIT license.
This is a forwarded sqll-sys option, see https://docs.rs/sqll-sys. ↩ 1 2 3
Modules§
- ty
- Module used which provides marker types for use with the
Typeassociated type inFromColumnorFromUnsizedColumn.
Structs§
- Capacity
Error - Error raised when failing to convert a string into a
FixedBlob. - Code
- Error code.
- Connection
- A SQLite database connection.
- Database
NotFound - Indicates that a database was not found.
- Error
- An error.
- Fixed
Blob - A byte slice type which can store at most
Nbytes from a column. - Fixed
Text - A
Texttype which can store at mostNbytes from a column. - NotThread
Safe - Error raised when attempting to convert a database object into a thread-safe container, but the database is not configured to be thread-safe.
- Null
- A marker type representing NULL.
- Open
Options - Opening an SQLite connection.
- Prepare
- A collection of flags use to prepare a statement.
- Send
Connection - A
Connectionthat can be sent between threads. - Send
Statement - A
Statementthat can be sent between threads. - Statement
- A prepared statement.
- Text
- A SQLite text value.
- Value
- A dynamic value.
- Value
Type - The type of a value.
Enums§
- State
- The state after stepping a statement.
Constants§
- BIND_
INDEX - The first index used when binding parameters into a
Statement.
Traits§
- Bind
- This allows a type to be used for structured binding of multiple parameters
into a
Statementusingbind. - Bind
Value - A type suitable for binding to a prepared statement.
- From
Column - A type suitable for reading a single value from a prepared statement.
- From
Unsized Column - A type suitable for borrow directly out of a prepared statement.
- Row
- This allows a type to be constructed from a
Statementusingnext,iter, orrow.
Functions§
- lib_
version - Return the version string of the SQLite library in use.
- lib_
version_ number - Return the version number of the SQLite library in use.
Type Aliases§
- Result
- A result type alias.