1use super::SqlGenerator;
4use crate::{
5 functions::AutogenFunction,
6 types::{BaseType, ReferentialAction, Type, WrappedDefault},
7};
8
9macro_rules! prefix {
11 ($schema:expr) => {
12 $schema
13 .map(|s| format!("\"{}\".", s))
14 .unwrap_or_else(|| String::new())
15 };
16}
17
18pub struct Sqlite;
21impl SqlGenerator for Sqlite {
22 fn create_table(name: &str, schema: Option<&str>) -> String {
23 format!("CREATE TABLE {}\"{}\"", prefix!(schema), name)
24 }
25
26 fn create_table_if_not_exists(name: &str, schema: Option<&str>) -> String {
27 format!("CREATE TABLE IF NOT EXISTS {}\"{}\"", prefix!(schema), name)
28 }
29
30 fn drop_table(name: &str, schema: Option<&str>) -> String {
31 format!("DROP TABLE {}\"{}\"", prefix!(schema), name)
32 }
33
34 fn drop_table_if_exists(name: &str, schema: Option<&str>) -> String {
35 format!("DROP TABLE IF EXISTS {}\"{}\"", prefix!(schema), name)
36 }
37
38 fn rename_table(old: &str, new: &str, schema: Option<&str>) -> String {
39 let schema = prefix!(schema);
40 format!("ALTER TABLE {}\"{}\" RENAME TO \"{}\"", schema, old, new)
41 }
42
43 fn alter_table(name: &str, schema: Option<&str>) -> String {
44 format!("ALTER TABLE {}\"{}\"", prefix!(schema), name)
45 }
46
47 fn add_column(ex: bool, _: Option<&str>, name: &str, tt: &Type) -> String {
48 let bt: BaseType = tt.get_inner();
49 let btc = bt.clone();
50 use self::BaseType::*;
51 let primary_definition = match tt.primary {
52 true => " PRIMARY KEY",
53 false => "",
54 };
55 let default_definition = match (&tt.default).as_ref() {
56 Some(ref m) => match m {
57 WrappedDefault::Function(ref fun) => match fun {
58 AutogenFunction::CurrentTimestamp => format!(" DEFAULT CURRENT_TIMESTAMP"),
59 },
60 WrappedDefault::Null => format!(" DEFAULT NULL"),
61 WrappedDefault::AnyText(ref val) => format!(" DEFAULT '{}'", val),
62 WrappedDefault::UUID(ref val) => format!(" DEFAULT '{}'", val),
63 WrappedDefault::Date(ref val) => format!(" DEFAULT '{:?}'", val),
64 WrappedDefault::Boolean(val) => format!(" DEFAULT {}", if *val { 1 } else { 0 }),
65 WrappedDefault::Custom(ref val) => format!(" DEFAULT '{}'", val),
66 _ => format!(" DEFAULT {}", m),
67 },
68 _ => format!(""),
69 };
70 let nullable_definition = match tt.nullable {
71 true => "",
72 false => " NOT NULL",
73 };
74 let unique_definition = match tt.unique {
75 true => " UNIQUE",
76 false => "",
77 };
78 #[cfg_attr(rustfmt, rustfmt_skip)] let base_type_definition = match bt {
80 Text => format!("{}\"{}\" {}", Sqlite::prefix(ex), name, Sqlite::print_type(bt)),
81 Varchar(_) => format!("{}\"{}\" {}", Sqlite::prefix(ex), name, Sqlite::print_type(bt)),
82 Char(_) => format!("{}\"{}\" {}", Sqlite::prefix(ex), name, Sqlite::print_type(bt)),
83 Primary => format!("{}\"{}\" {}", Sqlite::prefix(ex), name, Sqlite::print_type(bt)),
84 Integer => format!("{}\"{}\" {}", Sqlite::prefix(ex), name, Sqlite::print_type(bt)),
85 Serial => panic!("SQLite has no serials for non-primary key columns"),
86 Float => format!("{}\"{}\" {}", Sqlite::prefix(ex), name, Sqlite::print_type(bt)),
87 Double => format!("{}\"{}\" {}", Sqlite::prefix(ex), name, Sqlite::print_type(bt)),
88 UUID => panic!("`UUID` not supported by Sqlite3. Use `Text` instead!"),
89 Json => panic!("`Json` not supported by Sqlite3. Use `Text` instead!"),
90 Boolean => format!("{}\"{}\" {}", Sqlite::prefix(ex), name, Sqlite::print_type(bt)),
91 Date => format!("{}\"{}\" {}", Sqlite::prefix(ex), name, Sqlite::print_type(bt)),
92 Time => format!("{}\"{}\" {}", Sqlite::prefix(ex), name, Sqlite::print_type(bt)),
93 DateTime => format!("{}\"{}\" {}", Sqlite::prefix(ex), name, Sqlite::print_type(bt)),
94 Binary => format!("{}\"{}\" {}", Sqlite::prefix(ex), name, Sqlite::print_type(bt)),
95 Foreign(_, _, _, _, _) => format!("{}\"{}\" INTEGER{} REFERENCES {}", Sqlite::prefix(ex), name, nullable_definition, Sqlite::print_type(bt)),
96 Custom(_) => format!("{}\"{}\" {}", Sqlite::prefix(ex), name, Sqlite::print_type(bt)),
97 Array(it) => format!("{}\"{}\" {}", Sqlite::prefix(ex), name, Sqlite::print_type(Array(Box::new(*it)))),
98 Index(_) => unreachable!("Indices are handled via custom builder"),
99 Constraint(_, _) => unreachable!("Constraints are handled via custom builder"),
100 };
101
102 match btc {
103 Foreign(_, _, _, _, _) => {
104 format!(
105 "{}{}{}{}",
106 base_type_definition, primary_definition, default_definition, unique_definition,
107 )
108 }
109 _ => {
110 format!(
111 "{}{}{}{}{}",
112 base_type_definition,
113 primary_definition,
114 default_definition,
115 nullable_definition,
116 unique_definition,
117 )
118 }
119 }
120 }
131
132 fn create_index(table: &str, schema: Option<&str>, name: &str, _type: &Type) -> String {
134 format!(
135 "CREATE {} INDEX {}\"{}\" ON \"{}\" ({})",
136 match _type.unique {
137 true => "UNIQUE",
138 false => "",
139 },
140 prefix!(schema),
141 name,
142 table,
143 match _type.inner {
144 BaseType::Index(ref cols) => cols
145 .iter()
146 .map(|col| format!("\"{}\"", col))
147 .collect::<Vec<_>>()
148 .join(", "),
149 _ => unreachable!(),
150 }
151 )
152 }
153
154 fn create_constraint(name: &str, _type: &Type) -> String {
155 let (r#type, columns) = match _type.inner {
156 BaseType::Constraint(ref r#type, ref columns) => (
157 r#type.clone(),
158 columns
159 .iter()
160 .map(|col| format!("\"{}\"", col))
161 .collect::<Vec<_>>(),
162 ),
163 _ => unreachable!(),
164 };
165
166 format!(
167 "CONSTRAINT \"{}\" {} ({})",
168 name,
169 r#type,
170 columns.join(", "),
171 )
172 }
173
174 fn drop_index(name: &str) -> String {
176 format!("DROP INDEX \"{}\"", name)
177 }
178
179 fn drop_column(_: &str) -> String {
180 panic!("Sqlite does not support dropping columns!")
181 }
182
183 fn rename_column(_: &str, _: &str) -> String {
184 panic!("Sqlite does not support renaming columns!")
185 }
186
187 fn add_foreign_key(
188 columns: &[String],
189 table: &str,
190 relation_columns: &[String],
191 _: Option<&str>,
192 ) -> String {
193 let columns: Vec<_> = columns.into_iter().map(|c| format!("\"{}\"", c)).collect();
194
195 let relation_columns: Vec<_> = relation_columns
196 .into_iter()
197 .map(|c| format!("\"{}\"", c))
198 .collect();
199
200 format!(
201 "FOREIGN KEY({}) REFERENCES \"{}\"({})",
202 columns.join(","),
203 table,
204 relation_columns.join(","),
205 )
206 }
207
208 fn add_primary_key(columns: &[String]) -> String {
209 let columns: Vec<_> = columns.into_iter().map(|c| format!("\"{}\"", c)).collect();
210 format!("PRIMARY KEY ({})", columns.join(","))
211 }
212}
213
214impl Sqlite {
215 fn prefix(ex: bool) -> String {
216 match ex {
217 true => format!("ADD COLUMN "),
218 false => format!(""),
219 }
220 }
221
222 fn print_type(t: BaseType) -> String {
223 use self::BaseType::*;
224 match t {
225 Text => format!("TEXT"),
226 Varchar(l) => match l {
227 0 => format!("VARCHAR"), _ => format!("VARCHAR({})", l),
229 },
230 Char(l) => format!("CHAR({})", l),
231 Primary => format!("INTEGER NOT NULL PRIMARY KEY"),
232 Serial => panic!("SQLite has no serials for non-primary key columns"),
233 Integer => format!("INTEGER"),
234 Float => format!("REAL"),
235 Double => format!("DOUBLE"),
236 UUID => unimplemented!(),
237 Boolean => format!("BOOLEAN"),
238 Date => format!("DATE"),
239 Time => format!("TIME"),
240 DateTime => format!("DATETIME"),
241 Json => panic!("Json is not supported by Sqlite3"),
242 Binary => format!("BINARY"),
243 Foreign(_, t, refs, on_update, on_delete) => {
244 let d = match on_delete {
245 ReferentialAction::Unset => String::from(""),
246 _ => format!(" {}", on_delete.on_delete()),
247 };
248 let u = match on_update {
249 ReferentialAction::Unset => String::from(""),
250 _ => format!(" {}", on_update.on_update()),
251 };
252 format!("{}({}){}{}", t, refs.0.join(","), u, d)
253 }
254 Custom(t) => format!("{}", t),
255 Array(meh) => format!("{}[]", Sqlite::print_type(*meh)),
256 Index(_) => unimplemented!(),
257 Constraint(_, _) => unreachable!("Constraints are handled via custom builder"),
258 }
259 }
260}