1use super::*;
2use crate::extension::mysql::*;
3
4impl QueryBuilder for MysqlQueryBuilder {
5 fn values_list_tuple_prefix(&self) -> &str {
6 "ROW"
7 }
8
9 fn prepare_select_distinct(&self, select_distinct: &SelectDistinct, sql: &mut impl SqlWriter) {
10 match select_distinct {
11 SelectDistinct::All => sql.write_str("ALL").unwrap(),
12 SelectDistinct::Distinct => sql.write_str("DISTINCT").unwrap(),
13 SelectDistinct::DistinctRow => sql.write_str("DISTINCTROW").unwrap(),
14 _ => {}
15 };
16 }
17
18 fn prepare_select_into(&self, _: &SelectInto, _: &mut impl SqlWriter) {
19 }
22
23 fn prepare_index_hints(
24 &self,
25 table_ref: &TableRef,
26 select: &SelectStatement,
27 sql: &mut impl SqlWriter,
28 ) {
29 let Some(hints) = select.index_hints.get(&table_ref.into()) else {
30 return;
31 };
32 sql.write_str(" ").unwrap();
33
34 let mut hints = hints.iter();
35 join_io!(
36 hints,
37 hint,
38 join {
39 sql.write_str(" ").unwrap();
40 },
41 do {
42 match hint.r#type {
43 IndexHintType::Use => {
44 sql.write_str("USE INDEX ").unwrap();
45 self.prepare_index_hint_scope(&hint.scope, sql);
46 sql.write_str("(").unwrap();
47 self.prepare_iden(&hint.index, sql);
48 }
49 IndexHintType::Ignore => {
50 sql.write_str("IGNORE INDEX ").unwrap();
51 self.prepare_index_hint_scope(&hint.scope, sql);
52 sql.write_str("(").unwrap();
53 self.prepare_iden(&hint.index, sql);
54 }
55 IndexHintType::Force => {
56 sql.write_str("FORCE INDEX ").unwrap();
57 self.prepare_index_hint_scope(&hint.scope, sql);
58 sql.write_str("(").unwrap();
59 self.prepare_iden(&hint.index, sql);
60 }
61 }
62 sql.write_str(")").unwrap();
63 }
64 );
65 }
66
67 fn prepare_query_statement(&self, query: &SubQueryStatement, sql: &mut impl SqlWriter) {
68 query.prepare_statement(self, sql);
69 }
70
71 fn prepare_explain_statement(&self, explain: &ExplainStatement, sql: &mut impl SqlWriter) {
72 sql.write_str("EXPLAIN").unwrap();
73 if let Some(table) = &explain.mysql_opts.table {
74 sql.write_str(" ").unwrap();
75 self.prepare_table_ref(table, sql);
76 if let Some(target) = &explain.mysql_opts.target {
77 match target {
78 ExplainTableTarget::Column(column) => {
79 sql.write_str(" ").unwrap();
80 self.prepare_iden(column, sql);
81 }
82 ExplainTableTarget::Wildcard(wildcard) => {
83 sql.write_str(" '").unwrap();
84 if self.needs_escape(wildcard) {
85 sql.write_str(&self.escape_string(wildcard)).unwrap();
86 } else {
87 sql.write_str(wildcard).unwrap();
88 }
89 sql.write_str("'").unwrap();
90 }
91 }
92 }
93 return;
94 }
95
96 if let Some(analyze) = explain.analyze {
97 if analyze {
98 sql.write_str(" ANALYZE").unwrap();
99 } else {
100 sql.write_str(" ANALYZE FALSE").unwrap();
101 }
102 }
103
104 if let Some(format) = explain.format {
105 sql.write_str(" FORMAT = ").unwrap();
106 sql.write_str(format.as_str()).unwrap();
107 }
108
109 if let Some(variable) = &explain.mysql_opts.into_variable {
110 sql.write_str(" INTO ").unwrap();
111 sql.write_str(variable).unwrap();
112 }
113
114 if let Some(schema) = &explain.mysql_opts.schema_spec {
115 match schema {
116 MySqlExplainSchemaSpec::Schema(schema) => {
117 sql.write_str(" FOR SCHEMA ").unwrap();
118 self.prepare_iden(schema, sql);
119 }
120 MySqlExplainSchemaSpec::Database(schema) => {
121 sql.write_str(" FOR DATABASE ").unwrap();
122 self.prepare_iden(schema, sql);
123 }
124 }
125 }
126
127 if let Some(connection_id) = explain.mysql_opts.for_connection {
128 sql.write_str(" FOR CONNECTION ").unwrap();
129 write_int(sql, connection_id);
130 return;
131 }
132
133 if let Some(statement) = &explain.statement {
134 sql.write_str(" ").unwrap();
135 statement.write_to(self, sql);
136 }
137 }
138
139 fn prepare_with_clause_recursive_options(&self, _: &WithClause, _: &mut impl SqlWriter) {
140 }
142
143 fn prepare_with_query_clause_materialization(
144 &self,
145 _: &CommonTableExpression,
146 _: &mut impl SqlWriter,
147 ) {
148 }
150
151 fn prepare_update_join(
152 &self,
153 from: &[TableRef],
154 condition: &ConditionHolder,
155 sql: &mut impl SqlWriter,
156 ) {
157 if from.is_empty() {
158 return;
159 }
160
161 sql.write_str(" JOIN ").unwrap();
162
163 self.prepare_table_ref(&from[0], sql);
165
166 self.prepare_condition(condition, "ON", sql);
167 }
168
169 fn prepare_update_from(&self, _: &[TableRef], _: &mut impl SqlWriter) {}
170
171 fn prepare_update_column(
172 &self,
173 table: &Option<Box<TableRef>>,
174 from: &[TableRef],
175 column: &DynIden,
176 sql: &mut impl SqlWriter,
177 ) {
178 use std::ops::Deref;
179
180 if !from.is_empty() {
181 if let Some(table) = table {
182 if let TableRef::Table(TableName(None, table), None) = table.deref() {
184 let column_name = ColumnName::from((table.clone(), column.clone()));
185 self.prepare_column_ref(&ColumnRef::Column(column_name), sql);
186 return;
187 }
188 }
189 }
190 self.prepare_iden(column, sql)
191 }
192
193 fn prepare_update_condition(
194 &self,
195 from: &[TableRef],
196 condition: &ConditionHolder,
197 sql: &mut impl SqlWriter,
198 ) {
199 if !from.is_empty() {
200 return;
201 }
202 self.prepare_condition(condition, "WHERE", sql);
203 }
204
205 fn prepare_join_type(&self, join_type: &JoinType, sql: &mut impl SqlWriter) {
206 match join_type {
207 JoinType::FullOuterJoin => panic!("Mysql does not support FULL OUTER JOIN"),
208 _ => self.prepare_join_type_common(join_type, sql),
209 }
210 }
211
212 fn prepare_order_expr(&self, order_expr: &OrderExpr, sql: &mut impl SqlWriter) {
213 match order_expr.nulls {
214 None => (),
215 Some(NullOrdering::Last) => {
216 self.prepare_expr(&order_expr.expr, sql);
217 sql.write_str(" IS NULL ASC, ").unwrap()
218 }
219 Some(NullOrdering::First) => {
220 self.prepare_expr(&order_expr.expr, sql);
221 sql.write_str(" IS NULL DESC, ").unwrap()
222 }
223 }
224 if !matches!(order_expr.order, Order::Field(_)) {
225 self.prepare_expr(&order_expr.expr, sql);
226 }
227 self.prepare_order(order_expr, sql);
228 }
229
230 fn prepare_value(&self, value: Value, sql: &mut impl SqlWriter) {
231 sql.push_param(value, self as _);
232 }
233
234 fn prepare_on_conflict_target(&self, _: &OnConflictTarget, _: &mut impl SqlWriter) {
235 }
237
238 fn prepare_on_conflict_action(
239 &self,
240 on_conflict_action: &Option<OnConflictAction>,
241 sql: &mut impl SqlWriter,
242 ) {
243 match on_conflict_action {
244 Some(OnConflictAction::DoNothing(pk_cols)) => {
245 if !pk_cols.is_empty() {
246 self.prepare_on_conflict_do_update_keywords(sql);
247 let mut pk_cols_iter = pk_cols.iter();
248 join_io!(
249 pk_cols_iter,
250 pk_col,
251 join {
252 sql.write_str(", ").unwrap();
253 },
254 do {
255 self.prepare_iden(pk_col, sql);
256 sql.write_str(" = ").unwrap();
257 self.prepare_iden(pk_col, sql);
258 }
259 );
260 } else {
261 sql.write_str(" IGNORE").unwrap();
262 }
263 }
264 _ => self.prepare_on_conflict_action_common(on_conflict_action, sql),
265 }
266 }
267
268 fn prepare_on_conflict_keywords(&self, sql: &mut impl SqlWriter) {
269 sql.write_str(" ON DUPLICATE KEY").unwrap();
270 }
271
272 fn prepare_on_conflict_do_update_keywords(&self, sql: &mut impl SqlWriter) {
273 sql.write_str(" UPDATE ").unwrap();
274 }
275
276 fn prepare_on_conflict_excluded_table(&self, col: &DynIden, sql: &mut impl SqlWriter) {
277 sql.write_str("VALUES(").unwrap();
278 self.prepare_iden(col, sql);
279 sql.write_str(")").unwrap();
280 }
281
282 fn prepare_on_conflict_condition(&self, _: &ConditionHolder, _: &mut impl SqlWriter) {}
283
284 fn prepare_returning(&self, _returning: &Option<ReturningClause>, _sql: &mut impl SqlWriter) {}
285
286 fn random_function(&self) -> &str {
287 "RAND"
288 }
289
290 fn lock_phrase(&self, lock_type: LockType) -> &'static str {
291 match lock_type {
292 LockType::Update => "FOR UPDATE",
293 LockType::NoKeyUpdate => "FOR NO KEY UPDATE",
294 LockType::Share => "LOCK IN SHARE MODE",
295 LockType::KeyShare => "FOR KEY SHARE",
296 }
297 }
298
299 fn insert_default_keyword(&self) -> &str {
300 "()"
301 }
302}
303
304impl MysqlQueryBuilder {
305 fn prepare_index_hint_scope(
306 &self,
307 index_hint_scope: &IndexHintScope,
308 sql: &mut impl SqlWriter,
309 ) {
310 match index_hint_scope {
311 IndexHintScope::Join => {
312 sql.write_str("FOR JOIN ").unwrap();
313 }
314 IndexHintScope::OrderBy => {
315 sql.write_str("FOR ORDER BY ").unwrap();
316 }
317 IndexHintScope::GroupBy => {
318 sql.write_str("FOR GROUP BY ").unwrap();
319 }
320 IndexHintScope::All => {}
321 }
322 }
323}