mirror of
				https://github.com/isar/rusqlite.git
				synced 2025-10-31 22:08:55 +08:00 
			
		
		
		
	Merge branch 'master' into savepoint-improvements
This commit is contained in:
		
							
								
								
									
										91
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										91
									
								
								src/lib.rs
									
									
									
									
									
								
							| @@ -55,6 +55,7 @@ | ||||
|  | ||||
| extern crate libc; | ||||
| extern crate libsqlite3_sys as ffi; | ||||
| extern crate lru_cache; | ||||
| #[macro_use] | ||||
| extern crate bitflags; | ||||
| #[cfg(test)] | ||||
| @@ -76,24 +77,32 @@ use libc::{c_int, c_char}; | ||||
|  | ||||
| use types::{ToSql, FromSql}; | ||||
| use error::{error_from_sqlite_code, error_from_handle}; | ||||
| use raw_statement::RawStatement; | ||||
| use cache::StatementCache; | ||||
|  | ||||
| pub use transaction::{SqliteTransaction, Transaction, TransactionBehavior}; | ||||
| pub use error::{SqliteError, Error}; | ||||
| pub use cache::CachedStatement; | ||||
|  | ||||
| #[cfg(feature = "load_extension")] | ||||
| pub use load_extension_guard::{SqliteLoadExtensionGuard, LoadExtensionGuard}; | ||||
|  | ||||
| pub mod types; | ||||
| mod transaction; | ||||
| mod cache; | ||||
| mod named_params; | ||||
| mod error; | ||||
| mod convenient; | ||||
| mod raw_statement; | ||||
| #[cfg(feature = "load_extension")]mod load_extension_guard; | ||||
| #[cfg(feature = "trace")]pub mod trace; | ||||
| #[cfg(feature = "backup")]pub mod backup; | ||||
| #[cfg(feature = "functions")]pub mod functions; | ||||
| #[cfg(feature = "blob")]pub mod blob; | ||||
|  | ||||
| // Number of cached prepared statements we'll hold on to. | ||||
| const STATEMENT_CACHE_DEFAULT_CAPACITY: usize = 16; | ||||
|  | ||||
| /// Old name for `Result`. `SqliteResult` is deprecated. | ||||
| pub type SqliteResult<T> = Result<T>; | ||||
|  | ||||
| @@ -146,6 +155,7 @@ pub type SqliteConnection = Connection; | ||||
| /// A connection to a SQLite database. | ||||
| pub struct Connection { | ||||
|     db: RefCell<InnerConnection>, | ||||
|     cache: StatementCache, | ||||
|     path: Option<PathBuf>, | ||||
| } | ||||
|  | ||||
| @@ -190,6 +200,7 @@ impl Connection { | ||||
|         InnerConnection::open_with_flags(&c_path, flags).map(|db| { | ||||
|             Connection { | ||||
|                 db: RefCell::new(db), | ||||
|                 cache: StatementCache::with_capacity(STATEMENT_CACHE_DEFAULT_CAPACITY), | ||||
|                 path: Some(path.as_ref().to_path_buf()), | ||||
|             } | ||||
|         }) | ||||
| @@ -208,6 +219,7 @@ impl Connection { | ||||
|         InnerConnection::open_with_flags(&c_memory, flags).map(|db| { | ||||
|             Connection { | ||||
|                 db: RefCell::new(db), | ||||
|                 cache: StatementCache::with_capacity(STATEMENT_CACHE_DEFAULT_CAPACITY), | ||||
|                 path: None, | ||||
|             } | ||||
|         }) | ||||
| @@ -647,7 +659,7 @@ impl InnerConnection { | ||||
|                                     &mut c_stmt, | ||||
|                                     ptr::null_mut()) | ||||
|         }; | ||||
|         self.decode_result(r).map(|_| Statement::new(conn, c_stmt)) | ||||
|         self.decode_result(r).map(|_| Statement::new(conn, RawStatement::new(c_stmt))) | ||||
|     } | ||||
|  | ||||
|     fn changes(&mut self) -> c_int { | ||||
| @@ -668,25 +680,23 @@ pub type SqliteStatement<'conn> = Statement<'conn>; | ||||
| /// A prepared statement. | ||||
| pub struct Statement<'conn> { | ||||
|     conn: &'conn Connection, | ||||
|     stmt: *mut ffi::sqlite3_stmt, | ||||
|     column_count: c_int, | ||||
|     stmt: RawStatement, | ||||
| } | ||||
|  | ||||
| impl<'conn> Statement<'conn> { | ||||
|     fn new(conn: &Connection, stmt: *mut ffi::sqlite3_stmt) -> Statement { | ||||
|     fn new(conn: &Connection, stmt: RawStatement) -> Statement { | ||||
|         Statement { | ||||
|             conn: conn, | ||||
|             stmt: stmt, | ||||
|             column_count: unsafe { ffi::sqlite3_column_count(stmt) }, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// Get all the column names in the result set of the prepared statement. | ||||
|     pub fn column_names(&self) -> Vec<&str> { | ||||
|         let n = self.column_count; | ||||
|         let n = self.column_count(); | ||||
|         let mut cols = Vec::with_capacity(n as usize); | ||||
|         for i in 0..n { | ||||
|             let slice = unsafe { CStr::from_ptr(ffi::sqlite3_column_name(self.stmt, i)) }; | ||||
|             let slice = self.stmt.column_name(i); | ||||
|             let s = str::from_utf8(slice.to_bytes()).unwrap(); | ||||
|             cols.push(s); | ||||
|         } | ||||
| @@ -695,7 +705,7 @@ impl<'conn> Statement<'conn> { | ||||
|  | ||||
|     /// Return the number of columns in the result set returned by the prepared statement. | ||||
|     pub fn column_count(&self) -> i32 { | ||||
|         self.column_count | ||||
|         self.stmt.column_count() | ||||
|     } | ||||
|  | ||||
|     /// Returns the column index in the result set for a given column name. | ||||
| @@ -705,10 +715,9 @@ impl<'conn> Statement<'conn> { | ||||
|     /// Will return an `Error::InvalidColumnName` when there is no column with the specified `name`. | ||||
|     pub fn column_index(&self, name: &str) -> Result<i32> { | ||||
|         let bytes = name.as_bytes(); | ||||
|         let n = self.column_count; | ||||
|         let n = self.column_count(); | ||||
|         for i in 0..n { | ||||
|             let slice = unsafe { CStr::from_ptr(ffi::sqlite3_column_name(self.stmt, i)) }; | ||||
|             if bytes == slice.to_bytes() { | ||||
|             if bytes == self.stmt.column_name(i).to_bytes() { | ||||
|                 return Ok(i); | ||||
|             } | ||||
|         } | ||||
| @@ -739,18 +748,16 @@ impl<'conn> Statement<'conn> { | ||||
|     /// Will return `Err` if binding parameters fails, the executed statement returns rows (in | ||||
|     /// which case `query` should be used instead), or the underling SQLite call fails. | ||||
|     pub fn execute(&mut self, params: &[&ToSql]) -> Result<c_int> { | ||||
|         unsafe { | ||||
|             try!(self.bind_parameters(params)); | ||||
|             self.execute_() | ||||
|         } | ||||
|         try!(self.bind_parameters(params)); | ||||
|         self.execute_() | ||||
|     } | ||||
|  | ||||
|     unsafe fn execute_(&mut self) -> Result<c_int> { | ||||
|         let r = ffi::sqlite3_step(self.stmt); | ||||
|         ffi::sqlite3_reset(self.stmt); | ||||
|     fn execute_(&mut self) -> Result<c_int> { | ||||
|         let r = self.stmt.step(); | ||||
|         self.stmt.reset(); | ||||
|         match r { | ||||
|             ffi::SQLITE_DONE => { | ||||
|                 if self.column_count == 0 { | ||||
|                 if self.column_count() == 0 { | ||||
|                     Ok(self.conn.changes()) | ||||
|                 } else { | ||||
|                     Err(Error::ExecuteReturnedResults) | ||||
| @@ -785,10 +792,7 @@ impl<'conn> Statement<'conn> { | ||||
|     /// | ||||
|     /// Will return `Err` if binding parameters fails. | ||||
|     pub fn query<'a>(&'a mut self, params: &[&ToSql]) -> Result<Rows<'a>> { | ||||
|         unsafe { | ||||
|             try!(self.bind_parameters(params)); | ||||
|         } | ||||
|  | ||||
|         try!(self.bind_parameters(params)); | ||||
|         Ok(Rows::new(self)) | ||||
|     } | ||||
|  | ||||
| @@ -849,32 +853,39 @@ impl<'conn> Statement<'conn> { | ||||
|         self.finalize_() | ||||
|     } | ||||
|  | ||||
|     unsafe fn bind_parameters(&mut self, params: &[&ToSql]) -> Result<()> { | ||||
|         assert!(params.len() as c_int == ffi::sqlite3_bind_parameter_count(self.stmt), | ||||
|     fn bind_parameters(&mut self, params: &[&ToSql]) -> Result<()> { | ||||
|         assert!(params.len() as c_int == self.stmt.bind_parameter_count(), | ||||
|                 "incorrect number of parameters to query(): expected {}, got {}", | ||||
|                 ffi::sqlite3_bind_parameter_count(self.stmt), | ||||
|                 self.stmt.bind_parameter_count(), | ||||
|                 params.len()); | ||||
|  | ||||
|         for (i, p) in params.iter().enumerate() { | ||||
|             try!(self.conn.decode_result(p.bind_parameter(self.stmt, (i + 1) as c_int))); | ||||
|             try!(unsafe { | ||||
|                 self.conn.decode_result(p.bind_parameter(self.stmt.ptr(), (i + 1) as c_int)) | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     fn finalize_(&mut self) -> Result<()> { | ||||
|         let r = unsafe { ffi::sqlite3_finalize(self.stmt) }; | ||||
|         self.stmt = ptr::null_mut(); | ||||
|         self.conn.decode_result(r) | ||||
|         let mut stmt = RawStatement::new(ptr::null_mut()); | ||||
|         mem::swap(&mut stmt, &mut self.stmt); | ||||
|         self.conn.decode_result(stmt.finalize()) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<'conn> Into<RawStatement> for Statement<'conn> { | ||||
|     fn into(mut self) -> RawStatement { | ||||
|         let mut stmt = RawStatement::new(ptr::null_mut()); | ||||
|         mem::swap(&mut stmt, &mut self.stmt); | ||||
|         stmt | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<'conn> fmt::Debug for Statement<'conn> { | ||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         let sql = unsafe { | ||||
|             let c_slice = CStr::from_ptr(ffi::sqlite3_sql(self.stmt)).to_bytes(); | ||||
|             str::from_utf8(c_slice) | ||||
|         }; | ||||
|         let sql = str::from_utf8(self.stmt.sql().to_bytes()); | ||||
|         f.debug_struct("Statement") | ||||
|             .field("conn", self.conn) | ||||
|             .field("stmt", &self.stmt) | ||||
| @@ -984,9 +995,7 @@ impl<'stmt> Rows<'stmt> { | ||||
|  | ||||
|     fn reset(&mut self) { | ||||
|         if let Some(stmt) = self.stmt.take() { | ||||
|             unsafe { | ||||
|                 ffi::sqlite3_reset(stmt.stmt); | ||||
|             } | ||||
|             stmt.stmt.reset(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -996,7 +1005,7 @@ impl<'stmt> Iterator for Rows<'stmt> { | ||||
|  | ||||
|     fn next(&mut self) -> Option<Result<Row<'stmt>>> { | ||||
|         self.stmt.and_then(|stmt| { | ||||
|             match unsafe { ffi::sqlite3_step(stmt.stmt) } { | ||||
|             match stmt.stmt.step() { | ||||
|                 ffi::SQLITE_ROW => { | ||||
|                     let current_row = self.current_row.get() + 1; | ||||
|                     self.current_row.set(current_row); | ||||
| @@ -1091,8 +1100,8 @@ impl<'stmt> Row<'stmt> { | ||||
|         unsafe { | ||||
|             let idx = try!(idx.idx(self.stmt)); | ||||
|  | ||||
|             if T::column_has_valid_sqlite_type(self.stmt.stmt, idx) { | ||||
|                 FromSql::column_result(self.stmt.stmt, idx) | ||||
|             if T::column_has_valid_sqlite_type(self.stmt.stmt.ptr(), idx) { | ||||
|                 FromSql::column_result(self.stmt.stmt.ptr(), idx) | ||||
|             } else { | ||||
|                 Err(Error::InvalidColumnType) | ||||
|             } | ||||
| @@ -1115,7 +1124,7 @@ pub trait RowIndex { | ||||
| impl RowIndex for i32 { | ||||
|     #[inline] | ||||
|     fn idx(&self, stmt: &Statement) -> Result<i32> { | ||||
|         if *self < 0 || *self >= stmt.column_count { | ||||
|         if *self < 0 || *self >= stmt.column_count() { | ||||
|             Err(Error::InvalidColumnIndex(*self)) | ||||
|         } else { | ||||
|             Ok(*self) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user