pub struct SendStatement { /* private fields */ }Expand description
A Statement that can be sent between threads.
Constructed using Statement::into_send.
Methods from Deref<Target = Statement>§
Sourcepub fn next<'stmt, T>(&'stmt mut self) -> Result<Option<T>>where
T: Row<'stmt>,
pub fn next<'stmt, T>(&'stmt mut self) -> Result<Option<T>>where
T: Row<'stmt>,
Get and read the next row from the statement using the Row
trait.
The Row trait is a convenience trait which is usually
implemented using the Row derive.
Returns None when there are no more rows.
This is a higher level API than step and is less prone to misuse. Note
however that misuse never leads to corrupted data or undefined behavior,
only surprising behavior such as NULL values being auto-converted (see
Statement::step).
Note that since this borrows from a mutable reference, it is not
possible to decode multiple rows that borrow from the statement
simultaneously. This is intentional since the state of the row is stored
in the Statement from which it is returned.
use sqll::{Connection, Row};
#[derive(Row)]
struct Person {
name: String,
age: i64,
}
let c = Connection::open_in_memory()?;
c.execute(r#"
CREATE TABLE users (name TEXT, age INTEGER);
INSERT INTO users VALUES ('Alice', 72);
INSERT INTO users VALUES ('Bob', 40);
"#)?;
let mut stmt = c.prepare("SELECT * FROM users")?;
let a = stmt.next::<Person<'_>>()?;
let b = stmt.next::<Person<'_>>()?;§Examples
use sqll::{Connection, Row};
#[derive(Row)]
struct Person {
name: String,
age: i64,
}
let c = Connection::open_in_memory()?;
c.execute(r#"
CREATE TABLE users (name TEXT, age INTEGER);
INSERT INTO users VALUES ('Alice', 72);
INSERT INTO users VALUES ('Bob', 40);
"#)?;
let mut stmt = c.prepare("SELECT * FROM users WHERE age > ?")?;
let mut results = Vec::new();
for age in [30, 50] {
stmt.bind(age)?;
while let Some(person) = stmt.next::<Person>()? {
results.push((person.name, person.age));
}
}
let expected = [
(String::from("Alice"), 72),
(String::from("Bob"), 40),
(String::from("Alice"), 72),
];
assert_eq!(results, expected);Sourcepub fn step(&mut self) -> Result<State>
pub fn step(&mut self) -> Result<State>
Step the statement.
This is necessary in order to produce rows from a statement. It must be called once before the first row is returned in order for results to be meaningful.
When step returns State::Row it indicates that a row is ready to
read from the statement. When step returns State::Done no more rows
are available.
For a less error-prone alternative, consider using Statement::next.
Trying to read data from a statement which has not been stepped will always result in a NULL value being read which will always result in an error.
use sqll::{Connection, Code};
let c = Connection::open_in_memory()?;
c.execute(r#"
CREATE TABLE users (id INTEGER, name TEXT);
INSERT INTO users (id, name) VALUES (0, 'Alice'), (1, 'Bob');
"#)?;
let mut stmt = c.prepare("SELECT id, name FROM users;")?;
assert_eq!(stmt.column::<i64>(0).unwrap_err().code(), Code::MISMATCH);
assert_eq!(stmt.column::<String>(1).unwrap_err().code(), Code::MISMATCH);
assert!(stmt.step()?.is_row());
assert_eq!(stmt.column::<i64>(0)?, 0);
assert_eq!(stmt.unsized_column::<str>(1)?, "Alice");
assert!(stmt.step()?.is_row());
assert_eq!(stmt.column::<i64>(0)?, 1);
assert_eq!(stmt.unsized_column::<str>(1)?, "Bob");
assert!(stmt.step()?.is_done());
assert_eq!(stmt.column::<i64>(0).unwrap_err().code(), Code::MISMATCH);
assert_eq!(stmt.column::<String>(1).unwrap_err().code(), Code::MISMATCH);§Examples
use sqll::Connection;
let c = Connection::open_in_memory()?;
c.execute(r#"
CREATE TABLE users (name TEXT, age INTEGER);
INSERT INTO users VALUES ('Alice', 72);
INSERT INTO users VALUES ('Bob', 40);
"#)?;
let mut stmt = c.prepare("SELECT * FROM users WHERE age > ?")?;
let mut results = Vec::new();
for age in [30, 50] {
stmt.bind(age)?;
while let Some(row) = stmt.next::<(String, i64)>()? {
results.push(row);
}
}
let expected = [
(String::from("Alice"), 72),
(String::from("Bob"), 40),
(String::from("Alice"), 72),
];
assert_eq!(results, expected);Sourcepub fn execute(&mut self, bind: impl Bind) -> Result<()>
pub fn execute(&mut self, bind: impl Bind) -> Result<()>
In one call bind the specified values, and step until the
current statement reports State::is_done.
This is a convenience wrapper around those operations since they are commonly used together.
To not bind anything, use () as the argument.
§Examples
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', 69);
"#)?;
let mut stmt = c.prepare("UPDATE users SET age = age + 1")?;
stmt.execute(())?;
stmt.execute(())?;
let mut query = c.prepare("SELECT age FROM users ORDER BY name")?;
let results = query.iter::<i64>().collect::<Result<Vec<_>>>()?;
assert_eq!(results, [44, 71]);Sourcepub fn iter<T>(&mut self) -> Iter<'_, T>where
for<'stmt> T: Row<'stmt>,
pub fn iter<T>(&mut self) -> Iter<'_, T>where
for<'stmt> T: Row<'stmt>,
Coerce a statement into a typed iterator over the rows produced by this
statement through the Row trait.
Unlike next, this does not support borrowing from the columns of the
row because in order to allow multiple items to be accessed from the
iterator each row has to be owned. Columns therefore has to used owned
variants such as String or FixedBlob.
§Examples
use sqll::{Connection, Row, Result};
#[derive(Row, Debug, PartialEq)]
struct Person {
name: String,
age: i64,
}
let c = Connection::open_in_memory()?;
c.execute(r#"
CREATE TABLE users (name TEXT, age INTEGER);
INSERT INTO users VALUES ('Alice', 72);
INSERT INTO users VALUES ('Bob', 40);
"#)?;
let mut stmt = c.prepare("SELECT * FROM users WHERE age > 40")?;
stmt.reset()?;
let results = stmt.iter::<(String, i64)>().collect::<Result<Vec<_>>>()?;
let expected = [(String::from("Alice"), 72)];
assert_eq!(results, expected);
stmt.reset()?;
let results = stmt.iter::<Person>().collect::<Result<Vec<_>>>()?;
let expected = [Person { name: String::from("Alice"), age: 72 }];
assert_eq!(results, expected);Sourcepub fn reset(&mut self) -> Result<()>
pub fn reset(&mut self) -> Result<()>
Reset the statement allowing it to be re-executed.
The next call to Statement::step will start over from the first
resulting row again.
Note that resetting a statement doesn’t unset bindings set by
Statement::bind_value. To do this, use
Statement::clear_bindings.
§Examples
use sqll::Connection;
let c = Connection::open_in_memory()?;
c.execute(r#"
CREATE TABLE users (name TEXT, age INTEGER);
INSERT INTO users VALUES ('Alice', 72);
INSERT INTO users VALUES ('Bob', 40);
"#)?;
let mut stmt = c.prepare("SELECT * FROM users WHERE age > ?")?;
let mut results = Vec::new();
for age in [30, 50] {
stmt.bind(age)?;
while let Some(row) = stmt.next::<(String, i64)>()? {
results.push(row);
}
}
let expected = [
(String::from("Alice"), 72),
(String::from("Bob"), 40),
(String::from("Alice"), 72),
];
assert_eq!(results, expected);Sourcepub fn clear_bindings(&mut self) -> Result<()>
pub fn clear_bindings(&mut self) -> Result<()>
Contrary to the intuition of many, Statement::reset does not reset
the bindings on a Statement.
Use this routine to reset all host parameters to NULL.
§Examples
use sqll::Connection;
let c = Connection::open_in_memory()?;
c.execute(r#"
CREATE TABLE users (name TEXT, age INTEGER);
INSERT INTO users VALUES ('Alice', 72);
INSERT INTO users VALUES ('Bob', 40);
"#)?;
let mut stmt = c.prepare("SELECT * FROM users WHERE age > ?")?;
let mut results = Vec::new();
for age in [30, 50] {
stmt.bind(age)?;
while let Some(row) = stmt.next::<(String, i64)>()? {
results.push(row);
}
}
let expected = [
(String::from("Alice"), 72),
(String::from("Bob"), 40),
(String::from("Alice"), 72),
];
assert_eq!(results, expected);Sourcepub fn bind(&mut self, value: impl Bind) -> Result<()>
pub fn bind(&mut self, value: impl Bind) -> Result<()>
Reset the statement and bind values to parameters.
Note that this does not clear the bindings for any previous parameters
unless they are overriden. To clear any previous bindings, use
clear_bindings.
This always binds to the first index, to specify a custom index use
bind_value or configure the Bind derive with #[sqll(index = ..)].
If a statement is stepped without a parameter being bound, the parameter
is bound by sqlite to NULL by default.
§Examples
use sqll::{Connection, Bind};
#[derive(Bind)]
struct Binding<'a> {
name: &'a str,
age: u32,
order_by: &'a str,
}
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', 72);
"#)?;
let mut stmt = c.prepare("SELECT name, age FROM users WHERE name = ? AND age = ? ORDER BY ?")?;
stmt.bind(Binding { name: "Bob", age: 72, order_by: "age" })?;
assert_eq!(stmt.next::<(String, u32)>()?, Some(("Bob".to_string(), 72)));
assert_eq!(stmt.next::<(String, u32)>()?, None);Sourcepub fn bind_value(&mut self, index: c_int, value: impl BindValue) -> Result<()>
pub fn bind_value(&mut self, index: c_int, value: impl BindValue) -> Result<()>
Bind a value to a parameter by index.
If a statement is stepped without a parameter being bound, the parameter
is bound by sqlite to NULL by default.
Bindings are sticky and are not cleared when the statement is reset.
To explicitly clear bindings you have to call clear_bindings.
§Errors
The first parameter has index 1, attempting to bind to 0 will result in an error.
use sqll::{Connection, Code};
let c = Connection::open_in_memory()?;
c.execute(r#"
CREATE TABLE users (name STRING)
"#);
let mut stmt = c.prepare("SELECT * FROM users WHERE name = ?")?;
let e = stmt.bind_value(0, "Bob").unwrap_err();
assert_eq!(e.code(), Code::RANGE);§Examples
use sqll::{Connection, Code};
let c = Connection::open_in_memory()?;
c.execute(r#"
CREATE TABLE users (name STRING)
"#);
let mut stmt = c.prepare("SELECT * FROM users WHERE name = ?")?;
stmt.bind_value(1, "Bob")?;
assert!(stmt.step()?.is_done());Sourcepub fn bind_parameter_index(&self, parameter: impl AsRef<CStr>) -> Option<c_int>
pub fn bind_parameter_index(&self, parameter: impl AsRef<CStr>) -> Option<c_int>
Return the index for a named parameter if exists.
Note that this takes a c-string as the parameter name since that is what
the underlying API expects. To accomodate this, you can make use of the
c"string" syntax.
§Examples
use sqll::Connection;
let c = Connection::open_in_memory()?;
c.execute(r#"
CREATE TABLE users (name STRING)
"#);
let stmt = c.prepare("SELECT * FROM users WHERE name = :name")?;
assert_eq!(stmt.bind_parameter_index(c":name"), Some(1));
assert_eq!(stmt.bind_parameter_index(c":asdf"), None);Sourcepub fn column_count(&self) -> c_int
pub fn column_count(&self) -> c_int
Return the number of columns in the result set returned by the
Statement. If this routine returns 0, that means the Statement
returns no data (for example an UPDATE).
However, just because this routine returns a positive number does not mean that one or more rows of data will be returned.
A SELECT statement will always have a positive
column_count but depending on the WHERE clause constraints
and the table content, it might return no rows.
§Examples
use sqll::Connection;
let c = Connection::open_in_memory()?;
c.execute(r#"
CREATE TABLE users (name TEXT, age INTEGER);
"#)?;
let mut select_stmt = c.prepare("SELECT * FROM users")?;
assert_eq!(select_stmt.column_count(), 2);
c.execute(r#"
ALTER TABLE users ADD COLUMN occupation TEXT;
"#)?;
assert_eq!(select_stmt.column_count(), 2);
select_stmt.reset()?;
assert_eq!(select_stmt.column_count(), 2);
// In order to see the new column, we have to prepare a new statement.
let select_stmt = c.prepare("SELECT * FROM users")?;
assert_eq!(select_stmt.column_count(), 3);Sourcepub fn column_name(&self, index: c_int) -> Option<&Text>
pub fn column_name(&self, index: c_int) -> Option<&Text>
Return the name of a column.
Note that column names might internally undergo some normalization by SQLite, since we provide an API where we return UTF-8, if the opened database stores them in UTF-16 an internal conversion will take place.
Since we are not using the UTF-16 APIs, these conversions are cached and are expected to be one way. The returned references are therefore assumed to be valid for the shared lifetime of the statement.
If an invalid index is specified or some other error internal to sqlite
occurs, None is returned.
use sqll::{Connection, Text};
let c = Connection::open_in_memory()?;
c.execute(r#"
CREATE TABLE users (name TEXT, age INTEGER);
"#)?;
let stmt = c.prepare("SELECT * FROM users;")?;
assert_eq!(stmt.column_name(0), Some(Text::new("name")));
assert_eq!(stmt.column_name(1), Some(Text::new("age")));
assert_eq!(stmt.column_name(2), None);§Examples
use sqll::Connection;
let c = Connection::open_in_memory()?;
c.execute(r#"
CREATE TABLE users (name TEXT, age INTEGER);
"#)?;
let stmt = c.prepare("SELECT * FROM users;")?;
let cols = stmt.columns().collect::<Vec<_>>();
assert_eq!(cols, [0, 1]);
assert_eq!(cols.iter().flat_map(|i| stmt.column_name(*i)).collect::<Vec<_>>(), ["name", "age"]);
let cols = stmt.columns().rev().collect::<Vec<_>>();
assert_eq!(cols, [1, 0]);
assert_eq!(cols.iter().flat_map(|i| stmt.column_name(*i)).collect::<Vec<_>>(), ["age", "name"]);Sourcepub fn columns(&self) -> Columns
pub fn columns(&self) -> Columns
Return an iterator of column indexes.
Column names are visible even when a prepared statement has not been
advanced using Statement::step.
§Examples
use sqll::Connection;
let c = Connection::open_in_memory()?;
c.execute(r#"
CREATE TABLE users (name TEXT, age INTEGER);
"#)?;
let stmt = c.prepare("SELECT * FROM users;")?;
let cols = stmt.columns().collect::<Vec<_>>();
assert_eq!(cols, vec![0, 1]);
let cols = stmt.columns().rev().collect::<Vec<_>>();
assert_eq!(cols, vec![1, 0]);
let col = stmt.columns().nth(1);
assert_eq!(col, Some(1));
let col = stmt.columns().rev().nth(1);
assert_eq!(col, Some(0));Sourcepub fn column_names(&self) -> ColumnNames<'_>
pub fn column_names(&self) -> ColumnNames<'_>
Return an iterator of column names.
Column names are visible even when a prepared statement has not been
advanced using Statement::step.
Note that column names might internally undergo some normalization by SQLite, since we provide an API where we return UTF-8, if the opened database stores them in UTF-16 an internal conversion will take place.
Since we are not using the UTF-16 APIs, these conversions are cached and are expected to be one way. The returned references are therefore assumed to be valid for the shared lifetime of the statement.
§Examples
use sqll::{Connection, Text};
let c = Connection::open_in_memory()?;
c.execute(r#"
CREATE TABLE users (name TEXT, age INTEGER, occupation TEXT);
"#)?;
let stmt = c.prepare("SELECT * FROM users;")?;
let column_names = stmt.column_names().collect::<Vec<_>>();
assert_eq!(column_names, vec![Text::new("name"), Text::new("age"), Text::new("occupation")]);
let column_names = stmt.column_names().rev().collect::<Vec<_>>();
assert_eq!(column_names, vec![Text::new("occupation"), Text::new("age"), Text::new("name")]);
let name = stmt.column_names().nth(1);
assert_eq!(name, Some(Text::new("age")));
let name = stmt.column_names().nth(2);
assert_eq!(name, Some(Text::new("occupation")));
let name = stmt.column_names().rev().nth(2);
assert_eq!(name, Some(Text::new("name")));Sourcepub fn column_type(&self, index: c_int) -> ValueType
pub fn column_type(&self, index: c_int) -> ValueType
Return the type of a column.
The first column has index 0. The type becomes available after taking a step.
§Examples
use sqll::{Connection, ValueType};
let c = Connection::open_in_memory()?;
c.execute(r#"
CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, age REAL, photo BLOB);
INSERT INTO users (id, name, age, photo) VALUES (1, 'Bob', 30.5, X'01020304');
"#)?;
let mut stmt = c.prepare("SELECT * FROM users")?;
assert_eq!(stmt.column_type(0), ValueType::NULL);
assert_eq!(stmt.column_type(1), ValueType::NULL);
assert_eq!(stmt.column_type(2), ValueType::NULL);
assert_eq!(stmt.column_type(3), ValueType::NULL);
assert!(stmt.step()?.is_row());
assert_eq!(stmt.column_type(0), ValueType::INTEGER);
assert_eq!(stmt.column_type(1), ValueType::TEXT);
assert_eq!(stmt.column_type(2), ValueType::FLOAT);
assert_eq!(stmt.column_type(3), ValueType::BLOB);
// Since the fifth column does not exist it is always `Null`.
assert_eq!(stmt.column_type(4), ValueType::NULL);Sourcepub fn bind_parameter_name(&self, index: c_int) -> Option<&Text>
pub fn bind_parameter_name(&self, index: c_int) -> Option<&Text>
Return the name for a bind parameter if it exists.
If it does not exit, None is returned.
§Examples
use sqll::{Connection, Text};
let c = Connection::open_in_memory()?;
c.execute(r#"
CREATE TABLE users (name STRING)
"#);
let stmt = c.prepare("SELECT * FROM users WHERE name = :name")?;
assert_eq!(stmt.bind_parameter_name(1), Some(Text::new(":name")));
assert_eq!(stmt.bind_parameter_name(2), None);Sourcepub fn row<'stmt, T>(&'stmt mut self) -> Result<T>where
T: Row<'stmt>,
pub fn row<'stmt, T>(&'stmt mut self) -> Result<T>where
T: Row<'stmt>,
Read a value from the entire row using the Row trait.
This is usually implemented using the Row derive.
§Examples
use sqll::Connection;
let c = Connection::open_in_memory()?;
c.execute(r#"
CREATE TABLE users (name TEXT, age INTEGER);
INSERT INTO users VALUES ('Alice', 72);
INSERT INTO users VALUES ('Bob', 40);
"#)?;
let mut stmt = c.prepare("SELECT name, age FROM users")?;
assert!(stmt.step()?.is_row());
assert_eq!(stmt.row::<(&str, i64)>()?, ("Alice", 72));
assert!(stmt.step()?.is_row());
assert_eq!(stmt.row::<(&str, i64)>()?, ("Bob", 40));
assert!(stmt.step()?.is_done());Sourcepub fn column<'stmt, T>(&'stmt mut self, index: c_int) -> Result<T>where
T: FromColumn<'stmt>,
pub fn column<'stmt, T>(&'stmt mut self, index: c_int) -> Result<T>where
T: FromColumn<'stmt>,
Get a single value from a column through FromColumn.
The first column has index 0. The same column can be read multiple times.
§Examples
use sqll::Connection;
let c = Connection::open_in_memory()?;
c.execute(r#"
CREATE TABLE users (name TEXT, age INTEGER);
INSERT INTO users VALUES ('Alice', 72);
INSERT INTO users VALUES ('Bob', 40);
"#)?;
let mut stmt = c.prepare("SELECT * FROM users WHERE age > ?")?;
let mut results = Vec::new();
for age in [30, 50] {
stmt.bind(age)?;
while stmt.step()?.is_row() {
let name = stmt.column::<String>(0)?;
let age = stmt.column::<i64>(1)?;
results.push((name, age));
}
}
let expected = [
(String::from("Alice"), 72),
(String::from("Bob"), 40),
(String::from("Alice"), 72),
];
assert_eq!(results, expected);Sourcepub fn unsized_column<T>(&mut self, index: c_int) -> Result<&T>where
T: ?Sized + FromUnsizedColumn,
pub fn unsized_column<T>(&mut self, index: c_int) -> Result<&T>where
T: ?Sized + FromUnsizedColumn,
Borrow a value from a column using the FromUnsizedColumn trait.
The first column has index 0. The same column can be read multiple times.
§Examples
use sqll::Connection;
let c = Connection::open_in_memory()?;
c.execute(r#"
CREATE TABLE users (name TEXT, age INTEGER);
INSERT INTO users VALUES ('Alice', 72);
INSERT INTO users VALUES ('Bob', 40);
"#)?;
let mut stmt = c.prepare("SELECT name FROM users WHERE age > ?")?;
for age in [30, 50] {
stmt.bind(age)?;
while stmt.step()?.is_row() {
let name = stmt.unsized_column::<str>(0)?;
assert!(matches!(name, "Alice" | "Bob"));
}
}