1use super::{DialectImpl, DialectType};
6use crate::error::Result;
7use crate::expressions::{
8 AggFunc, BinaryFunc, BinaryOp, Case, Cast, CeilFunc, Expression, Function, LikeOp, UnaryFunc,
9 VarArgFunc,
10};
11use crate::generator::GeneratorConfig;
12use crate::tokens::TokenizerConfig;
13
14pub struct SQLiteDialect;
16
17impl DialectImpl for SQLiteDialect {
18 fn dialect_type(&self) -> DialectType {
19 DialectType::SQLite
20 }
21
22 fn tokenizer_config(&self) -> TokenizerConfig {
23 let mut config = TokenizerConfig::default();
24 config.identifiers.insert('"', '"');
26 config.identifiers.insert('[', ']');
27 config.identifiers.insert('`', '`');
28 config.nested_comments = false;
30 config.hex_number_strings = true;
32 config
33 }
34
35 fn generator_config(&self) -> GeneratorConfig {
36 use crate::generator::IdentifierQuoteStyle;
37 GeneratorConfig {
38 identifier_quote: '"',
39 identifier_quote_style: IdentifierQuoteStyle::DOUBLE_QUOTE,
40 dialect: Some(DialectType::SQLite),
41 json_key_value_pair_sep: ",",
43 supports_table_alias_columns: false,
45 ..Default::default()
46 }
47 }
48
49 fn transform_expr(&self, expr: Expression) -> Result<Expression> {
50 match expr {
51 Expression::Nvl(f) => Ok(Expression::IfNull(f)),
53
54 Expression::TryCast(c) => Ok(Expression::Cast(c)),
56
57 Expression::SafeCast(c) => Ok(Expression::Cast(c)),
59
60 Expression::Rand(r) => {
62 let _ = r.seed; Ok(Expression::Function(Box::new(Function::new(
65 "RANDOM".to_string(),
66 vec![],
67 ))))
68 }
69
70 Expression::Random(_) => Ok(Expression::Function(Box::new(Function::new(
72 "RANDOM".to_string(),
73 vec![],
74 )))),
75
76 Expression::ILike(op) => {
78 let lower_left = Expression::Lower(Box::new(UnaryFunc::new(op.left.clone())));
79 let lower_right = Expression::Lower(Box::new(UnaryFunc::new(op.right.clone())));
80 Ok(Expression::Like(Box::new(LikeOp {
81 left: lower_left,
82 right: lower_right,
83 escape: op.escape,
84 quantifier: op.quantifier.clone(),
85 inferred_type: None,
86 })))
87 }
88
89 Expression::CountIf(f) => {
91 let iif_expr = Expression::Function(Box::new(Function::new(
92 "IIF".to_string(),
93 vec![f.this.clone(), Expression::number(1), Expression::number(0)],
94 )));
95 Ok(Expression::Sum(Box::new(AggFunc {
96 ignore_nulls: None,
97 having_max: None,
98 this: iif_expr,
99 distinct: f.distinct,
100 filter: f.filter,
101 order_by: Vec::new(),
102 name: None,
103 limit: None,
104 inferred_type: None,
105 })))
106 }
107
108 Expression::Unnest(_) => Ok(expr),
110
111 Expression::Explode(_) => Ok(expr),
113
114 Expression::Concat(c) => {
116 Ok(Expression::Concat(c))
119 }
120
121 Expression::IfFunc(f) => {
123 let mut args = vec![f.condition, f.true_value];
124 if let Some(false_val) = f.false_value {
125 args.push(false_val);
126 }
127 Ok(Expression::Function(Box::new(Function::new(
128 "IIF".to_string(),
129 args,
130 ))))
131 }
132
133 Expression::Pragma(mut p) => {
135 if p.value.is_some() || p.args.len() == 1 {
136 p.use_assignment_syntax = true;
137 }
138 Ok(Expression::Pragma(p))
139 }
140
141 Expression::Function(f) => self.transform_function(*f),
143
144 Expression::AggregateFunction(f) => self.transform_aggregate_function(f),
146
147 Expression::Cast(c) => self.transform_cast(*c),
149
150 Expression::Div(mut op) => {
152 let right_is_float = matches!(&op.right, Expression::Literal(lit) if matches!(lit.as_ref(), crate::expressions::Literal::Number(n) if n.contains('.')));
154 let right_is_float_cast = Self::is_float_cast(&op.right);
155 if !Self::is_float_cast(&op.left) && !right_is_float && !right_is_float_cast {
156 op.left = Expression::Cast(Box::new(crate::expressions::Cast {
157 this: op.left,
158 to: crate::expressions::DataType::Float {
159 precision: None,
160 scale: None,
161 real_spelling: true,
162 },
163 trailing_comments: Vec::new(),
164 double_colon_syntax: false,
165 format: None,
166 default: None,
167 inferred_type: None,
168 }));
169 }
170 Ok(Expression::Div(op))
171 }
172
173 _ => Ok(expr),
175 }
176 }
177}
178
179impl SQLiteDialect {
180 fn is_float_cast(expr: &Expression) -> bool {
182 if let Expression::Cast(cast) = expr {
183 match &cast.to {
184 crate::expressions::DataType::Double { .. }
185 | crate::expressions::DataType::Float { .. } => true,
186 crate::expressions::DataType::Custom { name } => {
187 name.eq_ignore_ascii_case("REAL") || name.eq_ignore_ascii_case("DOUBLE")
188 }
189 _ => false,
190 }
191 } else {
192 false
193 }
194 }
195
196 fn transform_function(&self, f: Function) -> Result<Expression> {
197 let name_upper = f.name.to_uppercase();
198 match name_upper.as_str() {
199 "LIKE" if f.args.len() == 2 => {
201 let mut args = f.args;
202 let pattern = args.remove(0);
203 let string = args.remove(0);
204 Ok(Expression::Like(Box::new(LikeOp::new(string, pattern))))
206 }
207 "LIKE" if f.args.len() == 3 => {
209 let mut args = f.args;
210 let pattern = args.remove(0);
211 let string = args.remove(0);
212 let escape = args.remove(0);
213 Ok(Expression::Like(Box::new(LikeOp {
214 left: string,
215 right: pattern,
216 escape: Some(escape),
217 quantifier: None,
218 inferred_type: None,
219 })))
220 }
221 "GLOB" if f.args.len() == 2 => {
223 let mut args = f.args;
224 let pattern = args.remove(0);
225 let string = args.remove(0);
226 Ok(Expression::Glob(Box::new(BinaryOp::new(string, pattern))))
228 }
229 "NVL" if f.args.len() == 2 => {
231 let mut args = f.args;
232 let expr1 = args.remove(0);
233 let expr2 = args.remove(0);
234 Ok(Expression::IfNull(Box::new(BinaryFunc {
235 original_name: None,
236 this: expr1,
237 expression: expr2,
238 inferred_type: None,
239 })))
240 }
241
242 "COALESCE" => Ok(Expression::Coalesce(Box::new(VarArgFunc {
244 original_name: None,
245 expressions: f.args,
246 inferred_type: None,
247 }))),
248
249 "RAND" => Ok(Expression::Function(Box::new(Function::new(
251 "RANDOM".to_string(),
252 vec![],
253 )))),
254
255 "CHR" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
257 "CHAR".to_string(),
258 f.args,
259 )))),
260
261 "POSITION" if f.args.len() == 2 => {
263 let mut args = f.args;
264 let substring = args.remove(0);
265 let string = args.remove(0);
266 Ok(Expression::Function(Box::new(Function::new(
268 "INSTR".to_string(),
269 vec![string, substring],
270 ))))
271 }
272
273 "STRPOS" if f.args.len() == 2 => {
275 let mut args = f.args;
276 let string = args.remove(0);
277 let substring = args.remove(0);
278 Ok(Expression::Function(Box::new(Function::new(
280 "INSTR".to_string(),
281 vec![string, substring],
282 ))))
283 }
284
285 "CHARINDEX" if f.args.len() >= 2 => {
287 let mut args = f.args;
288 let substring = args.remove(0);
289 let string = args.remove(0);
290 Ok(Expression::Function(Box::new(Function::new(
292 "INSTR".to_string(),
293 vec![string, substring],
294 ))))
295 }
296
297 "LEVENSHTEIN" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
299 Function::new("EDITDIST3".to_string(), f.args),
300 ))),
301
302 "GETDATE" => Ok(Expression::CurrentTimestamp(
304 crate::expressions::CurrentTimestamp {
305 precision: None,
306 sysdate: false,
307 },
308 )),
309
310 "NOW" => Ok(Expression::CurrentTimestamp(
312 crate::expressions::CurrentTimestamp {
313 precision: None,
314 sysdate: false,
315 },
316 )),
317
318 "CEILING" if f.args.len() == 1 => Ok(Expression::Ceil(Box::new(CeilFunc {
320 this: f.args.into_iter().next().unwrap(),
321 decimals: None,
322 to: None,
323 }))),
324
325 "LEN" if f.args.len() == 1 => Ok(Expression::Length(Box::new(UnaryFunc::new(
327 f.args.into_iter().next().unwrap(),
328 )))),
329
330 "SUBSTRING" => Ok(Expression::Function(Box::new(Function::new(
332 "SUBSTRING".to_string(),
333 f.args,
334 )))),
335
336 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
338 Function::new("GROUP_CONCAT".to_string(), f.args),
339 ))),
340
341 "LISTAGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
343 "GROUP_CONCAT".to_string(),
344 f.args,
345 )))),
346
347 "DATEDIFF" | "DATE_DIFF" if f.args.len() == 3 => {
349 let mut args = f.args;
350 let first = args.remove(0); let second = args.remove(0); let unit_expr = args.remove(0); let unit_str = match &unit_expr {
356 Expression::Literal(lit)
357 if matches!(lit.as_ref(), crate::expressions::Literal::String(_)) =>
358 {
359 let crate::expressions::Literal::String(s) = lit.as_ref() else {
360 unreachable!()
361 };
362 s.to_lowercase()
363 }
364 Expression::Identifier(id) => id.name.to_lowercase(),
365 Expression::Var(v) => v.this.to_lowercase(),
366 Expression::Column(col) if col.table.is_none() => col.name.name.to_lowercase(),
367 _ => "day".to_string(),
368 };
369
370 let jd_first = Expression::Function(Box::new(Function::new(
372 "JULIANDAY".to_string(),
373 vec![first],
374 )));
375 let jd_second = Expression::Function(Box::new(Function::new(
376 "JULIANDAY".to_string(),
377 vec![second],
378 )));
379 let diff = Expression::Sub(Box::new(BinaryOp::new(jd_first, jd_second)));
380 let paren_diff = Expression::Paren(Box::new(crate::expressions::Paren {
381 this: diff,
382 trailing_comments: Vec::new(),
383 }));
384
385 let adjusted = match unit_str.as_str() {
387 "hour" => Expression::Mul(Box::new(BinaryOp::new(
388 paren_diff,
389 Expression::Literal(Box::new(crate::expressions::Literal::Number(
390 "24.0".to_string(),
391 ))),
392 ))),
393 "minute" => Expression::Mul(Box::new(BinaryOp::new(
394 paren_diff,
395 Expression::Literal(Box::new(crate::expressions::Literal::Number(
396 "1440.0".to_string(),
397 ))),
398 ))),
399 "second" => Expression::Mul(Box::new(BinaryOp::new(
400 paren_diff,
401 Expression::Literal(Box::new(crate::expressions::Literal::Number(
402 "86400.0".to_string(),
403 ))),
404 ))),
405 "month" => Expression::Div(Box::new(BinaryOp::new(
406 paren_diff,
407 Expression::Literal(Box::new(crate::expressions::Literal::Number(
408 "30.0".to_string(),
409 ))),
410 ))),
411 "year" => Expression::Div(Box::new(BinaryOp::new(
412 paren_diff,
413 Expression::Literal(Box::new(crate::expressions::Literal::Number(
414 "365.0".to_string(),
415 ))),
416 ))),
417 _ => paren_diff, };
419
420 Ok(Expression::Cast(Box::new(Cast {
422 this: adjusted,
423 to: crate::expressions::DataType::Int {
424 length: None,
425 integer_spelling: true,
426 },
427 trailing_comments: Vec::new(),
428 double_colon_syntax: false,
429 format: None,
430 default: None,
431 inferred_type: None,
432 })))
433 }
434
435 "STRFTIME" if f.args.len() == 1 => {
437 let mut args = f.args;
438 args.push(Expression::CurrentTimestamp(
439 crate::expressions::CurrentTimestamp {
440 precision: None,
441 sysdate: false,
442 },
443 ));
444 Ok(Expression::Function(Box::new(Function::new(
445 "STRFTIME".to_string(),
446 args,
447 ))))
448 }
449
450 "CONCAT" if f.args.len() >= 2 => {
452 let mut args = f.args;
453 let mut result = args.remove(0);
454 for arg in args {
455 result = Expression::DPipe(Box::new(crate::expressions::DPipe {
456 this: Box::new(result),
457 expression: Box::new(arg),
458 safe: None,
459 }));
460 }
461 Ok(result)
462 }
463
464 "TRUNC" if f.args.len() > 1 => Ok(Expression::Function(Box::new(Function::new(
466 "TRUNC".to_string(),
467 vec![f.args[0].clone()],
468 )))),
469
470 _ => Ok(Expression::Function(Box::new(f))),
472 }
473 }
474
475 fn transform_aggregate_function(
476 &self,
477 f: Box<crate::expressions::AggregateFunction>,
478 ) -> Result<Expression> {
479 let name_upper = f.name.to_uppercase();
480 match name_upper.as_str() {
481 "COUNT_IF" if !f.args.is_empty() => {
483 let condition = f.args.into_iter().next().unwrap();
484 let case_expr = Expression::Case(Box::new(Case {
485 operand: None,
486 whens: vec![(condition, Expression::number(1))],
487 else_: Some(Expression::number(0)),
488 comments: Vec::new(),
489 inferred_type: None,
490 }));
491 Ok(Expression::Sum(Box::new(AggFunc {
492 ignore_nulls: None,
493 having_max: None,
494 this: case_expr,
495 distinct: f.distinct,
496 filter: f.filter,
497 order_by: Vec::new(),
498 name: None,
499 limit: None,
500 inferred_type: None,
501 })))
502 }
503
504 "ANY_VALUE" if !f.args.is_empty() => {
506 let arg = f.args.into_iter().next().unwrap();
507 Ok(Expression::Max(Box::new(AggFunc {
508 ignore_nulls: None,
509 having_max: None,
510 this: arg,
511 distinct: f.distinct,
512 filter: f.filter,
513 order_by: Vec::new(),
514 name: None,
515 limit: None,
516 inferred_type: None,
517 })))
518 }
519
520 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
522 Function::new("GROUP_CONCAT".to_string(), f.args),
523 ))),
524
525 "LISTAGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
527 "GROUP_CONCAT".to_string(),
528 f.args,
529 )))),
530
531 "ARRAY_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
533 "GROUP_CONCAT".to_string(),
534 f.args,
535 )))),
536
537 _ => Ok(Expression::AggregateFunction(f)),
539 }
540 }
541
542 fn transform_cast(&self, c: Cast) -> Result<Expression> {
543 Ok(Expression::Cast(Box::new(c)))
547 }
548}