sqlite 0.31.1

The package provides an interface to SQLite.
Documentation
extern crate sqlite;

use sqlite::{Connection, State, Statement, Type, Value};

mod common;

use common::{setup_english, setup_users};

macro_rules! ok(($result:expr) => ($result.unwrap()));

#[test]
fn bind_with_index() {
    let connection = setup_users(":memory:");
    let query = "INSERT INTO users VALUES (?, ?, ?, ?, ?)";
    let mut statement = ok!(connection.prepare(query));

    ok!(statement.reset());
    ok!(statement.bind(&[(1, 2i64)][..]));
    ok!(statement.bind((2, "Bob")));
    ok!(statement.bind((3, 69.42)));
    ok!(statement.bind((4, &[0x69u8, 0x42u8][..])));
    ok!(statement.bind((5, ())));
    assert_eq!(ok!(statement.next()), State::Done);

    ok!(statement.reset());
    ok!(statement.bind((1, Some(2i64))));
    ok!(statement.bind((2, Some("Bob"))));
    ok!(statement.bind((3, Some(69.42))));
    ok!(statement.bind((4, Some(&[0x69u8, 0x42u8][..]))));
    ok!(statement.bind((5, None::<&str>)));
    assert_eq!(ok!(statement.next()), State::Done);

    ok!(statement.reset());
    ok!(statement.bind(
        &[
            Value::Integer(2),
            Value::String("Bob".into()),
            Value::Float(69.42),
            Value::Binary([0x69u8, 0x42u8].to_vec()),
            Value::Null,
        ][..]
    ));
    assert_eq!(ok!(statement.next()), State::Done);

    ok!(statement.reset());
    ok!(statement.bind(
        &[
            Some(Value::Integer(2)),
            Some(Value::String("Bob".into())),
            Some(Value::Float(69.42)),
            Some(Value::Binary([0x69u8, 0x42u8].to_vec())),
            Some(Value::Null),
        ][..]
    ));
    assert_eq!(ok!(statement.next()), State::Done);

    ok!(statement.reset());
    ok!(statement.bind(
        &[
            (1, Value::Integer(2)),
            (2, Value::String("Bob".into())),
            (3, Value::Float(69.42)),
            (4, Value::Binary([0x69u8, 0x42u8].to_vec())),
            (5, Value::Null),
        ][..]
    ));
    assert_eq!(ok!(statement.next()), State::Done);
}

#[test]
fn bind_with_name() {
    let connection = setup_users(":memory:");
    let query = "INSERT INTO users VALUES (:id, :name, :age, :photo, :email)";
    let mut statement = ok!(connection.prepare(query));

    ok!(statement.reset());
    ok!(statement.bind(&[(":id", 2i64)][..]));
    ok!(statement.bind((":name", "Bob")));
    ok!(statement.bind((":age", 69.42)));
    ok!(statement.bind((":photo", &[0x69u8, 0x42u8][..])));
    ok!(statement.bind((":email", ())));
    assert_eq!(ok!(statement.next()), State::Done);

    ok!(statement.reset());
    assert!(statement.bind((":missing", 404)).is_err());

    ok!(statement.reset());
    ok!(statement.bind(
        &[
            (":id", Value::Integer(2)),
            (":name", Value::String("Bob".into())),
            (":age", Value::Float(69.42)),
            (":photo", Value::Binary([0x69u8, 0x42u8].to_vec())),
            (":email", Value::Null),
        ][..]
    ));
    assert_eq!(ok!(statement.next()), State::Done);
}

#[test]
fn column_count() {
    let connection = setup_users(":memory:");
    let query = "SELECT * FROM users";
    let mut statement = ok!(connection.prepare(query));

    assert_eq!(ok!(statement.next()), State::Row);
    assert_eq!(statement.column_count(), 5);
}

#[test]
fn column_name() {
    let connection = setup_users(":memory:");
    let query = "SELECT id, name, age, photo AS user_photo FROM users";
    let statement = ok!(connection.prepare(query));

    let names = statement.column_names();
    assert_eq!(names, vec!["id", "name", "age", "user_photo"]);
    assert_eq!("user_photo", ok!(statement.column_name(3)));
}

#[test]
fn column_type() {
    let connection = setup_users(":memory:");
    let query = "SELECT * FROM users";
    let mut statement = ok!(connection.prepare(query));

    assert_eq!(ok!(statement.column_type(0)), Type::Null);
    assert_eq!(ok!(statement.column_type(1)), Type::Null);
    assert_eq!(ok!(statement.column_type(2)), Type::Null);
    assert_eq!(ok!(statement.column_type(3)), Type::Null);

    assert_eq!(ok!(statement.next()), State::Row);

    assert_eq!(ok!(statement.column_type(0)), Type::Integer);
    assert_eq!(ok!(statement.column_type(1)), Type::String);
    assert_eq!(ok!(statement.column_type(2)), Type::Float);
    assert_eq!(ok!(statement.column_type(3)), Type::Binary);
}

#[test]
fn count() {
    let connection = setup_english(":memory:");

    let query = "SELECT value FROM english WHERE value LIKE ?";
    let mut statement = ok!(connection.prepare(query));
    ok!(statement.bind((1, "%type")));
    let mut count = 0;
    while let State::Row = ok!(statement.next()) {
        count += 1;
    }
    assert_eq!(count, 6);

    let query = "SELECT value FROM english WHERE value LIKE '%type'";
    let mut statement = ok!(connection.prepare(query));
    let mut count = 0;
    while let State::Row = ok!(statement.next()) {
        count += 1;
    }
    assert_eq!(count, 6);
}

