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_index_hints(
19 &self,
20 table_ref: &TableRef,
21 select: &SelectStatement,
22 sql: &mut impl SqlWriter,
23 ) {
24 let Some(hints) = select.index_hints.get(&table_ref.into()) else {
25 return;
26 };
27 sql.write_str(" ").unwrap();
28
29 let mut hints = hints.iter();
30 join_io!(
31 hints,
32 hint,
33 join {
34 sql.write_str(" ").unwrap();
35 },
36 do {
37 match hint.r#type {
38 IndexHintType::Use => {
39 sql.write_str("USE INDEX ").unwrap();
40 self.prepare_index_hint_scope(&hint.scope, sql);
41 sql.write_str("(").unwrap();
42 self.prepare_iden(&hint.index, sql);
43 }
44 IndexHintType::Ignore => {
45 sql.write_str("IGNORE INDEX ").unwrap();
46 self.prepare_index_hint_scope(&hint.scope, sql);
47 sql.write_str("(").unwrap();
48 self.prepare_iden(&hint.index, sql);
49 }
50 IndexHintType::Force => {
51 sql.write_str("FORCE INDEX ").unwrap();
52 self.prepare_index_hint_scope(&hint.scope, sql);
53 sql.write_str("(").unwrap();
54 self.prepare_iden(&hint.index, sql);
55 }
56 }
57 sql.write_str(")").unwrap();
58 }
59 );
60 }
61
62 fn prepare_query_statement(&self, query: &SubQueryStatement, sql: &mut impl SqlWriter) {
63 query.prepare_statement(self, sql);
64 }
65
66 fn prepare_with_clause_recursive_options(&self, _: &WithClause, _: &mut impl SqlWriter) {
67 }
69
70 fn prepare_with_query_clause_materialization(
71 &self,
72 _: &CommonTableExpression,
73 _: &mut impl SqlWriter,
74 ) {
75 }
77
78 fn prepare_update_join(
79 &self,
80 from: &[TableRef],
81 condition: &ConditionHolder,
82 sql: &mut impl SqlWriter,
83 ) {
84 if from.is_empty() {
85 return;
86 }
87
88 sql.write_str(" JOIN ").unwrap();
89
90 self.prepare_table_ref(&from[0], sql);
92
93 self.prepare_condition(condition, "ON", sql);
94 }
95
96 fn prepare_update_from(&self, _: &[TableRef], _: &mut impl SqlWriter) {}
97
98 fn prepare_update_column(
99 &self,
100 table: &Option<Box<TableRef>>,
101 from: &[TableRef],
102 column: &DynIden,
103 sql: &mut impl SqlWriter,
104 ) {
105 use std::ops::Deref;
106
107 if !from.is_empty() {
108 if let Some(table) = table {
109 if let TableRef::Table(TableName(None, table), None) = table.deref() {
111 let column_name = ColumnName::from((table.clone(), column.clone()));
112 self.prepare_column_ref(&ColumnRef::Column(column_name), sql);
113 return;
114 }
115 }
116 }
117 self.prepare_iden(column, sql)
118 }
119
120 fn prepare_update_condition(
121 &self,
122 from: &[TableRef],
123 condition: &ConditionHolder,
124 sql: &mut impl SqlWriter,
125 ) {
126 if !from.is_empty() {
127 return;
128 }
129 self.prepare_condition(condition, "WHERE", sql);
130 }
131
132 fn prepare_join_type(&self, join_type: &JoinType, sql: &mut impl SqlWriter) {
133 match join_type {
134 JoinType::FullOuterJoin => panic!("Mysql does not support FULL OUTER JOIN"),
135 _ => self.prepare_join_type_common(join_type, sql),
136 }
137 }
138
139 fn prepare_order_expr(&self, order_expr: &OrderExpr, sql: &mut impl SqlWriter) {
140 match order_expr.nulls {
141 None => (),
142 Some(NullOrdering::Last) => {
143 self.prepare_expr(&order_expr.expr, sql);
144 sql.write_str(" IS NULL ASC, ").unwrap()
145 }
146 Some(NullOrdering::First) => {
147 self.prepare_expr(&order_expr.expr, sql);
148 sql.write_str(" IS NULL DESC, ").unwrap()
149 }
150 }
151 if !matches!(order_expr.order, Order::Field(_)) {
152 self.prepare_expr(&order_expr.expr, sql);
153 }
154 self.prepare_order(order_expr, sql);
155 }
156
157 fn prepare_value(&self, value: Value, sql: &mut impl SqlWriter) {
158 sql.push_param(value, self as _);
159 }
160
161 fn prepare_on_conflict_target(&self, _: &[OnConflictTarget], _: &mut impl SqlWriter) {
162 }
164
165 fn prepare_on_conflict_action(
166 &self,
167 on_conflict_action: &Option<OnConflictAction>,
168 sql: &mut impl SqlWriter,
169 ) {
170 match on_conflict_action {
171 Some(OnConflictAction::DoNothing(pk_cols)) => {
172 if !pk_cols.is_empty() {
173 self.prepare_on_conflict_do_update_keywords(sql);
174 let mut pk_cols_iter = pk_cols.iter();
175 join_io!(
176 pk_cols_iter,
177 pk_col,
178 join {
179 sql.write_str(", ").unwrap();
180 },
181 do {
182 self.prepare_iden(pk_col, sql);
183 sql.write_str(" = ").unwrap();
184 self.prepare_iden(pk_col, sql);
185 }
186 );
187 } else {
188 sql.write_str(" IGNORE").unwrap();
189 }
190 }
191 _ => self.prepare_on_conflict_action_common(on_conflict_action, sql),
192 }
193 }
194
195 fn prepare_on_conflict_keywords(&self, sql: &mut impl SqlWriter) {
196 sql.write_str(" ON DUPLICATE KEY").unwrap();
197 }
198
199 fn prepare_on_conflict_do_update_keywords(&self, sql: &mut impl SqlWriter) {
200 sql.write_str(" UPDATE ").unwrap();
201 }
202
203 fn prepare_on_conflict_excluded_table(&self, col: &DynIden, sql: &mut impl SqlWriter) {
204 sql.write_str("VALUES(").unwrap();
205 self.prepare_iden(col, sql);
206 sql.write_str(")").unwrap();
207 }
208
209 fn prepare_on_conflict_condition(&self, _: &ConditionHolder, _: &mut impl SqlWriter) {}
210
211 fn prepare_returning(&self, _returning: &Option<ReturningClause>, _sql: &mut impl SqlWriter) {}
212
213 fn random_function(&self) -> &str {
214 "RAND"
215 }
216
217 fn lock_phrase(&self, lock_type: LockType) -> &'static str {
218 match lock_type {
219 LockType::Update => "FOR UPDATE",
220 LockType::NoKeyUpdate => "FOR NO KEY UPDATE",
221 LockType::Share => "LOCK IN SHARE MODE",
222 LockType::KeyShare => "FOR KEY SHARE",
223 }
224 }
225
226 fn insert_default_keyword(&self) -> &str {
227 "()"
228 }
229}
230
231impl MysqlQueryBuilder {
232 fn prepare_index_hint_scope(
233 &self,
234 index_hint_scope: &IndexHintScope,
235 sql: &mut impl SqlWriter,
236 ) {
237 match index_hint_scope {
238 IndexHintScope::Join => {
239 sql.write_str("FOR JOIN ").unwrap();
240 }
241 IndexHintScope::OrderBy => {
242 sql.write_str("FOR ORDER BY ").unwrap();
243 }
244 IndexHintScope::GroupBy => {
245 sql.write_str("FOR GROUP BY ").unwrap();
246 }
247 IndexHintScope::All => {}
248 }
249 }
250}