Skip to main content

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