odbc_api/
statement_connection.rs

1use odbc_sys::{HStmt, Handle, HandleType};
2
3use crate::{
4    handles::{drop_handle, AsHandle, AsStatementRef, Statement, StatementRef},
5    Connection,
6};
7
8/// Statement handle which also takes ownership of Connection
9pub struct StatementConnection<'env> {
10    handle: HStmt,
11    _parent: Connection<'env>,
12}
13
14impl<'env> StatementConnection<'env> {
15    pub(crate) unsafe fn new(handle: HStmt, parent: Connection<'env>) -> Self {
16        Self {
17            _parent: parent,
18            handle,
19        }
20    }
21
22    pub fn as_stmt_ref(&mut self) -> StatementRef<'_> {
23        unsafe { StatementRef::new(self.handle) }
24    }
25}
26
27impl Drop for StatementConnection<'_> {
28    fn drop(&mut self) {
29        unsafe {
30            drop_handle(self.handle as Handle, HandleType::Stmt);
31        }
32    }
33}
34
35/// According to the ODBC documentation this is safe. See:
36/// <https://docs.microsoft.com/en-us/sql/odbc/reference/develop-app/multithreading>
37///
38/// Operations to a statement imply that interior state of the connection might be mutated,
39/// depending on the implementation detail of the ODBC driver. According to the ODBC documentation
40/// this could always be considered save, since Connection handles are basically described as
41/// `Sync`. Yet making connections `Send` could very well lead to different statements on different
42/// threads actually changing the connection at the same time and truly relying on the thread safety
43/// of the ODBC driver. I am sceptical. Especially if on Linux unixODBC would not be configured to
44/// protect connections.
45///
46/// Note to users of `unixodbc`: You may configure the threading level to make unixodbc
47/// synchronize access to the driver (and thereby making them thread safe if they are not thread
48/// safe by themself. This may however hurt your performance if the driver would actually be able to
49/// perform operations in parallel.
50///
51/// See: <https://stackoverflow.com/questions/4207458/using-unixodbc-in-a-multithreaded-concurrent-setting>
52///
53/// `StatementConnection` however also owns the connection exclusively. Since connections are `Send`
54/// it is reasonable to assume this would work even if implementers of the ODBC driver do not care
55/// in particular about thread safety.
56unsafe impl Send for StatementConnection<'_> {}
57
58unsafe impl AsHandle for StatementConnection<'_> {
59    fn as_handle(&self) -> Handle {
60        self.handle as Handle
61    }
62
63    fn handle_type(&self) -> HandleType {
64        HandleType::Stmt
65    }
66}
67
68impl Statement for StatementConnection<'_> {
69    fn as_sys(&self) -> HStmt {
70        self.handle
71    }
72}
73
74impl AsStatementRef for StatementConnection<'_> {
75    fn as_stmt_ref(&mut self) -> StatementRef<'_> {
76        self.as_stmt_ref()
77    }
78}