easy_sqlx_core/sql/dialects/
context.rs1use std::io;
2
3
4use easy_sqlx_utils::ternary;
5
6use crate::sql::schema::{column::Column, index::Index};
7
8use crate::sql::utils::quote::{ always_reserve, Quoter};
9
10const DEFAULT_SCHEMA: &str = "public";
11
12
13pub struct Context {
14 default_schema: String,
15 pub quoter: Quoter,
16}
17
18impl Default for Context {
19 fn default() -> Self {
20 Self {
21 default_schema: DEFAULT_SCHEMA.to_owned(),
22 #[cfg(feature = "postgres")]
23 quoter: Quoter::new(b'\"', b'\"', always_reserve),
24 }
25 }
26}
27
28impl Context {
29 pub fn new(schema: String) -> Self {
30 let mut s = Self::default();
31 if !schema.is_empty() {
32 s.default_schema = schema;
33 }
34 s
35 }
36 pub fn quote(&self, str: &String) -> String {
43 self.quoter.quote(str)
44 }
45
46 pub fn get_default_schema(&self) -> String {
47 self.default_schema.clone()
48 }
49
50 pub fn table_name_with_schema(&self, name: &String) -> String {
51 if !self.default_schema.is_empty() && !name.contains(".") {
52 return format!("{}.{}", self.default_schema, name);
53 }
54 name.clone()
55 }
56
57 pub fn is_table_name_equal(&self, table1: &String, table2: &String) -> bool {
58 self.table_name_with_schema(table1).to_uppercase()
59 == self.table_name_with_schema(table2).to_uppercase()
60 }
61
62 pub fn sql_column(
63 &self,
64 col: &Column,
65 inline_pk: bool,
66 auto_incr_str: Option<&str>,
67 fn_sql_type: fn(col: &Column) -> String,
68 ) -> String {
69 let mut sql = String::new();
70 self.quoter.quote_to(&mut sql, &col.get_column_name());
72 sql.push(' ');
76 let sql_type = fn_sql_type(col);
82 sql.push_str(&sql_type);
83 sql.push(' ');
84 if inline_pk && col.pk {
94 sql.push_str("PRIMARY KEY ");
96 }
110
111 if col.autoincr {
112 if let Some(incr) = auto_incr_str {
114 sql.push_str(incr);
115 sql.push(' ');
116 }
117 }
118
119 if let Some(def) = &col.default {
120 sql.push_str("DEFAULT ");
121 sql.push_str(&def.to_string());
122 sql.push_str(" ");
123 }
136
137 if col.nullable {
150 sql.push_str("NULL ");
151 } else {
152 sql.push_str("NOT NULL ");
153 }
154
155 sql
165 }
167
168 pub fn sql_add_column(
169 &self,
170 table_name: &String,
171 column: &Column,
172 auto_incr_str: Option<&str>,
173 fn_sql_type: fn(col: &Column) -> String,
174 ) -> String {
175 let col_def = self.sql_column(column, false, auto_incr_str, fn_sql_type);
176 format!(
177 "ALTER TABLE {} ADD COLUMN {col_def}",
178 self.quote(&self.table_name_with_schema(table_name))
179 )
180 }
181
182 pub fn sql_drop_column(&self, table_name: &String, column_name: &String) -> String {
183 format!(
184 "ALTER TABLE {} DROP COLUMN IF EXISTS {}",
185 self.quote(&self.table_name_with_schema(table_name)),
186 self.quote(column_name)
187 )
188 }
189
190 pub fn sql_alter_column(
191 &self,
192 table_name: &String,
193 old: &Column,
194 new: &Column,
195 fn_sql_type: fn(col: &Column) -> String,
196 ignore_default: bool,
197 ) -> io::Result<Vec<String>> {
198 let table = self.quote(&self.table_name_with_schema(table_name));
199 let column = old.get_column_name();
200 let mut sqls = vec![];
201
202 if fn_sql_type(old) != fn_sql_type(new) {
203 if new.typ.name == old.typ.name {
205 if let Some(len) = new.typ.len {
208 let sql_type = fn_sql_type(new);
209 sqls.push(format!(
210 "ALTER TABLE {table} ALTER COLUMN {column} TYPE {sql_type}"
211 ));
212 } else {
213 return Err(io::Error::new(
214 io::ErrorKind::Other,
215 format!("字符字段必须有长度: {column} on {table}"),
216 ));
217 }
218 } else {
219 let sql_type = fn_sql_type(new);
221 sqls.push(format!(
222 "ALTER TABLE {table} ALTER COLUMN {column} TYPE {sql_type}"
223 ));
224 }
225 }
226 if !ignore_default {
227 if old.default != new.default {
228 if let Some(def) = &new.default {
229 sqls.push(format!(
231 "ALTER TABLE {table} ALTER COLUMN {column} SET DEFAULT {def}"
232 ));
233 } else {
234 sqls.push(format!(
236 "ALTER TABLE {table} ALTER COLUMN {column} DROP DEFAULT"
237 ));
238 }
239 }
240 }
241 if old.nullable != new.nullable {
242 if new.nullable {
243 sqls.push(format!(
245 "ALTER TABLE {table} ALTER COLUMN {column} DROP NOT NULL"
246 ));
247 } else {
248 sqls.push(format!(
250 "ALTER TABLE {table} ALTER COLUMN {column} SET NOT NULL"
251 ));
252 }
253 }
254
255 Ok(sqls)
261 }
262
263 pub fn sql_drop_table(&self, table_name: &String) -> String {
264 format!(
265 "DROP TABLE IF EXISTS {}",
266 self.quote(&self.table_name_with_schema(table_name))
267 )
268 }
269
270 pub fn sql_create_index(&self, table_name: &String, index: &Index) -> Option<String> {
271 if index.columns.is_empty() {
272 return None;
273 }
274 let unique = ternary!(index.unique, " UNIQUE", ""); Some(format!(
276 "CREATE{unique} INDEX {} ON {} ({})",
277 self.quote(&index.name),
278 self.quote(&self.table_name_with_schema(table_name)),
279 index.columns.join(",")
280 ))
281 }
282
283 pub fn sql_drop_index(&self, index_name_with_schema: &String) -> String {
284 format!(
285 "DROP INDEX IF EXISTS {}",
286 self.quote(&self.table_name_with_schema(index_name_with_schema))
287 )
288 }
289}