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
14pub trait ConnAttr<C: ConnState, A: Ident, V: OdbcVersion>:
16 Attr<A> + AttrLen<Self::DefinedBy, SQLINTEGER>
17{
18 }
28
29pub trait BrowseConnect {}
31pub trait Disconnect {}
32
33#[derive(Debug)]
35pub enum C2 {}
36
37#[derive(Debug)]
39pub enum C3 {}
40
41#[derive(Debug)]
43pub enum C4 {}
44
45impl ConnState for C2 {}
46impl ConnState for C3 {}
47impl ConnState for C4 {}
48
49impl<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
75impl<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
97impl<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 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#[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)]
175pub 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)]
269pub 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#[derive(Ident)]
299#[identifier(SQLINTEGER, 1209)]
300#[allow(non_camel_case_types)]
301pub 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}
316impl 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)]
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
442pub 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#[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 }