rust_ef_mysql/
sql_generator.rs1use rust_ef::provider::ISqlGenerator;
2
3#[derive(Debug, Clone)]
4pub struct MySqlSqlGenerator;
5
6impl MySqlSqlGenerator {
7 #[allow(clippy::new_without_default)]
8 pub fn new() -> Self {
9 Self
10 }
11}
12
13impl ISqlGenerator for MySqlSqlGenerator {
14 fn select(&self, table: &str, columns: &[&str]) -> String {
15 let cols = if columns.is_empty() {
16 "*".to_string()
17 } else {
18 columns
19 .iter()
20 .map(|c| self.quote_identifier(c))
21 .collect::<Vec<_>>()
22 .join(", ")
23 };
24 format!("SELECT {} FROM {}", cols, self.quote_identifier(table))
25 }
26
27 fn insert(&self, table: &str, columns: &[&str], _returning: bool) -> String {
28 let cols = columns
29 .iter()
30 .map(|c| self.quote_identifier(c))
31 .collect::<Vec<_>>()
32 .join(", ");
33 let placeholders = vec!["?"; columns.len()].join(", ");
34 format!(
35 "INSERT INTO {} ({}) VALUES ({})",
36 self.quote_identifier(table),
37 cols,
38 placeholders
39 )
40 }
41
42 fn insert_batch(&self, table: &str, columns: &[&str], row_count: usize) -> String {
43 let cols = columns
44 .iter()
45 .map(|c| self.quote_identifier(c))
46 .collect::<Vec<_>>()
47 .join(", ");
48 let row = format!("({})", vec!["?"; columns.len()].join(", "));
49 let all_rows = vec![row; row_count].join(", ");
50 format!(
51 "INSERT INTO {} ({}) VALUES {}",
52 self.quote_identifier(table),
53 cols,
54 all_rows,
55 )
56 }
57
58 fn upsert_batch(
59 &self,
60 table: &str,
61 columns: &[&str],
62 conflict_cols: &[&str],
63 row_count: usize,
64 ) -> String {
65 let cols = columns
66 .iter()
67 .map(|c| self.quote_identifier(c))
68 .collect::<Vec<_>>()
69 .join(", ");
70 let row = format!("({})", vec!["?"; columns.len()].join(", "));
71 let all_rows = vec![row; row_count].join(", ");
72 let update_cols: Vec<&str> = columns
73 .iter()
74 .filter(|c| !conflict_cols.contains(c))
75 .copied()
76 .collect();
77 let sets = update_cols
78 .iter()
79 .map(|c| {
80 format!(
81 "{} = VALUES({})",
82 self.quote_identifier(c),
83 self.quote_identifier(c)
84 )
85 })
86 .collect::<Vec<_>>()
87 .join(", ");
88 format!(
89 "INSERT INTO {} ({}) VALUES {} ON DUPLICATE KEY UPDATE {}",
90 self.quote_identifier(table),
91 cols,
92 all_rows,
93 sets,
94 )
95 }
96
97 fn update(&self, table: &str, set_columns: &[&str], where_clause: &str) -> String {
98 let sets: Vec<String> = set_columns
99 .iter()
100 .map(|c| format!("{} = ?", self.quote_identifier(c)))
101 .collect();
102 format!(
103 "UPDATE {} SET {} WHERE {}",
104 self.quote_identifier(table),
105 sets.join(", "),
106 where_clause
107 )
108 }
109
110 fn delete(&self, table: &str, where_clause: &str) -> String {
111 format!(
112 "DELETE FROM {} WHERE {}",
113 self.quote_identifier(table),
114 where_clause
115 )
116 }
117
118 fn create_table(&self, table: &str, columns: &[(String, String)]) -> String {
119 let col_defs: Vec<String> = columns
120 .iter()
121 .map(|(name, type_def)| format!("{} {}", self.quote_identifier(name), type_def))
122 .collect();
123 format!(
124 "CREATE TABLE {} (\n {}\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
125 self.quote_identifier(table),
126 col_defs.join(",\n ")
127 )
128 }
129
130 fn drop_table(&self, table: &str) -> String {
131 format!("DROP TABLE IF EXISTS {}", self.quote_identifier(table))
132 }
133
134 fn pagination(&self, skip: Option<usize>, take: Option<usize>) -> String {
135 match (skip, take) {
136 (Some(s), Some(t)) => format!("LIMIT {} OFFSET {}", t, s),
137 (None, Some(t)) => format!("LIMIT {}", t),
138 (Some(s), None) => format!("LIMIT 18446744073709551615 OFFSET {}", s),
139 (None, None) => String::new(),
140 }
141 }
142
143 fn parameter_placeholder(&self, _index: usize) -> String {
144 "?".to_string()
145 }
146
147 fn quote_identifier(&self, identifier: &str) -> String {
148 format!("`{}`", identifier)
149 }
150
151 fn auto_increment_syntax(&self) -> &'static str {
152 "AUTO_INCREMENT"
153 }
154
155 fn supports_returning(&self) -> bool {
156 false
157 }
158
159 fn last_insert_id_sql(&self) -> Option<&'static str> {
160 Some("SELECT LAST_INSERT_ID()")
161 }
162
163 fn last_insert_id_returns_first(&self) -> bool {
164 true
165 }
166}