1use crate::prelude::*;
4use crate::{
5 sql::{ColumnRef, SQL, TableRef, Token},
6 traits::SQLParam,
7};
8
9#[cfg(feature = "uuid")]
10use uuid::Uuid;
11
12#[diagnostic::on_unimplemented(
18 message = "`{Self}` cannot be converted to SQL",
19 label = "this type does not implement ToSQL for the current dialect"
20)]
21pub trait ToSQL<'a, V: SQLParam> {
22 fn to_sql(&self) -> SQL<'a, V>;
23
24 fn into_sql(self) -> SQL<'a, V>
28 where
29 Self: Sized,
30 {
31 self.to_sql()
32 }
33}
34
35#[derive(Debug, Clone)]
47pub struct SQLBytes<'a>(pub Cow<'a, [u8]>);
48
49#[derive(Debug, Clone, Copy, Default)]
51pub struct SQLNull;
52
53impl<'a> SQLBytes<'a> {
54 #[inline]
55 pub fn new(bytes: impl Into<Cow<'a, [u8]>>) -> Self {
56 Self(bytes.into())
57 }
58}
59
60impl<'a, V: SQLParam + 'a> ToSQL<'a, V> for SQLNull {
61 fn to_sql(&self) -> SQL<'a, V> {
62 SQL::raw("NULL")
63 }
64}
65
66impl<'a, T, V> From<&T> for SQL<'a, V>
67where
68 T: ToSQL<'a, V>,
69 V: SQLParam,
70{
71 fn from(value: &T) -> Self {
72 value.to_sql()
73 }
74}
75
76impl<'a, V: SQLParam, T> ToSQL<'a, V> for &T
77where
78 T: ToSQL<'a, V>,
79{
80 fn to_sql(&self) -> SQL<'a, V> {
81 (**self).to_sql()
82 }
83}
84
85impl<'a, V: SQLParam + 'a> ToSQL<'a, V> for () {
86 fn to_sql(&self) -> SQL<'a, V> {
87 SQL::empty()
88 }
89}
90
91impl<'a, V, T> ToSQL<'a, V> for Vec<T>
92where
93 V: SQLParam + 'a,
94 T: ToSQL<'a, V>,
95{
96 fn to_sql(&self) -> SQL<'a, V> {
97 SQL::join(self.iter().map(ToSQL::to_sql), Token::COMMA)
98 }
99}
100
101impl<'a, V, T> ToSQL<'a, V> for &'a [T]
102where
103 V: SQLParam + 'a,
104 T: ToSQL<'a, V>,
105{
106 fn to_sql(&self) -> SQL<'a, V> {
107 SQL::join(self.iter().map(ToSQL::to_sql), Token::COMMA)
108 }
109}
110
111impl<'a, V, T, const N: usize> ToSQL<'a, V> for [T; N]
112where
113 V: SQLParam + 'a,
114 T: ToSQL<'a, V>,
115{
116 fn to_sql(&self) -> SQL<'a, V> {
117 SQL::join(self.iter().map(ToSQL::to_sql), Token::COMMA)
118 }
119}
120
121impl<'a, V: SQLParam + 'a> ToSQL<'a, V> for TableRef {
122 fn to_sql(&self) -> SQL<'a, V> {
123 SQL::table(*self)
124 }
125}
126
127impl<'a, V: SQLParam + 'a> ToSQL<'a, V> for ColumnRef {
128 fn to_sql(&self) -> SQL<'a, V> {
129 SQL::column(*self)
130 }
131}
132
133impl<'a, V> ToSQL<'a, V> for &'a str
135where
136 V: SQLParam + 'a + From<&'a str> + Into<Cow<'a, V>>,
137{
138 fn to_sql(&self) -> SQL<'a, V> {
139 SQL::param(V::from(self))
140 }
141}
142
143impl<'a, V> ToSQL<'a, V> for Box<str>
144where
145 V: SQLParam + 'a + From<String> + Into<Cow<'a, V>>,
146{
147 fn to_sql(&self) -> SQL<'a, V> {
148 SQL::param(V::from(self.to_string()))
149 }
150
151 fn into_sql(self) -> SQL<'a, V> {
152 SQL::param(V::from(self.into_string()))
153 }
154}
155
156#[cfg(any(feature = "std", feature = "alloc"))]
157impl<'a, V> ToSQL<'a, V> for Rc<str>
158where
159 V: SQLParam + 'a + From<String> + Into<Cow<'a, V>>,
160{
161 fn to_sql(&self) -> SQL<'a, V> {
162 SQL::param(V::from(self.as_ref().to_string()))
163 }
164}
165
166#[cfg(any(feature = "std", feature = "alloc"))]
167impl<'a, V> ToSQL<'a, V> for Arc<str>
168where
169 V: SQLParam + 'a + From<String> + Into<Cow<'a, V>>,
170{
171 fn to_sql(&self) -> SQL<'a, V> {
172 SQL::param(V::from(self.as_ref().to_string()))
173 }
174}
175
176impl<'a, V, T> ToSQL<'a, V> for Box<T>
177where
178 V: SQLParam + 'a,
179 T: ToSQL<'a, V>,
180{
181 fn to_sql(&self) -> SQL<'a, V> {
182 (**self).to_sql()
183 }
184}
185
186#[cfg(any(feature = "std", feature = "alloc"))]
187impl<'a, V, T> ToSQL<'a, V> for Rc<T>
188where
189 V: SQLParam + 'a,
190 T: ToSQL<'a, V>,
191{
192 fn to_sql(&self) -> SQL<'a, V> {
193 (**self).to_sql()
194 }
195}
196
197#[cfg(any(feature = "std", feature = "alloc"))]
198impl<'a, V, T> ToSQL<'a, V> for Arc<T>
199where
200 V: SQLParam + 'a,
201 T: ToSQL<'a, V>,
202{
203 fn to_sql(&self) -> SQL<'a, V> {
204 (**self).to_sql()
205 }
206}
207
208impl<'a, V> ToSQL<'a, V> for String
209where
210 V: SQLParam + 'a + From<Self> + Into<Cow<'a, V>>,
211{
212 fn to_sql(&self) -> SQL<'a, V> {
213 SQL::param(V::from(self.clone()))
214 }
215
216 fn into_sql(self) -> SQL<'a, V> {
217 SQL::param(V::from(self))
218 }
219}
220
221impl<'a, V> ToSQL<'a, V> for Cow<'a, str>
222where
223 V: SQLParam + 'a + From<&'a str> + From<String> + Into<Cow<'a, V>>,
224{
225 fn to_sql(&self) -> SQL<'a, V> {
226 match self {
227 Cow::Borrowed(value) => SQL::param(V::from(*value)),
228 Cow::Owned(value) => SQL::param(V::from(value.clone())),
229 }
230 }
231
232 fn into_sql(self) -> SQL<'a, V> {
233 match self {
234 Cow::Borrowed(value) => SQL::param(V::from(value)),
235 Cow::Owned(value) => SQL::param(V::from(value)),
236 }
237 }
238}
239
240impl<'a, V> ToSQL<'a, V> for Cow<'a, [u8]>
241where
242 V: SQLParam + 'a + From<&'a [u8]> + From<Vec<u8>> + Into<Cow<'a, V>>,
243{
244 fn to_sql(&self) -> SQL<'a, V> {
245 match self {
246 Cow::Borrowed(value) => SQL::param(V::from(*value)),
247 Cow::Owned(value) => SQL::param(V::from(value.clone())),
248 }
249 }
250
251 fn into_sql(self) -> SQL<'a, V> {
252 match self {
253 Cow::Borrowed(value) => SQL::param(V::from(value)),
254 Cow::Owned(value) => SQL::param(V::from(value)),
255 }
256 }
257}
258
259impl<'a, V> ToSQL<'a, V> for SQLBytes<'a>
260where
261 V: SQLParam + 'a + From<&'a [u8]> + From<Vec<u8>> + Into<Cow<'a, V>>,
262{
263 fn to_sql(&self) -> SQL<'a, V> {
264 match &self.0 {
265 Cow::Borrowed(value) => SQL::param(V::from(*value)),
266 Cow::Owned(value) => SQL::param(V::from(value.clone())),
267 }
268 }
269
270 fn into_sql(self) -> SQL<'a, V> {
271 match self.0 {
272 Cow::Borrowed(value) => SQL::param(V::from(value)),
273 Cow::Owned(value) => SQL::param(V::from(value)),
274 }
275 }
276}
277
278macro_rules! impl_tosql_param_copy {
279 ($($ty:ty),+ $(,)?) => {
280 $(
281 impl<'a, V> ToSQL<'a, V> for $ty
282 where
283 V: SQLParam + 'a + From<$ty>,
284 V: Into<Cow<'a, V>>,
285 {
286 fn to_sql(&self) -> SQL<'a, V> {
287 SQL::param(V::from(*self))
288 }
289 }
290 )+
291 };
292}
293
294impl_tosql_param_copy!(
295 i8, i16, i32, i64, f32, f64, bool, u8, u16, u32, u64, isize, usize
296);
297
298impl<'a, V, T> ToSQL<'a, V> for Option<T>
299where
300 V: SQLParam + 'a,
301 T: ToSQL<'a, V>,
302{
303 fn to_sql(&self) -> SQL<'a, V> {
304 self.as_ref()
305 .map_or_else(|| SQLNull.to_sql(), ToSQL::to_sql)
306 }
307}
308
309#[cfg(feature = "uuid")]
310impl<'a, V> ToSQL<'a, V> for Uuid
311where
312 V: SQLParam + 'a + From<Self> + Into<Cow<'a, V>>,
313{
314 fn to_sql(&self) -> SQL<'a, V> {
315 SQL::param(V::from(*self))
316 }
317}