#[test]
fn parameter_index() {
    let connection = setup_users(":memory:");
    let query = "INSERT INTO users VALUES (:id, :name, :age, :photo, :email)";
    let mut statement = ok!(connection.prepare(query));
    ok!(statement.bind((":id", 2i64)));
    ok!(statement.bind((":name", "Bob")));
    ok!(statement.bind((":age", 69.42)));
    ok!(statement.bind((":photo", &[0x69u8, 0x42u8][..])));
    ok!(statement.bind((":email", ())));
    assert_eq!(ok!(statement.parameter_index(":missing")), None);
    assert_eq!(ok!(statement.next()), State::Done);
}

#[test]
fn read_with_index() {
    let connection = setup_users(":memory:");
    let query = "SELECT * FROM users";
    let mut statement = ok!(connection.prepare(query));

    assert_eq!(ok!(statement.next()), State::Row);
    assert_eq!(ok!(statement.read::<i64, _>(0)), 1);
    assert_eq!(ok!(statement.read::<String, _>(1)), String::from("Alice"));
    assert_eq!(ok!(statement.read::<f64, _>(2)), 42.69);
    assert_eq!(ok!(statement.read::<Vec<u8>, _>(3)), vec![0x42, 0x69]);
    assert_eq!(ok!(statement.read::<Value, _>(4)), Value::Null);
    assert_eq!(ok!(statement.next()), State::Done);
}

#[test]
fn read_with_index_and_option() {
    let connection = setup_users(":memory:");
    let query = "SELECT * FROM users";
    let mut statement = ok!(connection.prepare(query));

    assert_eq!(ok!(statement.next()), State::Row);
    assert_eq!(ok!(statement.read::<Option<i64>, _>(0)), Some(1));
    assert_eq!(
        ok!(statement.read::<Option<String>, _>(1)),
        Some(String::from("Alice"))
    );
    assert_eq!(ok!(statement.read::<Option<f64>, _>(2)), Some(42.69));
    assert_eq!(
        ok!(statement.read::<Option<Vec<u8>>, _>(3)),
        Some(vec![0x42, 0x69])
    );
    assert_eq!(ok!(statement.read::<Option<String>, _>(4)), None);
    assert_eq!(ok!(statement.next()), State::Done);
}

#[test]
fn read_with_name_and_option() {
    let connection = setup_users(":memory:");
    let query = "SELECT * FROM users";
    let mut statement = ok!(connection.prepare(query));

    assert_eq!(ok!(statement.next()), State::Row);
    assert_eq!(ok!(statement.read::<Option<i64>, _>("id")), Some(1));
    assert_eq!(
        ok!(statement.read::<Option<String>, _>("name")),
        Some(String::from("Alice"))
    );
    assert_eq!(ok!(statement.read::<Option<f64>, _>("age")), Some(42.69));
    assert_eq!(
        ok!(statement.read::<Option<Vec<u8>>, _>("photo")),
        Some(vec![0x42, 0x69])
    );
    assert_eq!(ok!(statement.read::<Option<String>, _>("email")), None);
    assert_eq!(ok!(statement.next()), State::Done);
}

#[test]
fn read_with_name() {
    let connection = setup_users(":memory:");
    let query = "SELECT * FROM users";
    let mut statement = ok!(connection.prepare(query));

    assert_eq!(ok!(statement.next()), State::Row);
    assert_eq!(ok!(statement.read::<i64, _>("id")), 1);
    assert_eq!(
        ok!(statement.read::<String, _>("name")),
        String::from("Alice")
    );
    assert_eq!(ok!(statement.read::<f64, _>("age")), 42.69);
    assert_eq!(ok!(statement.read::<Vec<u8>, _>("photo")), vec![0x42, 0x69]);
    assert_eq!(ok!(statement.read::<Value, _>("email")), Value::Null);
    assert_eq!(ok!(statement.next()), State::Done);
}

#[test]
fn workflow_1() {
    struct Database<'l> {
        #[allow(dead_code)]
        connection: &'l Connection,
        statement: Statement<'l>,
    }

    impl<'l> Database<'l> {
        fn run_once(&mut self) -> sqlite::Result<()> {
            self.statement.reset()?;
            self.statement.bind((":age", 40))?;
            assert_eq!(ok!(self.statement.next()), State::Row);
            Ok(())
        }
    }

    let connection = setup_users(":memory:");
    let query = "SELECT name FROM users WHERE age > :age";
    let statement = ok!(connection.prepare(query));

    let mut database = Database {
        connection: &connection,
        statement: statement,
    };

    for _ in 0..5 {
        assert!(database.run_once().is_ok());
    }
}

#[test]
fn workflow_2() {
    let connection = ok!(Connection::open(":memory:"));
    ok!(connection.execute("CREATE TABLE users (name TEXT, age INTEGER, PRIMARY KEY (name))"));

    let mut statement = ok!(connection.prepare(
        "INSERT INTO users (name, age) VALUES ('jean', 49) ON CONFLICT DO UPDATE SET age = 49"
    ));
    ok!(statement.next());

    let mut statement = ok!(connection.prepare(
        "INSERT INTO users (name, age) VALUES ('jean', 50) ON CONFLICT DO UPDATE SET age = 50"
    ));
    ok!(statement.next());

    let mut statement = ok!(connection.prepare("SELECT * FROM users WHERE name = 'jean'"));
    ok!(statement.next());

    let age = ok!(statement.read::<i64, _>("age"));
    assert_eq!(age, 50);
}