Skip to main content

drizzle_types/sql/
mod.rs

1//! SQL data type markers for compile-time type safety.
2//!
3//! This module provides zero-sized type markers that represent SQL data types
4//! at the Rust type level, enabling the type system to verify compatible
5//! comparisons and operations at compile time.
6
7use core::marker::PhantomData;
8
9mod coerce;
10mod ops;
11
12pub use coerce::*;
13pub use ops::*;
14
15mod private {
16    pub trait Sealed {}
17}
18
19/// Represents a SQL data type at the type level.
20#[diagnostic::on_unimplemented(
21    message = "`{Self}` is not a recognized SQL data type",
22    label = "use a drizzle SQL type marker (Int, Text, Bool, etc.)"
23)]
24pub trait DataType: private::Sealed + Copy + 'static {}
25
26/// Numeric SQL types that support arithmetic operations (+, -, *, /).
27#[diagnostic::on_unimplemented(
28    message = "`{Self}` is not a numeric SQL type",
29    label = "arithmetic operations require Int, SmallInt, BigInt, Float, or Double"
30)]
31pub trait Numeric: DataType {}
32
33/// Integer SQL types (SMALLINT, INTEGER, BIGINT).
34#[diagnostic::on_unimplemented(
35    message = "`{Self}` is not an integer SQL type",
36    label = "expected SmallInt, Int, or BigInt"
37)]
38pub trait Integral: Numeric {}
39
40/// Floating-point SQL types (REAL, DOUBLE PRECISION).
41#[diagnostic::on_unimplemented(
42    message = "`{Self}` is not a floating-point SQL type",
43    label = "expected Float or Double"
44)]
45pub trait Floating: Numeric {}
46
47/// String/text SQL types (TEXT, VARCHAR, CHAR).
48#[diagnostic::on_unimplemented(
49    message = "`{Self}` is not a text SQL type",
50    label = "expected Text or VarChar"
51)]
52pub trait Textual: DataType {}
53
54/// Binary data types (BLOB, BYTEA).
55#[diagnostic::on_unimplemented(
56    message = "`{Self}` is not a binary SQL type",
57    label = "expected Bytes (BLOB/BYTEA)"
58)]
59pub trait Binary: DataType {}
60
61/// Temporal SQL types (DATE, TIME, TIMESTAMP).
62#[diagnostic::on_unimplemented(
63    message = "`{Self}` is not a temporal SQL type",
64    label = "expected Date, Time, Timestamp, or TimestampTz"
65)]
66pub trait Temporal: DataType {}
67
68/// Boolean-like SQL types that support logical operations (NOT, AND, OR).
69#[diagnostic::on_unimplemented(
70    message = "`{Self}` is not a boolean SQL type",
71    label = "logical operations require a boolean-typed expression"
72)]
73pub trait BooleanLike: DataType {}
74
75/// PostgreSQL-style SQL array type marker.
76///
77/// `Array<T>` represents an array whose element SQL type is `T`.
78#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
79pub struct Array<T: DataType>(pub PhantomData<T>);
80
81/// Placeholder marker used for bind parameters before concrete typing.
82#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
83pub struct Placeholder;
84
85impl<T: DataType> private::Sealed for Array<T> {}
86impl<T: DataType> DataType for Array<T> {}
87impl private::Sealed for Placeholder {}
88impl DataType for Placeholder {}
89impl Textual for Placeholder {}
90
91// =============================================================================
92// SQLite dialect marker impls
93// =============================================================================
94
95impl private::Sealed for crate::sqlite::types::Integer {}
96impl private::Sealed for crate::sqlite::types::Text {}
97impl private::Sealed for crate::sqlite::types::Real {}
98impl private::Sealed for crate::sqlite::types::Blob {}
99impl private::Sealed for crate::sqlite::types::Numeric {}
100impl private::Sealed for crate::sqlite::types::Any {}
101
102impl DataType for crate::sqlite::types::Integer {}
103impl DataType for crate::sqlite::types::Text {}
104impl DataType for crate::sqlite::types::Real {}
105impl DataType for crate::sqlite::types::Blob {}
106impl DataType for crate::sqlite::types::Numeric {}
107impl DataType for crate::sqlite::types::Any {}
108
109impl Numeric for crate::sqlite::types::Integer {}
110impl Numeric for crate::sqlite::types::Real {}
111impl Numeric for crate::sqlite::types::Numeric {}
112impl Numeric for crate::sqlite::types::Any {}
113
114impl Integral for crate::sqlite::types::Integer {}
115
116impl Floating for crate::sqlite::types::Real {}
117
118impl Textual for crate::sqlite::types::Text {}
119impl Textual for crate::sqlite::types::Any {}
120
121impl Binary for crate::sqlite::types::Blob {}
122
123impl Temporal for crate::sqlite::types::Integer {}
124impl Temporal for crate::sqlite::types::Real {}
125impl Temporal for crate::sqlite::types::Text {}
126impl Temporal for crate::sqlite::types::Numeric {}
127
128impl BooleanLike for crate::sqlite::types::Integer {}
129
130// =============================================================================
131// PostgreSQL dialect marker impls
132// =============================================================================
133
134impl private::Sealed for crate::postgres::types::Int2 {}
135impl private::Sealed for crate::postgres::types::Int4 {}
136impl private::Sealed for crate::postgres::types::Int8 {}
137impl private::Sealed for crate::postgres::types::Float4 {}
138impl private::Sealed for crate::postgres::types::Float8 {}
139impl private::Sealed for crate::postgres::types::Varchar {}
140impl private::Sealed for crate::postgres::types::Text {}
141impl private::Sealed for crate::postgres::types::Char {}
142impl private::Sealed for crate::postgres::types::Bytea {}
143impl private::Sealed for crate::postgres::types::Boolean {}
144impl private::Sealed for crate::postgres::types::Timestamptz {}
145impl private::Sealed for crate::postgres::types::Timestamp {}
146impl private::Sealed for crate::postgres::types::Date {}
147impl private::Sealed for crate::postgres::types::Time {}
148impl private::Sealed for crate::postgres::types::Timetz {}
149impl private::Sealed for crate::postgres::types::Numeric {}
150impl private::Sealed for crate::postgres::types::Uuid {}
151impl private::Sealed for crate::postgres::types::Json {}
152impl private::Sealed for crate::postgres::types::Jsonb {}
153impl private::Sealed for crate::postgres::types::Any {}
154impl private::Sealed for crate::postgres::types::Interval {}
155impl private::Sealed for crate::postgres::types::Inet {}
156impl private::Sealed for crate::postgres::types::Cidr {}
157impl private::Sealed for crate::postgres::types::MacAddr {}
158impl private::Sealed for crate::postgres::types::MacAddr8 {}
159impl private::Sealed for crate::postgres::types::Point {}
160impl private::Sealed for crate::postgres::types::LineString {}
161impl private::Sealed for crate::postgres::types::Rect {}
162impl private::Sealed for crate::postgres::types::BitString {}
163impl private::Sealed for crate::postgres::types::Line {}
164impl private::Sealed for crate::postgres::types::LineSegment {}
165impl private::Sealed for crate::postgres::types::Polygon {}
166impl private::Sealed for crate::postgres::types::Circle {}
167impl private::Sealed for crate::postgres::types::Enum {}
168
169impl DataType for crate::postgres::types::Int2 {}
170impl DataType for crate::postgres::types::Int4 {}
171impl DataType for crate::postgres::types::Int8 {}
172impl DataType for crate::postgres::types::Float4 {}
173impl DataType for crate::postgres::types::Float8 {}
174impl DataType for crate::postgres::types::Varchar {}
175impl DataType for crate::postgres::types::Text {}
176impl DataType for crate::postgres::types::Char {}
177impl DataType for crate::postgres::types::Bytea {}
178impl DataType for crate::postgres::types::Boolean {}
179impl DataType for crate::postgres::types::Timestamptz {}
180impl DataType for crate::postgres::types::Timestamp {}
181impl DataType for crate::postgres::types::Date {}
182impl DataType for crate::postgres::types::Time {}
183impl DataType for crate::postgres::types::Timetz {}
184impl DataType for crate::postgres::types::Numeric {}
185impl DataType for crate::postgres::types::Uuid {}
186impl DataType for crate::postgres::types::Json {}
187impl DataType for crate::postgres::types::Jsonb {}
188impl DataType for crate::postgres::types::Any {}
189impl DataType for crate::postgres::types::Interval {}
190impl DataType for crate::postgres::types::Inet {}
191impl DataType for crate::postgres::types::Cidr {}
192impl DataType for crate::postgres::types::MacAddr {}
193impl DataType for crate::postgres::types::MacAddr8 {}
194impl DataType for crate::postgres::types::Point {}
195impl DataType for crate::postgres::types::LineString {}
196impl DataType for crate::postgres::types::Rect {}
197impl DataType for crate::postgres::types::BitString {}
198impl DataType for crate::postgres::types::Line {}
199impl DataType for crate::postgres::types::LineSegment {}
200impl DataType for crate::postgres::types::Polygon {}
201impl DataType for crate::postgres::types::Circle {}
202impl DataType for crate::postgres::types::Enum {}
203
204impl Numeric for crate::postgres::types::Int2 {}
205impl Numeric for crate::postgres::types::Int4 {}
206impl Numeric for crate::postgres::types::Int8 {}
207impl Numeric for crate::postgres::types::Float4 {}
208impl Numeric for crate::postgres::types::Float8 {}
209impl Numeric for crate::postgres::types::Numeric {}
210
211impl Integral for crate::postgres::types::Int2 {}
212impl Integral for crate::postgres::types::Int4 {}
213impl Integral for crate::postgres::types::Int8 {}
214
215impl Floating for crate::postgres::types::Float4 {}
216impl Floating for crate::postgres::types::Float8 {}
217
218impl Textual for crate::postgres::types::Varchar {}
219impl Textual for crate::postgres::types::Text {}
220impl Textual for crate::postgres::types::Char {}
221impl Textual for crate::postgres::types::Enum {}
222
223impl Binary for crate::postgres::types::Bytea {}
224
225impl Temporal for crate::postgres::types::Timestamptz {}
226impl Temporal for crate::postgres::types::Timestamp {}
227impl Temporal for crate::postgres::types::Date {}
228impl Temporal for crate::postgres::types::Time {}
229impl Temporal for crate::postgres::types::Timetz {}
230
231impl Temporal for crate::postgres::types::Interval {}
232
233impl BooleanLike for crate::postgres::types::Boolean {}
234
235// =============================================================================
236// Tuple SQL type markers
237// =============================================================================
238
239macro_rules! seq_tuples {
240    (@acc $callback:ident [$($aT:ident),*] [$($ai:tt),*]) => {};
241    (@acc $callback:ident [$($aT:ident),*] [$($ai:tt),*] ($T:ident, $i:tt) $($rest:tt)*) => {
242        $callback!($($aT,)* $T; $($ai,)* $i);
243        seq_tuples!(@acc $callback [$($aT,)* $T] [$($ai,)* $i] $($rest)*);
244    };
245    ($callback:ident; $($pairs:tt)+) => {
246        seq_tuples!(@acc $callback [] [] $($pairs)+);
247    };
248    (@from $callback:ident [$($aT:ident),*] [$($ai:tt),*]; $($pairs:tt)+) => {
249        seq_tuples!(@acc $callback [$($aT),*] [$($ai),*] $($pairs)+);
250    };
251}
252
253macro_rules! with_col_sizes_8 {
254    ($callback:ident) => {
255        seq_tuples!($callback;
256            (T0,0) (T1,1) (T2,2) (T3,3)
257            (T4,4) (T5,5) (T6,6) (T7,7)
258        );
259    };
260}
261
262#[allow(unused_macros)]
263macro_rules! with_col_sizes_16 {
264    ($callback:ident) => {
265        seq_tuples!(@from $callback
266            [T0,T1,T2,T3,T4,T5,T6,T7]
267            [0,1,2,3,4,5,6,7];
268            (T8,8) (T9,9) (T10,10) (T11,11)
269            (T12,12) (T13,13) (T14,14) (T15,15)
270        );
271    };
272}
273
274#[allow(unused_macros)]
275macro_rules! with_col_sizes_32 {
276    ($callback:ident) => {
277        seq_tuples!(@from $callback
278            [T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15]
279            [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
280            (T16,16) (T17,17) (T18,18) (T19,19)
281            (T20,20) (T21,21) (T22,22) (T23,23)
282            (T24,24) (T25,25) (T26,26) (T27,27)
283            (T28,28) (T29,29) (T30,30) (T31,31)
284        );
285    };
286}
287
288#[allow(unused_macros)]
289macro_rules! with_col_sizes_64 {
290    ($callback:ident) => {
291        seq_tuples!(@from $callback
292            [T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,
293             T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31]
294            [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
295             16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31];
296            (T32,32) (T33,33) (T34,34) (T35,35)
297            (T36,36) (T37,37) (T38,38) (T39,39)
298            (T40,40) (T41,41) (T42,42) (T43,43)
299            (T44,44) (T45,45) (T46,46) (T47,47)
300            (T48,48) (T49,49) (T50,50) (T51,51)
301            (T52,52) (T53,53) (T54,54) (T55,55)
302            (T56,56) (T57,57) (T58,58) (T59,59)
303            (T60,60) (T61,61) (T62,62) (T63,63)
304        );
305    };
306}
307
308#[allow(unused_macros)]
309macro_rules! with_col_sizes_128 {
310    ($callback:ident) => {
311        seq_tuples!(@from $callback
312            [T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,
313             T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,
314             T32,T33,T34,T35,T36,T37,T38,T39,T40,T41,T42,T43,T44,T45,T46,T47,
315             T48,T49,T50,T51,T52,T53,T54,T55,T56,T57,T58,T59,T60,T61,T62,T63]
316            [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
317             16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
318             32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
319             48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63];
320            (T64,64) (T65,65) (T66,66) (T67,67)
321            (T68,68) (T69,69) (T70,70) (T71,71)
322            (T72,72) (T73,73) (T74,74) (T75,75)
323            (T76,76) (T77,77) (T78,78) (T79,79)
324            (T80,80) (T81,81) (T82,82) (T83,83)
325            (T84,84) (T85,85) (T86,86) (T87,87)
326            (T88,88) (T89,89) (T90,90) (T91,91)
327            (T92,92) (T93,93) (T94,94) (T95,95)
328            (T96,96) (T97,97) (T98,98) (T99,99)
329            (T100,100) (T101,101) (T102,102) (T103,103)
330            (T104,104) (T105,105) (T106,106) (T107,107)
331            (T108,108) (T109,109) (T110,110) (T111,111)
332            (T112,112) (T113,113) (T114,114) (T115,115)
333            (T116,116) (T117,117) (T118,118) (T119,119)
334            (T120,120) (T121,121) (T122,122) (T123,123)
335            (T124,124) (T125,125) (T126,126) (T127,127)
336        );
337    };
338}
339
340#[allow(unused_macros)]
341macro_rules! with_col_sizes_200 {
342    ($callback:ident) => {
343        seq_tuples!(@from $callback
344            [T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,
345             T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,
346             T32,T33,T34,T35,T36,T37,T38,T39,T40,T41,T42,T43,T44,T45,T46,T47,
347             T48,T49,T50,T51,T52,T53,T54,T55,T56,T57,T58,T59,T60,T61,T62,T63,
348             T64,T65,T66,T67,T68,T69,T70,T71,T72,T73,T74,T75,T76,T77,T78,T79,
349             T80,T81,T82,T83,T84,T85,T86,T87,T88,T89,T90,T91,T92,T93,T94,T95,
350             T96,T97,T98,T99,T100,T101,T102,T103,T104,T105,T106,T107,T108,T109,T110,T111,
351             T112,T113,T114,T115,T116,T117,T118,T119,T120,T121,T122,T123,T124,T125,T126,T127]
352            [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
353             16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
354             32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
355             48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
356             64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
357             80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,
358             96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,
359             112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127];
360            (T128,128) (T129,129) (T130,130) (T131,131)
361            (T132,132) (T133,133) (T134,134) (T135,135)
362            (T136,136) (T137,137) (T138,138) (T139,139)
363            (T140,140) (T141,141) (T142,142) (T143,143)
364            (T144,144) (T145,145) (T146,146) (T147,147)
365            (T148,148) (T149,149) (T150,150) (T151,151)
366            (T152,152) (T153,153) (T154,154) (T155,155)
367            (T156,156) (T157,157) (T158,158) (T159,159)
368            (T160,160) (T161,161) (T162,162) (T163,163)
369            (T164,164) (T165,165) (T166,166) (T167,167)
370            (T168,168) (T169,169) (T170,170) (T171,171)
371            (T172,172) (T173,173) (T174,174) (T175,175)
372            (T176,176) (T177,177) (T178,178) (T179,179)
373            (T180,180) (T181,181) (T182,182) (T183,183)
374            (T184,184) (T185,185) (T186,186) (T187,187)
375            (T188,188) (T189,189) (T190,190) (T191,191)
376            (T192,192) (T193,193) (T194,194) (T195,195)
377            (T196,196) (T197,197) (T198,198) (T199,199)
378        );
379    };
380}
381
382macro_rules! impl_tuple_datatype {
383    ($($T:ident),+; $($idx:tt),+) => {
384        impl<$($T: DataType),+> private::Sealed for ($($T,)+) {}
385        impl<$($T: DataType),+> DataType for ($($T,)+) {}
386    };
387}
388
389with_col_sizes_8!(impl_tuple_datatype);
390
391#[cfg(any(
392    feature = "col16",
393    feature = "col32",
394    feature = "col64",
395    feature = "col128",
396    feature = "col200"
397))]
398with_col_sizes_16!(impl_tuple_datatype);
399
400#[cfg(any(
401    feature = "col32",
402    feature = "col64",
403    feature = "col128",
404    feature = "col200"
405))]
406with_col_sizes_32!(impl_tuple_datatype);
407
408#[cfg(any(feature = "col64", feature = "col128", feature = "col200"))]
409with_col_sizes_64!(impl_tuple_datatype);
410
411#[cfg(any(feature = "col128", feature = "col200"))]
412with_col_sizes_128!(impl_tuple_datatype);
413
414#[cfg(feature = "col200")]
415with_col_sizes_200!(impl_tuple_datatype);