1use serde::{Deserialize, Serialize};
4
5use crate::dialect::Dialect;
6
7#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
8pub enum ColumnType {
9 Text,
11 Integer,
12 Real,
13 Blob,
14 Uuid,
16 Boolean,
17 Timestamp,
18 Date,
19 Time,
20 Json,
21 BigInt,
22 SmallInt,
23 Varchar(u32),
24 Serial,
26 BigSerial,
27 Jsonb,
28 Numeric,
29 Char(u32),
30 Array(Box<ColumnType>),
31}
32
33impl ColumnType {
34 pub fn as_sql(&self) -> String {
36 match self {
37 Self::Text | Self::Jsonb | Self::Char(_) | Self::Array(_) => "TEXT".to_owned(),
38 Self::Integer | Self::Serial | Self::BigSerial => "INTEGER".to_owned(),
39 Self::Real | Self::Numeric => "REAL".to_owned(),
40 Self::Blob => "BLOB".to_owned(),
41 Self::Uuid => "uuid".to_owned(),
42 Self::Boolean => "boolean".to_owned(),
43 Self::Timestamp => "timestamp".to_owned(),
44 Self::Date => "date".to_owned(),
45 Self::Time => "time".to_owned(),
46 Self::Json => "json".to_owned(),
47 Self::BigInt => "bigint".to_owned(),
48 Self::SmallInt => "smallint".to_owned(),
49 Self::Varchar(n) => format!("varchar({n})"),
50 }
51 }
52
53 pub fn as_compat_sql(&self) -> String {
55 match self {
56 Self::Text
57 | Self::Uuid
58 | Self::Date
59 | Self::Time
60 | Self::Json
61 | Self::Jsonb
62 | Self::Varchar(_)
63 | Self::Char(_)
64 | Self::Array(_) => "TEXT".to_owned(),
65 Self::Integer
66 | Self::BigInt
67 | Self::SmallInt
68 | Self::Timestamp
69 | Self::Boolean
70 | Self::Serial
71 | Self::BigSerial => "INTEGER".to_owned(),
72 Self::Real | Self::Numeric => "REAL".to_owned(),
73 Self::Blob => "BLOB".to_owned(),
74 }
75 }
76
77 pub fn as_ddl_sql(&self, dialect: Dialect) -> String {
83 match dialect {
84 Dialect::Sqlite => match self {
85 Self::Text
86 | Self::Uuid
87 | Self::Date
88 | Self::Time
89 | Self::Json
90 | Self::Jsonb
91 | Self::Varchar(_)
92 | Self::Char(_)
93 | Self::Array(_) => "TEXT".to_owned(),
94 Self::Integer
95 | Self::Boolean
96 | Self::Timestamp
97 | Self::BigInt
98 | Self::SmallInt
99 | Self::Serial
100 | Self::BigSerial => "INTEGER".to_owned(),
101 Self::Real | Self::Numeric => "REAL".to_owned(),
102 Self::Blob => "BLOB".to_owned(),
103 },
104 Dialect::Postgres => match self {
105 Self::Text => "TEXT".to_owned(),
106 Self::Integer => "INTEGER".to_owned(),
107 Self::Real => "DOUBLE PRECISION".to_owned(),
108 Self::Blob => "BYTEA".to_owned(),
109 Self::Uuid => "UUID".to_owned(),
110 Self::Boolean => "BOOLEAN".to_owned(),
111 Self::Timestamp => "TIMESTAMPTZ".to_owned(),
112 Self::Date => "DATE".to_owned(),
113 Self::Time => "TIME".to_owned(),
114 Self::Json => "JSON".to_owned(),
115 Self::Jsonb => "JSONB".to_owned(),
116 Self::BigInt => "BIGINT".to_owned(),
117 Self::SmallInt => "SMALLINT".to_owned(),
118 Self::Serial => "SERIAL".to_owned(),
119 Self::BigSerial => "BIGSERIAL".to_owned(),
120 Self::Numeric => "NUMERIC".to_owned(),
121 Self::Varchar(n) => format!("VARCHAR({n})"),
122 Self::Char(n) => format!("CHAR({n})"),
123 Self::Array(inner) => format!("{}[]", inner.as_ddl_sql(Dialect::Postgres)),
124 },
125 }
126 }
127}
128
129#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
130pub enum ForeignKeyAction {
131 Cascade,
132 SetNull,
133 SetDefault,
134 Restrict,
135 NoAction,
136}
137
138impl ForeignKeyAction {
139 pub fn as_sql(self) -> &'static str {
140 match self {
141 Self::Cascade => "CASCADE",
142 Self::SetNull => "SET NULL",
143 Self::SetDefault => "SET DEFAULT",
144 Self::Restrict => "RESTRICT",
145 Self::NoAction => "NO ACTION",
146 }
147 }
148}
149
150pub trait EnumSchema {
152 fn variants() -> &'static [&'static str];
153}
154
155#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
156pub struct ColumnDef {
157 pub name: String,
158 pub column_type: ColumnType,
159 pub primary_key: bool,
160 pub not_null: bool,
161 #[serde(default, skip_serializing_if = "Option::is_none")]
162 pub default: Option<String>,
163 pub unique: bool,
164 #[serde(default, skip_serializing_if = "Option::is_none")]
165 pub references: Option<String>,
166 #[serde(default, skip_serializing_if = "Option::is_none")]
167 pub on_delete: Option<ForeignKeyAction>,
168 #[serde(default, skip_serializing_if = "Option::is_none")]
169 pub on_update: Option<ForeignKeyAction>,
170 #[serde(default, skip_serializing_if = "Option::is_none")]
171 pub check: Option<String>,
172}
173
174pub struct Text;
176pub struct Integer;
177pub struct Real;
178pub struct Blob;
179pub struct Uuid;
180pub struct Boolean;
181pub struct Timestamp;
182pub struct Date;
183pub struct Time;
184pub struct Json;
185pub struct BigInt;
186pub struct SmallInt;
187pub struct Varchar<const N: u32>;
188pub struct Serial;
189pub struct BigSerial;
190pub struct Jsonb;
191pub struct Numeric;
192pub struct Char<const N: u32>;