rs_odbc/
conn.rs

1use crate::attr::{Attr, AttrGet, AttrLen, AttrSet};
2use crate::env::{OdbcVersion, SQL_OV_ODBC3, SQL_OV_ODBC3_80, SQL_OV_ODBC4};
3use crate::handle::SQLHDBC;
4use crate::str::{OdbcChar, OdbcStr};
5use crate::{
6    info::TxnIsolation, Ident, OdbcBool, OdbcDefined, Scalar, SQLCHAR, SQLINTEGER, SQLUINTEGER,
7    SQLWCHAR,
8};
9use rs_odbc_derive::{odbc_type, Ident};
10use core::mem::MaybeUninit;
11
12pub trait ConnState: private::ConnState {}
13
14/// C3 is not a valid state for setting or getting attributes
15pub trait ConnAttr<C: ConnState, A: Ident, V: OdbcVersion>:
16    Attr<A> + AttrLen<Self::DefinedBy, SQLINTEGER>
17{
18    // TODO: Attributes for which the value wasn't set with SQLSetConnectAttr
19    // cannot be used in SQLGetConnectAttr except for:
20    // SQL_ATTR_ACCESS_MODE, SQL_ATTR_AUTOCOMMIT, SQL_ATTR_LOGIN_TIMEOUT,
21    // SQL_ATTR_ODBC_CURSORS, SQL_ATTR_TRACE, or SQL_ATTR_TRACEFILE
22    // which have defined default values by the ODBC specification
23    // Check: https://docs.microsoft.com/en-us/sql/odbc/reference/appendixes/connection-transitions?view=sql-server-ver15#sqlbrowseconnect
24
25    // TODO: Track active statements in debug mode because SQL_ATTR_ASYNC_ENABLE
26    // can only be set when there are no active statements
27}
28
29// TODO: Where to keep these two traits? here in api.rs or handle.rs?
30pub trait BrowseConnect {}
31pub trait Disconnect {}
32
33/// Allocated
34#[derive(Debug)]
35pub enum C2 {}
36
37/// Need data
38#[derive(Debug)]
39pub enum C3 {}
40
41/// Connected
42#[derive(Debug)]
43pub enum C4 {}
44
45impl ConnState for C2 {}
46impl ConnState for C3 {}
47impl ConnState for C4 {}
48
49// Implement ConnAttr for all versions of connection attributes
50impl<C: ConnState, A: Ident, T: Scalar> ConnAttr<C, A, SQL_OV_ODBC3_80> for T where
51    T: ConnAttr<C, A, <SQL_OV_ODBC3_80 as OdbcVersion>::PrevVersion>
52{
53}
54impl<C: ConnState, A: Ident, T: Scalar> ConnAttr<C, A, SQL_OV_ODBC4> for T where
55    T: ConnAttr<C, A, <SQL_OV_ODBC4 as OdbcVersion>::PrevVersion>
56{
57}
58impl<C: ConnState, A: Ident, T: Scalar> ConnAttr<C, A, SQL_OV_ODBC3_80> for [T] where
59    [T]: ConnAttr<C, A, <SQL_OV_ODBC3_80 as OdbcVersion>::PrevVersion>
60{
61}
62impl<C: ConnState, A: Ident, T: Scalar> ConnAttr<C, A, SQL_OV_ODBC4> for [T] where
63    [T]: ConnAttr<C, A, <SQL_OV_ODBC4 as OdbcVersion>::PrevVersion>
64{
65}
66impl<C: ConnState, A: Ident, CH: OdbcChar> ConnAttr<C, A, SQL_OV_ODBC3_80> for OdbcStr<CH> where
67    OdbcStr<CH>: ConnAttr<C, A, <SQL_OV_ODBC3_80 as OdbcVersion>::PrevVersion>
68{
69}
70impl<C: ConnState, A: Ident, CH: OdbcChar> ConnAttr<C, A, SQL_OV_ODBC4> for OdbcStr<CH> where
71    OdbcStr<CH>: ConnAttr<C, A, <SQL_OV_ODBC4 as OdbcVersion>::PrevVersion>
72{
73}
74
75// Implement ConnAttr for uninitialized connection attributes
76impl<C: ConnState, A: Ident, T: Scalar, V: OdbcVersion> ConnAttr<C, A, V> for MaybeUninit<T>
77where
78    T: ConnAttr<C, A, V> + AttrGet<A>,
79    Self: AttrLen<Self::DefinedBy, SQLINTEGER>,
80{
81}
82impl<C: ConnState, A: Ident, T: Scalar, V: OdbcVersion> ConnAttr<C, A, V> for [MaybeUninit<T>]
83where
84    [T]: ConnAttr<C, A, V> + AttrGet<A>,
85    Self: AttrLen<Self::DefinedBy, SQLINTEGER>,
86{
87}
88impl<C: ConnState, A: Ident, V: OdbcVersion> ConnAttr<C, A, V> for OdbcStr<MaybeUninit<SQLCHAR>> where
89    OdbcStr<SQLCHAR>: ConnAttr<C, A, V> + AttrGet<A>
90{
91}
92impl<C: ConnState, A: Ident, V: OdbcVersion> ConnAttr<C, A, V> for OdbcStr<MaybeUninit<SQLWCHAR>> where
93    OdbcStr<SQLWCHAR>: ConnAttr<C, A, V> + AttrGet<A>
94{
95}
96
97// Implement ConnAttr for references to unsized types (used by AttrSet)
98impl<C: ConnState, A: Ident, T: Scalar, V: OdbcVersion> ConnAttr<C, A, V> for &[T]
99where
100    [T]: ConnAttr<C, A, V>,
101    Self: AttrSet<A>,
102{
103}
104impl<C: ConnState, A: Ident, CH: OdbcChar, V: OdbcVersion> ConnAttr<C, A, V> for &OdbcStr<CH>
105where
106    OdbcStr<CH>: ConnAttr<C, A, V>,
107    Self: AttrSet<A>,
108{
109}
110
111impl<V: OdbcVersion> BrowseConnect for SQLHDBC<'_, C2, V> {}
112impl<V: OdbcVersion> BrowseConnect for SQLHDBC<'_, C3, V> {}
113impl<V: OdbcVersion> Disconnect for SQLHDBC<'_, C3, V> {}
114impl<V: OdbcVersion> Disconnect for SQLHDBC<'_, C4, V> {}
115
116mod private {
117    use super::{C2, C3, C4};
118    #[double]
119    use crate::api::ffi;
120    use crate::convert::AsSQLHANDLE;
121    use crate::handle::SQLHDBC;
122    use crate::{env, sqlreturn};
123    use mockall_double::double;
124    use core::any;
125
126    pub trait ConnState {
127        // TODO: If drop impl specialization is allowed this fn will not be required
128        // Related to https://github.com/rust-lang/rust/issues/20400
129        fn disconnect<V: env::OdbcVersion>(handle: &mut SQLHDBC<Self, V>)
130        where
131            Self: super::ConnState + Sized,
132        {
133            let sql_return = unsafe { ffi::SQLDisconnect(handle.as_SQLHANDLE()) };
134
135            #[cfg(feature = "std")]
136            if std::thread::panicking() {
137                return;
138            }
139
140            if sql_return != sqlreturn::SQL_SUCCESS {
141                panic!(
142                    "{}: SQLDisconnect returned {:?}",
143                    any::type_name::<Self>(),
144                    sql_return
145                )
146            }
147        }
148    }
149
150    impl ConnState for C2 {
151        fn disconnect<V: env::OdbcVersion>(_: &mut SQLHDBC<Self, V>) {}
152    }
153    impl ConnState for C3 {}
154    impl ConnState for C4 {}
155}
156
157//=====================================================================================//
158//-------------------------------------Attributes--------------------------------------//
159
160#[derive(Ident)]
161#[identifier(SQLINTEGER, 101)]
162#[allow(non_camel_case_types)]
163pub struct SQL_ATTR_ACCESS_MODE;
164unsafe impl Attr<SQL_ATTR_ACCESS_MODE> for AccessMode {
165    type DefinedBy = OdbcDefined;
166}
167impl ConnAttr<C2, SQL_ATTR_ACCESS_MODE, SQL_OV_ODBC3> for AccessMode {}
168impl ConnAttr<C4, SQL_ATTR_ACCESS_MODE, SQL_OV_ODBC3> for AccessMode {}
169unsafe impl AttrGet<SQL_ATTR_ACCESS_MODE> for AccessMode {}
170unsafe impl AttrSet<SQL_ATTR_ACCESS_MODE> for AccessMode {}
171
172#[derive(Ident)]
173#[identifier(SQLINTEGER, 102)]
174#[allow(non_camel_case_types)]
175// TODO: Implement in type system
176pub struct SQL_ATTR_AUTOCOMMIT;
177unsafe impl Attr<SQL_ATTR_AUTOCOMMIT> for AutoCommit {
178    type DefinedBy = OdbcDefined;
179}
180impl ConnAttr<C2, SQL_ATTR_AUTOCOMMIT, SQL_OV_ODBC3> for AutoCommit {}
181impl ConnAttr<C4, SQL_ATTR_AUTOCOMMIT, SQL_OV_ODBC3> for AutoCommit {}
182unsafe impl AttrGet<SQL_ATTR_AUTOCOMMIT> for AutoCommit {}
183unsafe impl AttrSet<SQL_ATTR_AUTOCOMMIT> for AutoCommit {}
184
185#[derive(Ident)]
186#[identifier(SQLINTEGER, 113)]
187#[allow(non_camel_case_types)]
188pub struct SQL_ATTR_CONNECTION_TIMEOUT;
189unsafe impl Attr<SQL_ATTR_CONNECTION_TIMEOUT> for SQLUINTEGER {
190    type DefinedBy = OdbcDefined;
191}
192impl ConnAttr<C2, SQL_ATTR_CONNECTION_TIMEOUT, SQL_OV_ODBC3> for SQLUINTEGER {}
193impl ConnAttr<C4, SQL_ATTR_CONNECTION_TIMEOUT, SQL_OV_ODBC3> for SQLUINTEGER {}
194unsafe impl AttrGet<SQL_ATTR_CONNECTION_TIMEOUT> for SQLUINTEGER {}
195unsafe impl AttrSet<SQL_ATTR_CONNECTION_TIMEOUT> for SQLUINTEGER {}
196
197#[derive(Ident)]
198#[identifier(SQLINTEGER, 109)]
199#[allow(non_camel_case_types)]
200pub struct SQL_ATTR_CURRENT_CATALOG;
201unsafe impl<CH: OdbcChar> Attr<SQL_ATTR_CURRENT_CATALOG> for OdbcStr<CH> {
202    type DefinedBy = OdbcDefined;
203}
204impl<CH: OdbcChar> ConnAttr<C2, SQL_ATTR_CURRENT_CATALOG, SQL_OV_ODBC3> for OdbcStr<CH> {}
205impl<CH: OdbcChar> ConnAttr<C4, SQL_ATTR_CURRENT_CATALOG, SQL_OV_ODBC3> for OdbcStr<CH> {}
206unsafe impl<CH: OdbcChar> AttrGet<SQL_ATTR_CURRENT_CATALOG> for OdbcStr<CH> {}
207unsafe impl<CH: OdbcChar> AttrSet<SQL_ATTR_CURRENT_CATALOG> for &OdbcStr<CH> {}
208
209#[derive(Ident)]
210#[identifier(SQLINTEGER, 103)]
211#[allow(non_camel_case_types)]
212pub struct SQL_ATTR_LOGIN_TIMEOUT;
213unsafe impl Attr<SQL_ATTR_LOGIN_TIMEOUT> for SQLUINTEGER {
214    type DefinedBy = OdbcDefined;
215}
216impl ConnAttr<C2, SQL_ATTR_LOGIN_TIMEOUT, SQL_OV_ODBC3> for SQLUINTEGER {}
217unsafe impl AttrGet<SQL_ATTR_LOGIN_TIMEOUT> for SQLUINTEGER {}
218unsafe impl AttrSet<SQL_ATTR_LOGIN_TIMEOUT> for SQLUINTEGER {}
219
220#[derive(Ident)]
221#[identifier(SQLINTEGER, 112)]
222#[allow(non_camel_case_types)]
223pub struct SQL_ATTR_PACKET_SIZE;
224unsafe impl Attr<SQL_ATTR_PACKET_SIZE> for SQLUINTEGER {
225    type DefinedBy = OdbcDefined;
226}
227impl ConnAttr<C2, SQL_ATTR_PACKET_SIZE, SQL_OV_ODBC3> for SQLUINTEGER {}
228unsafe impl AttrGet<SQL_ATTR_PACKET_SIZE> for SQLUINTEGER {}
229unsafe impl AttrSet<SQL_ATTR_PACKET_SIZE> for SQLUINTEGER {}
230
231#[derive(Ident)]
232#[identifier(SQLINTEGER, 104)]
233#[allow(non_camel_case_types)]
234pub struct SQL_ATTR_TRACE;
235unsafe impl Attr<SQL_ATTR_TRACE> for Trace {
236    type DefinedBy = OdbcDefined;
237}
238impl ConnAttr<C2, SQL_ATTR_TRACE, SQL_OV_ODBC3> for Trace {}
239impl ConnAttr<C4, SQL_ATTR_TRACE, SQL_OV_ODBC3> for Trace {}
240unsafe impl AttrGet<SQL_ATTR_TRACE> for Trace {}
241unsafe impl AttrSet<SQL_ATTR_TRACE> for Trace {}
242
243#[derive(Ident)]
244#[identifier(SQLINTEGER, 105)]
245#[allow(non_camel_case_types)]
246pub struct SQL_ATTR_TRACEFILE;
247unsafe impl<CH: OdbcChar> Attr<SQL_ATTR_TRACEFILE> for OdbcStr<CH> {
248    type DefinedBy = OdbcDefined;
249}
250impl<CH: OdbcChar> ConnAttr<C2, SQL_ATTR_TRACEFILE, SQL_OV_ODBC3> for OdbcStr<CH> {}
251impl<CH: OdbcChar> ConnAttr<C4, SQL_ATTR_TRACEFILE, SQL_OV_ODBC3> for OdbcStr<CH> {}
252unsafe impl<CH: OdbcChar> AttrGet<SQL_ATTR_TRACEFILE> for OdbcStr<CH> {}
253unsafe impl<CH: OdbcChar> AttrSet<SQL_ATTR_TRACEFILE> for &OdbcStr<CH> {}
254
255#[derive(Ident)]
256#[identifier(SQLINTEGER, 106)]
257#[allow(non_camel_case_types)]
258pub struct SQL_ATTR_TRANSLATE_LIB;
259unsafe impl<CH: OdbcChar> Attr<SQL_ATTR_TRANSLATE_LIB> for OdbcStr<CH> {
260    type DefinedBy = OdbcDefined;
261}
262impl<CH: OdbcChar> ConnAttr<C4, SQL_ATTR_TRANSLATE_LIB, SQL_OV_ODBC3> for OdbcStr<CH> {}
263unsafe impl<CH: OdbcChar> AttrGet<SQL_ATTR_TRANSLATE_LIB> for OdbcStr<CH> {}
264unsafe impl<CH: OdbcChar> AttrSet<SQL_ATTR_TRANSLATE_LIB> for &OdbcStr<CH> {}
265
266#[derive(Ident)]
267#[identifier(SQLINTEGER, 10001)]
268#[allow(non_camel_case_types)]
269// This is read-only attribute
270pub struct SQL_ATTR_AUTO_IPD;
271unsafe impl Attr<SQL_ATTR_AUTO_IPD> for OdbcBool {
272    type DefinedBy = OdbcDefined;
273}
274impl ConnAttr<C2, SQL_ATTR_AUTO_IPD, SQL_OV_ODBC3> for OdbcBool {}
275impl ConnAttr<C4, SQL_ATTR_AUTO_IPD, SQL_OV_ODBC3> for OdbcBool {}
276unsafe impl AttrGet<SQL_ATTR_AUTO_IPD> for OdbcBool {}
277
278#[derive(Ident)]
279#[identifier(SQLINTEGER, 117)]
280#[allow(non_camel_case_types)]
281pub struct SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE;
282unsafe impl Attr<SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE> for AsyncDbcFunctionsEnable {
283    type DefinedBy = OdbcDefined;
284}
285impl ConnAttr<C2, SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE, SQL_OV_ODBC3_80>
286    for AsyncDbcFunctionsEnable
287{
288}
289impl ConnAttr<C4, SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE, SQL_OV_ODBC3_80>
290    for AsyncDbcFunctionsEnable
291{
292}
293unsafe impl AttrGet<SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE> for AsyncDbcFunctionsEnable {}
294unsafe impl AttrSet<SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE> for AsyncDbcFunctionsEnable {}
295
296// TODO: Spec says this is 3.5, but it is not 3.5 in implementation ???
297// but it says that drivers conforming to earlier versions can support this field
298#[derive(Ident)]
299#[identifier(SQLINTEGER, 1209)]
300#[allow(non_camel_case_types)]
301// This is read-only attribute
302pub struct SQL_ATTR_CONNECTION_DEAD;
303unsafe impl Attr<SQL_ATTR_CONNECTION_DEAD> for ConnectionDead {
304    type DefinedBy = OdbcDefined;
305}
306impl ConnAttr<C4, SQL_ATTR_CONNECTION_DEAD, SQL_OV_ODBC3_80> for ConnectionDead {}
307unsafe impl AttrGet<SQL_ATTR_CONNECTION_DEAD> for ConnectionDead {}
308
309#[derive(Ident)]
310#[identifier(SQLINTEGER, 108)]
311#[allow(non_camel_case_types)]
312pub struct SQL_ATTR_TXN_ISOLATION;
313unsafe impl Attr<SQL_ATTR_TXN_ISOLATION> for TxnIsolation {
314    type DefinedBy = OdbcDefined;
315}
316// TODO: Check for open transaction
317impl ConnAttr<C2, SQL_ATTR_TXN_ISOLATION, SQL_OV_ODBC3> for TxnIsolation {}
318impl ConnAttr<C4, SQL_ATTR_TXN_ISOLATION, SQL_OV_ODBC3> for TxnIsolation {}
319unsafe impl AttrGet<SQL_ATTR_TXN_ISOLATION> for TxnIsolation {}
320unsafe impl AttrSet<SQL_ATTR_TXN_ISOLATION> for TxnIsolation {}
321
322//#[derive(Ident)]
323//#[identifier(SQLINTEGER, 107)]
324//#[allow(non_camel_case_types)]
325//pub struct SQL_ATTR_TRANSLATE_OPTION;
326//unsafe impl Attr<SQL_ATTR_TRANSLATE_OPTION> for SQLUINTEGER {
327//    type DefinedBy = OdbcDefined;
328//}
329//impl ConnAttr<C, SQL_ATTR_TRANSLATE_OPTION, SQL_OV_ODBC3> for SQLUINTEGER {
330//    #[cfg(feature = "odbc_debug")]
331//    fn check_attr(&self, ConnectionHandle: &SQLHDBC<SQL_OV_ODBC3>) {
332//        ConnectionHandle.assert_connected();
333//    }
334//}
335//unsafe impl AttrGet<SQL_ATTR_TRANSLATE_OPTION> for SQLUINTEGER {}
336//unsafe impl AttrSet<SQL_ATTR_TRANSLATE_OPTION> for SQLUINTEGER {}
337
338//#[derive(Ident)]
339//#[identifier(SQLINTEGER, 118)]
340//// This is set-only attribute
341//pub struct SQL_ATTR_DBC_INFO_TOKEN;
342//unsafe impl Attr<SQL_ATTR_DBC_INFO_TOKEN> for SQLPOINTER {
343//    type DefinedBy = OdbcDefined;
344//}
345//impl ConnAttr<C, SQL_ATTR_DBC_INFO_TOKEN, SQL_OV_ODBC3_80> for SQLPOINTER {
346//    #[cfg(feature = "odbc_debug")]
347//    fn check_attr(&self, ConnectionHandle: &SQLHDBC<SQL_OV_ODBC3_80>) {
348//        assert_connected(ConnectionHandle);
349//    }
350//impl AttrSet<SQL_ATTR_DBC_INFO_TOKEN> for SQLPOINTER {}
351
352//#[derive(Ident)]
353//#[identifier(SQLINTEGER, 119)]
354//pub struct SQL_ATTR_ASYNC_DBC_EVENT;
355//// TODO: It's an Event handle. Should probably implement event handle
356//unsafe impl Attr<SQL_ATTR_ASYNC_DBC_EVENT> for SQLPOINTER {
357//    type DefinedBy = OdbcDefined;
358//}
359//impl ConnAttr<C, SQL_ATTR_ASYNC_DBC_EVENT, SQL_OV_ODBC3_80> for SQLPOINTER {}
360//impl AttrGet<SQL_ATTR_ASYNC_DBC_EVENT> for SQLPOINTER {}
361
362//#[derive(Ident)]
363//#[identifier(SQLINTEGER, 111)]
364//#[allow(non_camel_case_types)]
365//pub struct SQL_ATTR_QUIET_MODE;
366//impl ConnAttr<C, SQL_ATTR_QUIET_MODE, SQL_OV_ODBC3> for {}
367
368// TODO: Not found in documentation, only in implementation
369//#[derive(Ident)]
370//#[identifier(SQLINTEGER, 114)]
371//#[allow(non_camel_case_types)]
372//pub struct SQL_ATTR_DISCONNECT_BEHAVIOR;
373
374//#[derive(odbc_type)]
375//#[allow(non_camel_case_types)]
376//pub struct DisconnectBehavior;
377//pub const SQL_DB_RETURN_TO_POOL: DisconnectBehavior = DisconnectBehavior(0);
378//pub const SQL_DB_DISCONNECT: DisconnectBehavior = DisconnectBehavior(1);
379
380//*  ODBC Driver Manager sets this connection attribute to a unicode driver
381//    (which supports SQLConnectW) when the application is an ANSI application
382//    (which calls SQLConnect, SQLDriverConnect, or SQLBrowseConnect).
383//    This is SetConnectAttr only and application does not set this attribute
384//    This attribute was introduced because some unicode driver's some APIs may
385//    need to behave differently on ANSI or Unicode applications. A unicode
386//    driver, which  has same behavior for both ANSI or Unicode applications,
387//    should return SQL_ERROR when the driver manager sets this connection
388//    attribute. When a unicode driver returns SQL_SUCCESS on this attribute,
389//    the driver manager treates ANSI and Unicode connections differently in
390//    connection pooling.
391//*/
392//// TODO: These 4 are not in Documentation??
393//#[derive(Ident)]
394//#[identifier(SQLINTEGER, 115)]
395//#[allow(non_camel_case_types)]
396//pub struct SQL_ATTR_ANSI_APP;
397//impl ConnAttr<SQL_OV_ODBC3_51, SQL_ATTR_ANSI_APP>, for AnsiApp {}
398//impl AttrGet<SQL_ATTR_ANSI_APP>> for AnsiApp {}
399//impl AttrSet<SQL_ATTR_ANSI_APP> for AnsiApp {}
400
401//pub enum AnsiApp {
402//    SQL_AA_TRUE = 1,  /* the application is an ANSI app */
403//    SQL_AA_FALSE = 0,  /* the application is a Unicode app */
404//}
405
406//#[derive(Ident)]
407//#[identifier(SQLINTEGER, 116)]
408//#[allow(non_camel_case_types)]
409//pub struct SQL_ATTR_RESET_CONNECTION;
410//impl ConnAttr<SQL_OV_ODBC3_80, SQL_ATTR_RESET_CONNECTION> for ResetConnection {}
411//impl AttrGet<SQL_ATTR_RESET_CONNECTION>> for ResetConnection {}
412//impl AttrSet<SQL_ATTR_RESET_CONNECTION> for ResetConnection {}
413
414//#[derive(Debug, PartialEq, Eq, Clone, Copy)]
415//pub enum ResetConnection {
416//    SQL_RESET_CONNECTION_YES = 1,
417//}
418
419//#[derive(Ident)]
420//#[identifier(SQLINTEGER, 122)]
421//#[allow(non_camel_case_types)]
422//pub struct SQL_ATTR_CREDENTIALS;
423//unsafe impl<CH: OdbcChar> Attr<SQL_ATTR_CREDENTIALS> for OdbcStr<CH> {
424//    type DefinedBy = OdbcDefined;
425//}
426//impl<CH: OdbcChar> ConnAttr<SQL_OV_ODBC4, SQL_ATTR_CREDENTIALS> for OdbcStr<CH> {}
427//unsafe impl<CH: OdbcChar> AttrGet<SQL_ATTR_CREDENTIALS> for OdbcStr<CH> {}
428//unsafe impl<CH: OdbcChar> AttrSet<SQL_ATTR_CREDENTIALS> for OdbcStr<CH> {}
429
430#[derive(Ident)]
431#[identifier(SQLINTEGER, 123)]
432#[allow(non_camel_case_types)]
433pub struct SQL_ATTR_REFRESH_CONNECTION;
434unsafe impl Attr<SQL_ATTR_REFRESH_CONNECTION> for RefreshConnection {
435    type DefinedBy = OdbcDefined;
436}
437impl ConnAttr<C2, SQL_ATTR_REFRESH_CONNECTION, SQL_OV_ODBC4> for RefreshConnection {}
438impl ConnAttr<C4, SQL_ATTR_REFRESH_CONNECTION, SQL_OV_ODBC4> for RefreshConnection {}
439unsafe impl AttrGet<SQL_ATTR_REFRESH_CONNECTION> for RefreshConnection {}
440unsafe impl AttrSet<SQL_ATTR_REFRESH_CONNECTION> for RefreshConnection {}
441
442// Re-exported as connection attributes
443pub use crate::stmt::SQL_ATTR_ASYNC_ENABLE;
444impl<C: ConnState> ConnAttr<C, SQL_ATTR_ASYNC_ENABLE, SQL_OV_ODBC3> for crate::stmt::AsyncEnable {}
445
446pub use crate::stmt::SQL_ATTR_METADATA_ID;
447impl<C: ConnState> ConnAttr<C, SQL_ATTR_METADATA_ID, SQL_OV_ODBC3> for OdbcBool {}
448
449//=====================================================================================//
450
451#[odbc_type(SQLUINTEGER)]
452pub struct AccessMode;
453pub const SQL_MODE_READ_WRITE: AccessMode = AccessMode(0);
454pub const SQL_MODE_READ_ONLY: AccessMode = AccessMode(1);
455
456#[odbc_type(SQLUINTEGER)]
457pub struct AutoCommit;
458pub const SQL_AUTOCOMMIT_OFF: AutoCommit = AutoCommit(0);
459pub const SQL_AUTOCOMMIT_ON: AutoCommit = AutoCommit(1);
460
461#[odbc_type(SQLUINTEGER)]
462pub struct Trace;
463pub const SQL_OPT_TRACE_OFF: Trace = Trace(0);
464pub const SQL_OPT_TRACE_ON: Trace = Trace(1);
465
466#[odbc_type(SQLUINTEGER)]
467pub struct AsyncDbcFunctionsEnable;
468pub const SQL_ASYNC_DBC_ENABLE_OFF: AsyncDbcFunctionsEnable = AsyncDbcFunctionsEnable(0);
469pub const SQL_ASYNC_DBC_ENABLE_ON: AsyncDbcFunctionsEnable = AsyncDbcFunctionsEnable(1);
470
471#[odbc_type(SQLUINTEGER)]
472pub struct ConnectionDead;
473pub const SQL_CD_FALSE: ConnectionDead = ConnectionDead(0);
474pub const SQL_CD_TRUE: ConnectionDead = ConnectionDead(1);
475
476#[odbc_type(SQLINTEGER)]
477#[allow(non_camel_case_types)]
478pub struct RefreshConnection;
479pub const SQL_REFRESH_NOW: RefreshConnection = RefreshConnection(-1);
480pub const SQL_REFRESH_AUTO: RefreshConnection = RefreshConnection(0);
481pub const SQL_REFRESH_MANUAL: RefreshConnection = RefreshConnection(1);
482
483#[cfg(test)]
484mod test {
485    #![allow(non_snake_case)]
486
487    use super::*;
488    use crate::api::mock_ffi as ffi;
489    use crate::api::Allocate;
490    use crate::env::SQL_OV_ODBC3_80;
491    use crate::handle::SQLHANDLE;
492    use crate::sqlreturn::SQL_SUCCESS;
493    use crate::stmt::SQL_ASYNC_ENABLE_OFF;
494    use crate::SQL_TRUE;
495
496    //#[test]
497    //fn test_SQL_ATTR_METADATA_ID_is_ConnAttr() {
498    //    let SQLSetConnectAttr_ctx = ffi::SQLSetConnectAttrA_context();
499    //    SQLSetConnectAttr_ctx.expect().once().return_const(SQL_SUCCESS);
500    //    let SQLFreeHandle_ctx = ffi::SQLFreeHandle_context();
501    //    SQLFreeHandle_ctx.expect().once()0return_const(SQL_SUCCESS);
502
503    //    let handle = unsafe { SQLHDBC::<C2, SQL_OV_ODBC3_80>::from_raw(13 as SQLHANDLE)};
504    //    assert_eq!(SQL_SUCCESS, handle.SQLSetConnectAttrA(SQL_ATTR_METADATA_ID, SQL_TRUE));
505    //}
506
507    //#[test]
508    //fn test_SQL_ATTR_ASYNC_ENABLE_is_ConnAttr() {
509    //    let SQLSetConnectAttr_ctx = ffi::SQLSetConnectAttrA_context();
510    //    SQLSetConnectAttr_ctx.expect().once().return_const(SQL_SUCCESS);
511
512    //    let handle = unsafe { SQLHDBC::<C2, SQL_OV_ODBC3_80>::from_raw(13 as SQLHANDLE)};
513    //    assert_eq!(SQL_SUCCESS, handle.SQLSetConnectAttrA(SQL_ATTR_ASYNC_ENABLE, SQL_ASYNC_ENABLE_OFF));
514    //}
515}