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