1use schemars::JsonSchema;
2use serde::{Deserialize, Serialize};
3
4use crate::schema::{foreign_key::ForeignKeyDef, names::ColumnName, str_or_bool::StrOrBoolOrArray};
5
6#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
7#[serde(rename_all = "snake_case")]
8pub struct ColumnDef {
9 pub name: ColumnName,
10 pub r#type: ColumnType,
11 pub nullable: bool,
12 pub default: Option<String>,
13 pub comment: Option<String>,
14 pub primary_key: Option<bool>,
15 pub unique: Option<StrOrBoolOrArray>,
16 pub index: Option<StrOrBoolOrArray>,
17 pub foreign_key: Option<ForeignKeyDef>,
18}
19
20#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
21#[serde(rename_all = "snake_case", untagged)]
22pub enum ColumnType {
23 Simple(SimpleColumnType),
24 Complex(ComplexColumnType),
25}
26
27impl ColumnType {
28 pub fn to_sql(&self) -> String {
30 match self {
31 ColumnType::Simple(ty) => match ty {
32 SimpleColumnType::SmallInt => "SMALLINT".into(),
33 SimpleColumnType::Integer => "INTEGER".into(),
34 SimpleColumnType::BigInt => "BIGINT".into(),
35 SimpleColumnType::Real => "REAL".into(),
36 SimpleColumnType::DoublePrecision => "DOUBLE PRECISION".into(),
37 SimpleColumnType::Text => "TEXT".into(),
38 SimpleColumnType::Boolean => "BOOLEAN".into(),
39 SimpleColumnType::Date => "DATE".into(),
40 SimpleColumnType::Time => "TIME".into(),
41 SimpleColumnType::Timestamp => "TIMESTAMP".into(),
42 SimpleColumnType::Timestamptz => "TIMESTAMPTZ".into(),
43 SimpleColumnType::Bytea => "BYTEA".into(),
44 SimpleColumnType::Uuid => "UUID".into(),
45 SimpleColumnType::Json => "JSON".into(),
46 SimpleColumnType::Jsonb => "JSONB".into(),
47 SimpleColumnType::Inet => "INET".into(),
48 SimpleColumnType::Cidr => "CIDR".into(),
49 SimpleColumnType::Macaddr => "MACADDR".into(),
50 },
51 ColumnType::Complex(ty) => match ty {
52 ComplexColumnType::Varchar { length } => format!("VARCHAR({})", length),
53 ComplexColumnType::Custom { custom_type } => custom_type.clone(),
54 },
55 }
56 }
57
58 pub fn to_rust_type(&self, nullable: bool) -> String {
60 let base = match self {
61 ColumnType::Simple(ty) => match ty {
62 SimpleColumnType::SmallInt => "i16".to_string(),
63 SimpleColumnType::Integer => "i32".to_string(),
64 SimpleColumnType::BigInt => "i64".to_string(),
65 SimpleColumnType::Real => "f32".to_string(),
66 SimpleColumnType::DoublePrecision => "f64".to_string(),
67 SimpleColumnType::Text => "String".to_string(),
68 SimpleColumnType::Boolean => "bool".to_string(),
69 SimpleColumnType::Date => "Date".to_string(),
70 SimpleColumnType::Time => "Time".to_string(),
71 SimpleColumnType::Timestamp => "DateTime".to_string(),
72 SimpleColumnType::Timestamptz => "DateTimeWithTimeZone".to_string(),
73 SimpleColumnType::Bytea => "Vec<u8>".to_string(),
74 SimpleColumnType::Uuid => "Uuid".to_string(),
75 SimpleColumnType::Json | SimpleColumnType::Jsonb => "Json".to_string(),
76 SimpleColumnType::Inet | SimpleColumnType::Cidr => "String".to_string(),
77 SimpleColumnType::Macaddr => "String".to_string(),
78 },
79 ColumnType::Complex(ty) => match ty {
80 ComplexColumnType::Varchar { .. } => "String".to_string(),
81 ComplexColumnType::Custom { .. } => "String".to_string(), },
83 };
84
85 if nullable {
86 format!("Option<{}>", base)
87 } else {
88 base
89 }
90 }
91}
92
93#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
94#[serde(rename_all = "snake_case")]
95pub enum SimpleColumnType {
96 SmallInt,
97 Integer,
98 BigInt,
99 Real,
100 DoublePrecision,
101
102 Text,
104
105 Boolean,
107
108 Date,
110 Time,
111 Timestamp,
112 Timestamptz,
113
114 Bytea,
116
117 Uuid,
119
120 Json,
122 Jsonb,
123
124 Inet,
126 Cidr,
127 Macaddr,
128}
129
130#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
131#[serde(rename_all = "snake_case", tag = "kind")]
132pub enum ComplexColumnType {
133 Varchar { length: u32 },
134 Custom { custom_type: String },
135}
136
137impl From<SimpleColumnType> for ColumnType {
138 fn from(ty: SimpleColumnType) -> Self {
139 ColumnType::Simple(ty)
140 }
141}
142
143impl From<ComplexColumnType> for ColumnType {
144 fn from(ty: ComplexColumnType) -> Self {
145 ColumnType::Complex(ty)
146 }
147}