1use crate::dialect::{MySQLDialect, PostgresDialect, SQLiteDialect};
2use crate::traits::SQLParam;
3use crate::types::{Assignable, DataType};
4
5#[cfg(any(feature = "alloc", feature = "std"))]
6use crate::prelude::{Arc, Box, Cow, Rc, String, Vec};
7
8pub trait ValueTypeForDialect<D> {
12 type SQLType: DataType;
14}
15
16#[diagnostic::on_unimplemented(
22 message = "`{Self}` cannot bind to a `{Expected}` placeholder",
23 label = "bind a value of the placeholder column's type",
24 note = "`None` binds only to the placeholder of a nullable column"
25)]
26pub trait BindValue<'a, V: SQLParam, Expected: DataType>: Sized {
27 fn into_bind_value(self) -> V;
29}
30
31pub trait NullableBindValue<'a, V: SQLParam, Expected: DataType>: Sized {
35 fn into_nullable_bind_value(self) -> V;
38}
39
40impl<V, Expected, T> BindValue<'_, V, Expected> for T
41where
42 V: SQLParam + From<T>,
43 Expected: DataType + Assignable<<T as ValueTypeForDialect<V::DialectMarker>>::SQLType>,
44 T: ValueTypeForDialect<V::DialectMarker>,
45{
46 fn into_bind_value(self) -> V {
47 V::from(self)
48 }
49}
50
51impl<V, Expected, T> NullableBindValue<'_, V, Expected> for Option<T>
52where
53 V: SQLParam + From<Self>,
54 Expected: DataType + Assignable<<T as ValueTypeForDialect<V::DialectMarker>>::SQLType>,
55 T: ValueTypeForDialect<V::DialectMarker>,
56{
57 fn into_nullable_bind_value(self) -> V {
58 V::from(self)
59 }
60}
61
62macro_rules! impl_value_type {
68 ($dialect:ty, $sql:ty => $($ty:ty),+ $(,)?) => {
69 $(
70 impl ValueTypeForDialect<$dialect> for $ty {
71 type SQLType = $sql;
72 }
73 )+
74 };
75}
76
77macro_rules! impl_value_type_const_n {
81 ($dialect:ty, $sql:ty => $($ty:ty),+ $(,)?) => {
82 $(
83 impl<const N: usize> ValueTypeForDialect<$dialect> for $ty {
84 type SQLType = $sql;
85 }
86 )+
87 };
88}
89
90use drizzle_types::sqlite::types as sqlite_ty;
95
96impl_value_type!(SQLiteDialect, sqlite_ty::Integer =>
97 i8, i16, i32, i64, isize, u8, u16, u32, u64, usize, bool);
98
99impl_value_type!(SQLiteDialect, sqlite_ty::Real => f32, f64);
100
101impl_value_type!(SQLiteDialect, sqlite_ty::Text => &str);
102
103#[cfg(any(feature = "alloc", feature = "std"))]
104impl_value_type!(SQLiteDialect, sqlite_ty::Text =>
105 Cow<'_, str>,
106 String,
107 Box<String>,
108 Rc<String>,
109 Arc<String>,
110 Box<str>,
111 Rc<str>,
112 Arc<str>,
113);
114
115impl_value_type!(SQLiteDialect, sqlite_ty::Text => compact_str::CompactString);
116
117#[cfg(feature = "arrayvec")]
118impl_value_type_const_n!(SQLiteDialect, sqlite_ty::Text => arrayvec::ArrayString<N>);
119
120impl_value_type!(SQLiteDialect, sqlite_ty::Blob => &[u8]);
121
122#[cfg(any(feature = "alloc", feature = "std"))]
123impl_value_type!(SQLiteDialect, sqlite_ty::Blob =>
124 Cow<'_, [u8]>,
125 Vec<u8>,
126 Box<Vec<u8>>,
127 Rc<Vec<u8>>,
128 Arc<Vec<u8>>,
129);
130
131#[cfg(feature = "arrayvec")]
132impl_value_type_const_n!(SQLiteDialect, sqlite_ty::Blob => arrayvec::ArrayVec<u8, N>);
133
134#[cfg(feature = "bytes")]
135impl_value_type!(SQLiteDialect, sqlite_ty::Blob => bytes::Bytes, bytes::BytesMut);
136
137#[cfg(feature = "smallvec-types")]
138impl_value_type_const_n!(SQLiteDialect, sqlite_ty::Blob => smallvec::SmallVec<[u8; N]>);
139
140#[cfg(feature = "uuid")]
141impl_value_type!(SQLiteDialect, sqlite_ty::Blob => uuid::Uuid, &uuid::Uuid);
142
143#[cfg(feature = "chrono")]
144impl_value_type!(SQLiteDialect, sqlite_ty::Text =>
145 chrono::NaiveDate,
146 chrono::NaiveTime,
147 chrono::NaiveDateTime,
148 chrono::DateTime<chrono::FixedOffset>,
149 chrono::DateTime<chrono::Utc>,
150 chrono::Duration,
151);
152
153#[cfg(feature = "time")]
154impl_value_type!(SQLiteDialect, sqlite_ty::Text =>
155 time::Date,
156 time::Time,
157 time::PrimitiveDateTime,
158 time::OffsetDateTime,
159 time::Duration,
160);
161
162#[cfg(feature = "jiff")]
163impl_value_type!(SQLiteDialect, sqlite_ty::Text =>
164 jiff::civil::Date,
165 jiff::civil::Time,
166 jiff::civil::DateTime,
167 jiff::Timestamp,
168);
169
170#[cfg(feature = "rust-decimal")]
171impl_value_type!(SQLiteDialect, sqlite_ty::Text =>
172 rust_decimal::Decimal,
173 &rust_decimal::Decimal,
174);
175
176#[cfg(feature = "serde")]
177impl_value_type!(SQLiteDialect, sqlite_ty::Text => serde_json::Value);
178
179use drizzle_types::postgres::types as pg_ty;
184
185impl_value_type!(PostgresDialect, pg_ty::Int2 => i8, i16, u8);
186impl_value_type!(PostgresDialect, pg_ty::Int4 => i32, u16);
187impl_value_type!(PostgresDialect, pg_ty::Int8 => i64, u32, u64, isize, usize);
188impl_value_type!(PostgresDialect, pg_ty::Float4 => f32);
189impl_value_type!(PostgresDialect, pg_ty::Float8 => f64);
190impl_value_type!(PostgresDialect, pg_ty::Boolean => bool);
191
192impl_value_type!(PostgresDialect, pg_ty::Text => &str);
193
194#[cfg(any(feature = "alloc", feature = "std"))]
195impl_value_type!(PostgresDialect, pg_ty::Text =>
196 Cow<'_, str>,
197 String,
198 Box<String>,
199 Rc<String>,
200 Arc<String>,
201 Box<str>,
202 Rc<str>,
203 Arc<str>,
204);
205
206#[cfg(feature = "compact-str")]
207impl_value_type!(PostgresDialect, pg_ty::Text => compact_str::CompactString);
208
209#[cfg(feature = "arrayvec")]
210impl_value_type_const_n!(PostgresDialect, pg_ty::Text => arrayvec::ArrayString<N>);
211
212impl_value_type!(PostgresDialect, pg_ty::Bytea => &[u8]);
213
214#[cfg(any(feature = "alloc", feature = "std"))]
215impl_value_type!(PostgresDialect, pg_ty::Bytea =>
216 Cow<'_, [u8]>,
217 Vec<u8>,
218 Box<Vec<u8>>,
219 Rc<Vec<u8>>,
220 Arc<Vec<u8>>,
221);
222
223#[cfg(feature = "arrayvec")]
224impl_value_type_const_n!(PostgresDialect, pg_ty::Bytea => arrayvec::ArrayVec<u8, N>);
225
226#[cfg(feature = "bytes")]
227impl_value_type!(PostgresDialect, pg_ty::Bytea => bytes::Bytes, bytes::BytesMut);
228
229#[cfg(feature = "smallvec-types")]
230impl_value_type_const_n!(PostgresDialect, pg_ty::Bytea => smallvec::SmallVec<[u8; N]>);
231
232#[cfg(feature = "uuid")]
233impl_value_type!(PostgresDialect, pg_ty::Uuid => uuid::Uuid, &uuid::Uuid);
234
235#[cfg(feature = "rust-decimal")]
236impl_value_type!(PostgresDialect, pg_ty::Numeric =>
237 rust_decimal::Decimal,
238 &rust_decimal::Decimal,
239);
240
241#[cfg(feature = "serde")]
242impl_value_type!(PostgresDialect, pg_ty::Json => serde_json::Value);
243
244#[cfg(feature = "chrono")]
245impl_value_type!(PostgresDialect, pg_ty::Date => chrono::NaiveDate);
246#[cfg(feature = "chrono")]
247impl_value_type!(PostgresDialect, pg_ty::Time => chrono::NaiveTime);
248#[cfg(feature = "chrono")]
249impl_value_type!(PostgresDialect, pg_ty::Timestamp => chrono::NaiveDateTime);
250#[cfg(feature = "chrono")]
251impl_value_type!(PostgresDialect, pg_ty::Timestamptz =>
252 chrono::DateTime<chrono::FixedOffset>,
253 chrono::DateTime<chrono::Utc>,
254);
255#[cfg(feature = "chrono")]
256impl_value_type!(PostgresDialect, pg_ty::Interval => chrono::Duration);
257
258#[cfg(feature = "time")]
259impl_value_type!(PostgresDialect, pg_ty::Date => time::Date);
260#[cfg(feature = "time")]
261impl_value_type!(PostgresDialect, pg_ty::Time => time::Time);
262#[cfg(feature = "time")]
263impl_value_type!(PostgresDialect, pg_ty::Timestamp => time::PrimitiveDateTime);
264#[cfg(feature = "time")]
265impl_value_type!(PostgresDialect, pg_ty::Timestamptz => time::OffsetDateTime);
266#[cfg(feature = "time")]
267impl_value_type!(PostgresDialect, pg_ty::Interval => time::Duration);
268
269#[cfg(feature = "jiff")]
270impl_value_type!(PostgresDialect, pg_ty::Date => jiff::civil::Date);
271#[cfg(feature = "jiff")]
272impl_value_type!(PostgresDialect, pg_ty::Time => jiff::civil::Time);
273#[cfg(feature = "jiff")]
274impl_value_type!(PostgresDialect, pg_ty::Timestamp => jiff::civil::DateTime);
275#[cfg(feature = "jiff")]
276impl_value_type!(PostgresDialect, pg_ty::Timestamptz => jiff::Timestamp);
277
278#[cfg(feature = "cidr")]
279impl_value_type!(PostgresDialect, pg_ty::Inet => cidr::IpInet);
280#[cfg(feature = "cidr")]
281impl_value_type!(PostgresDialect, pg_ty::Cidr => cidr::IpCidr);
282#[cfg(feature = "cidr")]
283impl_value_type!(PostgresDialect, pg_ty::MacAddr => [u8; 6]);
284#[cfg(feature = "cidr")]
285impl_value_type!(PostgresDialect, pg_ty::MacAddr8 => [u8; 8]);
286
287#[cfg(feature = "geo-types")]
288impl_value_type!(PostgresDialect, pg_ty::Point => geo_types::Point<f64>);
289#[cfg(feature = "geo-types")]
290impl_value_type!(PostgresDialect, pg_ty::LineString => geo_types::LineString<f64>);
291#[cfg(feature = "geo-types")]
292impl_value_type!(PostgresDialect, pg_ty::Rect => geo_types::Rect<f64>);
293
294#[cfg(feature = "bit-vec")]
295impl_value_type!(PostgresDialect, pg_ty::BitString => bit_vec::BitVec);
296
297#[cfg(any(feature = "alloc", feature = "std"))]
300impl_value_type!(PostgresDialect, drizzle_types::Array<pg_ty::Text> =>
301 Vec<String>, Vec<&str>);
302
303#[cfg(any(feature = "alloc", feature = "std"))]
304impl_value_type!(PostgresDialect, drizzle_types::Array<pg_ty::Int2> => Vec<i16>);
305
306#[cfg(any(feature = "alloc", feature = "std"))]
307impl_value_type!(PostgresDialect, drizzle_types::Array<pg_ty::Int4> => Vec<i32>);
308
309#[cfg(any(feature = "alloc", feature = "std"))]
310impl_value_type!(PostgresDialect, drizzle_types::Array<pg_ty::Int8> => Vec<i64>);
311
312#[cfg(any(feature = "alloc", feature = "std"))]
313impl_value_type!(PostgresDialect, drizzle_types::Array<pg_ty::Float4> => Vec<f32>);
314
315#[cfg(any(feature = "alloc", feature = "std"))]
316impl_value_type!(PostgresDialect, drizzle_types::Array<pg_ty::Float8> => Vec<f64>);
317
318#[cfg(any(feature = "alloc", feature = "std"))]
319impl_value_type!(PostgresDialect, drizzle_types::Array<pg_ty::Boolean> => Vec<bool>);
320
321#[cfg(all(any(feature = "alloc", feature = "std"), feature = "uuid"))]
322impl_value_type!(PostgresDialect, drizzle_types::Array<pg_ty::Uuid> => Vec<uuid::Uuid>);
323
324#[cfg(all(any(feature = "alloc", feature = "std"), feature = "chrono"))]
325impl_value_type!(PostgresDialect, drizzle_types::Array<pg_ty::Date> => Vec<chrono::NaiveDate>);
326
327#[cfg(all(any(feature = "alloc", feature = "std"), feature = "chrono"))]
328impl_value_type!(PostgresDialect, drizzle_types::Array<pg_ty::Time> => Vec<chrono::NaiveTime>);
329
330#[cfg(all(any(feature = "alloc", feature = "std"), feature = "chrono"))]
331impl_value_type!(PostgresDialect, drizzle_types::Array<pg_ty::Timestamp> => Vec<chrono::NaiveDateTime>);
332
333#[cfg(all(any(feature = "alloc", feature = "std"), feature = "chrono"))]
334impl_value_type!(PostgresDialect, drizzle_types::Array<pg_ty::Timestamptz> => Vec<chrono::DateTime<chrono::Utc>>);
335
336#[cfg(all(any(feature = "alloc", feature = "std"), feature = "rust-decimal"))]
337impl_value_type!(PostgresDialect, drizzle_types::Array<pg_ty::Numeric> => Vec<rust_decimal::Decimal>);
338
339use drizzle_types::mysql::types as mysql_ty;
344
345impl_value_type!(MySQLDialect, mysql_ty::TinyInt => i8);
346impl_value_type!(MySQLDialect, mysql_ty::SmallInt => i16);
347impl_value_type!(MySQLDialect, mysql_ty::Int => i32);
348impl_value_type!(MySQLDialect, mysql_ty::BigInt => i64, isize);
349impl_value_type!(MySQLDialect, mysql_ty::TinyIntUnsigned => u8);
350impl_value_type!(MySQLDialect, mysql_ty::SmallIntUnsigned => u16);
351impl_value_type!(MySQLDialect, mysql_ty::IntUnsigned => u32);
352impl_value_type!(MySQLDialect, mysql_ty::BigIntUnsigned => u64, usize);
353impl_value_type!(MySQLDialect, mysql_ty::Float => f32);
354impl_value_type!(MySQLDialect, mysql_ty::Double => f64);
355impl_value_type!(MySQLDialect, mysql_ty::Boolean => bool);
356
357impl_value_type!(MySQLDialect, mysql_ty::Text => &str);
358
359#[cfg(any(feature = "alloc", feature = "std"))]
360impl_value_type!(MySQLDialect, mysql_ty::Text =>
361 Cow<'_, str>,
362 String,
363 Box<String>,
364 Rc<String>,
365 Arc<String>,
366 Box<str>,
367 Rc<str>,
368 Arc<str>,
369);
370
371#[cfg(feature = "compact-str")]
372impl_value_type!(MySQLDialect, mysql_ty::Text => compact_str::CompactString);
373
374#[cfg(feature = "arrayvec")]
375impl_value_type_const_n!(MySQLDialect, mysql_ty::Varchar => arrayvec::ArrayString<N>);
376
377impl_value_type!(MySQLDialect, mysql_ty::Blob => &[u8]);
378
379#[cfg(any(feature = "alloc", feature = "std"))]
380impl_value_type!(MySQLDialect, mysql_ty::Blob =>
381 Cow<'_, [u8]>,
382 Vec<u8>,
383 Box<Vec<u8>>,
384 Rc<Vec<u8>>,
385 Arc<Vec<u8>>,
386);
387
388#[cfg(feature = "arrayvec")]
389impl_value_type_const_n!(MySQLDialect, mysql_ty::Varbinary => arrayvec::ArrayVec<u8, N>);
390
391impl_value_type_const_n!(MySQLDialect, mysql_ty::Binary => [u8; N]);
392impl_value_type_const_n!(MySQLDialect, mysql_ty::Char => [char; N]);
393
394#[cfg(feature = "bytes")]
395impl_value_type!(MySQLDialect, mysql_ty::Blob => bytes::Bytes, bytes::BytesMut);
396
397#[cfg(feature = "smallvec-types")]
398impl_value_type_const_n!(MySQLDialect, mysql_ty::Blob => smallvec::SmallVec<[u8; N]>);
399
400#[cfg(feature = "uuid")]
401impl_value_type!(MySQLDialect, mysql_ty::Binary => uuid::Uuid, &uuid::Uuid);
402
403#[cfg(feature = "rust-decimal")]
404impl_value_type!(MySQLDialect, mysql_ty::Decimal =>
405 rust_decimal::Decimal,
406 &rust_decimal::Decimal,
407);
408
409#[cfg(feature = "serde")]
410impl_value_type!(MySQLDialect, mysql_ty::Json => serde_json::Value);
411
412#[cfg(feature = "chrono")]
413impl_value_type!(MySQLDialect, mysql_ty::Date => chrono::NaiveDate);
414#[cfg(feature = "chrono")]
415impl_value_type!(MySQLDialect, mysql_ty::Time => chrono::NaiveTime);
416#[cfg(feature = "chrono")]
417impl_value_type!(MySQLDialect, mysql_ty::DateTime => chrono::NaiveDateTime);
418#[cfg(feature = "chrono")]
419impl_value_type!(MySQLDialect, mysql_ty::Timestamp =>
420 chrono::DateTime<chrono::FixedOffset>,
421 chrono::DateTime<chrono::Utc>,
422);
423
424#[cfg(feature = "time")]
425impl_value_type!(MySQLDialect, mysql_ty::Date => time::Date);
426#[cfg(feature = "time")]
427impl_value_type!(MySQLDialect, mysql_ty::Time => time::Time);
428#[cfg(feature = "time")]
429impl_value_type!(MySQLDialect, mysql_ty::DateTime => time::PrimitiveDateTime);
430#[cfg(feature = "time")]
431impl_value_type!(MySQLDialect, mysql_ty::Timestamp => time::OffsetDateTime);
432
433#[cfg(feature = "jiff")]
434impl_value_type!(MySQLDialect, mysql_ty::Date => jiff::civil::Date);
435#[cfg(feature = "jiff")]
436impl_value_type!(MySQLDialect, mysql_ty::Time => jiff::civil::Time);
437#[cfg(feature = "jiff")]
438impl_value_type!(MySQLDialect, mysql_ty::DateTime => jiff::civil::DateTime);
439#[cfg(feature = "jiff")]
440impl_value_type!(MySQLDialect, mysql_ty::Timestamp => jiff::Timestamp);