From 4e780d4e38b82938426dbcea368b4392151f9fd9 Mon Sep 17 00:00:00 2001 From: Jakub Pastuszek Date: Thu, 7 May 2020 13:39:42 +0100 Subject: [PATCH 1/2] moved PhantomData<'con> to Raii to prevent Raii drop after 'con drop when Statement bound to temporary at final expression in block --- examples/custom_get_data.rs | 2 +- src/raii.rs | 18 ++++++++++++------ src/statement/input.rs | 2 +- src/statement/mod.rs | 24 +++++++++++------------- src/statement/output.rs | 2 +- src/statement/prepare.rs | 2 +- tests/gbk.rs | 16 +++++++--------- tests/input_parameter.rs | 2 +- tests/libs.rs | 6 +++--- 9 files changed, 38 insertions(+), 36 deletions(-) diff --git a/examples/custom_get_data.rs b/examples/custom_get_data.rs index 614e2c62..fe1f07c9 100644 --- a/examples/custom_get_data.rs +++ b/examples/custom_get_data.rs @@ -14,7 +14,7 @@ trait Extract { T: MySupportedType; } -impl<'a, S, AC: AutocommitMode> Extract for Cursor<'a, 'a, 'a, S, AC> { +impl<'s, 'a: 's, S: 's, AC: AutocommitMode> Extract for Cursor<'s, 'a, 'a, S, AC> { fn extract(&mut self, index: u16) -> Option where T: MySupportedType, diff --git a/src/raii.rs b/src/raii.rs index d90e8b7d..a0faff42 100644 --- a/src/raii.rs +++ b/src/raii.rs @@ -1,23 +1,27 @@ use super::{ffi, safe, DiagnosticRecord, GetDiagRec, Handle, OdbcObject, Return}; use std::ptr::null_mut; +use std::marker::PhantomData; /// Wrapper around handle types which ensures the wrapped value is always valid. /// /// Resource Acquisition Is Initialization #[derive(Debug)] -pub struct Raii { +pub struct Raii<'p, T: OdbcObject> { //Invariant: Should always point to a valid odbc Object handle: *mut T, + // we use phantom data to tell the borrow checker that we need to keep the data source alive + // for the lifetime of the handle + parent: PhantomData<&'p ()>, } -impl Handle for Raii { +impl<'p, T: OdbcObject> Handle for Raii<'p, T> { type To = T; unsafe fn handle(&self) -> *mut T { self.handle } } -unsafe impl safe::Handle for Raii { +unsafe impl<'p, T: OdbcObject> safe::Handle for Raii<'p, T> { const HANDLE_TYPE: ffi::HandleType = T::HANDLE_TYPE; fn handle(&self) -> ffi::SQLHANDLE { @@ -25,7 +29,7 @@ unsafe impl safe::Handle for Raii { } } -impl Drop for Raii { +impl<'p, T: OdbcObject> Drop for Raii<'p, T> { fn drop(&mut self) { match unsafe { ffi::SQLFreeHandle(T::HANDLE_TYPE, self.handle() as ffi::SQLHANDLE) } { ffi::SQL_SUCCESS => (), @@ -38,8 +42,8 @@ impl Drop for Raii { } } -impl Raii { - pub fn with_parent

(parent: &P) -> Return +impl<'p, T: OdbcObject> Raii<'p, T> { + pub fn with_parent

(parent: &'p P) -> Return where P: Handle, { @@ -53,9 +57,11 @@ impl Raii { } { ffi::SQL_SUCCESS => Return::Success(Raii { handle: handle as *mut T, + parent: PhantomData, }), ffi::SQL_SUCCESS_WITH_INFO => Return::SuccessWithInfo(Raii { handle: handle as *mut T, + parent: PhantomData, }), ffi::SQL_ERROR => Return::Error, _ => panic!("SQLAllocHandle returned unexpected result"), diff --git a/src/statement/input.rs b/src/statement/input.rs index 60034f5d..bb7dffa3 100644 --- a/src/statement/input.rs +++ b/src/statement/input.rs @@ -75,7 +75,7 @@ impl<'a, 'b, S, R, AC: AutocommitMode> Statement<'a, 'b, S, R, AC> { } } -impl Raii { +impl<'p> Raii<'p, ffi::Stmt> { fn bind_input_parameter<'c, T>( &mut self, parameter_index: u16, diff --git a/src/statement/mod.rs b/src/statement/mod.rs index b2ec314d..0429484b 100644 --- a/src/statement/mod.rs +++ b/src/statement/mod.rs @@ -66,12 +66,10 @@ use std::ptr::null_mut; use odbc_safe::AutocommitMode; /// A `Statement` can be used to execute queries and retrieves results. -pub struct Statement<'con, 'b, S, R, AC: AutocommitMode> { - raii: Raii, - // we use phantom data to tell the borrow checker that we need to keep the data source alive - // for the lifetime of the statement - parent: PhantomData<&'con Connection<'con, AC>>, +pub struct Statement<'a, 'b, S, R, AC: AutocommitMode> { + raii: Raii<'a, ffi::Stmt>, state: PhantomData, + autocommit_mode: PhantomData, // Indicates wether there is an open result set or not associated with this statement. result: PhantomData, parameters: PhantomData<&'b [u8]>, @@ -81,8 +79,8 @@ pub struct Statement<'con, 'b, S, R, AC: AutocommitMode> { } /// Used to retrieve data from the fields of a query result -pub struct Cursor<'a, 'b: 'a, 'c: 'a, S: 'a, AC: AutocommitMode> { - stmt: &'a mut Statement<'b, 'c, S, HasResult, AC>, +pub struct Cursor<'s, 'a: 's, 'b: 's, S: 's, AC: AutocommitMode> { + stmt: &'s mut Statement<'a, 'b, S, HasResult, AC>, buffer: Vec, } @@ -103,10 +101,10 @@ impl<'a, 'b, S, R, AC: AutocommitMode> Handle for Statement<'a, 'b, S, R, AC> { } impl<'a, 'b, S, R, AC: AutocommitMode> Statement<'a, 'b, S, R, AC> { - fn with_raii(raii: Raii) -> Self { + fn with_raii(raii: Raii<'a, ffi::Stmt>) -> Self { Statement { raii: raii, - parent: PhantomData, + autocommit_mode: PhantomData, state: PhantomData, result: PhantomData, parameters: PhantomData, @@ -194,7 +192,7 @@ impl<'a, 'b, S, AC: AutocommitMode> Statement<'a, 'b, S, HasResult, AC> { } /// Fetches the next rowset of data from the result set and returns data for all bound columns. - pub fn fetch<'c>(&'c mut self) -> Result>> { + pub fn fetch<'s>(&'s mut self) -> Result>> { if self.raii.fetch().into_result(self)? { Ok(Some(Cursor { stmt: self, @@ -240,9 +238,9 @@ impl<'a, 'b, S, AC: AutocommitMode> Statement<'a, 'b, S, HasResult, AC> { impl<'a, 'b, 'c, S, AC: AutocommitMode> Cursor<'a, 'b, 'c, S, AC> { /// Retrieves data for a single column in the result set - /// + /// /// ## Panics - /// + /// /// If you try to convert to `&str` but the data can't be converted /// without allocating an intermediate buffer. pub fn get_data<'d, T>(&'d mut self, col_or_param_num: u16) -> Result> @@ -253,7 +251,7 @@ impl<'a, 'b, 'c, S, AC: AutocommitMode> Cursor<'a, 'b, 'c, S, AC> { } } -impl Raii { +impl<'p> Raii<'p, ffi::Stmt> { fn affected_row_count(&self) -> Return { let mut count: ffi::SQLLEN = 0; unsafe { diff --git a/src/statement/output.rs b/src/statement/output.rs index bd359c4c..9e46a1f9 100644 --- a/src/statement/output.rs +++ b/src/statement/output.rs @@ -24,7 +24,7 @@ where } } -impl Raii { +impl<'p> Raii<'p, ffi::Stmt> { fn get_data<'a, T>( &mut self, col_or_param_num: u16, diff --git a/src/statement/prepare.rs b/src/statement/prepare.rs index 9811ea9f..67193a55 100644 --- a/src/statement/prepare.rs +++ b/src/statement/prepare.rs @@ -98,7 +98,7 @@ impl<'a, 'b, AC: AutocommitMode> Statement<'a, 'b, Prepared, NoResult, AC> { } } -impl Raii { +impl<'p> Raii<'p, ffi::Stmt> { fn prepare(&mut self, sql_text: &str) -> Return<()> { let bytes = unsafe { crate::environment::DB_ENCODING }.encode(sql_text).0; match unsafe { diff --git a/tests/gbk.rs b/tests/gbk.rs index b463183c..583d1048 100644 --- a/tests/gbk.rs +++ b/tests/gbk.rs @@ -23,7 +23,7 @@ fn _exec_direct() { } } else { panic!("SELECT did not return result set"); - } + }; } #[test] @@ -48,8 +48,7 @@ fn _prepare_1() { NoData(_) => { panic!("SELECT did not return result set"); } - } - + }; } #[test] @@ -77,7 +76,7 @@ fn _prepare_2() { } } else { panic!("SELECT did not return result set"); - } + }; } #[test] @@ -98,7 +97,7 @@ fn exec_direct() { } } else { panic!("SELECT did not return result set"); - } + }; } #[test] @@ -120,8 +119,7 @@ fn prepare_1() { } } else { panic!("SELECT did not return result set"); - } - + }; } /// CustomOdbcType for bindParameter @@ -150,7 +148,7 @@ unsafe impl<'a> OdbcType<'a> for CustomOdbcType<'a> { fn value_ptr(&self) -> ffi::SQLPOINTER { self.data.as_ptr() as *const Self as ffi::SQLPOINTER } - + fn encoded_value(&self) -> EncodedValue { EncodedValue::new(None) } @@ -180,5 +178,5 @@ fn prepare_2() { } } else { panic!("SELECT did not return result set"); - } + }; } diff --git a/tests/input_parameter.rs b/tests/input_parameter.rs index 0a728579..42f1632b 100644 --- a/tests/input_parameter.rs +++ b/tests/input_parameter.rs @@ -25,7 +25,7 @@ macro_rules! test_type { } }else{ panic!("SELECT did not return result set"); - } + }; }) } diff --git a/tests/libs.rs b/tests/libs.rs index d437db67..2042fd82 100644 --- a/tests/libs.rs +++ b/tests/libs.rs @@ -329,7 +329,7 @@ fn zero_truncation_bug() { NoData(stmt) => stmt, }; // Reproduction of zeroes truncation bug. Until now there is no chance to query binary data - // with zero at 512 byte border. + // with zero at 512 byte border. let data = vec![0;513]; stmt .prepare("INSERT INTO ZERO_TRUNCATION_BUG VALUES (?)") @@ -349,5 +349,5 @@ fn zero_truncation_bug() { stmt.exec_direct("DROP TABLE ZERO_TRUNCATION_BUG").unwrap(); } else { panic!("SELECT statement returned no result set") - } -} \ No newline at end of file + }; +} From 18f7015955977e34e7f53e34e53210b025ccd2f2 Mon Sep 17 00:00:00 2001 From: Jakub Pastuszek Date: Thu, 7 May 2020 14:35:46 +0100 Subject: [PATCH 2/2] fixed more tests --- tests/native_types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/native_types.rs b/tests/native_types.rs index 5f20b27e..f181d619 100644 --- a/tests/native_types.rs +++ b/tests/native_types.rs @@ -24,7 +24,7 @@ macro_rules! test_type { } } else { panic!("SELECT did not return result set"); - } + }; }) }