odbc_sys/
handles.rs

1use std::{ffi::c_void, ptr::null_mut};
2
3// ODBC handles are pointers to opaque C types. We do not know their memory layout or other details
4// of their implementation. This RFC suggest how to represent them in Rust:
5// <https://rust-lang.github.io/rfcs/1861-extern-types.html>
6//
7// Until this is stable we could choose to represent them like suggested in the nomicon:
8// <https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs>
9//
10// However, we know in the context of ODBC that we are always interested in the *mut versions of
11// this pointer. For now a strict alias around `*mut c_void` seems to be the most pragmatic
12// solution.
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15#[repr(transparent)]
16pub struct Handle(pub *mut c_void);
17
18impl Handle {
19    pub fn null() -> Self {
20        Self(null_mut())
21    }
22
23    pub fn as_henv(self) -> HEnv {
24        HEnv(self.0)
25    }
26
27    pub fn as_hdbc(self) -> HDbc {
28        HDbc(self.0)
29    }
30
31    pub fn as_hstmt(self) -> HStmt {
32        HStmt(self.0)
33    }
34}
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq)]
37#[repr(transparent)]
38pub struct HEnv(pub *mut c_void);
39
40impl HEnv {
41    pub fn null() -> Self {
42        Self(null_mut())
43    }
44
45    pub fn as_handle(self) -> Handle {
46        Handle(self.0)
47    }
48}
49
50#[derive(Debug, Clone, Copy, PartialEq, Eq)]
51#[repr(transparent)]
52pub struct HDesc(pub *mut c_void);
53
54impl HDesc {
55    pub fn null() -> Self {
56        Self(null_mut())
57    }
58
59    pub fn as_handle(self) -> Handle {
60        Handle(self.0)
61    }
62}
63
64/// The connection handle references storage of all information about the connection to the data
65/// source, including status, transaction state, and error information.
66#[derive(Debug, Clone, Copy, PartialEq, Eq)]
67#[repr(transparent)]
68pub struct HDbc(pub *mut c_void);
69
70impl HDbc {
71    pub fn as_handle(self) -> Handle {
72        Handle(self.0)
73    }
74}
75
76#[derive(Debug, Clone, Copy, PartialEq, Eq)]
77#[repr(transparent)]
78pub struct HStmt(pub *mut c_void);
79
80impl HStmt {
81    pub fn as_handle(self) -> Handle {
82        Handle(self.0)
83    }
84}
85
86// Handles are `Send` according to ODBC spec, since they must be able to be used from different
87// threads. They even must protect their inner state. This would also make them `Sync`, yet they do
88// have interior mutability for error handling.
89// See: <https://docs.microsoft.com/en-us/sql/odbc/reference/develop-app/multithreading>
90
91unsafe impl Send for HEnv {}
92
93unsafe impl Send for HDbc {}
94
95// Send may not be implemented for HStmt, since statements may bind other parameters and there is no
96// guarantee that the parameter pointers bound to the statement are `Send`. Safe abstractions over
97// statement handles may of course only allow `Send` parameters to bind and then implement `Send`.