mirror of
https://github.com/isar/rusqlite.git
synced 2024-11-23 00:39:20 +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]
|
[package]
|
||||||
name = "rusqlite"
|
name = "rusqlite"
|
||||||
version = "0.0.5"
|
version = "0.0.6"
|
||||||
authors = ["John Gallagher <jgallagher@bignerdranch.com>"]
|
authors = ["John Gallagher <jgallagher@bignerdranch.com>"]
|
||||||
description = "Ergonomic wrapper for SQLite"
|
description = "Ergonomic wrapper for SQLite"
|
||||||
homepage = "https://github.com/jgallagher/rusqlite"
|
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)
|
# Version 0.0.5 (2014-01-07)
|
||||||
|
|
||||||
* Updates to track latest rustc changes (closure syntax).
|
* 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 type SqliteDestructor = extern "C" fn(*mut c_void);
|
||||||
|
|
||||||
pub fn SQLITE_TRANSIENT() -> SqliteDestructor {
|
pub fn SQLITE_TRANSIENT() -> SqliteDestructor {
|
||||||
unsafe { mem::transmute(-1i) }
|
unsafe { mem::transmute(-1is) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn code_to_str(code: c_int) -> &'static str {
|
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).
|
//! an interface similar to [rust-postgres](https://github.com/sfackler/rust-postgres).
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
|
//! #![allow(unstable)]
|
||||||
//! extern crate rusqlite;
|
//! extern crate rusqlite;
|
||||||
//! extern crate time;
|
//! extern crate time;
|
||||||
//!
|
//!
|
||||||
@ -43,11 +44,12 @@
|
|||||||
//! time_created: row.get(2),
|
//! time_created: row.get(2),
|
||||||
//! data: row.get(3)
|
//! data: row.get(3)
|
||||||
//! };
|
//! };
|
||||||
//! println!("Found person {}", person);
|
//! println!("Found person {:?}", person);
|
||||||
//! }
|
//! }
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
#![feature(unsafe_destructor)]
|
#![feature(unsafe_destructor)]
|
||||||
|
#![allow(unstable)]
|
||||||
|
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
|
|
||||||
@ -96,6 +98,12 @@ pub struct SqliteError {
|
|||||||
pub message: String,
|
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 {
|
impl SqliteError {
|
||||||
fn from_handle(db: *mut ffi::Struct_sqlite3, code: c_int) -> SqliteError {
|
fn from_handle(db: *mut ffi::Struct_sqlite3, code: c_int) -> SqliteError {
|
||||||
let message = if db.is_null() {
|
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))
|
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())
|
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.
|
/// Prepare a SQL statement for execution.
|
||||||
///
|
///
|
||||||
/// ## Example
|
/// ## Example
|
||||||
@ -280,7 +317,7 @@ impl SqliteConnection {
|
|||||||
self.db.borrow_mut().decode_result(code)
|
self.db.borrow_mut().decode_result(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn changes(&self) -> uint {
|
fn changes(&self) -> c_int {
|
||||||
self.db.borrow_mut().changes()
|
self.db.borrow_mut().changes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -390,8 +427,8 @@ impl InnerSqliteConnection {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn changes(&mut self) -> uint {
|
fn changes(&mut self) -> c_int {
|
||||||
unsafe{ ffi::sqlite3_changes(self.db) as uint }
|
unsafe{ ffi::sqlite3_changes(self.db) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -432,7 +469,7 @@ impl<'conn> SqliteStatement<'conn> {
|
|||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn execute(&mut self, params: &[&ToSql]) -> SqliteResult<uint> {
|
pub fn execute(&mut self, params: &[&ToSql]) -> SqliteResult<c_int> {
|
||||||
self.reset_if_needed();
|
self.reset_if_needed();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -511,7 +548,7 @@ impl<'conn> SqliteStatement<'conn> {
|
|||||||
|
|
||||||
impl<'conn> fmt::Show for SqliteStatement<'conn> {
|
impl<'conn> fmt::Show for SqliteStatement<'conn> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
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]
|
#[test]
|
||||||
fn test_prepare_failures() {
|
fn test_prepare_failures() {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
@ -796,7 +860,7 @@ mod test {
|
|||||||
assert_eq!(db.last_insert_rowid(), 1);
|
assert_eq!(db.last_insert_rowid(), 1);
|
||||||
|
|
||||||
let mut stmt = db.prepare("INSERT INTO foo DEFAULT VALUES").unwrap();
|
let mut stmt = db.prepare("INSERT INTO foo DEFAULT VALUES").unwrap();
|
||||||
for _ in range(0i, 9) {
|
for _ in range(0i32, 9) {
|
||||||
stmt.execute(&[]).unwrap();
|
stmt.execute(&[]).unwrap();
|
||||||
}
|
}
|
||||||
assert_eq!(db.last_insert_rowid(), 10);
|
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
|
/// ## Example
|
||||||
///
|
///
|
||||||
/// ```rust,no_run
|
/// ```rust,no_run
|
||||||
|
/// #![allow(unstable)]
|
||||||
|
/// # extern crate libc;
|
||||||
|
/// # extern crate rusqlite;
|
||||||
/// # use rusqlite::{SqliteConnection, SqliteResult};
|
/// # use rusqlite::{SqliteConnection, SqliteResult};
|
||||||
/// # use rusqlite::types::{Null};
|
/// # 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])
|
/// 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 c_blob = ffi::sqlite3_column_blob(stmt, col);
|
||||||
let len = ffi::sqlite3_column_bytes(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))
|
Ok(Vec::from_raw_buf(mem::transmute(c_blob), len))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user