remodel_core/sql/
dialect.rs1use serde::{Deserialize, Serialize};
4
5use crate::models::logical::ReferentialAction;
6use crate::models::types::DataType;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
10pub enum SqlDialect {
11 Postgres,
13 MySql,
15 Sqlite,
17}
18
19impl SqlDialect {
20 pub fn renderer(self) -> Box<dyn Dialect> {
22 match self {
23 SqlDialect::Postgres => Box::new(Postgres),
24 SqlDialect::MySql => Box::new(MySql),
25 SqlDialect::Sqlite => Box::new(Sqlite),
26 }
27 }
28}
29
30pub trait Dialect {
32 fn render_type(&self, ty: &DataType) -> String;
34
35 fn quote_ident(&self, ident: &str) -> String;
37
38 fn render_action(&self, action: ReferentialAction) -> &'static str {
40 match action {
41 ReferentialAction::NoAction => "NO ACTION",
42 ReferentialAction::Restrict => "RESTRICT",
43 ReferentialAction::Cascade => "CASCADE",
44 ReferentialAction::SetNull => "SET NULL",
45 ReferentialAction::SetDefault => "SET DEFAULT",
46 }
47 }
48
49 fn terminator(&self) -> &'static str {
51 ";"
52 }
53}
54
55pub struct Postgres;
57impl Dialect for Postgres {
58 fn render_type(&self, ty: &DataType) -> String {
59 match ty {
60 DataType::Integer => "INTEGER".into(),
61 DataType::BigInt => "BIGINT".into(),
62 DataType::SmallInt => "SMALLINT".into(),
63 DataType::Real => "DOUBLE PRECISION".into(),
64 DataType::Decimal(p, s) => format!("NUMERIC({p},{s})"),
65 DataType::Boolean => "BOOLEAN".into(),
66 DataType::Varchar(n) => format!("VARCHAR({n})"),
67 DataType::Char(n) => format!("CHAR({n})"),
68 DataType::Text => "TEXT".into(),
69 DataType::Date => "DATE".into(),
70 DataType::Time => "TIME".into(),
71 DataType::Timestamp => "TIMESTAMP".into(),
72 DataType::Uuid => "UUID".into(),
73 DataType::Bytes => "BYTEA".into(),
74 DataType::Custom(s) => s.clone(),
75 }
76 }
77
78 fn quote_ident(&self, ident: &str) -> String {
79 format!("\"{}\"", ident.replace('"', "\"\""))
80 }
81}
82
83pub struct MySql;
85impl Dialect for MySql {
86 fn render_type(&self, ty: &DataType) -> String {
87 match ty {
88 DataType::Integer => "INT".into(),
89 DataType::BigInt => "BIGINT".into(),
90 DataType::SmallInt => "SMALLINT".into(),
91 DataType::Real => "DOUBLE".into(),
92 DataType::Decimal(p, s) => format!("DECIMAL({p},{s})"),
93 DataType::Boolean => "TINYINT(1)".into(),
94 DataType::Varchar(n) => format!("VARCHAR({n})"),
95 DataType::Char(n) => format!("CHAR({n})"),
96 DataType::Text => "TEXT".into(),
97 DataType::Date => "DATE".into(),
98 DataType::Time => "TIME".into(),
99 DataType::Timestamp => "DATETIME".into(),
100 DataType::Uuid => "CHAR(36)".into(),
101 DataType::Bytes => "BLOB".into(),
102 DataType::Custom(s) => s.clone(),
103 }
104 }
105
106 fn quote_ident(&self, ident: &str) -> String {
107 format!("`{}`", ident.replace('`', "``"))
108 }
109}
110
111pub struct Sqlite;
113impl Dialect for Sqlite {
114 fn render_type(&self, ty: &DataType) -> String {
115 match ty {
116 DataType::Integer | DataType::SmallInt | DataType::BigInt => "INTEGER".into(),
117 DataType::Real | DataType::Decimal(_, _) => "REAL".into(),
118 DataType::Boolean => "INTEGER".into(),
119 DataType::Varchar(_) | DataType::Char(_) | DataType::Text | DataType::Uuid => "TEXT".into(),
120 DataType::Date | DataType::Time | DataType::Timestamp => "TEXT".into(),
121 DataType::Bytes => "BLOB".into(),
122 DataType::Custom(s) => s.clone(),
123 }
124 }
125
126 fn quote_ident(&self, ident: &str) -> String {
127 format!("\"{}\"", ident.replace('"', "\"\""))
128 }
129}