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