Skip to main content

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}