Skip to main content

sqlx_cloudflare_d1/
arguments.rs

1use sqlx_cloudflare_core::add_argument;
2use sqlx_core::arguments::Arguments;
3use sqlx_core::encode::Encode;
4use sqlx_core::error::BoxDynError;
5use sqlx_core::types::Type;
6
7use crate::{D1ArgumentValue, D1};
8
9/// The parameters bound to one query, in placeholder order.
10///
11/// `format_placeholder` keeps its default, `?`, which is what D1 expects.
12#[derive(Debug, Default, Clone)]
13pub struct D1Arguments {
14    pub(crate) values: Vec<D1ArgumentValue>,
15}
16
17impl D1Arguments {
18    pub(crate) fn values(&self) -> &[D1ArgumentValue] {
19        &self.values
20    }
21}
22
23impl Arguments for D1Arguments {
24    type Database = D1;
25
26    fn reserve(&mut self, additional: usize, _size: usize) {
27        self.values.reserve(additional);
28    }
29
30    fn add<'t, T>(&mut self, value: T) -> Result<(), BoxDynError>
31    where
32        T: Encode<'t, D1> + Type<D1>,
33    {
34        add_argument(&mut self.values, value)
35    }
36
37    fn len(&self) -> usize {
38        self.values.len()
39    }
40}
41
42#[cfg(test)]
43mod tests {
44    use sqlx_core::arguments::Arguments;
45
46    use super::{D1ArgumentValue, D1Arguments};
47
48    #[test]
49    fn values_line_up_with_placeholders() {
50        let mut arguments = D1Arguments::default();
51
52        arguments.add(7_i64).unwrap();
53        arguments.add(Option::<String>::None).unwrap();
54        arguments.add("x").unwrap();
55        arguments.add(true).unwrap();
56        arguments.add(1.5_f64).unwrap();
57        arguments.add(vec![1_u8, 2]).unwrap();
58
59        assert_eq!(
60            arguments.values(),
61            [
62                D1ArgumentValue::Integer(7),
63                D1ArgumentValue::Null,
64                D1ArgumentValue::Text("x".into()),
65                D1ArgumentValue::Integer(1),
66                D1ArgumentValue::Real(1.5),
67                D1ArgumentValue::Blob(vec![1, 2]),
68            ]
69        );
70    }
71
72    #[test]
73    fn an_integer_beyond_2_53_is_refused_and_leaves_no_trace() {
74        let mut arguments = D1Arguments::default();
75
76        arguments.add(1_i64).unwrap();
77        assert!(arguments.add(1_i64 << 53).is_err());
78        assert!(arguments.add(i64::MIN).is_err());
79        arguments.add(2_i64).unwrap();
80
81        // The failed binds pushed nothing, so `?2` is still the second value.
82        assert_eq!(
83            arguments.values(),
84            [D1ArgumentValue::Integer(1), D1ArgumentValue::Integer(2)]
85        );
86    }
87}