Skip to main content

drizzle_core/param/
mod.rs

1mod owned;
2pub use owned::*;
3
4use crate::prelude::*;
5use crate::{placeholder::Placeholder, traits::SQLParam};
6
7/// A placeholder in a SQL fragment, with its value once bound.
8#[derive(Debug, Clone)]
9pub struct Param<'a, V: SQLParam> {
10    /// The placeholder written into the SQL text.
11    pub placeholder: Placeholder,
12    /// The bound value, or `None` until one is bound.
13    pub value: Option<Cow<'a, V>>,
14}
15
16impl<'a, V: SQLParam> Param<'a, V> {
17    /// Creates a parameter from a placeholder and an optional value.
18    pub const fn new(placeholder: Placeholder, value: Option<Cow<'a, V>>) -> Self {
19        Self { placeholder, value }
20    }
21}
22
23impl<V: SQLParam> From<OwnedParam<V>> for Param<'_, V> {
24    fn from(value: OwnedParam<V>) -> Self {
25        Self {
26            placeholder: value.placeholder,
27            value: value.value.map(|v| Cow::Owned(v)),
28        }
29    }
30}
31
32impl<'a, V: SQLParam> From<&'a OwnedParam<V>> for Param<'a, V> {
33    fn from(value: &'a OwnedParam<V>) -> Self {
34        Self {
35            placeholder: value.placeholder,
36            value: value.value.as_ref().map(|v| Cow::Borrowed(v)),
37        }
38    }
39}
40
41impl<V: SQLParam> From<Placeholder> for Param<'_, V> {
42    fn from(value: Placeholder) -> Self {
43        Self {
44            placeholder: value,
45            value: None,
46        }
47    }
48}
49
50impl<T: SQLParam> Param<'_, T> {
51    /// Creates an anonymous (positional) parameter holding `value`.
52    pub const fn positional(value: T) -> Self {
53        Self {
54            placeholder: Placeholder::anonymous(),
55            value: Some(Cow::Owned(value)),
56        }
57    }
58
59    /// Creates a parameter with no value yet.
60    #[must_use]
61    pub const fn from_placeholder(placeholder: Placeholder) -> Self {
62        Self {
63            placeholder,
64            value: None,
65        }
66    }
67
68    /// Creates a named parameter holding `value`.
69    pub const fn named(name: &'static str, value: T) -> Self {
70        Self {
71            placeholder: Placeholder::named(name),
72            value: Some(Cow::Owned(value)),
73        }
74    }
75
76    /// Creates a parameter with the given placeholder, holding `value`.
77    pub const fn with_placeholder(placeholder: Placeholder, value: T) -> Self {
78        Self {
79            placeholder,
80            value: Some(Cow::Owned(value)),
81        }
82    }
83}
84
85/// A value to bind to the placeholder called `name`.
86///
87/// Pass these to [`SQL::bind`](crate::SQL::bind) or to a prepared
88/// statement. [`TypedPlaceholder::bind`](crate::TypedPlaceholder::bind)
89/// creates one with a type check.
90///
91/// # Examples
92///
93/// ```
94/// use drizzle_core::{ParamBind, Placeholder, SQL, ToSQL};
95/// # use drizzle_core::{Dialect, SQLParam, SQLiteDialect};
96/// # use std::borrow::Cow;
97/// # #[derive(Debug, Clone, PartialEq)]
98/// # struct Value(i64);
99/// # impl SQLParam for Value {
100/// #     const DIALECT: Dialect = Dialect::SQLite;
101/// #     type DialectMarker = SQLiteDialect;
102/// # }
103/// # impl From<Value> for Cow<'_, Value> {
104/// #     fn from(value: Value) -> Self { Cow::Owned(value) }
105/// # }
106///
107/// let sql: SQL<'_, Value> = Placeholder::named("limit").to_sql();
108/// let bound = sql.bind([ParamBind::new("limit", Value(20))]);
109/// assert_eq!(bound.params().collect::<Vec<_>>(), [&Value(20)]);
110/// ```
111#[derive(Debug, Clone)]
112pub struct ParamBind<'a, V: SQLParam> {
113    /// The placeholder name. Empty for a positional binding.
114    pub name: &'a str,
115    /// The value to bind.
116    pub value: V,
117}
118
119impl<'a, V: SQLParam> ParamBind<'a, V> {
120    /// Creates a binding for the placeholder `name`.
121    pub const fn new(name: &'a str, value: V) -> Self {
122        Self { name, value }
123    }
124
125    /// Creates a binding with no name, matched by position.
126    pub const fn positional(value: V) -> Self {
127        Self { name: "", value }
128    }
129}
130
131/// A fixed-size set of [`ParamBind`]s, iterated in order.
132#[derive(Debug, Clone)]
133pub struct ParamSet<'a, V: SQLParam, const N: usize> {
134    binds: [ParamBind<'a, V>; N],
135}
136
137impl<'a, V: SQLParam, const N: usize> ParamSet<'a, V, N> {
138    /// Creates a set from an array of bindings.
139    pub const fn new(binds: [ParamBind<'a, V>; N]) -> Self {
140        Self { binds }
141    }
142}
143
144impl<'a, V: SQLParam, const N: usize> From<[ParamBind<'a, V>; N]> for ParamSet<'a, V, N> {
145    fn from(value: [ParamBind<'a, V>; N]) -> Self {
146        Self::new(value)
147    }
148}
149
150impl<'a, V: SQLParam, const N: usize> IntoIterator for ParamSet<'a, V, N> {
151    type Item = ParamBind<'a, V>;
152    type IntoIter = core::array::IntoIter<ParamBind<'a, V>, N>;
153
154    fn into_iter(self) -> Self::IntoIter {
155        self.binds.into_iter()
156    }
157}