limbo_sqlite3_parser/to_sql_string/
expr.rs1use std::fmt::Display;
2
3use crate::ast::{self, fmt::ToTokens, Expr};
4
5use super::ToSqlString;
6
7impl ToSqlString for Expr {
8 fn to_sql_string<C: super::ToSqlContext>(&self, context: &C) -> String {
9 let mut ret = String::new();
10 match self {
11 Expr::Between {
12 lhs,
13 not,
14 start,
15 end,
16 } => {
17 ret.push_str(&lhs.to_sql_string(context));
18 ret.push(' ');
19
20 if *not {
21 ret.push_str("NOT ");
22 }
23
24 ret.push_str("BETWEEN ");
25
26 ret.push_str(&start.to_sql_string(context));
27
28 ret.push_str(" AND ");
29
30 ret.push_str(&end.to_sql_string(context));
31 }
32 Expr::Binary(lhs, op, rhs) => {
33 ret.push_str(&lhs.to_sql_string(context));
34 ret.push(' ');
35 ret.push_str(&op.to_string());
36 ret.push(' ');
37 ret.push_str(&rhs.to_sql_string(context));
38 }
39 Expr::Case {
40 base,
41 when_then_pairs,
42 else_expr,
43 } => {
44 ret.push_str("CASE ");
45 if let Some(base) = base {
46 ret.push_str(&base.to_sql_string(context));
47 ret.push(' ');
48 }
49 for (when, then) in when_then_pairs {
50 ret.push_str("WHEN ");
51 ret.push_str(&when.to_sql_string(context));
52 ret.push_str(" THEN ");
53 ret.push_str(&then.to_sql_string(context));
54 }
55 if let Some(else_expr) = else_expr {
56 ret.push_str(" ELSE ");
57 ret.push_str(&else_expr.to_sql_string(context));
58 }
59 ret.push_str(" END");
60 }
61 Expr::Cast { expr, type_name } => {
62 ret.push_str("CAST");
63 ret.push('(');
64 ret.push_str(&expr.to_sql_string(context));
65 if let Some(type_name) = type_name {
66 ret.push_str(" AS ");
67 ret.push_str(&type_name.to_sql_string(context));
68 }
69 ret.push(')');
70 }
71 Expr::Collate(expr, name) => {
72 ret.push_str(&expr.to_sql_string(context));
73 ret.push_str(" COLLATE ");
74 ret.push_str(&name);
75 }
76 Expr::DoublyQualified(name, name1, name2) => {
77 ret.push_str(&name.0);
78 ret.push('.');
79 ret.push_str(&name1.0);
80 ret.push('.');
81 ret.push_str(&name2.0);
82 }
83 Expr::Exists(select) => {
84 ret.push_str("EXISTS (");
85 ret.push_str(&select.to_sql_string(context));
86 ret.push(')');
87 }
88 Expr::FunctionCall {
89 name,
90 distinctness: _,
91 args,
92 order_by: _,
93 filter_over,
94 } => {
95 ret.push_str(&name.0);
96 ret.push('(');
98 if let Some(args) = args {
99 let joined_args = args
100 .iter()
101 .map(|arg| arg.to_sql_string(context))
102 .collect::<Vec<_>>()
103 .join(", ");
104 ret.push_str(&joined_args);
105 }
106 ret.push(')');
107 if let Some(filter_over) = filter_over {
108 if let Some(filter) = &filter_over.filter_clause {
109 ret.push_str(&format!(
110 " FILTER (WHERE {})",
111 filter.to_sql_string(context)
112 ));
113 }
114 if let Some(over) = &filter_over.over_clause {
115 ret.push(' ');
116 ret.push_str(&over.to_sql_string(context));
117 }
118 }
119 }
120 Expr::FunctionCallStar { name, filter_over } => {
121 ret.push_str(&name.0);
122 ret.push_str("(*)");
123 if let Some(filter_over) = filter_over {
124 if let Some(filter) = &filter_over.filter_clause {
125 ret.push_str(&format!(
126 " FILTER (WHERE {})",
127 filter.to_sql_string(context)
128 ));
129 }
130 if let Some(over) = &filter_over.over_clause {
131 ret.push(' ');
132 ret.push_str(&over.to_sql_string(context));
133 }
134 }
135 }
136 Expr::Id(id) => {
137 ret.push_str(&id.0);
138 }
139 Expr::Column {
140 database: _, table,
142 column,
143 is_rowid_alias: _,
144 } => {
145 ret.push_str(context.get_table_name(*table));
146 ret.push('.');
147 ret.push_str(context.get_column_name(*table, *column));
148 }
149 Expr::RowId { database: _, table } => {
150 ret.push_str(&format!("{}.rowid", context.get_table_name(*table)))
151 }
152 Expr::InList { lhs, not, rhs } => {
153 ret.push_str(&format!(
154 "{} {}IN ({})",
155 lhs.to_sql_string(context),
156 if *not { "NOT " } else { "" },
157 if let Some(rhs) = rhs {
158 rhs.iter()
159 .map(|expr| expr.to_sql_string(context))
160 .collect::<Vec<_>>()
161 .join(", ")
162 } else {
163 "".to_string()
164 }
165 ));
166 }
167 Expr::InSelect { lhs, not, rhs } => {
168 ret.push_str(&format!(
169 "{} {}IN ({})",
170 lhs.to_sql_string(context),
171 if *not { "NOT " } else { "" },
172 rhs.to_sql_string(context)
173 ));
174 }
175 Expr::InTable {
176 lhs,
177 not,
178 rhs,
179 args,
180 } => {
181 ret.push_str(&lhs.to_sql_string(context));
182 ret.push(' ');
183 if *not {
184 ret.push_str("NOT ");
185 }
186 ret.push_str(&rhs.to_sql_string(context));
187
188 if let Some(args) = args {
189 ret.push('(');
190 let joined_args = args
191 .iter()
192 .map(|expr| expr.to_sql_string(context))
193 .collect::<Vec<_>>()
194 .join(", ");
195 ret.push_str(&joined_args);
196 ret.push(')');
197 }
198 }
199 Expr::IsNull(expr) => {
200 ret.push_str(&expr.to_sql_string(context));
201 ret.push_str(" ISNULL");
202 }
203 Expr::Like {
204 lhs,
205 not,
206 op,
207 rhs,
208 escape,
209 } => {
210 ret.push_str(&lhs.to_sql_string(context));
211 ret.push(' ');
212 if *not {
213 ret.push_str("NOT ");
214 }
215 ret.push_str(&op.to_string());
216 ret.push(' ');
217 ret.push_str(&rhs.to_sql_string(context));
218 if let Some(escape) = escape {
219 ret.push_str(" ESCAPE ");
220 ret.push_str(&escape.to_sql_string(context));
221 }
222 }
223 Expr::Literal(literal) => {
224 ret.push_str(&literal.to_string());
225 }
226 Expr::Name(name) => {
227 ret.push_str(&name.0);
228 }
229 Expr::NotNull(expr) => {
230 ret.push_str(&expr.to_sql_string(context));
231 ret.push_str(" NOT NULL");
232 }
233 Expr::Parenthesized(exprs) => {
234 ret.push('(');
235 let joined_args = exprs
236 .iter()
237 .map(|expr| expr.to_sql_string(context))
238 .collect::<Vec<_>>()
239 .join(", ");
240 ret.push_str(&joined_args);
241 ret.push(')');
242 }
243 Expr::Qualified(name, name1) => {
244 ret.push_str(&name.0);
245 ret.push('.');
246 ret.push_str(&name1.0);
247 }
248 Expr::Raise(resolve_type, expr) => {
249 ret.push_str("RAISE(");
250 ret.push_str(&resolve_type.to_string());
251 if let Some(expr) = expr {
252 ret.push_str(", ");
253 ret.push_str(&expr.to_sql_string(context));
254 }
255 ret.push(')');
256 }
257 Expr::Subquery(select) => {
258 ret.push('(');
259 ret.push_str(&select.to_sql_string(context));
260 ret.push(')');
261 }
262 Expr::Unary(unary_operator, expr) => {
263 ret.push_str(&unary_operator.to_string());
264 ret.push(' ');
265 ret.push_str(&expr.to_sql_string(context));
266 }
267 Expr::Variable(variable) => {
268 ret.push_str(variable);
269 }
270 };
271 ret
272 }
273}
274
275impl Display for ast::Operator {
276 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
277 let value = match self {
278 Self::Add => "+",
279 Self::And => "AND",
280 Self::ArrowRight => "->",
281 Self::ArrowRightShift => "->>",
282 Self::BitwiseAnd => "&",
283 Self::BitwiseNot => "~",
284 Self::BitwiseOr => "|",
285 Self::Concat => "||",
286 Self::Divide => "/",
287 Self::Equals => "=",
288 Self::Greater => ">",
289 Self::GreaterEquals => ">=",
290 Self::Is => "IS",
291 Self::IsNot => "IS NOT",
292 Self::LeftShift => "<<",
293 Self::Less => "<",
294 Self::LessEquals => "<=",
295 Self::Modulus => "%",
296 Self::Multiply => "*",
297 Self::NotEquals => "!=",
298 Self::Or => "OR",
299 Self::RightShift => ">>",
300 Self::Subtract => "-",
301 };
302 write!(f, "{}", value)
303 }
304}
305
306impl ToSqlString for ast::Type {
307 fn to_sql_string<C: super::ToSqlContext>(&self, context: &C) -> String {
308 let mut ret = self.name.clone();
309 if let Some(size) = &self.size {
310 ret.push(' ');
311 ret.push('(');
312 ret.push_str(&size.to_sql_string(context));
313 ret.push(')');
314 }
315 ret
316 }
317}
318
319impl ToSqlString for ast::TypeSize {
320 fn to_sql_string<C: super::ToSqlContext>(&self, context: &C) -> String {
321 let mut ret = String::new();
322 match self {
323 Self::MaxSize(e) => {
324 ret.push_str(&e.to_sql_string(context));
325 }
326 Self::TypeSize(lhs, rhs) => {
327 ret.push_str(&lhs.to_sql_string(context));
328 ret.push_str(", ");
329 ret.push_str(&rhs.to_sql_string(context));
330 }
331 };
332 ret
333 }
334}
335
336impl Display for ast::Distinctness {
337 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
338 write!(
339 f,
340 "{}",
341 match self {
342 Self::All => "ALL",
343 Self::Distinct => "DISTINCT",
344 }
345 )
346 }
347}
348
349impl ToSqlString for ast::QualifiedName {
351 fn to_sql_string<C: super::ToSqlContext>(&self, _context: &C) -> String {
352 let mut ret = String::new();
353 if let Some(db_name) = &self.db_name {
354 ret.push_str(&db_name.0);
355 ret.push('.');
356 }
357 if let Some(alias) = &self.alias {
358 ret.push_str(&alias.0);
359 ret.push('.');
360 }
361 ret.push_str(&self.name.0);
362 ret
363 }
364}
365
366impl Display for ast::LikeOperator {
367 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
368 self.to_fmt(f)
369 }
370}
371
372impl Display for ast::Literal {
373 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
374 write!(
375 f,
376 "{}",
377 match self {
378 Self::Blob(b) => format!("x'{b}'"),
379 Self::CurrentDate => "CURRENT_DATE".to_string(),
380 Self::CurrentTime => "CURRENT_TIME".to_string(),
381 Self::CurrentTimestamp => "CURRENT_TIMESTAMP".to_string(),
382 Self::Keyword(keyword) => keyword.clone(),
383 Self::Null => "NULL".to_string(),
384 Self::Numeric(num) => num.clone(),
385 Self::String(s) => s.clone(),
386 }
387 )
388 }
389}
390
391impl Display for ast::ResolveType {
392 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
393 self.to_fmt(f)
394 }
395}
396
397impl Display for ast::UnaryOperator {
398 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
399 write!(
400 f,
401 "{}",
402 match self {
403 Self::BitwiseNot => "~",
404 Self::Negative => "-",
405 Self::Not => "NOT",
406 Self::Positive => "+",
407 }
408 )
409 }
410}
411
412impl ToSqlString for ast::Over {
413 fn to_sql_string<C: super::ToSqlContext>(&self, context: &C) -> String {
414 let mut ret = vec!["OVER".to_string()];
415 match self {
416 Self::Name(name) => {
417 ret.push(name.0.clone());
418 }
419 Self::Window(window) => {
420 ret.push(window.to_sql_string(context));
421 }
422 }
423 ret.join(" ")
424 }
425}
426
427#[cfg(test)]
428mod tests {}