odbc_api/parameter_collection/
tuple.rs

1//! Implement `Parameters` trait for tuples consisting of elements implementing `SingleParameter`
2//! trait.
3
4use super::ParameterCollectionRef;
5use crate::{handles::Statement, parameter::InputParameter, Error, InOut, Out, OutputParameter};
6
7macro_rules! impl_bind_parameters {
8    ($offset:expr, $stmt:ident) => (
9        Ok(())
10    );
11    ($offset:expr, $stmt:ident $head:ident $($tail:ident)*) => (
12        {
13            $head.bind_to($offset+1, $stmt)?;
14            impl_bind_parameters!($offset+1, $stmt $($tail)*)
15        }
16    );
17}
18
19macro_rules! impl_parameters_for_tuple{
20    ($($t:ident)*) => (
21        #[allow(unused_parens)]
22        #[allow(unused_variables)]
23        #[allow(non_snake_case)]
24        unsafe impl<$($t:ParameterTupleElement,)*> ParameterCollectionRef for ($($t,)*)
25        {
26            fn parameter_set_size(&self) -> usize {
27                1
28            }
29
30            unsafe fn bind_parameters_to(&mut self, stmt: &mut impl Statement) -> Result<(), Error> {
31                let ($($t,)*) = self;
32                impl_bind_parameters!(0, stmt $($t)*)
33            }
34        }
35    );
36}
37
38// The unit type is used to signal no parameters.
39impl_parameters_for_tuple! {}
40impl_parameters_for_tuple! { A }
41impl_parameters_for_tuple! { A B }
42impl_parameters_for_tuple! { A B C }
43impl_parameters_for_tuple! { A B C D }
44impl_parameters_for_tuple! { A B C D E }
45impl_parameters_for_tuple! { A B C D E F }
46impl_parameters_for_tuple! { A B C D E F G }
47impl_parameters_for_tuple! { A B C D E F G H }
48impl_parameters_for_tuple! { A B C D E F G H I }
49impl_parameters_for_tuple! { A B C D E F G H I J }
50impl_parameters_for_tuple! { A B C D E F G H I J K }
51impl_parameters_for_tuple! { A B C D E F G H I J K L }
52impl_parameters_for_tuple! { A B C D E F G H I J K L M }
53impl_parameters_for_tuple! { A B C D E F G H I J K L M N }
54impl_parameters_for_tuple! { A B C D E F G H I J K L M N O }
55impl_parameters_for_tuple! { A B C D E F G H I J K L M N O P }
56impl_parameters_for_tuple! { A B C D E F G H I J K L M N O P Q }
57impl_parameters_for_tuple! { A B C D E F G H I J K L M N O P Q R }
58impl_parameters_for_tuple! { A B C D E F G H I J K L M N O P Q R S }
59impl_parameters_for_tuple! { A B C D E F G H I J K L M N O P Q R S T }
60impl_parameters_for_tuple! { A B C D E F G H I J K L M N O P Q R S T U }
61impl_parameters_for_tuple! { A B C D E F G H I J K L M N O P Q R S T U V }
62impl_parameters_for_tuple! { A B C D E F G H I J K L M N O P Q R S T U V W }
63impl_parameters_for_tuple! { A B C D E F G H I J K L M N O P Q R S T U V W X }
64impl_parameters_for_tuple! { A B C D E F G H I J K L M N O P Q R S T U V W X Y }
65impl_parameters_for_tuple! { A B C D E F G H I J K L M N O P Q R S T U V W X Y Z}
66
67/// Implementers of this trait can be used as individual parameters of in a tuple of parameter
68/// references. This includes input parameters, output or in/out parameters.
69///
70/// # Safety
71///
72/// Parameters bound to the statement must remain valid for the lifetime of the instance.
73pub unsafe trait ParameterTupleElement {
74    /// Bind the parameter in question to a specific `parameter_number`.
75    ///
76    /// # Safety
77    ///
78    /// Since the parameter is now bound to `stmt` callers must take care that it is ensured that
79    /// the parameter remains valid while it is used. If the parameter is bound as an output
80    /// parameter it must also be ensured that it is exclusively referenced by statement.
81    unsafe fn bind_to(
82        &mut self,
83        parameter_number: u16,
84        stmt: &mut impl Statement,
85    ) -> Result<(), Error>;
86}
87
88/// Bind immutable references as input parameters.
89unsafe impl<T: ?Sized> ParameterTupleElement for &T
90where
91    T: InputParameter,
92{
93    unsafe fn bind_to(
94        &mut self,
95        parameter_number: u16,
96        stmt: &mut impl Statement,
97    ) -> Result<(), Error> {
98        self.assert_completness();
99        stmt.bind_input_parameter(parameter_number, *self)
100            .into_result(stmt)
101    }
102}
103
104/// Bind mutable references as input/output parameter.
105unsafe impl<T> ParameterTupleElement for InOut<'_, T>
106where
107    T: OutputParameter + InputParameter,
108{
109    unsafe fn bind_to(
110        &mut self,
111        parameter_number: u16,
112        stmt: &mut impl Statement,
113    ) -> Result<(), Error> {
114        self.0.assert_completness();
115        stmt.bind_parameter(parameter_number, odbc_sys::ParamType::InputOutput, self.0)
116            .into_result(stmt)
117    }
118}
119
120/// Mutable references wrapped in `Out` are bound as output parameters.
121unsafe impl<T> ParameterTupleElement for Out<'_, T>
122where
123    T: OutputParameter,
124{
125    unsafe fn bind_to(
126        &mut self,
127        parameter_number: u16,
128        stmt: &mut impl Statement,
129    ) -> Result<(), Error> {
130        stmt.bind_parameter(parameter_number, odbc_sys::ParamType::Output, self.0)
131            .into_result(stmt)
132    }
133}