odbc_api/handles/statement_connection.rs
1use odbc_sys::{HStmt, Handle, HandleType};
2
3use crate::handles::{AnyHandle, SqlResult, Statement, StatementRef, drop_handle};
4
5/// Statement handle which also takes ownership of Connection
6#[derive(Debug)]
7pub struct StatementConnection<C> {
8 handle: HStmt,
9 /// We keep the parent connection alive. It must not be used for any action which could
10 /// invalidate the statement handle.
11 parent: C,
12}
13
14impl<C> StatementConnection<C>
15where
16 C: StatementParent,
17{
18 /// # Safety
19 ///
20 /// Handle must be a valid statement handle and the parent connection must be valid for the
21 /// lifetime of parent.
22 pub(crate) unsafe fn new(handle: HStmt, parent: C) -> Self {
23 Self { parent, handle }
24 }
25
26 pub fn as_stmt_ref(&mut self) -> StatementRef<'_> {
27 unsafe { StatementRef::new(self.handle) }
28 }
29
30 /// Access the parent connection.
31 ///
32 /// # Safety
33 ///
34 /// The parent must not be used for anything which could invalidate the statement handle.
35 pub unsafe fn parent(&self) -> &C {
36 &self.parent
37 }
38}
39
40impl<C> Drop for StatementConnection<C> {
41 fn drop(&mut self) {
42 unsafe {
43 drop_handle(self.handle.as_handle(), HandleType::Stmt);
44 }
45 }
46}
47
48/// Implementers of this trait are guaranteed to keep a connection alive and in connected state for
49/// the lifetime of the instance.
50///
51/// E.g. [`super::Connection`] is not a [`StatementParent`], since it is not guaranteed to keep the
52/// connection alive. Nor would it close the connection at the end of the lifetime on Drop.
53///
54/// # Safety
55///
56/// Instance must keep the connection it owns alive and open.
57pub unsafe trait StatementParent {}
58
59/// According to the ODBC documentation this is safe. See:
60/// <https://docs.microsoft.com/en-us/sql/odbc/reference/develop-app/multithreading>
61///
62/// Operations to a statement imply that interior state of the connection might be mutated,
63/// depending on the implementation detail of the ODBC driver. According to the ODBC documentation
64/// this could always be considered save.
65unsafe impl<C> Send for StatementConnection<C> where C: StatementParent {}
66
67unsafe impl<C> AnyHandle for StatementConnection<C>
68where
69 C: StatementParent,
70{
71 fn as_handle(&self) -> Handle {
72 self.handle.as_handle()
73 }
74
75 fn handle_type(&self) -> HandleType {
76 HandleType::Stmt
77 }
78}
79
80impl<C> Statement for StatementConnection<C>
81where
82 C: StatementParent,
83{
84 fn as_sys(&self) -> HStmt {
85 self.handle
86 }
87
88 fn end_cursor_scope(&mut self) -> SqlResult<()> {
89 SqlResult::Success(())
90 }
91}