odbc_api/parameter_collection/
tuple.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//! Implement `Parameters` trait for tuples consisting of elements implementing `SingleParameter`
//! trait.

use super::ParameterCollectionRef;
use crate::{handles::Statement, parameter::InputParameter, Error, InOut, Out, OutputParameter};

macro_rules! impl_bind_parameters {
    ($offset:expr, $stmt:ident) => (
        Ok(())
    );
    ($offset:expr, $stmt:ident $head:ident $($tail:ident)*) => (
        {
            $head.bind_to($offset+1, $stmt)?;
            impl_bind_parameters!($offset+1, $stmt $($tail)*)
        }
    );
}

macro_rules! impl_parameters_for_tuple{
    ($($t:ident)*) => (
        #[allow(unused_parens)]
        #[allow(unused_variables)]
        #[allow(non_snake_case)]
        unsafe impl<$($t:ParameterTupleElement,)*> ParameterCollectionRef for ($($t,)*)
        {
            fn parameter_set_size(&self) -> usize {
                1
            }

            unsafe fn bind_parameters_to(&mut self, stmt: &mut impl Statement) -> Result<(), Error> {
                let ($($t,)*) = self;
                impl_bind_parameters!(0, stmt $($t)*)
            }
        }
    );
}

// The unit type is used to signal no parameters.
impl_parameters_for_tuple! {}
impl_parameters_for_tuple! { A }
impl_parameters_for_tuple! { A B }
impl_parameters_for_tuple! { A B C }
impl_parameters_for_tuple! { A B C D }
impl_parameters_for_tuple! { A B C D E }
impl_parameters_for_tuple! { A B C D E F }
impl_parameters_for_tuple! { A B C D E F G }
impl_parameters_for_tuple! { A B C D E F G H }
impl_parameters_for_tuple! { A B C D E F G H I }
impl_parameters_for_tuple! { A B C D E F G H I J }
impl_parameters_for_tuple! { A B C D E F G H I J K }
impl_parameters_for_tuple! { A B C D E F G H I J K L }
impl_parameters_for_tuple! { A B C D E F G H I J K L M }
impl_parameters_for_tuple! { A B C D E F G H I J K L M N }
impl_parameters_for_tuple! { A B C D E F G H I J K L M N O }
impl_parameters_for_tuple! { A B C D E F G H I J K L M N O P }
impl_parameters_for_tuple! { A B C D E F G H I J K L M N O P Q }
impl_parameters_for_tuple! { A B C D E F G H I J K L M N O P Q R }
impl_parameters_for_tuple! { A B C D E F G H I J K L M N O P Q R S }
impl_parameters_for_tuple! { A B C D E F G H I J K L M N O P Q R S T }
impl_parameters_for_tuple! { A B C D E F G H I J K L M N O P Q R S T U }
impl_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 }
impl_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 }
impl_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 }
impl_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 }
impl_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}

/// Implementers of this trait can be used as individual parameters of in a tuple of parameter
/// references. This includes input parameters, output or in/out parameters.
///
/// # Safety
///
/// Parameters bound to the statement must remain valid for the lifetime of the instance.
pub unsafe trait ParameterTupleElement {
    /// Bind the parameter in question to a specific `parameter_number`.
    ///
    /// # Safety
    ///
    /// Since the parameter is now bound to `stmt` callers must take care that it is ensured that
    /// the parameter remains valid while it is used. If the parameter is bound as an output
    /// parameter it must also be ensured that it is exclusively referenced by statement.
    unsafe fn bind_to(
        &mut self,
        parameter_number: u16,
        stmt: &mut impl Statement,
    ) -> Result<(), Error>;
}

/// Bind immutable references as input parameters.
unsafe impl<T: ?Sized> ParameterTupleElement for &T
where
    T: InputParameter,
{
    unsafe fn bind_to(
        &mut self,
        parameter_number: u16,
        stmt: &mut impl Statement,
    ) -> Result<(), Error> {
        self.assert_completness();
        stmt.bind_input_parameter(parameter_number, *self)
            .into_result(stmt)
    }
}

/// Bind mutable references as input/output parameter.
unsafe impl<'a, T> ParameterTupleElement for InOut<'a, T>
where
    T: OutputParameter + InputParameter,
{
    unsafe fn bind_to(
        &mut self,
        parameter_number: u16,
        stmt: &mut impl Statement,
    ) -> Result<(), Error> {
        self.0.assert_completness();
        stmt.bind_parameter(parameter_number, odbc_sys::ParamType::InputOutput, self.0)
            .into_result(stmt)
    }
}

/// Mutable references wrapped in `Out` are bound as output parameters.
unsafe impl<'a, T> ParameterTupleElement for Out<'a, T>
where
    T: OutputParameter,
{
    unsafe fn bind_to(
        &mut self,
        parameter_number: u16,
        stmt: &mut impl Statement,
    ) -> Result<(), Error> {
        stmt.bind_parameter(parameter_number, odbc_sys::ParamType::Output, self.0)
            .into_result(stmt)
    }
}