mirror of
				https://github.com/isar/rusqlite.git
				synced 2025-11-01 06:18:54 +08:00 
			
		
		
		
	Merge remote-tracking branch 'jgallagher/master' into vtab
This commit is contained in:
		| @@ -1,6 +1,6 @@ | |||||||
| [package] | [package] | ||||||
| name = "rusqlite" | name = "rusqlite" | ||||||
| version = "0.6.0" | version = "0.7.2" | ||||||
| authors = ["John Gallagher <jgallagher@bignerdranch.com>"] | authors = ["John Gallagher <jgallagher@bignerdranch.com>"] | ||||||
| description = "Ergonomic wrapper for SQLite" | description = "Ergonomic wrapper for SQLite" | ||||||
| repository = "https://github.com/jgallagher/rusqlite" | repository = "https://github.com/jgallagher/rusqlite" | ||||||
| @@ -37,7 +37,7 @@ regex = "~0.1.41" | |||||||
|  |  | ||||||
| [dependencies.libsqlite3-sys] | [dependencies.libsqlite3-sys] | ||||||
| path = "libsqlite3-sys" | path = "libsqlite3-sys" | ||||||
| version = "0.4.0" | version = "0.5.0" | ||||||
|  |  | ||||||
| [dependencies.csv] | [dependencies.csv] | ||||||
| version = "~0.14.3" | version = "~0.14.3" | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| # Version UPCOMING (...) | # Version 0.7.2 (2016-05-19) | ||||||
|  |  | ||||||
| * BREAKING CHANGE: `Rows` no longer implements `Iterator`. It still has a `next()` method, but | * BREAKING CHANGE: `Rows` no longer implements `Iterator`. It still has a `next()` method, but | ||||||
|   the lifetime of the returned `Row` is now tied to the lifetime of the vending `Rows` object. |   the lifetime of the returned `Row` is now tied to the lifetime of the vending `Rows` object. | ||||||
|   | |||||||
| @@ -72,6 +72,12 @@ features](http://doc.crates.io/manifest.html#the-features-section). They are: | |||||||
|   allows hooks into SQLite's tracing and profiling APIs. |   allows hooks into SQLite's tracing and profiling APIs. | ||||||
| * [`blob`](http://jgallagher.github.io/rusqlite/rusqlite/blob/index.html) | * [`blob`](http://jgallagher.github.io/rusqlite/rusqlite/blob/index.html) | ||||||
|   gives `std::io::{Read, Write, Seek}` access to SQL BLOBs. |   gives `std::io::{Read, Write, Seek}` access to SQL BLOBs. | ||||||
|  | * `chrono` implements [`FromSql`](http://jgallagher.github.io/rusqlite/rusqlite/types/trait.FromSql.html) | ||||||
|  |   and [`ToSql`](http://jgallagher.github.io/rusqlite/rusqlite/types/trait.ToSql.html) for various | ||||||
|  |   types from the [`chrono` crate](https://crates.io/crates/chrono). | ||||||
|  | * `serde_json` implements [`FromSql`](http://jgallagher.github.io/rusqlite/rusqlite/types/trait.FromSql.html) | ||||||
|  |   and [`ToSql`](http://jgallagher.github.io/rusqlite/rusqlite/types/trait.ToSql.html) for the | ||||||
|  |   `Value` type from the [`serde_json` crate](https://crates.io/crates/serde_json). | ||||||
|  |  | ||||||
| ## Author | ## Author | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								clippy.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								clippy.toml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | doc-valid-idents = ["SQLite", "lang_transaction"] | ||||||
| @@ -1,6 +1,6 @@ | |||||||
| [package] | [package] | ||||||
| name = "libsqlite3-sys" | name = "libsqlite3-sys" | ||||||
| version = "0.4.0" | version = "0.5.0" | ||||||
| authors = ["John Gallagher <jgallagher@bignerdranch.com>"] | authors = ["John Gallagher <jgallagher@bignerdranch.com>"] | ||||||
| repository = "https://github.com/jgallagher/rusqlite" | repository = "https://github.com/jgallagher/rusqlite" | ||||||
| description = "Native bindings to the libsqlite3 library" | description = "Native bindings to the libsqlite3 library" | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ fi | |||||||
|  |  | ||||||
| cd $(git rev-parse --show-toplevel) | cd $(git rev-parse --show-toplevel) | ||||||
| rm -rf target/doc/ | rm -rf target/doc/ | ||||||
| multirust run nightly cargo doc --no-deps --features "backup cache functions load_extension trace blob" | rustup run nightly cargo doc --no-deps --features "backup blob chrono functions load_extension serde_json trace" | ||||||
| echo '<meta http-equiv=refresh content=0;url=rusqlite/index.html>' > target/doc/index.html | echo '<meta http-equiv=refresh content=0;url=rusqlite/index.html>' > target/doc/index.html | ||||||
| ghp-import target/doc | ghp-import target/doc | ||||||
| git push origin gh-pages:gh-pages | git push origin gh-pages:gh-pages | ||||||
|   | |||||||
| @@ -235,7 +235,10 @@ impl<'conn> Drop for Blob<'conn> { | |||||||
| } | } | ||||||
|  |  | ||||||
| /// BLOB of length N that is filled with zeroes. | /// BLOB of length N that is filled with zeroes. | ||||||
| /// Zeroblobs are intended to serve as placeholders for BLOBs whose content is later written using incremental BLOB I/O routines. | /// | ||||||
|  | /// Zeroblobs are intended to serve as placeholders for BLOBs whose content is later written using | ||||||
|  | /// incremental BLOB I/O routines. | ||||||
|  | /// | ||||||
| /// A negative value for the zeroblob results in a zero-length BLOB. | /// A negative value for the zeroblob results in a zero-length BLOB. | ||||||
| #[derive(Copy,Clone)] | #[derive(Copy,Clone)] | ||||||
| pub struct ZeroBlob(pub i32); | pub struct ZeroBlob(pub i32); | ||||||
|   | |||||||
| @@ -34,7 +34,7 @@ impl Connection { | |||||||
|     /// Will return `Err` if `sql` cannot be converted to a C-compatible string or if the |     /// Will return `Err` if `sql` cannot be converted to a C-compatible string or if the | ||||||
|     /// underlying SQLite call fails. |     /// underlying SQLite call fails. | ||||||
|     pub fn prepare_cached<'a>(&'a self, sql: &str) -> Result<CachedStatement<'a>> { |     pub fn prepare_cached<'a>(&'a self, sql: &str) -> Result<CachedStatement<'a>> { | ||||||
|         self.cache.get(&self, sql) |         self.cache.get(self, sql) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Set the maximum number of cached prepared statements this connection will hold. |     /// Set the maximum number of cached prepared statements this connection will hold. | ||||||
| @@ -90,6 +90,8 @@ impl<'conn> CachedStatement<'conn> { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /// Discard the statement, preventing it from being returned to its `Connection`'s collection | ||||||
|  |     /// of cached statements. | ||||||
|     pub fn discard(mut self) { |     pub fn discard(mut self) { | ||||||
|         self.stmt = None; |         self.stmt = None; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -170,8 +170,8 @@ impl error::Error for Error { | |||||||
|             Error::InvalidColumnIndex(_) | |             Error::InvalidColumnIndex(_) | | ||||||
|             Error::InvalidColumnName(_) | |             Error::InvalidColumnName(_) | | ||||||
|             Error::InvalidColumnType(_, _) | |             Error::InvalidColumnType(_, _) | | ||||||
|             Error::InvalidPath(_) => None, |             Error::InvalidPath(_) | | ||||||
|             Error::StatementChangedRows(_) => None, |             Error::StatementChangedRows(_) | | ||||||
|             Error::StatementFailedToInsertRow => None, |             Error::StatementFailedToInsertRow => None, | ||||||
|  |  | ||||||
|             #[cfg(feature = "functions")] |             #[cfg(feature = "functions")] | ||||||
|   | |||||||
| @@ -111,7 +111,8 @@ impl<'a> ToResult for &'a str { | |||||||
|                                          length as c_int, |                                          length as c_int, | ||||||
|                                          ffi::SQLITE_TRANSIENT()) |                                          ffi::SQLITE_TRANSIENT()) | ||||||
|             } |             } | ||||||
|             Err(_) => ffi::sqlite3_result_error_code(ctx, ffi::SQLITE_MISUSE), // TODO sqlite3_result_error |             // TODO sqlite3_result_error | ||||||
|  |             Err(_) => ffi::sqlite3_result_error_code(ctx, ffi::SQLITE_MISUSE), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -730,9 +731,10 @@ mod test { | |||||||
|  |  | ||||||
|         assert_eq!(true, result.unwrap()); |         assert_eq!(true, result.unwrap()); | ||||||
|  |  | ||||||
|         let result: Result<i64> = db.query_row("SELECT COUNT(*) FROM foo WHERE regexp('l.s[aeiouy]', x) == 1", |         let result: Result<i64> = | ||||||
|                                   &[], |             db.query_row("SELECT COUNT(*) FROM foo WHERE regexp('l.s[aeiouy]', x) == 1", | ||||||
|                                   |r| r.get(0)); |                          &[], | ||||||
|  |                          |r| r.get(0)); | ||||||
|  |  | ||||||
|         assert_eq!(2, result.unwrap()); |         assert_eq!(2, result.unwrap()); | ||||||
|     } |     } | ||||||
| @@ -780,9 +782,10 @@ mod test { | |||||||
|  |  | ||||||
|         assert_eq!(true, result.unwrap()); |         assert_eq!(true, result.unwrap()); | ||||||
|  |  | ||||||
|         let result: Result<i64> = db.query_row("SELECT COUNT(*) FROM foo WHERE regexp('l.s[aeiouy]', x) == 1", |         let result: Result<i64> = | ||||||
|                                   &[], |             db.query_row("SELECT COUNT(*) FROM foo WHERE regexp('l.s[aeiouy]', x) == 1", | ||||||
|                                   |r| r.get(0)); |                          &[], | ||||||
|  |                          |r| r.get(0)); | ||||||
|  |  | ||||||
|         assert_eq!(2, result.unwrap()); |         assert_eq!(2, result.unwrap()); | ||||||
|     } |     } | ||||||
|   | |||||||
							
								
								
									
										29
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								src/lib.rs
									
									
									
									
									
								
							| @@ -80,7 +80,8 @@ use error::{error_from_sqlite_code, error_from_handle}; | |||||||
| use raw_statement::RawStatement; | use raw_statement::RawStatement; | ||||||
| use cache::StatementCache; | use cache::StatementCache; | ||||||
|  |  | ||||||
| pub use transaction::{SqliteTransaction, Transaction, TransactionBehavior}; | pub use transaction::{SqliteTransaction, SqliteTransactionBehavior, DropBehavior, Savepoint, | ||||||
|  |                       Transaction, TransactionBehavior}; | ||||||
| pub use error::{SqliteError, Error}; | pub use error::{SqliteError, Error}; | ||||||
| pub use cache::CachedStatement; | pub use cache::CachedStatement; | ||||||
|  |  | ||||||
| @@ -320,7 +321,9 @@ impl Connection { | |||||||
|     /// ```rust,no_run |     /// ```rust,no_run | ||||||
|     /// # use rusqlite::{Result,Connection}; |     /// # use rusqlite::{Result,Connection}; | ||||||
|     /// fn preferred_locale(conn: &Connection) -> Result<String> { |     /// fn preferred_locale(conn: &Connection) -> Result<String> { | ||||||
|     ///     conn.query_row_and_then("SELECT value FROM preferences WHERE name='locale'", &[], |row| { |     ///     conn.query_row_and_then("SELECT value FROM preferences WHERE name='locale'", | ||||||
|  |     ///                             &[], | ||||||
|  |     ///                             |row| { | ||||||
|     ///         row.get_checked(0) |     ///         row.get_checked(0) | ||||||
|     ///     }) |     ///     }) | ||||||
|     /// } |     /// } | ||||||
| @@ -710,9 +713,12 @@ impl<'conn> Statement<'conn> { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Returns the column index in the result set for a given column name. |     /// Returns the column index in the result set for a given column name. | ||||||
|     /// If there is no AS clause then the name of the column is unspecified and may change from one release of SQLite to the next. |     /// | ||||||
|  |     /// If there is no AS clause then the name of the column is unspecified and may change from one | ||||||
|  |     /// release of SQLite to the next. | ||||||
|     /// |     /// | ||||||
|     /// # Failure |     /// # Failure | ||||||
|  |     /// | ||||||
|     /// Will return an `Error::InvalidColumnName` when there is no column with the specified `name`. |     /// Will return an `Error::InvalidColumnName` when there is no column with the specified `name`. | ||||||
|     pub fn column_index(&self, name: &str) -> Result<i32> { |     pub fn column_index(&self, name: &str) -> Result<i32> { | ||||||
|         let bytes = name.as_bytes(); |         let bytes = name.as_bytes(); | ||||||
| @@ -966,9 +972,7 @@ pub struct Rows<'stmt> { | |||||||
|  |  | ||||||
| impl<'stmt> Rows<'stmt> { | impl<'stmt> Rows<'stmt> { | ||||||
|     fn new(stmt: &'stmt Statement<'stmt>) -> Rows<'stmt> { |     fn new(stmt: &'stmt Statement<'stmt>) -> Rows<'stmt> { | ||||||
|         Rows { |         Rows { stmt: Some(stmt) } | ||||||
|             stmt: Some(stmt), |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn get_expected_row<'a>(&'a mut self) -> Result<Row<'a, 'stmt>> { |     fn get_expected_row<'a>(&'a mut self) -> Result<Row<'a, 'stmt>> { | ||||||
| @@ -1372,19 +1376,6 @@ mod test { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     #[test] |  | ||||||
|     #[should_panic] |  | ||||||
|     fn test_rows_dropped() { |  | ||||||
|         let db = checked_memory_handle(); |  | ||||||
|         db.execute_batch("CREATE TABLE foo(x INTEGER)").unwrap(); |  | ||||||
|         db.execute_batch("INSERT INTO foo(x) VALUES(1)").unwrap(); |  | ||||||
|  |  | ||||||
|         let mut stmt = db.prepare("SELECT x FROM foo").unwrap(); |  | ||||||
|         let row = stmt.query(&[]).unwrap().next().unwrap().unwrap(); |  | ||||||
|  |  | ||||||
|         assert_eq!(1i32, row.get(0)); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     mod query_and_then_tests { |     mod query_and_then_tests { | ||||||
|         extern crate libsqlite3_sys as ffi; |         extern crate libsqlite3_sys as ffi; | ||||||
|         use super::*; |         use super::*; | ||||||
|   | |||||||
| @@ -279,9 +279,10 @@ mod test { | |||||||
|  |  | ||||||
|         let mut stmt = db.prepare("SELECT id FROM test where name = :name").unwrap(); |         let mut stmt = db.prepare("SELECT id FROM test where name = :name").unwrap(); | ||||||
|         let mut rows = stmt.query_map_named(&[(":name", &"one")], |row| { |         let mut rows = stmt.query_map_named(&[(":name", &"one")], |row| { | ||||||
|             let id: i32 = row.get(0); |                 let id: i32 = row.get(0); | ||||||
|             2 * id |                 2 * id | ||||||
|         }).unwrap(); |             }) | ||||||
|  |             .unwrap(); | ||||||
|  |  | ||||||
|         let doubled_id: i32 = rows.next().unwrap().unwrap(); |         let doubled_id: i32 = rows.next().unwrap().unwrap(); | ||||||
|         assert_eq!(2, doubled_id); |         assert_eq!(2, doubled_id); | ||||||
| @@ -298,15 +299,17 @@ mod test { | |||||||
|         "#; |         "#; | ||||||
|         db.execute_batch(sql).unwrap(); |         db.execute_batch(sql).unwrap(); | ||||||
|  |  | ||||||
|         let mut stmt = db.prepare("SELECT id FROM test where name = :name ORDER BY id ASC").unwrap(); |         let mut stmt = db.prepare("SELECT id FROM test where name = :name ORDER BY id ASC") | ||||||
|  |             .unwrap(); | ||||||
|         let mut rows = stmt.query_and_then_named(&[(":name", &"one")], |row| { |         let mut rows = stmt.query_and_then_named(&[(":name", &"one")], |row| { | ||||||
|             let id: i32 = row.get(0); |                 let id: i32 = row.get(0); | ||||||
|             if id == 1 { |                 if id == 1 { | ||||||
|                 Ok(id) |                     Ok(id) | ||||||
|             } else { |                 } else { | ||||||
|                 Err(Error::SqliteSingleThreadedMode) |                     Err(Error::SqliteSingleThreadedMode) | ||||||
|             } |                 } | ||||||
|         }).unwrap(); |             }) | ||||||
|  |             .unwrap(); | ||||||
|  |  | ||||||
|         // first row should be Ok |         // first row should be Ok | ||||||
|         let doubled_id: i32 = rows.next().unwrap().unwrap(); |         let doubled_id: i32 = rows.next().unwrap().unwrap(); | ||||||
|   | |||||||
| @@ -59,7 +59,8 @@ pub fn log(err_code: c_int, msg: &str) { | |||||||
| } | } | ||||||
|  |  | ||||||
| impl Connection { | impl Connection { | ||||||
|     /// Register or clear a callback function that can be used for tracing the execution of SQL statements. |     /// Register or clear a callback function that can be used for tracing the execution of SQL | ||||||
|  |     /// statements. | ||||||
|     /// |     /// | ||||||
|     /// Prepared statement placeholders are replaced/logged with their assigned values. |     /// Prepared statement placeholders are replaced/logged with their assigned values. | ||||||
|     /// There can only be a single tracer defined for each database connection. |     /// There can only be a single tracer defined for each database connection. | ||||||
| @@ -83,7 +84,8 @@ impl Connection { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Register or clear a callback function that can be used for profiling the execution of SQL statements. |     /// Register or clear a callback function that can be used for profiling the execution of SQL | ||||||
|  |     /// statements. | ||||||
|     /// |     /// | ||||||
|     /// There can only be a single profiler defined for each database connection. |     /// There can only be a single profiler defined for each database connection. | ||||||
|     /// Setting a new profiler clears the old one. |     /// Setting a new profiler clears the old one. | ||||||
|   | |||||||
| @@ -209,7 +209,10 @@ impl<'conn> Drop for Transaction<'conn> { | |||||||
| } | } | ||||||
|  |  | ||||||
| impl<'conn> Savepoint<'conn> { | impl<'conn> Savepoint<'conn> { | ||||||
|     fn with_depth_and_name<T: Into<String>>(conn: &Connection, depth: u32, name: T) -> Result<Savepoint> { |     fn with_depth_and_name<T: Into<String>>(conn: &Connection, | ||||||
|  |                                             depth: u32, | ||||||
|  |                                             name: T) | ||||||
|  |                                             -> Result<Savepoint> { | ||||||
|         let name = name.into(); |         let name = name.into(); | ||||||
|         conn.execute_batch(&format!("SAVEPOINT {}", name)).map(|_| { |         conn.execute_batch(&format!("SAVEPOINT {}", name)).map(|_| { | ||||||
|             Savepoint { |             Savepoint { | ||||||
| @@ -349,7 +352,9 @@ impl Connection { | |||||||
|     /// # Failure |     /// # Failure | ||||||
|     /// |     /// | ||||||
|     /// Will return `Err` if the underlying SQLite call fails. |     /// Will return `Err` if the underlying SQLite call fails. | ||||||
|     pub fn transaction_with_behavior(&mut self, behavior: TransactionBehavior) -> Result<Transaction> { |     pub fn transaction_with_behavior(&mut self, | ||||||
|  |                                      behavior: TransactionBehavior) | ||||||
|  |                                      -> Result<Transaction> { | ||||||
|         Transaction::new(self, behavior) |         Transaction::new(self, behavior) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -228,7 +228,7 @@ impl From<csv::Error> for Error { | |||||||
|  |  | ||||||
| #[cfg(test)] | #[cfg(test)] | ||||||
| mod test { | mod test { | ||||||
|     use Connection; |     use {Connection,Result}; | ||||||
|     use vtab::csvtab; |     use vtab::csvtab; | ||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
| @@ -244,13 +244,8 @@ mod test { | |||||||
|                 assert_eq!(vec!["rowid", "colA", "colB", "colC"], headers); |                 assert_eq!(vec!["rowid", "colA", "colB", "colC"], headers); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             let rows = s.query(&[]).unwrap(); |             let ids: Result<Vec<i32>> = s.query_map(&[], |row| row.get::<i32, i32>(0)).unwrap().collect(); | ||||||
|             let mut sum = 0; |             let sum = ids.unwrap().iter().fold(0, |acc, &id| acc + id); | ||||||
|             for row in rows { |  | ||||||
|                 let row = row.unwrap(); |  | ||||||
|                 let id: i64 = row.get(0); |  | ||||||
|                 sum = sum + id; |  | ||||||
|             } |  | ||||||
|             assert_eq!(sum, 15); |             assert_eq!(sum, 15); | ||||||
|         } |         } | ||||||
|         db.execute_batch("DROP TABLE vtab").unwrap(); |         db.execute_batch("DROP TABLE vtab").unwrap(); | ||||||
|   | |||||||
| @@ -163,14 +163,12 @@ mod test { | |||||||
|         p3.borrow_mut().append(&mut vec![-1, -5, -10]); |         p3.borrow_mut().append(&mut vec![-1, -5, -10]); | ||||||
|  |  | ||||||
|         { |         { | ||||||
|             let rows = s.query(&[]).unwrap(); |             s.query_map(&[], |row| { | ||||||
|             for row in rows { |  | ||||||
|                 let row = row.unwrap(); |  | ||||||
|                 let i1: i64 = row.get(0); |                 let i1: i64 = row.get(0); | ||||||
|                 assert!(i1 == 1 || i1 == 3); |                 assert!(i1 == 1 || i1 == 3); | ||||||
|                 assert_eq!(11, row.get(1)); |                 assert_eq!(11, row.get(1)); | ||||||
|                 assert_eq!(-5, row.get(2)); |                 assert_eq!(-5, row.get(2)); | ||||||
|             } |             }).unwrap(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         p1.borrow_mut().clear(); |         p1.borrow_mut().clear(); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user