mirror of
https://github.com/isar/rusqlite.git
synced 2024-11-26 19:41:37 +08:00
Roll convenient.rs into statement.rs.
This commit is contained in:
parent
5bd7cb37c7
commit
6bd8516511
@ -1,121 +0,0 @@
|
|||||||
use {Error, Result, Row, Statement};
|
|
||||||
use types::ToSql;
|
|
||||||
use statement::StatementCrateImpl;
|
|
||||||
|
|
||||||
impl<'conn> Statement<'conn> {
|
|
||||||
/// Execute an INSERT and return the ROWID.
|
|
||||||
///
|
|
||||||
/// # Note
|
|
||||||
///
|
|
||||||
/// This function is a convenience wrapper around `execute()` intended for queries that
|
|
||||||
/// insert a single item. It is possible to misuse this function in a way that it cannot
|
|
||||||
/// detect, such as by calling it on a statement which _updates_ a single item rather than
|
|
||||||
/// inserting one. Please don't do that.
|
|
||||||
///
|
|
||||||
/// # Failure
|
|
||||||
///
|
|
||||||
/// Will return `Err` if no row is inserted or many rows are inserted.
|
|
||||||
pub fn insert(&mut self, params: &[&ToSql]) -> Result<i64> {
|
|
||||||
let changes = try!(self.execute(params));
|
|
||||||
match changes {
|
|
||||||
1 => Ok(self.last_insert_rowid()),
|
|
||||||
_ => Err(Error::StatementChangedRows(changes)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return `true` if a query in the SQL statement it executes returns one or more rows
|
|
||||||
/// and `false` if the SQL returns an empty set.
|
|
||||||
pub fn exists(&mut self, params: &[&ToSql]) -> Result<bool> {
|
|
||||||
let mut rows = try!(self.query(params));
|
|
||||||
let exists = {
|
|
||||||
match rows.next() {
|
|
||||||
Some(_) => true,
|
|
||||||
None => false,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Ok(exists)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convenience method to execute a query that is expected to return a single row.
|
|
||||||
///
|
|
||||||
/// If the query returns more than one row, all rows except the first are ignored.
|
|
||||||
///
|
|
||||||
/// # Failure
|
|
||||||
///
|
|
||||||
/// Will return `Err` if the underlying SQLite call fails.
|
|
||||||
pub fn query_row<T, F>(&mut self, params: &[&ToSql], f: F) -> Result<T>
|
|
||||||
where F: FnOnce(&Row) -> T
|
|
||||||
{
|
|
||||||
let mut rows = try!(self.query(params));
|
|
||||||
|
|
||||||
rows.get_expected_row().map(|r| f(&r))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use {Connection, Error, Result};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_insert() {
|
|
||||||
let db = Connection::open_in_memory().unwrap();
|
|
||||||
db.execute_batch("CREATE TABLE foo(x INTEGER UNIQUE)").unwrap();
|
|
||||||
let mut stmt = db.prepare("INSERT OR IGNORE INTO foo (x) VALUES (?)").unwrap();
|
|
||||||
assert_eq!(stmt.insert(&[&1i32]).unwrap(), 1);
|
|
||||||
assert_eq!(stmt.insert(&[&2i32]).unwrap(), 2);
|
|
||||||
match stmt.insert(&[&1i32]).unwrap_err() {
|
|
||||||
Error::StatementChangedRows(0) => (),
|
|
||||||
err => panic!("Unexpected error {}", err),
|
|
||||||
}
|
|
||||||
let mut multi = db.prepare("INSERT INTO foo (x) SELECT 3 UNION ALL SELECT 4").unwrap();
|
|
||||||
match multi.insert(&[]).unwrap_err() {
|
|
||||||
Error::StatementChangedRows(2) => (),
|
|
||||||
err => panic!("Unexpected error {}", err),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_insert_different_tables() {
|
|
||||||
// Test for https://github.com/jgallagher/rusqlite/issues/171
|
|
||||||
let db = Connection::open_in_memory().unwrap();
|
|
||||||
db.execute_batch(r"
|
|
||||||
CREATE TABLE foo(x INTEGER);
|
|
||||||
CREATE TABLE bar(x INTEGER);
|
|
||||||
")
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(db.prepare("INSERT INTO foo VALUES (10)").unwrap().insert(&[]).unwrap(),
|
|
||||||
1);
|
|
||||||
assert_eq!(db.prepare("INSERT INTO bar VALUES (10)").unwrap().insert(&[]).unwrap(),
|
|
||||||
1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_exists() {
|
|
||||||
let db = Connection::open_in_memory().unwrap();
|
|
||||||
let sql = "BEGIN;
|
|
||||||
CREATE TABLE foo(x INTEGER);
|
|
||||||
INSERT INTO foo VALUES(1);
|
|
||||||
INSERT INTO foo VALUES(2);
|
|
||||||
END;";
|
|
||||||
db.execute_batch(sql).unwrap();
|
|
||||||
let mut stmt = db.prepare("SELECT 1 FROM foo WHERE x = ?").unwrap();
|
|
||||||
assert!(stmt.exists(&[&1i32]).unwrap());
|
|
||||||
assert!(stmt.exists(&[&2i32]).unwrap());
|
|
||||||
assert!(!stmt.exists(&[&0i32]).unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_query_row() {
|
|
||||||
let db = Connection::open_in_memory().unwrap();
|
|
||||||
let sql = "BEGIN;
|
|
||||||
CREATE TABLE foo(x INTEGER, y INTEGER);
|
|
||||||
INSERT INTO foo VALUES(1, 3);
|
|
||||||
INSERT INTO foo VALUES(2, 4);
|
|
||||||
END;";
|
|
||||||
db.execute_batch(sql).unwrap();
|
|
||||||
let mut stmt = db.prepare("SELECT y FROM foo WHERE x = ?").unwrap();
|
|
||||||
let y: Result<i64> = stmt.query_row(&[&1i32], |r| r.get(0));
|
|
||||||
assert_eq!(3i64, y.unwrap());
|
|
||||||
}
|
|
||||||
}
|
|
@ -104,7 +104,6 @@ mod version;
|
|||||||
mod transaction;
|
mod transaction;
|
||||||
mod cache;
|
mod cache;
|
||||||
mod error;
|
mod error;
|
||||||
mod convenient;
|
|
||||||
mod raw_statement;
|
mod raw_statement;
|
||||||
mod statement;
|
mod statement;
|
||||||
#[cfg(feature = "load_extension")]
|
#[cfg(feature = "load_extension")]
|
||||||
|
119
src/statement.rs
119
src/statement.rs
@ -106,6 +106,26 @@ impl<'conn> Statement<'conn> {
|
|||||||
self.execute_with_bound_parameters()
|
self.execute_with_bound_parameters()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Execute an INSERT and return the ROWID.
|
||||||
|
///
|
||||||
|
/// # Note
|
||||||
|
///
|
||||||
|
/// This function is a convenience wrapper around `execute()` intended for queries that
|
||||||
|
/// insert a single item. It is possible to misuse this function in a way that it cannot
|
||||||
|
/// detect, such as by calling it on a statement which _updates_ a single item rather than
|
||||||
|
/// inserting one. Please don't do that.
|
||||||
|
///
|
||||||
|
/// # Failure
|
||||||
|
///
|
||||||
|
/// Will return `Err` if no row is inserted or many rows are inserted.
|
||||||
|
pub fn insert(&mut self, params: &[&ToSql]) -> Result<i64> {
|
||||||
|
let changes = try!(self.execute(params));
|
||||||
|
match changes {
|
||||||
|
1 => Ok(self.conn.last_insert_rowid()),
|
||||||
|
_ => Err(Error::StatementChangedRows(changes)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Execute the prepared statement, returning a handle to the resulting rows.
|
/// Execute the prepared statement, returning a handle to the resulting rows.
|
||||||
///
|
///
|
||||||
/// Due to lifetime restricts, the rows handle returned by `query` does not
|
/// Due to lifetime restricts, the rows handle returned by `query` does not
|
||||||
@ -309,6 +329,34 @@ impl<'conn> Statement<'conn> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return `true` if a query in the SQL statement it executes returns one or more rows
|
||||||
|
/// and `false` if the SQL returns an empty set.
|
||||||
|
pub fn exists(&mut self, params: &[&ToSql]) -> Result<bool> {
|
||||||
|
let mut rows = try!(self.query(params));
|
||||||
|
let exists = {
|
||||||
|
match rows.next() {
|
||||||
|
Some(_) => true,
|
||||||
|
None => false,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok(exists)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convenience method to execute a query that is expected to return a single row.
|
||||||
|
///
|
||||||
|
/// If the query returns more than one row, all rows except the first are ignored.
|
||||||
|
///
|
||||||
|
/// # Failure
|
||||||
|
///
|
||||||
|
/// Will return `Err` if the underlying SQLite call fails.
|
||||||
|
pub fn query_row<T, F>(&mut self, params: &[&ToSql], f: F) -> Result<T>
|
||||||
|
where F: FnOnce(&Row) -> T
|
||||||
|
{
|
||||||
|
let mut rows = try!(self.query(params));
|
||||||
|
|
||||||
|
rows.get_expected_row().map(|r| f(&r))
|
||||||
|
}
|
||||||
|
|
||||||
/// Consumes the statement.
|
/// Consumes the statement.
|
||||||
///
|
///
|
||||||
/// Functionally equivalent to the `Drop` implementation, but allows callers to see any errors
|
/// Functionally equivalent to the `Drop` implementation, but allows callers to see any errors
|
||||||
@ -458,7 +506,6 @@ impl<'conn> Drop for Statement<'conn> {
|
|||||||
// once pub(crate) is stable.
|
// once pub(crate) is stable.
|
||||||
pub trait StatementCrateImpl<'conn> {
|
pub trait StatementCrateImpl<'conn> {
|
||||||
fn new(conn: &'conn Connection, stmt: RawStatement) -> Self;
|
fn new(conn: &'conn Connection, stmt: RawStatement) -> Self;
|
||||||
fn last_insert_rowid(&self) -> i64;
|
|
||||||
fn value_ref(&self, col: c_int) -> ValueRef;
|
fn value_ref(&self, col: c_int) -> ValueRef;
|
||||||
fn step(&self) -> Result<bool>;
|
fn step(&self) -> Result<bool>;
|
||||||
fn reset(&self) -> c_int;
|
fn reset(&self) -> c_int;
|
||||||
@ -472,10 +519,6 @@ impl<'conn> StatementCrateImpl<'conn> for Statement<'conn> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn last_insert_rowid(&self) -> i64 {
|
|
||||||
self.conn.last_insert_rowid()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn value_ref(&self, col: c_int) -> ValueRef {
|
fn value_ref(&self, col: c_int) -> ValueRef {
|
||||||
let raw = unsafe { self.stmt.ptr() };
|
let raw = unsafe { self.stmt.ptr() };
|
||||||
|
|
||||||
@ -533,8 +576,7 @@ impl<'conn> StatementCrateImpl<'conn> for Statement<'conn> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use Connection;
|
use {Connection, Error, Result};
|
||||||
use error::Error;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_execute_named() {
|
fn test_execute_named() {
|
||||||
@ -671,4 +713,67 @@ mod test {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(result, "one");
|
assert_eq!(result, "one");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_insert() {
|
||||||
|
let db = Connection::open_in_memory().unwrap();
|
||||||
|
db.execute_batch("CREATE TABLE foo(x INTEGER UNIQUE)").unwrap();
|
||||||
|
let mut stmt = db.prepare("INSERT OR IGNORE INTO foo (x) VALUES (?)").unwrap();
|
||||||
|
assert_eq!(stmt.insert(&[&1i32]).unwrap(), 1);
|
||||||
|
assert_eq!(stmt.insert(&[&2i32]).unwrap(), 2);
|
||||||
|
match stmt.insert(&[&1i32]).unwrap_err() {
|
||||||
|
Error::StatementChangedRows(0) => (),
|
||||||
|
err => panic!("Unexpected error {}", err),
|
||||||
|
}
|
||||||
|
let mut multi = db.prepare("INSERT INTO foo (x) SELECT 3 UNION ALL SELECT 4").unwrap();
|
||||||
|
match multi.insert(&[]).unwrap_err() {
|
||||||
|
Error::StatementChangedRows(2) => (),
|
||||||
|
err => panic!("Unexpected error {}", err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_insert_different_tables() {
|
||||||
|
// Test for https://github.com/jgallagher/rusqlite/issues/171
|
||||||
|
let db = Connection::open_in_memory().unwrap();
|
||||||
|
db.execute_batch(r"
|
||||||
|
CREATE TABLE foo(x INTEGER);
|
||||||
|
CREATE TABLE bar(x INTEGER);
|
||||||
|
")
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(db.prepare("INSERT INTO foo VALUES (10)").unwrap().insert(&[]).unwrap(),
|
||||||
|
1);
|
||||||
|
assert_eq!(db.prepare("INSERT INTO bar VALUES (10)").unwrap().insert(&[]).unwrap(),
|
||||||
|
1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_exists() {
|
||||||
|
let db = Connection::open_in_memory().unwrap();
|
||||||
|
let sql = "BEGIN;
|
||||||
|
CREATE TABLE foo(x INTEGER);
|
||||||
|
INSERT INTO foo VALUES(1);
|
||||||
|
INSERT INTO foo VALUES(2);
|
||||||
|
END;";
|
||||||
|
db.execute_batch(sql).unwrap();
|
||||||
|
let mut stmt = db.prepare("SELECT 1 FROM foo WHERE x = ?").unwrap();
|
||||||
|
assert!(stmt.exists(&[&1i32]).unwrap());
|
||||||
|
assert!(stmt.exists(&[&2i32]).unwrap());
|
||||||
|
assert!(!stmt.exists(&[&0i32]).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_query_row() {
|
||||||
|
let db = Connection::open_in_memory().unwrap();
|
||||||
|
let sql = "BEGIN;
|
||||||
|
CREATE TABLE foo(x INTEGER, y INTEGER);
|
||||||
|
INSERT INTO foo VALUES(1, 3);
|
||||||
|
INSERT INTO foo VALUES(2, 4);
|
||||||
|
END;";
|
||||||
|
db.execute_batch(sql).unwrap();
|
||||||
|
let mut stmt = db.prepare("SELECT y FROM foo WHERE x = ?").unwrap();
|
||||||
|
let y: Result<i64> = stmt.query_row(&[&1i32], |r| r.get(0));
|
||||||
|
assert_eq!(3i64, y.unwrap());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user