easy_sqlx_core/sql/dialects/
context.rs

1use 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 with_schema(default_schema: String) -> Self {
37    //     let mut ctx = Self::default();
38    //     ctx.default_schema = default_schema;
39    //     ctx
40    // }
41
42    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        // 字段名称
71        self.quoter.quote_to(&mut sql, &col.get_column_name());
72        // if err := bd.Quoter().QuoteTo(&sql, col.FieldName()); err != nil {
73        // 	return "", err
74        // }
75        sql.push(' ');
76        // if err := sql.WriteByte(' '); err != nil {
77        // 	return "", err
78        // }
79
80        // 数据类型
81        let sql_type = fn_sql_type(col);
82        sql.push_str(&sql_type);
83        sql.push(' ');
84        // sqlType := bd.SQLType(col)
85
86        // if _, err := sql.WriteString(sqlType); err != nil {
87        // 	return "", err
88        // }
89        // if err := sql.WriteByte(' '); err != nil {
90        // 	return "", err
91        // }
92
93        if inline_pk && col.pk {
94            // 只有一个字段是主键,且该字段是主键
95            sql.push_str("PRIMARY KEY ");
96            // if _, err := sql.WriteString("PRIMARY KEY "); err != nil {
97            // 	return "", err
98            // }
99
100            // if col.IsAutoIncrement {
101
102            // 	if _, err := sql.WriteString(bd.AutoIncrStr()); err != nil {
103            // 		return "", err
104            // 	}
105            // 	if err := sql.WriteByte(' '); err != nil {
106            // 		return "", err
107            // 	}
108            // }
109        }
110
111        if col.autoincr {
112            // 该字段是自增类型
113            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            // if col.typ.name == sql_types::VARCHAR
124            //     || (col.typ.name == sql_types::CHAR && col.typ.fixed_len.is_none())
125            //     || col.typ.name == sql_types::TEXT
126            // {
127            //     // 文本类型
128            //     // 这里需要改代码
129            //     sql.push_str("DEFAULT ('') ");
130            // } else {
131            //     sql.push_str("DEFAULT ");
132            //     sql.push_str(&def.to_string());
133            //     sql.push_str(" ");
134            // }
135        }
136
137        // else if col.Default != "" {
138        // 	if _, err := sql.WriteString("DEFAULT "); err != nil {
139        // 		return "", err
140        // 	}
141        // 	if _, err := sql.WriteString(col.Default); err != nil {
142        // 		return "", err
143        // 	}
144        // 	if err := sql.WriteByte(' '); err != nil {
145        // 		return "", err
146        // 	}
147        // }
148
149        if col.nullable {
150            sql.push_str("NULL ");
151        } else {
152            sql.push_str("NOT NULL ");
153        }
154
155        // if col.Nullable {
156        // 	if _, err := sql.WriteString("NULL "); err != nil {
157        // 		return "", err
158        // 	}
159        // } else {
160        // 	if _, err := sql.WriteString("NOT NULL "); err != nil {
161        // 		return "", err
162        // 	}
163        // }
164        sql
165        // return sql.String(), nil
166    }
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            // 类型发生变化
204            if new.typ.name == old.typ.name {
205                // 类型名称没有变化,大概是字符串长度发生变化
206                // ALTER TABLE table_name ALTER COLUMN column_name TYPE character_type(length);
207                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                // ALTER TABLE table_name ALTER COLUMN column_name TYPE new_data_type;
220                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                    // ALTER TABLE table_name ALTER COLUMN column_name SET DEFAULT default_value;
230                    sqls.push(format!(
231                        "ALTER TABLE {table} ALTER COLUMN {column} SET DEFAULT {def}"
232                    ));
233                } else {
234                    // ALTER TABLE table_name ALTER COLUMN column_name DROP DEFAULT;
235                    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                // ALTER TABLE table_name ALTER COLUMN column_name DROP NOT NULL;
244                sqls.push(format!(
245                    "ALTER TABLE {table} ALTER COLUMN {column} DROP NOT NULL"
246                ));
247            } else {
248                // ALTER TABLE table_name ALTER COLUMN column_name SET NOT NULL;
249                sqls.push(format!(
250                    "ALTER TABLE {table} ALTER COLUMN {column} SET NOT NULL"
251                ));
252            }
253        }
254
255        // let col_def = self.sql_column(column, false, auto_incr_str);
256        // format!(
257        //     "ALTER TABLE {} ALTER COLUMN {col_def}",
258        //     self.quote(&self.table_name_with_schema(table_name))
259        // )
260        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", ""); // if index.unique { " UNIQUE" } else { "" };
275        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}