mirror of
https://github.com/isar/rusqlite.git
synced 2025-10-24 01:38:54 +08:00
Merge remote-tracking branch 'jgallagher/master' into fallible-iterator
This commit is contained in:
115
src/lib.rs
115
src/lib.rs
@@ -3,7 +3,7 @@
|
||||
//!
|
||||
//! ```rust
|
||||
//! use rusqlite::types::ToSql;
|
||||
//! use rusqlite::{params, Connection};
|
||||
//! use rusqlite::{params, Connection, Result};
|
||||
//! use time::Timespec;
|
||||
//!
|
||||
//! #[derive(Debug)]
|
||||
@@ -14,8 +14,8 @@
|
||||
//! data: Option<Vec<u8>>,
|
||||
//! }
|
||||
//!
|
||||
//! fn main() {
|
||||
//! let conn = Connection::open_in_memory().unwrap();
|
||||
//! fn main() -> Result<()> {
|
||||
//! let conn = Connection::open_in_memory()?;
|
||||
//!
|
||||
//! conn.execute(
|
||||
//! "CREATE TABLE person (
|
||||
@@ -25,8 +25,7 @@
|
||||
//! data BLOB
|
||||
//! )",
|
||||
//! params![],
|
||||
//! )
|
||||
//! .unwrap();
|
||||
//! )?;
|
||||
//! let me = Person {
|
||||
//! id: 0,
|
||||
//! name: "Steven".to_string(),
|
||||
@@ -37,24 +36,22 @@
|
||||
//! "INSERT INTO person (name, time_created, data)
|
||||
//! VALUES (?1, ?2, ?3)",
|
||||
//! params![me.name, me.time_created, me.data],
|
||||
//! )
|
||||
//! .unwrap();
|
||||
//! )?;
|
||||
//!
|
||||
//! let mut stmt = conn
|
||||
//! .prepare("SELECT id, name, time_created, data FROM person")
|
||||
//! .unwrap();
|
||||
//! let person_iter = stmt
|
||||
//! .query_map(params![], |row| Person {
|
||||
//! id: row.get(0),
|
||||
//! name: row.get(1),
|
||||
//! time_created: row.get(2),
|
||||
//! data: row.get(3),
|
||||
//! let mut stmt = conn.prepare("SELECT id, name, time_created, data FROM person")?;
|
||||
//! let person_iter = stmt.query_map(params![], |row| {
|
||||
//! Ok(Person {
|
||||
//! id: row.get(0)?,
|
||||
//! name: row.get(1)?,
|
||||
//! time_created: row.get(2)?,
|
||||
//! data: row.get(3)?,
|
||||
//! })
|
||||
//! .unwrap();
|
||||
//! })?;
|
||||
//!
|
||||
//! for person in person_iter {
|
||||
//! println!("Found person {:?}", person.unwrap());
|
||||
//! }
|
||||
//! Ok(())
|
||||
//! }
|
||||
//! ```
|
||||
#![allow(unknown_lints)]
|
||||
@@ -121,6 +118,7 @@ mod inner_connection;
|
||||
pub mod limits;
|
||||
#[cfg(feature = "load_extension")]
|
||||
mod load_extension_guard;
|
||||
mod pragma;
|
||||
mod raw_statement;
|
||||
mod row;
|
||||
#[cfg(feature = "session")]
|
||||
@@ -242,6 +240,42 @@ fn str_to_cstring(s: &str) -> Result<CString> {
|
||||
Ok(CString::new(s)?)
|
||||
}
|
||||
|
||||
/// Returns `Ok((string ptr, len as c_int, SQLITE_STATIC | SQLITE_TRANSIENT))`
|
||||
/// normally.
|
||||
/// Returns errors if the string has embedded nuls or is too large for sqlite.
|
||||
/// The `sqlite3_destructor_type` item is always `SQLITE_TRANSIENT` unless
|
||||
/// the string was empty (in which case it's `SQLITE_STATIC`, and the ptr is
|
||||
/// static).
|
||||
fn str_for_sqlite(s: &str) -> Result<(*const c_char, c_int, ffi::sqlite3_destructor_type)> {
|
||||
let len = len_as_c_int(s.len())?;
|
||||
if memchr::memchr(0, s.as_bytes()).is_none() {
|
||||
let (ptr, dtor_info) = if len != 0 {
|
||||
(s.as_ptr() as *const c_char, ffi::SQLITE_TRANSIENT())
|
||||
} else {
|
||||
// Return a pointer guaranteed to live forever
|
||||
("".as_ptr() as *const c_char, ffi::SQLITE_STATIC())
|
||||
};
|
||||
Ok((ptr, len, dtor_info))
|
||||
} else {
|
||||
// There's an embedded nul, so we fabricate a NulError.
|
||||
let e = CString::new(s);
|
||||
Err(Error::NulError(e.unwrap_err()))
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to cast to c_int safely, returning the correct error type if the cast
|
||||
// failed.
|
||||
fn len_as_c_int(len: usize) -> Result<c_int> {
|
||||
if len >= (c_int::max_value() as usize) {
|
||||
Err(Error::SqliteFailure(
|
||||
ffi::Error::new(ffi::SQLITE_TOOBIG),
|
||||
None,
|
||||
))
|
||||
} else {
|
||||
Ok(len as c_int)
|
||||
}
|
||||
}
|
||||
|
||||
fn path_to_cstring(p: &Path) -> Result<CString> {
|
||||
let s = p.to_str().ok_or_else(|| Error::InvalidPath(p.to_owned()))?;
|
||||
str_to_cstring(s)
|
||||
@@ -478,7 +512,7 @@ impl Connection {
|
||||
where
|
||||
P: IntoIterator,
|
||||
P::Item: ToSql,
|
||||
F: FnOnce(&Row<'_>) -> T,
|
||||
F: FnOnce(&Row<'_>) -> Result<T>,
|
||||
{
|
||||
let mut stmt = self.prepare(sql)?;
|
||||
stmt.query_row(params, f)
|
||||
@@ -500,12 +534,12 @@ impl Connection {
|
||||
/// or if the underlying SQLite call fails.
|
||||
pub fn query_row_named<T, F>(&self, sql: &str, params: &[(&str, &dyn ToSql)], f: F) -> Result<T>
|
||||
where
|
||||
F: FnOnce(&Row<'_>) -> T,
|
||||
F: FnOnce(&Row<'_>) -> Result<T>,
|
||||
{
|
||||
let mut stmt = self.prepare(sql)?;
|
||||
let mut rows = stmt.query_named(params)?;
|
||||
|
||||
rows.get_expected_row().map(|r| f(&r))
|
||||
rows.get_expected_row().and_then(|r| f(&r))
|
||||
}
|
||||
|
||||
/// Convenience method to execute a query that is expected to return a
|
||||
@@ -521,7 +555,7 @@ impl Connection {
|
||||
/// conn.query_row_and_then(
|
||||
/// "SELECT value FROM preferences WHERE name='locale'",
|
||||
/// NO_PARAMS,
|
||||
/// |row| row.get_checked(0),
|
||||
/// |row| row.get(0),
|
||||
/// )
|
||||
/// }
|
||||
/// ```
|
||||
@@ -692,7 +726,7 @@ impl Connection {
|
||||
/// Return the number of rows modified, inserted or deleted by the most
|
||||
/// recently completed INSERT, UPDATE or DELETE statement on the database
|
||||
/// connection.
|
||||
pub fn changes(&self) -> usize {
|
||||
fn changes(&self) -> usize {
|
||||
self.db.borrow_mut().changes()
|
||||
}
|
||||
|
||||
@@ -863,9 +897,9 @@ mod test {
|
||||
let tx2 = db2.transaction().unwrap();
|
||||
|
||||
// SELECT first makes sqlite lock with a shared lock
|
||||
tx1.query_row("SELECT x FROM foo LIMIT 1", NO_PARAMS, |_| ())
|
||||
tx1.query_row("SELECT x FROM foo LIMIT 1", NO_PARAMS, |_| Ok(()))
|
||||
.unwrap();
|
||||
tx2.query_row("SELECT x FROM foo LIMIT 1", NO_PARAMS, |_| ())
|
||||
tx2.query_row("SELECT x FROM foo LIMIT 1", NO_PARAMS, |_| Ok(()))
|
||||
.unwrap();
|
||||
|
||||
tx1.execute("INSERT INTO foo VALUES(?1)", &[1]).unwrap();
|
||||
@@ -1066,7 +1100,7 @@ mod test {
|
||||
let mut v = Vec::<i32>::new();
|
||||
|
||||
while let Some(row) = rows.next().unwrap() {
|
||||
v.push(row.get(0));
|
||||
v.push(row.get(0).unwrap());
|
||||
}
|
||||
|
||||
assert_eq!(v, [3i32, 2, 1]);
|
||||
@@ -1077,7 +1111,7 @@ mod test {
|
||||
let mut v = Vec::<i32>::new();
|
||||
|
||||
while let Some(row) = rows.next().unwrap() {
|
||||
v.push(row.get(0));
|
||||
v.push(row.get(0).unwrap());
|
||||
}
|
||||
|
||||
assert_eq!(v, [2i32, 1]);
|
||||
@@ -1130,7 +1164,7 @@ mod test {
|
||||
err => panic!("Unexpected error {}", err),
|
||||
}
|
||||
|
||||
let bad_query_result = db.query_row("NOT A PROPER QUERY; test123", NO_PARAMS, |_| ());
|
||||
let bad_query_result = db.query_row("NOT A PROPER QUERY; test123", NO_PARAMS, |_| Ok(()));
|
||||
|
||||
assert!(bad_query_result.is_err());
|
||||
}
|
||||
@@ -1404,7 +1438,7 @@ mod test {
|
||||
|
||||
let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC").unwrap();
|
||||
let results: Result<Vec<String>> = query
|
||||
.query_and_then(NO_PARAMS, |row| row.get_checked(1))
|
||||
.query_and_then(NO_PARAMS, |row| row.get(1))
|
||||
.unwrap()
|
||||
.collect();
|
||||
|
||||
@@ -1425,7 +1459,7 @@ mod test {
|
||||
|
||||
let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC").unwrap();
|
||||
let bad_type: Result<Vec<f64>> = query
|
||||
.query_and_then(NO_PARAMS, |row| row.get_checked(1))
|
||||
.query_and_then(NO_PARAMS, |row| row.get(1))
|
||||
.unwrap()
|
||||
.collect();
|
||||
|
||||
@@ -1435,7 +1469,7 @@ mod test {
|
||||
}
|
||||
|
||||
let bad_idx: Result<Vec<String>> = query
|
||||
.query_and_then(NO_PARAMS, |row| row.get_checked(3))
|
||||
.query_and_then(NO_PARAMS, |row| row.get(3))
|
||||
.unwrap()
|
||||
.collect();
|
||||
|
||||
@@ -1459,9 +1493,7 @@ mod test {
|
||||
|
||||
let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC").unwrap();
|
||||
let results: CustomResult<Vec<String>> = query
|
||||
.query_and_then(NO_PARAMS, |row| {
|
||||
row.get_checked(1).map_err(CustomError::Sqlite)
|
||||
})
|
||||
.query_and_then(NO_PARAMS, |row| row.get(1).map_err(CustomError::Sqlite))
|
||||
.unwrap()
|
||||
.collect();
|
||||
|
||||
@@ -1482,9 +1514,7 @@ mod test {
|
||||
|
||||
let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC").unwrap();
|
||||
let bad_type: CustomResult<Vec<f64>> = query
|
||||
.query_and_then(NO_PARAMS, |row| {
|
||||
row.get_checked(1).map_err(CustomError::Sqlite)
|
||||
})
|
||||
.query_and_then(NO_PARAMS, |row| row.get(1).map_err(CustomError::Sqlite))
|
||||
.unwrap()
|
||||
.collect();
|
||||
|
||||
@@ -1494,9 +1524,7 @@ mod test {
|
||||
}
|
||||
|
||||
let bad_idx: CustomResult<Vec<String>> = query
|
||||
.query_and_then(NO_PARAMS, |row| {
|
||||
row.get_checked(3).map_err(CustomError::Sqlite)
|
||||
})
|
||||
.query_and_then(NO_PARAMS, |row| row.get(3).map_err(CustomError::Sqlite))
|
||||
.unwrap()
|
||||
.collect();
|
||||
|
||||
@@ -1527,7 +1555,7 @@ mod test {
|
||||
|
||||
let query = "SELECT x, y FROM foo ORDER BY x DESC";
|
||||
let results: CustomResult<String> = db.query_row_and_then(query, NO_PARAMS, |row| {
|
||||
row.get_checked(1).map_err(CustomError::Sqlite)
|
||||
row.get(1).map_err(CustomError::Sqlite)
|
||||
});
|
||||
|
||||
assert_eq!(results.unwrap(), "hello");
|
||||
@@ -1544,7 +1572,7 @@ mod test {
|
||||
|
||||
let query = "SELECT x, y FROM foo ORDER BY x DESC";
|
||||
let bad_type: CustomResult<f64> = db.query_row_and_then(query, NO_PARAMS, |row| {
|
||||
row.get_checked(1).map_err(CustomError::Sqlite)
|
||||
row.get(1).map_err(CustomError::Sqlite)
|
||||
});
|
||||
|
||||
match bad_type.unwrap_err() {
|
||||
@@ -1553,7 +1581,7 @@ mod test {
|
||||
}
|
||||
|
||||
let bad_idx: CustomResult<String> = db.query_row_and_then(query, NO_PARAMS, |row| {
|
||||
row.get_checked(3).map_err(CustomError::Sqlite)
|
||||
row.get(3).map_err(CustomError::Sqlite)
|
||||
});
|
||||
|
||||
match bad_idx.unwrap_err() {
|
||||
@@ -1580,7 +1608,8 @@ mod test {
|
||||
db.execute_batch(sql).unwrap();
|
||||
|
||||
db.query_row("SELECT * FROM foo", params![], |r| {
|
||||
assert_eq!(2, r.column_count())
|
||||
assert_eq!(2, r.column_count());
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
Reference in New Issue
Block a user