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