Skip to main content

drizzle_types/sql/
mod.rs

1//! Traits that classify SQL type markers, so query builders can check
2//! operations at compile time.
3//!
4//! Every expression carries a SQL type marker, a zero-sized type such as
5//! [`postgres::types::Int4`](crate::postgres::types::Int4) or
6//! [`sqlite::types::Text`](crate::sqlite::types::Text). The traits here say
7//! what a marker can do:
8//!
9//! | Trait | Question it answers | Used for |
10//! |---|---|---|
11//! | [`DataType`] | Is this a SQL type marker? | every typed expression |
12//! | [`Compatible`] | Can these two types be compared? | `eq`, `lt`, `IN`, `LIKE`, ... |
13//! | [`Assignable`] | Can a value of this type be stored in that column? | bind values, `INSERT ... SELECT` |
14//! | [`Numeric`] | Is it a number? | `+ - * /`, `SUM`, `AVG`, `ABS` |
15//! | [`Integral`] | Is it an integer? | `LIMIT`/`OFFSET`, `SUBSTR` positions |
16//! | [`Floating`] | Is it a floating-point number? | dialect type aliases |
17//! | [`Textual`] | Is it a string? | `LIKE`, `UPPER`, `LENGTH`, `ILIKE`, regex |
18//! | [`Binary`] | Is it raw bytes? | dialect type aliases |
19//! | [`Temporal`] | Is it a date, time or timestamp? | date/time functions |
20//! | [`BooleanLike`] | Can it be a condition? | `WHERE`, `AND`/`OR`/`NOT`, join `ON` |
21//! | [`ArithmeticOutput`] / [`NegOutput`] | What type does arithmetic produce? | result type of `a + b`, `-a` |
22//!
23//! All traits are implemented by this crate for the dialect markers in
24//! [`sqlite::types`](crate::sqlite::types), [`postgres::types`](crate::postgres::types)
25//! and [`mysql::types`](crate::mysql::types). [`DataType`] is sealed, so
26//! other crates cannot add new markers.
27//!
28//! # Examples
29//!
30//! Generic code can require a capability with a trait bound:
31//!
32//! ```
33//! use drizzle_types::{Compatible, Numeric, postgres::types::{Float8, Int4, Text}};
34//!
35//! fn comparable<L: Compatible<R>, R: drizzle_types::DataType>() {}
36//! fn numeric<T: Numeric>() {}
37//!
38//! comparable::<Int4, Float8>(); // int4 = float8 is allowed
39//! numeric::<Int4>();
40//! // numeric::<Text>(); // error: `Text` is not a numeric SQL type
41//! # let _ = Text;
42//! ```
43
44use core::marker::PhantomData;
45
46mod coerce;
47mod ops;
48
49pub use coerce::*;
50pub use ops::*;
51
52mod private {
53    pub trait Sealed {}
54}
55
56/// A SQL type marker: a zero-sized type that stands for one SQL type.
57///
58/// Every typed expression names its SQL type through a `DataType`. This
59/// crate implements it for each dialect marker (for example
60/// [`postgres::types::Int4`](crate::postgres::types::Int4)), for
61/// [`Array<T>`], [`Placeholder`], [`Conjunction`], and for tuples of markers
62/// (row values such as `(a, b) IN (...)`; up to 8 elements by default, more
63/// with the `col16` ... `col200` features).
64///
65/// The trait is sealed: other crates cannot implement it.
66#[diagnostic::on_unimplemented(
67    message = "`{Self}` is not a recognized SQL data type",
68    label = "use a drizzle SQL type marker (Int, Text, Bool, etc.)"
69)]
70pub trait DataType: private::Sealed + Copy + 'static {}
71
72/// Numeric SQL types: operands of arithmetic (`+`, `-`, `*`, `/`, `%`) and
73/// numeric functions such as `SUM`, `AVG`, `ABS` and `ROUND`.
74///
75/// | Dialect | Markers |
76/// |---|---|
77/// | SQLite | `Integer`, `Real`, `Numeric`, `Any` |
78/// | PostgreSQL | `Int2`, `Int4`, `Int8`, `Float4`, `Float8`, `Numeric` |
79/// | MySQL | every integer marker (signed and unsigned), `Year`, `Float`, `Double`, `Decimal` |
80///
81/// Text, boolean, date and JSON markers are not numeric. The result type of an
82/// operation comes from [`ArithmeticOutput`].
83#[diagnostic::on_unimplemented(
84    message = "`{Self}` is not a numeric SQL type",
85    label = "arithmetic operations require Int, SmallInt, BigInt, Float, or Double"
86)]
87pub trait Numeric: DataType {}
88
89/// Integer SQL types, required where SQL expects a whole number, such as
90/// `LIMIT`/`OFFSET` and string positions.
91///
92/// | Dialect | Markers |
93/// |---|---|
94/// | SQLite | `Integer` |
95/// | PostgreSQL | `Int2`, `Int4`, `Int8` |
96/// | MySQL | every integer marker (signed and unsigned), `Year` |
97///
98/// Floating-point and decimal markers (`Real`, `Float8`, `Numeric`, ...) are not integral.
99#[diagnostic::on_unimplemented(
100    message = "`{Self}` is not an integer SQL type",
101    label = "expected SmallInt, Int, or BigInt"
102)]
103pub trait Integral: Numeric {}
104
105/// Floating-point SQL types.
106///
107/// | Dialect | Markers |
108/// |---|---|
109/// | SQLite | `Real` |
110/// | PostgreSQL | `Float4` (`real`), `Float8` (`double precision`) |
111/// | MySQL | `Float`, `Double` |
112///
113/// Exact decimals (`Numeric`, `Decimal`) are not floating.
114#[diagnostic::on_unimplemented(
115    message = "`{Self}` is not a floating-point SQL type",
116    label = "expected Float or Double"
117)]
118pub trait Floating: Numeric {}
119
120/// String SQL types: operands of `LIKE`, `ILIKE`, regex matching and string
121/// functions such as `UPPER`, `LOWER`, `LENGTH` and `CONCAT`.
122///
123/// | Dialect | Markers |
124/// |---|---|
125/// | SQLite | `Text`, `Any` |
126/// | PostgreSQL | `Text`, `Varchar`, `Char`, `Enum` |
127/// | MySQL | `Char`, `Varchar`, `TinyText`, `Text`, `MediumText`, `LongText`, `Enum`, `Set` |
128///
129/// [`Placeholder`] is also textual, so a placeholder can be a pattern. JSON,
130/// UUID and binary markers are not textual.
131#[diagnostic::on_unimplemented(
132    message = "`{Self}` is not a text SQL type",
133    label = "expected Text or VarChar"
134)]
135pub trait Textual: DataType {}
136
137/// Raw byte SQL types.
138///
139/// | Dialect | Markers |
140/// |---|---|
141/// | SQLite | `Blob` |
142/// | PostgreSQL | `Bytea` |
143/// | MySQL | `Binary`, `Varbinary`, `TinyBlob`, `Blob`, `MediumBlob`, `LongBlob`, `Bit` |
144#[diagnostic::on_unimplemented(
145    message = "`{Self}` is not a binary SQL type",
146    label = "expected Bytes (BLOB/BYTEA)"
147)]
148pub trait Binary: DataType {}
149
150/// Date and time SQL types: operands of date/time functions.
151///
152/// | Dialect | Markers |
153/// |---|---|
154/// | SQLite | `Integer`, `Real`, `Text`, `Numeric` (SQLite stores dates as Unix times, Julian days or ISO-8601 text) |
155/// | PostgreSQL | `Date`, `Time`, `Timetz`, `Timestamp`, `Timestamptz`, `Interval` |
156/// | MySQL | `Date`, `Time`, `DateTime`, `Timestamp` |
157#[diagnostic::on_unimplemented(
158    message = "`{Self}` is not a temporal SQL type",
159    label = "expected Date, Time, Timestamp, or TimestampTz"
160)]
161pub trait Temporal: DataType {}
162
163/// SQL types that can be used as a condition: in `WHERE`, `HAVING`, join
164/// `ON`, `CASE WHEN`, and with `AND`, `OR` and `NOT`.
165///
166/// | Dialect | Markers |
167/// |---|---|
168/// | SQLite | `Integer` (SQLite has no boolean type; `0` is false) |
169/// | PostgreSQL | `Boolean` |
170/// | MySQL | `Boolean` |
171///
172/// [`Conjunction`], the type of a tuple of conditions, is also boolean-like.
173/// Comparisons such as `eq` produce a boolean-like type, so they can be used
174/// as conditions directly.
175#[diagnostic::on_unimplemented(
176    message = "`{Self}` is not a boolean SQL type",
177    label = "logical operations require a boolean-typed expression"
178)]
179pub trait BooleanLike: DataType {}
180
181/// SQL array type marker: `Array<T>` is an array whose elements have SQL type `T`.
182///
183/// Used for `PostgreSQL` array columns, such as `Array<Text>` for `text[]`.
184/// `Array<T>` is [`Compatible`] and [`Assignable`] only with the same
185/// `Array<T>`.
186#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
187pub struct Array<T: DataType>(pub PhantomData<T>);
188
189/// SQL type of an untyped placeholder, whose value is bound when the query runs.
190///
191/// A placeholder has no known type yet, so it is [`Compatible`] with every
192/// dialect marker in both directions and is [`Textual`]. This lets
193/// `eq(column, Placeholder::named("id"))` compile for any column.
194#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
195pub struct Placeholder;
196
197/// The SQL type of a condition list — a tuple of conditions combined with AND.
198///
199/// Boolean-like, so a condition list is accepted anywhere a condition is, but
200/// deliberately **not** [`Compatible`] with
201/// itself. A condition list occupies one expression slot rather than one column
202/// slot, and self-incompatibility is what lets APIs that accept either a single
203/// column or a tuple of columns (`IN (subquery)` row values) tell the two apart.
204#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
205pub struct Conjunction;
206
207impl<T: DataType> private::Sealed for Array<T> {}
208impl<T: DataType> DataType for Array<T> {}
209impl private::Sealed for Placeholder {}
210impl DataType for Placeholder {}
211impl Textual for Placeholder {}
212impl private::Sealed for Conjunction {}
213impl DataType for Conjunction {}
214impl BooleanLike for Conjunction {}
215
216// =============================================================================
217// SQLite dialect marker impls
218// =============================================================================
219
220impl private::Sealed for crate::sqlite::types::Integer {}
221impl private::Sealed for crate::sqlite::types::Text {}
222impl private::Sealed for crate::sqlite::types::Real {}
223impl private::Sealed for crate::sqlite::types::Blob {}
224impl private::Sealed for crate::sqlite::types::Numeric {}
225impl private::Sealed for crate::sqlite::types::Any {}
226
227impl DataType for crate::sqlite::types::Integer {}
228impl DataType for crate::sqlite::types::Text {}
229impl DataType for crate::sqlite::types::Real {}
230impl DataType for crate::sqlite::types::Blob {}
231impl DataType for crate::sqlite::types::Numeric {}
232impl DataType for crate::sqlite::types::Any {}
233
234impl Numeric for crate::sqlite::types::Integer {}
235impl Numeric for crate::sqlite::types::Real {}
236impl Numeric for crate::sqlite::types::Numeric {}
237impl Numeric for crate::sqlite::types::Any {}
238
239impl Integral for crate::sqlite::types::Integer {}
240
241impl Floating for crate::sqlite::types::Real {}
242
243impl Textual for crate::sqlite::types::Text {}
244impl Textual for crate::sqlite::types::Any {}
245
246impl Binary for crate::sqlite::types::Blob {}
247
248impl Temporal for crate::sqlite::types::Integer {}
249impl Temporal for crate::sqlite::types::Real {}
250impl Temporal for crate::sqlite::types::Text {}
251impl Temporal for crate::sqlite::types::Numeric {}
252
253impl BooleanLike for crate::sqlite::types::Integer {}
254
255// =============================================================================
256// PostgreSQL dialect marker impls
257// =============================================================================
258
259impl private::Sealed for crate::postgres::types::Int2 {}
260impl private::Sealed for crate::postgres::types::Int4 {}
261impl private::Sealed for crate::postgres::types::Int8 {}
262impl private::Sealed for crate::postgres::types::Float4 {}
263impl private::Sealed for crate::postgres::types::Float8 {}
264impl private::Sealed for crate::postgres::types::Varchar {}
265impl private::Sealed for crate::postgres::types::Text {}
266impl private::Sealed for crate::postgres::types::Char {}
267impl private::Sealed for crate::postgres::types::Bytea {}
268impl private::Sealed for crate::postgres::types::Boolean {}
269impl private::Sealed for crate::postgres::types::Timestamptz {}
270impl private::Sealed for crate::postgres::types::Timestamp {}
271impl private::Sealed for crate::postgres::types::Date {}
272impl private::Sealed for crate::postgres::types::Time {}
273impl private::Sealed for crate::postgres::types::Timetz {}
274impl private::Sealed for crate::postgres::types::Numeric {}
275impl private::Sealed for crate::postgres::types::Uuid {}
276impl private::Sealed for crate::postgres::types::Json {}
277impl private::Sealed for crate::postgres::types::Jsonb {}
278impl private::Sealed for crate::postgres::types::Any {}
279impl private::Sealed for crate::postgres::types::Interval {}
280impl private::Sealed for crate::postgres::types::Inet {}
281impl private::Sealed for crate::postgres::types::Cidr {}
282impl private::Sealed for crate::postgres::types::MacAddr {}
283impl private::Sealed for crate::postgres::types::MacAddr8 {}
284impl private::Sealed for crate::postgres::types::Point {}
285impl private::Sealed for crate::postgres::types::LineString {}
286impl private::Sealed for crate::postgres::types::Rect {}
287impl private::Sealed for crate::postgres::types::BitString {}
288impl private::Sealed for crate::postgres::types::Line {}
289impl private::Sealed for crate::postgres::types::LineSegment {}
290impl private::Sealed for crate::postgres::types::Polygon {}
291impl private::Sealed for crate::postgres::types::Circle {}
292impl private::Sealed for crate::postgres::types::Enum {}
293
294impl DataType for crate::postgres::types::Int2 {}
295impl DataType for crate::postgres::types::Int4 {}
296impl DataType for crate::postgres::types::Int8 {}
297impl DataType for crate::postgres::types::Float4 {}
298impl DataType for crate::postgres::types::Float8 {}
299impl DataType for crate::postgres::types::Varchar {}
300impl DataType for crate::postgres::types::Text {}
301impl DataType for crate::postgres::types::Char {}
302impl DataType for crate::postgres::types::Bytea {}
303impl DataType for crate::postgres::types::Boolean {}
304impl DataType for crate::postgres::types::Timestamptz {}
305impl DataType for crate::postgres::types::Timestamp {}
306impl DataType for crate::postgres::types::Date {}
307impl DataType for crate::postgres::types::Time {}
308impl DataType for crate::postgres::types::Timetz {}
309impl DataType for crate::postgres::types::Numeric {}
310impl DataType for crate::postgres::types::Uuid {}
311impl DataType for crate::postgres::types::Json {}
312impl DataType for crate::postgres::types::Jsonb {}
313impl DataType for crate::postgres::types::Any {}
314impl DataType for crate::postgres::types::Interval {}
315impl DataType for crate::postgres::types::Inet {}
316impl DataType for crate::postgres::types::Cidr {}
317impl DataType for crate::postgres::types::MacAddr {}
318impl DataType for crate::postgres::types::MacAddr8 {}
319impl DataType for crate::postgres::types::Point {}
320impl DataType for crate::postgres::types::LineString {}
321impl DataType for crate::postgres::types::Rect {}
322impl DataType for crate::postgres::types::BitString {}
323impl DataType for crate::postgres::types::Line {}
324impl DataType for crate::postgres::types::LineSegment {}
325impl DataType for crate::postgres::types::Polygon {}
326impl DataType for crate::postgres::types::Circle {}
327impl DataType for crate::postgres::types::Enum {}
328
329impl Numeric for crate::postgres::types::Int2 {}
330impl Numeric for crate::postgres::types::Int4 {}
331impl Numeric for crate::postgres::types::Int8 {}
332impl Numeric for crate::postgres::types::Float4 {}
333impl Numeric for crate::postgres::types::Float8 {}
334impl Numeric for crate::postgres::types::Numeric {}
335
336impl Integral for crate::postgres::types::Int2 {}
337impl Integral for crate::postgres::types::Int4 {}
338impl Integral for crate::postgres::types::Int8 {}
339
340impl Floating for crate::postgres::types::Float4 {}
341impl Floating for crate::postgres::types::Float8 {}
342
343impl Textual for crate::postgres::types::Varchar {}
344impl Textual for crate::postgres::types::Text {}
345impl Textual for crate::postgres::types::Char {}
346impl Textual for crate::postgres::types::Enum {}
347
348impl Binary for crate::postgres::types::Bytea {}
349
350impl Temporal for crate::postgres::types::Timestamptz {}
351impl Temporal for crate::postgres::types::Timestamp {}
352impl Temporal for crate::postgres::types::Date {}
353impl Temporal for crate::postgres::types::Time {}
354impl Temporal for crate::postgres::types::Timetz {}
355
356impl Temporal for crate::postgres::types::Interval {}
357
358impl BooleanLike for crate::postgres::types::Boolean {}
359
360// =============================================================================
361// MySQL dialect marker impls
362// =============================================================================
363
364macro_rules! impl_mysql_data_types {
365    ($($marker:ident),+ $(,)?) => {
366        $(
367            impl private::Sealed for crate::mysql::types::$marker {}
368            impl DataType for crate::mysql::types::$marker {}
369        )+
370    };
371}
372
373impl_mysql_data_types!(
374    TinyInt,
375    TinyIntUnsigned,
376    SmallInt,
377    SmallIntUnsigned,
378    MediumInt,
379    MediumIntUnsigned,
380    Int,
381    IntUnsigned,
382    BigInt,
383    BigIntUnsigned,
384    Float,
385    Double,
386    Decimal,
387    Boolean,
388    Char,
389    Varchar,
390    TinyText,
391    Text,
392    MediumText,
393    LongText,
394    Binary,
395    Varbinary,
396    TinyBlob,
397    Blob,
398    MediumBlob,
399    LongBlob,
400    Json,
401    Date,
402    Time,
403    DateTime,
404    Timestamp,
405    Year,
406    Enum,
407    Set,
408    Bit,
409    Any,
410);
411
412macro_rules! impl_mysql_marker_trait {
413    ($trait:ident; $($marker:ident),+ $(,)?) => {
414        $(impl $trait for crate::mysql::types::$marker {})+
415    };
416}
417
418impl_mysql_marker_trait!(Numeric;
419    TinyInt,
420    TinyIntUnsigned,
421    SmallInt,
422    SmallIntUnsigned,
423    MediumInt,
424    MediumIntUnsigned,
425    Int,
426    IntUnsigned,
427    BigInt,
428    BigIntUnsigned,
429    Year,
430    Float,
431    Double,
432    Decimal,
433);
434
435impl_mysql_marker_trait!(Integral;
436    TinyInt,
437    TinyIntUnsigned,
438    SmallInt,
439    SmallIntUnsigned,
440    MediumInt,
441    MediumIntUnsigned,
442    Int,
443    IntUnsigned,
444    BigInt,
445    BigIntUnsigned,
446    Year,
447);
448
449impl Floating for crate::mysql::types::Float {}
450impl Floating for crate::mysql::types::Double {}
451
452impl_mysql_marker_trait!(Textual;
453    Char, Varchar, TinyText, Text, MediumText, LongText, Enum, Set,
454);
455
456impl_mysql_marker_trait!(Binary; Binary, Varbinary, TinyBlob, Blob, MediumBlob, LongBlob, Bit,);
457
458impl Temporal for crate::mysql::types::Date {}
459impl Temporal for crate::mysql::types::Time {}
460impl Temporal for crate::mysql::types::DateTime {}
461impl Temporal for crate::mysql::types::Timestamp {}
462
463impl BooleanLike for crate::mysql::types::Boolean {}
464
465// =============================================================================
466// Tuple SQL type markers
467// =============================================================================
468
469macro_rules! seq_tuples {
470    (@acc $callback:ident [$($aT:ident),*] [$($ai:tt),*]) => {};
471    (@acc $callback:ident [$($aT:ident),*] [$($ai:tt),*] ($T:ident, $i:tt) $($rest:tt)*) => {
472        $callback!($($aT,)* $T; $($ai,)* $i);
473        seq_tuples!(@acc $callback [$($aT,)* $T] [$($ai,)* $i] $($rest)*);
474    };
475    ($callback:ident; $($pairs:tt)+) => {
476        seq_tuples!(@acc $callback [] [] $($pairs)+);
477    };
478    (@from $callback:ident [$($aT:ident),*] [$($ai:tt),*]; $($pairs:tt)+) => {
479        seq_tuples!(@acc $callback [$($aT),*] [$($ai),*] $($pairs)+);
480    };
481}
482
483macro_rules! with_col_sizes_8 {
484    ($callback:ident) => {
485        seq_tuples!($callback;
486            (T0,0) (T1,1) (T2,2) (T3,3)
487            (T4,4) (T5,5) (T6,6) (T7,7)
488        );
489    };
490}
491
492#[allow(unused_macros)]
493macro_rules! with_col_sizes_16 {
494    ($callback:ident) => {
495        seq_tuples!(@from $callback
496            [T0,T1,T2,T3,T4,T5,T6,T7]
497            [0,1,2,3,4,5,6,7];
498            (T8,8) (T9,9) (T10,10) (T11,11)
499            (T12,12) (T13,13) (T14,14) (T15,15)
500        );
501    };
502}
503
504#[allow(unused_macros)]
505macro_rules! with_col_sizes_32 {
506    ($callback:ident) => {
507        seq_tuples!(@from $callback
508            [T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15]
509            [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
510            (T16,16) (T17,17) (T18,18) (T19,19)
511            (T20,20) (T21,21) (T22,22) (T23,23)
512            (T24,24) (T25,25) (T26,26) (T27,27)
513            (T28,28) (T29,29) (T30,30) (T31,31)
514        );
515    };
516}
517
518#[allow(unused_macros)]
519macro_rules! with_col_sizes_64 {
520    ($callback:ident) => {
521        seq_tuples!(@from $callback
522            [T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,
523             T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31]
524            [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
525             16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31];
526            (T32,32) (T33,33) (T34,34) (T35,35)
527            (T36,36) (T37,37) (T38,38) (T39,39)
528            (T40,40) (T41,41) (T42,42) (T43,43)
529            (T44,44) (T45,45) (T46,46) (T47,47)
530            (T48,48) (T49,49) (T50,50) (T51,51)
531            (T52,52) (T53,53) (T54,54) (T55,55)
532            (T56,56) (T57,57) (T58,58) (T59,59)
533            (T60,60) (T61,61) (T62,62) (T63,63)
534        );
535    };
536}
537
538#[allow(unused_macros)]
539macro_rules! with_col_sizes_128 {
540    ($callback:ident) => {
541        seq_tuples!(@from $callback
542            [T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,
543             T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,
544             T32,T33,T34,T35,T36,T37,T38,T39,T40,T41,T42,T43,T44,T45,T46,T47,
545             T48,T49,T50,T51,T52,T53,T54,T55,T56,T57,T58,T59,T60,T61,T62,T63]
546            [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
547             16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
548             32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
549             48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63];
550            (T64,64) (T65,65) (T66,66) (T67,67)
551            (T68,68) (T69,69) (T70,70) (T71,71)
552            (T72,72) (T73,73) (T74,74) (T75,75)
553            (T76,76) (T77,77) (T78,78) (T79,79)
554            (T80,80) (T81,81) (T82,82) (T83,83)
555            (T84,84) (T85,85) (T86,86) (T87,87)
556            (T88,88) (T89,89) (T90,90) (T91,91)
557            (T92,92) (T93,93) (T94,94) (T95,95)
558            (T96,96) (T97,97) (T98,98) (T99,99)
559            (T100,100) (T101,101) (T102,102) (T103,103)
560            (T104,104) (T105,105) (T106,106) (T107,107)
561            (T108,108) (T109,109) (T110,110) (T111,111)
562            (T112,112) (T113,113) (T114,114) (T115,115)
563            (T116,116) (T117,117) (T118,118) (T119,119)
564            (T120,120) (T121,121) (T122,122) (T123,123)
565            (T124,124) (T125,125) (T126,126) (T127,127)
566        );
567    };
568}
569
570#[allow(unused_macros)]
571macro_rules! with_col_sizes_200 {
572    ($callback:ident) => {
573        seq_tuples!(@from $callback
574            [T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,
575             T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,
576             T32,T33,T34,T35,T36,T37,T38,T39,T40,T41,T42,T43,T44,T45,T46,T47,
577             T48,T49,T50,T51,T52,T53,T54,T55,T56,T57,T58,T59,T60,T61,T62,T63,
578             T64,T65,T66,T67,T68,T69,T70,T71,T72,T73,T74,T75,T76,T77,T78,T79,
579             T80,T81,T82,T83,T84,T85,T86,T87,T88,T89,T90,T91,T92,T93,T94,T95,
580             T96,T97,T98,T99,T100,T101,T102,T103,T104,T105,T106,T107,T108,T109,T110,T111,
581             T112,T113,T114,T115,T116,T117,T118,T119,T120,T121,T122,T123,T124,T125,T126,T127]
582            [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
583             16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
584             32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
585             48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
586             64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
587             80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,
588             96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,
589             112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127];
590            (T128,128) (T129,129) (T130,130) (T131,131)
591            (T132,132) (T133,133) (T134,134) (T135,135)
592            (T136,136) (T137,137) (T138,138) (T139,139)
593            (T140,140) (T141,141) (T142,142) (T143,143)
594            (T144,144) (T145,145) (T146,146) (T147,147)
595            (T148,148) (T149,149) (T150,150) (T151,151)
596            (T152,152) (T153,153) (T154,154) (T155,155)
597            (T156,156) (T157,157) (T158,158) (T159,159)
598            (T160,160) (T161,161) (T162,162) (T163,163)
599            (T164,164) (T165,165) (T166,166) (T167,167)
600            (T168,168) (T169,169) (T170,170) (T171,171)
601            (T172,172) (T173,173) (T174,174) (T175,175)
602            (T176,176) (T177,177) (T178,178) (T179,179)
603            (T180,180) (T181,181) (T182,182) (T183,183)
604            (T184,184) (T185,185) (T186,186) (T187,187)
605            (T188,188) (T189,189) (T190,190) (T191,191)
606            (T192,192) (T193,193) (T194,194) (T195,195)
607            (T196,196) (T197,197) (T198,198) (T199,199)
608        );
609    };
610}
611
612macro_rules! impl_tuple_datatype {
613    ($($T:ident),+; $($idx:tt),+) => {
614        impl<$($T: DataType),+> private::Sealed for ($($T,)+) {}
615        impl<$($T: DataType),+> DataType for ($($T,)+) {}
616    };
617}
618
619with_col_sizes_8!(impl_tuple_datatype);
620
621#[cfg(any(
622    feature = "col16",
623    feature = "col32",
624    feature = "col64",
625    feature = "col128",
626    feature = "col200"
627))]
628with_col_sizes_16!(impl_tuple_datatype);
629
630#[cfg(any(
631    feature = "col32",
632    feature = "col64",
633    feature = "col128",
634    feature = "col200"
635))]
636with_col_sizes_32!(impl_tuple_datatype);
637
638#[cfg(any(feature = "col64", feature = "col128", feature = "col200"))]
639with_col_sizes_64!(impl_tuple_datatype);
640
641#[cfg(any(feature = "col128", feature = "col200"))]
642with_col_sizes_128!(impl_tuple_datatype);
643
644#[cfg(feature = "col200")]
645with_col_sizes_200!(impl_tuple_datatype);
646
647#[cfg(test)]
648mod tests {
649    use super::*;
650
651    fn assert_data_type<T: DataType>() {}
652    fn assert_integral<T: Integral>() {}
653    fn assert_floating<T: Floating>() {}
654    fn assert_textual<T: Textual>() {}
655    fn assert_binary<T: Binary>() {}
656    fn assert_temporal<T: Temporal>() {}
657    fn assert_boolean_like<T: BooleanLike>() {}
658
659    #[test]
660    fn mysql_markers_have_their_expected_type_capabilities() {
661        assert_data_type::<crate::mysql::types::Any>();
662        assert_integral::<crate::mysql::types::IntUnsigned>();
663        assert_integral::<crate::mysql::types::Year>();
664        assert_floating::<crate::mysql::types::Float>();
665        assert_floating::<crate::mysql::types::Double>();
666        assert_textual::<crate::mysql::types::Enum>();
667        assert_textual::<crate::mysql::types::Set>();
668        assert_binary::<crate::mysql::types::Varbinary>();
669        assert_binary::<crate::mysql::types::Bit>();
670        assert_temporal::<crate::mysql::types::DateTime>();
671        assert_boolean_like::<crate::mysql::types::Boolean>();
672    }
673}