mirror of
https://github.com/isar/rusqlite.git
synced 2024-11-26 11:31:37 +08:00
Merge pull request #11 from jgallagher/rust-1.0.0-alpha-changes
Rust 1.0.0 alpha changes, add `query_row_safe`
This commit is contained in:
commit
befe94494e
5
CONTRIBUTORS.md
Normal file
5
CONTRIBUTORS.md
Normal file
@ -0,0 +1,5 @@
|
||||
rusqlite contributors (sorted alphabetically)
|
||||
=============================================
|
||||
|
||||
* [John Gallagher](https://github.com/jgallagher)
|
||||
* [Marcus Klaas de Vries](https://github.com/marcusklaas)
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "rusqlite"
|
||||
version = "0.0.5"
|
||||
version = "0.0.6"
|
||||
authors = ["John Gallagher <jgallagher@bignerdranch.com>"]
|
||||
description = "Ergonomic wrapper for SQLite"
|
||||
homepage = "https://github.com/jgallagher/rusqlite"
|
||||
|
@ -1,3 +1,8 @@
|
||||
# Version 0.0.6 (2014-01-10)
|
||||
|
||||
* Updates to track latest rustc changes (1.0.0-alpha).
|
||||
* Add `query_row_safe`, a `SqliteResult`-returning variant of `query_row`.
|
||||
|
||||
# Version 0.0.5 (2014-01-07)
|
||||
|
||||
* Updates to track latest rustc changes (closure syntax).
|
||||
|
@ -42,7 +42,7 @@ pub const SQLITE_NULL : c_int = 5;
|
||||
pub type SqliteDestructor = extern "C" fn(*mut c_void);
|
||||
|
||||
pub fn SQLITE_TRANSIENT() -> SqliteDestructor {
|
||||
unsafe { mem::transmute(-1i) }
|
||||
unsafe { mem::transmute(-1is) }
|
||||
}
|
||||
|
||||
pub fn code_to_str(code: c_int) -> &'static str {
|
||||
|
80
src/lib.rs
80
src/lib.rs
@ -2,6 +2,7 @@
|
||||
//! an interface similar to [rust-postgres](https://github.com/sfackler/rust-postgres).
|
||||
//!
|
||||
//! ```rust
|
||||
//! #![allow(unstable)]
|
||||
//! extern crate rusqlite;
|
||||
//! extern crate time;
|
||||
//!
|
||||
@ -43,11 +44,12 @@
|
||||
//! time_created: row.get(2),
|
||||
//! data: row.get(3)
|
||||
//! };
|
||||
//! println!("Found person {}", person);
|
||||
//! println!("Found person {:?}", person);
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
#![feature(unsafe_destructor)]
|
||||
#![allow(unstable)]
|
||||
|
||||
extern crate libc;
|
||||
|
||||
@ -96,6 +98,12 @@ pub struct SqliteError {
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
impl fmt::String for SqliteError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
write!(f, "SqliteError( code: {}, message: {} )", self.code, self.message)
|
||||
}
|
||||
}
|
||||
|
||||
impl SqliteError {
|
||||
fn from_handle(db: *mut ffi::Struct_sqlite3, code: c_int) -> SqliteError {
|
||||
let message = if db.is_null() {
|
||||
@ -210,7 +218,7 @@ impl SqliteConnection {
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub fn execute(&self, sql: &str, params: &[&ToSql]) -> SqliteResult<uint> {
|
||||
pub fn execute(&self, sql: &str, params: &[&ToSql]) -> SqliteResult<c_int> {
|
||||
self.prepare(sql).and_then(|mut stmt| stmt.execute(params))
|
||||
}
|
||||
|
||||
@ -251,6 +259,35 @@ impl SqliteConnection {
|
||||
f(rows.next().expect("Query did not return a row").unwrap())
|
||||
}
|
||||
|
||||
/// Convenience method to execute a query that is expected to return a single row.
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// # use rusqlite::{SqliteResult,SqliteConnection};
|
||||
/// fn preferred_locale(conn: &SqliteConnection) -> SqliteResult<String> {
|
||||
/// conn.query_row_safe("SELECT value FROM preferences WHERE name='locale'", &[], |row| {
|
||||
/// row.get(0)
|
||||
/// })
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// If the query returns more than one row, all rows except the first are ignored.
|
||||
pub fn query_row_safe<T, F>(&self, sql: &str, params: &[&ToSql], f: F) -> SqliteResult<T>
|
||||
where F: FnOnce(SqliteRow) -> T {
|
||||
let mut stmt = try!(self.prepare(sql));
|
||||
let mut rows = try!(stmt.query(params));
|
||||
|
||||
if let Some(row) = rows.next() {
|
||||
row.map(f)
|
||||
} else {
|
||||
Err(SqliteError{
|
||||
code: ffi::SQLITE_NOTICE,
|
||||
message: "Query did not return a row".to_string(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Prepare a SQL statement for execution.
|
||||
///
|
||||
/// ## Example
|
||||
@ -280,7 +317,7 @@ impl SqliteConnection {
|
||||
self.db.borrow_mut().decode_result(code)
|
||||
}
|
||||
|
||||
fn changes(&self) -> uint {
|
||||
fn changes(&self) -> c_int {
|
||||
self.db.borrow_mut().changes()
|
||||
}
|
||||
}
|
||||
@ -390,8 +427,8 @@ impl InnerSqliteConnection {
|
||||
})
|
||||
}
|
||||
|
||||
fn changes(&mut self) -> uint {
|
||||
unsafe{ ffi::sqlite3_changes(self.db) as uint }
|
||||
fn changes(&mut self) -> c_int {
|
||||
unsafe{ ffi::sqlite3_changes(self.db) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -432,7 +469,7 @@ impl<'conn> SqliteStatement<'conn> {
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
pub fn execute(&mut self, params: &[&ToSql]) -> SqliteResult<uint> {
|
||||
pub fn execute(&mut self, params: &[&ToSql]) -> SqliteResult<c_int> {
|
||||
self.reset_if_needed();
|
||||
|
||||
unsafe {
|
||||
@ -511,7 +548,7 @@ impl<'conn> SqliteStatement<'conn> {
|
||||
|
||||
impl<'conn> fmt::Show for SqliteStatement<'conn> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Statement( conn: {}, stmt: {} )", self.conn, self.stmt)
|
||||
write!(f, "Statement( conn: {:?}, stmt: {:?} )", self.conn, self.stmt)
|
||||
}
|
||||
}
|
||||
|
||||
@ -760,6 +797,33 @@ mod test {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_query_row_safe() {
|
||||
let db = checked_memory_handle();
|
||||
let sql = "BEGIN;
|
||||
CREATE TABLE foo(x INTEGER);
|
||||
INSERT INTO foo VALUES(1);
|
||||
INSERT INTO foo VALUES(2);
|
||||
INSERT INTO foo VALUES(3);
|
||||
INSERT INTO foo VALUES(4);
|
||||
END;";
|
||||
db.execute_batch(sql).unwrap();
|
||||
|
||||
assert_eq!(10i64, db.query_row_safe("SELECT SUM(x) FROM foo", &[], |r| {
|
||||
r.get::<i64>(0)
|
||||
}).unwrap());
|
||||
|
||||
let result = db.query_row_safe("SELECT x FROM foo WHERE x > 5", &[], |r| r.get::<i64>(0));
|
||||
let error = result.unwrap_err();
|
||||
|
||||
assert!(error.code == ffi::SQLITE_NOTICE);
|
||||
assert!(error.message.as_slice() == "Query did not return a row");
|
||||
|
||||
let bad_query_result = db.query_row_safe("NOT A PROPER QUERY; test123", &[], |_| ());
|
||||
|
||||
assert!(bad_query_result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_prepare_failures() {
|
||||
let db = checked_memory_handle();
|
||||
@ -796,7 +860,7 @@ mod test {
|
||||
assert_eq!(db.last_insert_rowid(), 1);
|
||||
|
||||
let mut stmt = db.prepare("INSERT INTO foo DEFAULT VALUES").unwrap();
|
||||
for _ in range(0i, 9) {
|
||||
for _ in range(0i32, 9) {
|
||||
stmt.execute(&[]).unwrap();
|
||||
}
|
||||
assert_eq!(db.last_insert_rowid(), 10);
|
||||
|
10
src/types.rs
10
src/types.rs
@ -136,9 +136,15 @@ impl<T: ToSql> ToSql for Option<T> {
|
||||
/// ## Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// #![allow(unstable)]
|
||||
/// # extern crate libc;
|
||||
/// # extern crate rusqlite;
|
||||
/// # use rusqlite::{SqliteConnection, SqliteResult};
|
||||
/// # use rusqlite::types::{Null};
|
||||
/// fn insert_null(conn: &SqliteConnection) -> SqliteResult<uint> {
|
||||
/// # use libc::{c_int};
|
||||
/// fn main() {
|
||||
/// }
|
||||
/// fn insert_null(conn: &SqliteConnection) -> SqliteResult<c_int> {
|
||||
/// conn.execute("INSERT INTO people (name) VALUES (?)", &[&Null])
|
||||
/// }
|
||||
/// ```
|
||||
@ -186,7 +192,7 @@ impl FromSql for Vec<u8> {
|
||||
let c_blob = ffi::sqlite3_column_blob(stmt, col);
|
||||
let len = ffi::sqlite3_column_bytes(stmt, col);
|
||||
|
||||
assert!(len >= 0); let len = len as uint;
|
||||
assert!(len >= 0); let len = len as usize;
|
||||
|
||||
Ok(Vec::from_raw_buf(mem::transmute(c_blob), len))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user