1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
7pub enum FieldType {
8 BigInteger,
11 Integer,
13 SmallInteger,
15 TinyInt, MediumInt, Char(u32),
23 VarChar(u32),
25 Text,
27 TinyText, MediumText, LongText, Date,
37 Time,
39 DateTime,
41 TimestampTz, Decimal {
47 precision: u32,
49 scale: u32,
51 },
52 Float,
54 Double,
56 Real,
58
59 Boolean,
62
63 Binary,
66 Blob, TinyBlob, MediumBlob, LongBlob, Bytea, Json,
80 JsonBinary, Array(Box<FieldType>),
86 HStore,
88 CIText,
90 Int4Range,
92 Int8Range,
94 NumRange,
96 DateRange,
98 TsRange,
100 TsTzRange,
102 TsVector,
104 TsQuery,
106
107 Uuid,
110 Year, Enum {
116 values: Vec<String>,
118 },
119 Set {
121 values: Vec<String>,
123 },
124
125 ForeignKey {
128 to_table: String,
130 to_field: String,
132 on_delete: super::ForeignKeyAction,
134 },
135
136 OneToOne {
138 to: String, on_delete: super::ForeignKeyAction,
142 on_update: super::ForeignKeyAction,
144 },
145
146 ManyToMany {
148 to: String, through: Option<String>, },
153
154 Custom(String),
157}
158
159impl FieldType {
160 pub fn to_sql_for_dialect(&self, dialect: &super::operations::SqlDialect) -> String {
165 use super::operations::SqlDialect;
166
167 match self {
168 FieldType::DateTime => match dialect {
169 SqlDialect::Postgres | SqlDialect::Cockroachdb => "TIMESTAMP".to_string(),
170 SqlDialect::Mysql | SqlDialect::Sqlite => "DATETIME".to_string(),
171 },
172 FieldType::TimestampTz => match dialect {
173 SqlDialect::Postgres | SqlDialect::Cockroachdb => "TIMESTAMPTZ".to_string(),
174 SqlDialect::Mysql => "DATETIME".to_string(), SqlDialect::Sqlite => "DATETIME".to_string(), },
177 FieldType::Boolean => match dialect {
183 SqlDialect::Postgres | SqlDialect::Cockroachdb => "BOOLEAN".to_string(),
184 SqlDialect::Mysql => "TINYINT(1)".to_string(), SqlDialect::Sqlite => "BOOLEAN".to_string(), },
187 FieldType::Uuid => match dialect {
188 SqlDialect::Postgres | SqlDialect::Cockroachdb => "UUID".to_string(),
189 SqlDialect::Mysql => "CHAR(36)".to_string(), SqlDialect::Sqlite => "TEXT".to_string(), },
192 FieldType::JsonBinary => match dialect {
193 SqlDialect::Postgres | SqlDialect::Cockroachdb => "JSONB".to_string(),
194 SqlDialect::Mysql | SqlDialect::Sqlite => "JSON".to_string(), },
196 FieldType::Array(inner) => match dialect {
198 SqlDialect::Postgres | SqlDialect::Cockroachdb => {
199 format!("{}[]", inner.to_sql_for_dialect(dialect))
200 }
201 SqlDialect::Mysql | SqlDialect::Sqlite => "JSON".to_string(),
203 },
204 FieldType::HStore => match dialect {
205 SqlDialect::Postgres | SqlDialect::Cockroachdb => "HSTORE".to_string(),
206 SqlDialect::Mysql | SqlDialect::Sqlite => "JSON".to_string(),
208 },
209 FieldType::CIText => match dialect {
210 SqlDialect::Postgres | SqlDialect::Cockroachdb => "CITEXT".to_string(),
211 SqlDialect::Mysql | SqlDialect::Sqlite => "TEXT".to_string(),
213 },
214 FieldType::Int4Range => match dialect {
215 SqlDialect::Postgres | SqlDialect::Cockroachdb => "INT4RANGE".to_string(),
216 SqlDialect::Mysql | SqlDialect::Sqlite => "VARCHAR(50)".to_string(),
218 },
219 FieldType::Int8Range => match dialect {
220 SqlDialect::Postgres | SqlDialect::Cockroachdb => "INT8RANGE".to_string(),
221 SqlDialect::Mysql | SqlDialect::Sqlite => "VARCHAR(50)".to_string(),
222 },
223 FieldType::NumRange => match dialect {
224 SqlDialect::Postgres | SqlDialect::Cockroachdb => "NUMRANGE".to_string(),
225 SqlDialect::Mysql | SqlDialect::Sqlite => "VARCHAR(100)".to_string(),
226 },
227 FieldType::DateRange => match dialect {
228 SqlDialect::Postgres | SqlDialect::Cockroachdb => "DATERANGE".to_string(),
229 SqlDialect::Mysql | SqlDialect::Sqlite => "VARCHAR(50)".to_string(),
230 },
231 FieldType::TsRange => match dialect {
232 SqlDialect::Postgres | SqlDialect::Cockroachdb => "TSRANGE".to_string(),
233 SqlDialect::Mysql | SqlDialect::Sqlite => "VARCHAR(100)".to_string(),
234 },
235 FieldType::TsTzRange => match dialect {
236 SqlDialect::Postgres | SqlDialect::Cockroachdb => "TSTZRANGE".to_string(),
237 SqlDialect::Mysql | SqlDialect::Sqlite => "VARCHAR(100)".to_string(),
238 },
239 FieldType::TsVector => match dialect {
240 SqlDialect::Postgres | SqlDialect::Cockroachdb => "TSVECTOR".to_string(),
241 SqlDialect::Mysql | SqlDialect::Sqlite => "TEXT".to_string(),
243 },
244 FieldType::TsQuery => match dialect {
245 SqlDialect::Postgres | SqlDialect::Cockroachdb => "TSQUERY".to_string(),
246 SqlDialect::Mysql | SqlDialect::Sqlite => "TEXT".to_string(),
247 },
248 FieldType::BigInteger => match dialect {
251 SqlDialect::Sqlite => "INTEGER".to_string(),
252 _ => self.to_sql_string(),
253 },
254 FieldType::Float => match dialect {
255 SqlDialect::Postgres | SqlDialect::Cockroachdb => "REAL".to_string(),
256 _ => self.to_sql_string(),
257 },
258 FieldType::Double => match dialect {
259 SqlDialect::Postgres | SqlDialect::Cockroachdb => "DOUBLE PRECISION".to_string(),
260 _ => self.to_sql_string(),
261 },
262 _ => self.to_sql_string(),
264 }
265 }
266
267 pub fn to_sql_string(&self) -> String {
272 match self {
273 FieldType::BigInteger => "BIGINT".to_string(),
274 FieldType::Integer => "INTEGER".to_string(),
275 FieldType::SmallInteger => "SMALLINT".to_string(),
276 FieldType::TinyInt => "TINYINT".to_string(),
277 FieldType::MediumInt => "MEDIUMINT".to_string(),
278 FieldType::Char(max_length) => format!("CHAR({})", max_length),
279 FieldType::VarChar(max_length) => format!("VARCHAR({})", max_length),
280 FieldType::Text => "TEXT".to_string(),
281 FieldType::TinyText => "TINYTEXT".to_string(),
282 FieldType::MediumText => "MEDIUMTEXT".to_string(),
283 FieldType::LongText => "LONGTEXT".to_string(),
284 FieldType::Date => "DATE".to_string(),
285 FieldType::Time => "TIME".to_string(),
286 FieldType::DateTime => "DATETIME".to_string(),
287 FieldType::TimestampTz => "TIMESTAMPTZ".to_string(),
288 FieldType::Decimal { precision, scale } => format!("DECIMAL({}, {})", precision, scale),
289 FieldType::Float => "FLOAT".to_string(),
290 FieldType::Double => "DOUBLE".to_string(),
291 FieldType::Real => "REAL".to_string(),
292 FieldType::Boolean => "BOOLEAN".to_string(),
293 FieldType::Binary => "BINARY".to_string(),
294 FieldType::Blob => "BLOB".to_string(),
295 FieldType::TinyBlob => "TINYBLOB".to_string(),
296 FieldType::MediumBlob => "MEDIUMBLOB".to_string(),
297 FieldType::LongBlob => "LONGBLOB".to_string(),
298 FieldType::Bytea => "BYTEA".to_string(),
299 FieldType::Json => "JSON".to_string(),
300 FieldType::JsonBinary => "JSONB".to_string(),
301 FieldType::Array(inner) => format!("{}[]", inner.to_sql_string()),
303 FieldType::HStore => "HSTORE".to_string(),
304 FieldType::CIText => "CITEXT".to_string(),
305 FieldType::Int4Range => "INT4RANGE".to_string(),
306 FieldType::Int8Range => "INT8RANGE".to_string(),
307 FieldType::NumRange => "NUMRANGE".to_string(),
308 FieldType::DateRange => "DATERANGE".to_string(),
309 FieldType::TsRange => "TSRANGE".to_string(),
310 FieldType::TsTzRange => "TSTZRANGE".to_string(),
311 FieldType::TsVector => "TSVECTOR".to_string(),
312 FieldType::TsQuery => "TSQUERY".to_string(),
313 FieldType::Uuid => "UUID".to_string(),
314 FieldType::Year => "YEAR".to_string(),
315 FieldType::Enum { values } => {
316 let values_str = values
317 .iter()
318 .map(|v| format!("'{}'", v))
319 .collect::<Vec<_>>()
320 .join(",");
321 format!("ENUM({})", values_str)
322 }
323 FieldType::Set { values } => {
324 let values_str = values
325 .iter()
326 .map(|v| format!("'{}'", v))
327 .collect::<Vec<_>>()
328 .join(",");
329 format!("SET({})", values_str)
330 }
331 FieldType::ForeignKey { to_table, .. } => {
332 format!("-- ForeignKey to {}", to_table)
333 }
334 FieldType::OneToOne { to, .. } => {
335 format!("-- OneToOne relationship to {}", to)
336 }
337 FieldType::ManyToMany { to, through } => match through {
338 Some(table) => format!("-- ManyToMany through {}", table),
339 None => format!("-- ManyToMany to {} (auto-generated)", to),
340 },
341 FieldType::Custom(custom_type) => custom_type.clone(),
342 }
343 }
344
345 pub fn max_length(&self) -> Option<u32> {
347 match self {
348 FieldType::Char(max_length) | FieldType::VarChar(max_length) => Some(*max_length),
349 _ => None,
350 }
351 }
352}
353
354pub trait FieldTypeName {
356 const NAME: &'static str;
358}
359
360pub struct BigIntegerField;
363impl FieldTypeName for BigIntegerField {
364 const NAME: &'static str = "BigIntegerField";
365}
366
367pub struct IntegerField;
369impl FieldTypeName for IntegerField {
370 const NAME: &'static str = "IntegerField";
371}
372
373pub struct SmallIntegerField;
375impl FieldTypeName for SmallIntegerField {
376 const NAME: &'static str = "SmallIntegerField";
377}
378
379pub struct CharField;
381impl FieldTypeName for CharField {
382 const NAME: &'static str = "CharField";
383}
384
385pub struct TextField;
387impl FieldTypeName for TextField {
388 const NAME: &'static str = "TextField";
389}
390
391pub struct DateTimeField;
393impl FieldTypeName for DateTimeField {
394 const NAME: &'static str = "DateTimeField";
395}
396
397pub struct DateField;
399impl FieldTypeName for DateField {
400 const NAME: &'static str = "DateField";
401}
402
403pub struct TimeField;
405impl FieldTypeName for TimeField {
406 const NAME: &'static str = "TimeField";
407}
408
409pub struct BooleanField;
411impl FieldTypeName for BooleanField {
412 const NAME: &'static str = "BooleanField";
413}
414
415pub struct DecimalField;
417impl FieldTypeName for DecimalField {
418 const NAME: &'static str = "DecimalField";
419}
420
421pub struct BinaryField;
423impl FieldTypeName for BinaryField {
424 const NAME: &'static str = "BinaryField";
425}
426
427pub struct JSONField;
429impl FieldTypeName for JSONField {
430 const NAME: &'static str = "JSONField";
431}
432
433pub struct UUIDField;
435impl FieldTypeName for UUIDField {
436 const NAME: &'static str = "UUIDField";
437}
438
439pub struct ArrayField;
442impl FieldTypeName for ArrayField {
443 const NAME: &'static str = "ArrayField";
444}
445
446pub struct HStoreField;
448impl FieldTypeName for HStoreField {
449 const NAME: &'static str = "HStoreField";
450}
451
452pub struct CITextField;
454impl FieldTypeName for CITextField {
455 const NAME: &'static str = "CITextField";
456}
457
458pub struct Int4RangeField;
460impl FieldTypeName for Int4RangeField {
461 const NAME: &'static str = "Int4RangeField";
462}
463
464pub struct Int8RangeField;
466impl FieldTypeName for Int8RangeField {
467 const NAME: &'static str = "Int8RangeField";
468}
469
470pub struct NumRangeField;
472impl FieldTypeName for NumRangeField {
473 const NAME: &'static str = "NumRangeField";
474}
475
476pub struct DateRangeField;
478impl FieldTypeName for DateRangeField {
479 const NAME: &'static str = "DateRangeField";
480}
481
482pub struct TsRangeField;
484impl FieldTypeName for TsRangeField {
485 const NAME: &'static str = "TsRangeField";
486}
487
488pub struct TsTzRangeField;
490impl FieldTypeName for TsTzRangeField {
491 const NAME: &'static str = "TsTzRangeField";
492}
493
494pub struct TsVectorField;
496impl FieldTypeName for TsVectorField {
497 const NAME: &'static str = "TsVectorField";
498}
499
500pub struct TsQueryField;
502impl FieldTypeName for TsQueryField {
503 const NAME: &'static str = "TsQueryField";
504}
505
506pub mod prelude {
508 pub use super::{
509 ArrayField,
511 BigIntegerField,
513 BinaryField,
514 BooleanField,
515 CITextField,
516 CharField,
517 DateField,
518 DateRangeField,
519 DateTimeField,
520 DecimalField,
521 FieldTypeName,
522 HStoreField,
523 Int4RangeField,
524 Int8RangeField,
525 IntegerField,
526 JSONField,
527 NumRangeField,
528 SmallIntegerField,
529 TextField,
530 TimeField,
531 TsQueryField,
532 TsRangeField,
533 TsTzRangeField,
534 TsVectorField,
535 UUIDField,
536 };
537}
538
539impl std::fmt::Display for FieldType {
541 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
542 write!(f, "{}", self.to_sql_string())
543 }
544}