Skip to main content

SendStatement

Struct SendStatement 

Source
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>§

Source

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);
Source

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);
Source

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]);
Source

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);
Source

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);
Source

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);
Source

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);
Source

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());
Source

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);
Source

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);
Source

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"]);
Source

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));
Source

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")));
Source

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);
Source

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);
Source

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());
Source

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);
Source

pub fn unsized_column<T>(&mut self, index: c_int) -> Result<&T>

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"));
    }
}

Trait Implementations§

Source§

impl Debug for SendStatement

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Deref for SendStatement

Source§

type Target = Statement

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.
Source§

impl DerefMut for SendStatement

Source§

fn deref_mut(&mut self) -> &mut Self::Target

Mutably dereferences the value.
Source§

impl Send for SendStatement

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.