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