1use crate::prelude::*;
4use crate::{
5 sql::{SQL, Token},
6 traits::{SQLColumnInfo, SQLParam, SQLTableInfo},
7};
8
9#[cfg(feature = "uuid")]
10use uuid::Uuid;
11
12pub trait ToSQL<'a, V: SQLParam> {
18 fn to_sql(&self) -> SQL<'a, V>;
19 fn alias(&self, alias: &'static str) -> SQL<'a, V> {
20 self.to_sql().alias(alias)
21 }
22}
23
24#[derive(Debug, Clone)]
34pub struct SQLBytes<'a>(pub Cow<'a, [u8]>);
35
36impl<'a> SQLBytes<'a> {
37 #[inline]
38 pub fn new(bytes: impl Into<Cow<'a, [u8]>>) -> Self {
39 Self(bytes.into())
40 }
41}
42
43impl<'a, T, V> From<&T> for SQL<'a, V>
44where
45 T: ToSQL<'a, V>,
46 V: SQLParam,
47{
48 fn from(value: &T) -> Self {
49 value.to_sql()
50 }
51}
52
53impl<'a, V: SQLParam, T> ToSQL<'a, V> for &T
54where
55 T: ToSQL<'a, V>,
56{
57 fn to_sql(&self) -> SQL<'a, V> {
58 (**self).to_sql()
59 }
60}
61
62impl<'a, V: SQLParam + 'a> ToSQL<'a, V> for () {
63 fn to_sql(&self) -> SQL<'a, V> {
64 SQL::empty()
65 }
66}
67
68impl<'a, V, T> ToSQL<'a, V> for Vec<T>
69where
70 V: SQLParam + 'a,
71 T: ToSQL<'a, V>,
72{
73 fn to_sql(&self) -> SQL<'a, V> {
74 SQL::join(self.iter().map(ToSQL::to_sql), Token::COMMA)
75 }
76}
77
78impl<'a, V, T> ToSQL<'a, V> for &'a [T]
79where
80 V: SQLParam + 'a,
81 T: ToSQL<'a, V>,
82{
83 fn to_sql(&self) -> SQL<'a, V> {
84 SQL::join(self.iter().map(ToSQL::to_sql), Token::COMMA)
85 }
86}
87
88impl<'a, V, T, const N: usize> ToSQL<'a, V> for [T; N]
89where
90 V: SQLParam + 'a,
91 T: ToSQL<'a, V>,
92{
93 fn to_sql(&self) -> SQL<'a, V> {
94 SQL::join(self.iter().map(ToSQL::to_sql), Token::COMMA)
95 }
96}
97
98impl<'a, V: SQLParam + 'a> ToSQL<'a, V> for &'static dyn SQLTableInfo {
100 fn to_sql(&self) -> SQL<'a, V> {
101 SQL::table(*self)
102 }
103}
104
105impl<'a, V: SQLParam + 'a> ToSQL<'a, V> for &'static dyn SQLColumnInfo {
106 fn to_sql(&self) -> SQL<'a, V> {
107 SQL::column(*self)
108 }
109}
110
111impl<'a, V: SQLParam + 'a> ToSQL<'a, V> for Box<[&'static dyn SQLColumnInfo]> {
112 fn to_sql(&self) -> SQL<'a, V> {
113 SQL::join(self.iter().map(|&v| SQL::column(v)), Token::COMMA)
114 }
115}
116
117impl<'a, V: SQLParam + 'a> ToSQL<'a, V> for Box<[&'static dyn SQLTableInfo]> {
118 fn to_sql(&self) -> SQL<'a, V> {
119 SQL::join(self.iter().map(|&v| SQL::table(v)), Token::COMMA)
120 }
121}
122
123impl<'a, V> ToSQL<'a, V> for &'a str
125where
126 V: SQLParam + 'a,
127 V: From<&'a str>,
128 V: Into<Cow<'a, V>>,
129{
130 fn to_sql(&self) -> SQL<'a, V> {
131 SQL::param(V::from(self))
132 }
133}
134
135impl<'a, V> ToSQL<'a, V> for String
136where
137 V: SQLParam + 'a,
138 V: From<String>,
139 V: Into<Cow<'a, V>>,
140{
141 fn to_sql(&self) -> SQL<'a, V> {
142 SQL::param(V::from(self.clone()))
143 }
144}
145
146impl<'a, V> ToSQL<'a, V> for Cow<'a, str>
147where
148 V: SQLParam + 'a,
149 V: From<&'a str>,
150 V: From<String>,
151 V: Into<Cow<'a, V>>,
152{
153 fn to_sql(&self) -> SQL<'a, V> {
154 match self {
155 Cow::Borrowed(value) => SQL::param(V::from(*value)),
156 Cow::Owned(value) => SQL::param(V::from(value.clone())),
157 }
158 }
159}
160
161impl<'a, V> ToSQL<'a, V> for Cow<'a, [u8]>
162where
163 V: SQLParam + 'a,
164 V: From<&'a [u8]>,
165 V: From<Vec<u8>>,
166 V: Into<Cow<'a, V>>,
167{
168 fn to_sql(&self) -> SQL<'a, V> {
169 match self {
170 Cow::Borrowed(value) => SQL::param(V::from(*value)),
171 Cow::Owned(value) => SQL::param(V::from(value.clone())),
172 }
173 }
174}
175
176impl<'a, V> ToSQL<'a, V> for SQLBytes<'a>
177where
178 V: SQLParam + 'a,
179 V: From<&'a [u8]>,
180 V: From<Vec<u8>>,
181 V: Into<Cow<'a, V>>,
182{
183 fn to_sql(&self) -> SQL<'a, V> {
184 match &self.0 {
185 Cow::Borrowed(value) => SQL::param(V::from(*value)),
186 Cow::Owned(value) => SQL::param(V::from(value.clone())),
187 }
188 }
189}
190
191macro_rules! impl_tosql_param_copy {
192 ($($ty:ty),+ $(,)?) => {
193 $(
194 impl<'a, V> ToSQL<'a, V> for $ty
195 where
196 V: SQLParam + 'a + From<$ty>,
197 V: Into<Cow<'a, V>>,
198 {
199 fn to_sql(&self) -> SQL<'a, V> {
200 SQL::param(V::from(*self))
201 }
202 }
203 )+
204 };
205}
206
207impl_tosql_param_copy!(
208 i8, i16, i32, i64, f32, f64, bool, u8, u16, u32, u64, isize, usize
209);
210
211impl<'a, V, T> ToSQL<'a, V> for Option<T>
212where
213 V: SQLParam + 'a,
214 T: ToSQL<'a, V>,
215{
216 fn to_sql(&self) -> SQL<'a, V> {
217 match self {
218 Some(value) => value.to_sql(), None => SQL::raw("NULL"), }
221 }
222}
223
224#[cfg(feature = "uuid")]
225impl<'a, V> ToSQL<'a, V> for Uuid
226where
227 V: SQLParam + 'a,
228 V: From<Uuid>,
229 V: Into<Cow<'a, V>>,
230{
231 fn to_sql(&self) -> SQL<'a, V> {
232 SQL::param(V::from(*self))
233 }
234}