1use super::{DialectImpl, DialectType};
6use crate::error::Result;
7use crate::expressions::{
8 AggFunc, BinaryFunc, BinaryOp, Case, Cast, CeilFunc, DataType, DateTimeField, DateTruncFunc,
9 Expression, ExtractFunc, Function, LikeOp, Literal, TrimFunc, TrimPosition, UnaryFunc,
10 VarArgFunc,
11};
12#[cfg(feature = "generate")]
13use crate::generator::GeneratorConfig;
14use crate::tokens::TokenizerConfig;
15
16pub struct SQLiteDialect;
18
19impl DialectImpl for SQLiteDialect {
20 fn dialect_type(&self) -> DialectType {
21 DialectType::SQLite
22 }
23
24 fn tokenizer_config(&self) -> TokenizerConfig {
25 let mut config = TokenizerConfig::default();
26 config.identifiers.insert('"', '"');
28 config.identifiers.insert('[', ']');
29 config.identifiers.insert('`', '`');
30 config.nested_comments = false;
32 config.hex_number_strings = true;
34 config
35 }
36
37 #[cfg(feature = "generate")]
38
39 fn generator_config(&self) -> GeneratorConfig {
40 use crate::generator::IdentifierQuoteStyle;
41 GeneratorConfig {
42 identifier_quote: '"',
43 identifier_quote_style: IdentifierQuoteStyle::DOUBLE_QUOTE,
44 dialect: Some(DialectType::SQLite),
45 json_key_value_pair_sep: ",",
47 supports_table_alias_columns: false,
49 ..Default::default()
50 }
51 }
52
53 #[cfg(feature = "transpile")]
54
55 fn transform_expr(&self, expr: Expression) -> Result<Expression> {
56 match expr {
57 Expression::Nvl(f) => Ok(Expression::IfNull(f)),
59
60 Expression::TryCast(c) => Ok(Expression::Cast(c)),
62
63 Expression::SafeCast(c) => Ok(Expression::Cast(c)),
65
66 Expression::Rand(r) => {
68 let _ = r.seed; Ok(Expression::Function(Box::new(Function::new(
71 "RANDOM".to_string(),
72 vec![],
73 ))))
74 }
75
76 Expression::Random(_) => Ok(Expression::Function(Box::new(Function::new(
78 "RANDOM".to_string(),
79 vec![],
80 )))),
81
82 Expression::ILike(op) => {
84 let lower_left = Expression::Lower(Box::new(UnaryFunc::new(op.left.clone())));
85 let lower_right = Expression::Lower(Box::new(UnaryFunc::new(op.right.clone())));
86 Ok(Expression::Like(Box::new(LikeOp {
87 left: lower_left,
88 right: lower_right,
89 escape: op.escape,
90 quantifier: op.quantifier.clone(),
91 inferred_type: None,
92 })))
93 }
94
95 Expression::CountIf(f) => {
97 let iif_expr = Expression::Function(Box::new(Function::new(
98 "IIF".to_string(),
99 vec![f.this.clone(), Expression::number(1), Expression::number(0)],
100 )));
101 Ok(Expression::Sum(Box::new(AggFunc {
102 ignore_nulls: None,
103 having_max: None,
104 this: iif_expr,
105 distinct: f.distinct,
106 filter: f.filter,
107 order_by: Vec::new(),
108 name: None,
109 limit: None,
110 inferred_type: None,
111 })))
112 }
113
114 Expression::Unnest(_) => Ok(expr),
116
117 Expression::Explode(_) => Ok(expr),
119
120 Expression::Concat(c) => {
122 Ok(Expression::Concat(c))
125 }
126
127 Expression::IfFunc(f) => {
129 let mut args = vec![f.condition, f.true_value];
130 if let Some(false_val) = f.false_value {
131 args.push(false_val);
132 }
133 Ok(Expression::Function(Box::new(Function::new(
134 "IIF".to_string(),
135 args,
136 ))))
137 }
138
139 Expression::Pragma(mut p) => {
141 if p.value.is_some() || p.args.len() == 1 {
142 p.use_assignment_syntax = true;
143 }
144 Ok(Expression::Pragma(p))
145 }
146
147 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Date(_)) => {
149 let Literal::Date(date) = lit.as_ref() else {
150 unreachable!()
151 };
152 Ok(Self::string_literal(date))
153 }
154
155 Expression::Least(f) => Ok(Self::function("MIN", f.expressions)),
157 Expression::Greatest(f) => Ok(Self::function("MAX", f.expressions)),
158
159 Expression::Extract(f) => Self::transform_extract(*f),
161
162 Expression::DateTrunc(f) => Self::transform_date_trunc(*f),
164
165 Expression::Substring(mut f) => {
167 f.from_for_syntax = false;
168 Ok(Expression::Substring(f))
169 }
170
171 Expression::Trim(f) => Ok(Self::transform_trim(*f)),
173
174 Expression::CreateTable(mut ct)
176 if ct
177 .name
178 .schema
179 .as_ref()
180 .is_some_and(|schema| schema.name.eq_ignore_ascii_case("public"))
181 && ct.name.catalog.is_none() =>
182 {
183 ct.name.schema = None;
184 Ok(Expression::CreateTable(ct))
185 }
186
187 Expression::Function(f) => self.transform_function(*f),
189
190 Expression::AggregateFunction(f) => self.transform_aggregate_function(f),
192
193 Expression::Cast(c) => self.transform_cast(*c),
195
196 Expression::Div(mut op) => {
198 let right_is_float = matches!(&op.right, Expression::Literal(lit) if matches!(lit.as_ref(), crate::expressions::Literal::Number(n) if n.contains('.')));
200 let right_is_float_cast = Self::is_float_cast(&op.right);
201 if !Self::is_float_cast(&op.left) && !right_is_float && !right_is_float_cast {
202 op.left = Expression::Cast(Box::new(crate::expressions::Cast {
203 this: op.left,
204 to: crate::expressions::DataType::Float {
205 precision: None,
206 scale: None,
207 real_spelling: true,
208 },
209 trailing_comments: Vec::new(),
210 double_colon_syntax: false,
211 format: None,
212 default: None,
213 inferred_type: None,
214 }));
215 }
216 Ok(Expression::Div(op))
217 }
218
219 _ => Ok(expr),
221 }
222 }
223}
224
225#[cfg(feature = "transpile")]
226impl SQLiteDialect {
227 fn function(name: &str, args: Vec<Expression>) -> Expression {
228 Expression::Function(Box::new(Function::new(name.to_string(), args)))
229 }
230
231 fn string_literal(value: &str) -> Expression {
232 Expression::Literal(Box::new(Literal::String(value.to_string())))
233 }
234
235 fn strftime(format: &str, expr: Expression) -> Expression {
236 Expression::Function(Box::new(Function::new(
237 "STRFTIME".to_string(),
238 vec![Self::string_literal(format), expr],
239 )))
240 }
241
242 fn cast(expr: Expression, to: DataType) -> Expression {
243 Expression::Cast(Box::new(Cast {
244 this: expr,
245 to,
246 trailing_comments: Vec::new(),
247 double_colon_syntax: false,
248 format: None,
249 default: None,
250 inferred_type: None,
251 }))
252 }
253
254 fn sqlite_int_type() -> DataType {
255 DataType::Int {
256 length: None,
257 integer_spelling: true,
258 }
259 }
260
261 fn sqlite_real_type() -> DataType {
262 DataType::Float {
263 precision: None,
264 scale: None,
265 real_spelling: true,
266 }
267 }
268
269 fn transform_extract(f: ExtractFunc) -> Result<Expression> {
270 let strftime_format = match &f.field {
271 DateTimeField::Year => "%Y",
272 DateTimeField::Month => "%m",
273 DateTimeField::Day => "%d",
274 DateTimeField::Hour => "%H",
275 DateTimeField::Minute => "%M",
276 DateTimeField::Second => "%f",
277 DateTimeField::DayOfWeek => "%w",
278 DateTimeField::DayOfYear => "%j",
279 DateTimeField::Epoch => "%s",
280 _ => return Ok(Expression::Extract(Box::new(f))),
281 };
282 let target_type = if matches!(f.field, DateTimeField::Epoch | DateTimeField::Second) {
283 Self::sqlite_real_type()
284 } else {
285 Self::sqlite_int_type()
286 };
287 Ok(Self::cast(
288 Self::strftime(strftime_format, f.this),
289 target_type,
290 ))
291 }
292
293 fn transform_date_trunc(f: DateTruncFunc) -> Result<Expression> {
294 match &f.unit {
295 DateTimeField::Day => Ok(Self::function("DATE", vec![f.this])),
296 DateTimeField::Hour => Ok(Self::strftime("%Y-%m-%d %H:00:00", f.this)),
297 DateTimeField::Minute => Ok(Self::strftime("%Y-%m-%d %H:%M:00", f.this)),
298 DateTimeField::Second => Ok(Self::strftime("%Y-%m-%d %H:%M:%S", f.this)),
299 DateTimeField::Month => Ok(Self::strftime("%Y-%m-01", f.this)),
300 DateTimeField::Year => Ok(Self::strftime("%Y-01-01", f.this)),
301 _ => Ok(Expression::DateTrunc(Box::new(f))),
302 }
303 }
304
305 fn datetime_field_from_expr(expr: &Expression) -> Option<DateTimeField> {
306 let unit = match expr {
307 Expression::Literal(lit) => match lit.as_ref() {
308 Literal::String(s) => s.as_str(),
309 _ => return None,
310 },
311 Expression::Identifier(id) => id.name.as_str(),
312 Expression::Var(v) => v.this.as_str(),
313 Expression::Column(col) if col.table.is_none() => col.name.name.as_str(),
314 _ => return None,
315 };
316 match unit.to_ascii_lowercase().as_str() {
317 "year" | "yyyy" | "yy" => Some(DateTimeField::Year),
318 "month" | "mon" | "mm" => Some(DateTimeField::Month),
319 "day" | "dd" => Some(DateTimeField::Day),
320 "hour" | "hours" | "h" | "hh" | "hr" | "hrs" => Some(DateTimeField::Hour),
321 "minute" | "minutes" | "mi" | "min" | "mins" => Some(DateTimeField::Minute),
322 "second" | "seconds" | "s" | "sec" | "secs" | "ss" => Some(DateTimeField::Second),
323 "dow" | "dayofweek" | "dw" => Some(DateTimeField::DayOfWeek),
324 "doy" | "dayofyear" | "dy" => Some(DateTimeField::DayOfYear),
325 "epoch" => Some(DateTimeField::Epoch),
326 _ => None,
327 }
328 }
329
330 fn transform_trim(f: TrimFunc) -> Expression {
331 let function_name = match f.position {
332 TrimPosition::Leading => "LTRIM",
333 TrimPosition::Trailing => "RTRIM",
334 TrimPosition::Both => "TRIM",
335 };
336 let mut args = vec![f.this];
337 if let Some(characters) = f.characters {
338 args.push(characters);
339 }
340 Expression::Function(Box::new(Function::new(function_name.to_string(), args)))
341 }
342
343 fn is_float_cast(expr: &Expression) -> bool {
345 if let Expression::Cast(cast) = expr {
346 match &cast.to {
347 crate::expressions::DataType::Double { .. }
348 | crate::expressions::DataType::Float { .. } => true,
349 crate::expressions::DataType::Custom { name } => {
350 name.eq_ignore_ascii_case("REAL") || name.eq_ignore_ascii_case("DOUBLE")
351 }
352 _ => false,
353 }
354 } else {
355 false
356 }
357 }
358
359 fn transform_function(&self, f: Function) -> Result<Expression> {
360 let name_upper = f.name.to_uppercase();
361 match name_upper.as_str() {
362 "LIKE" if f.args.len() == 2 => {
364 let mut args = f.args;
365 let pattern = args.remove(0);
366 let string = args.remove(0);
367 Ok(Expression::Like(Box::new(LikeOp::new(string, pattern))))
369 }
370 "LIKE" if f.args.len() == 3 => {
372 let mut args = f.args;
373 let pattern = args.remove(0);
374 let string = args.remove(0);
375 let escape = args.remove(0);
376 Ok(Expression::Like(Box::new(LikeOp {
377 left: string,
378 right: pattern,
379 escape: Some(escape),
380 quantifier: None,
381 inferred_type: None,
382 })))
383 }
384 "GLOB" if f.args.len() == 2 => {
386 let mut args = f.args;
387 let pattern = args.remove(0);
388 let string = args.remove(0);
389 Ok(Expression::Glob(Box::new(BinaryOp::new(string, pattern))))
391 }
392 "NVL" if f.args.len() == 2 => {
394 let mut args = f.args;
395 let expr1 = args.remove(0);
396 let expr2 = args.remove(0);
397 Ok(Expression::IfNull(Box::new(BinaryFunc {
398 original_name: None,
399 this: expr1,
400 expression: expr2,
401 inferred_type: None,
402 })))
403 }
404
405 "COALESCE" => Ok(Expression::Coalesce(Box::new(VarArgFunc {
407 original_name: None,
408 expressions: f.args,
409 inferred_type: None,
410 }))),
411
412 "RAND" => Ok(Expression::Function(Box::new(Function::new(
414 "RANDOM".to_string(),
415 vec![],
416 )))),
417
418 "CHR" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
420 "CHAR".to_string(),
421 f.args,
422 )))),
423
424 "POSITION" if f.args.len() == 2 => {
426 let mut args = f.args;
427 let substring = args.remove(0);
428 let string = args.remove(0);
429 Ok(Expression::Function(Box::new(Function::new(
431 "INSTR".to_string(),
432 vec![string, substring],
433 ))))
434 }
435
436 "STRPOS" if f.args.len() == 2 => {
438 let mut args = f.args;
439 let string = args.remove(0);
440 let substring = args.remove(0);
441 Ok(Expression::Function(Box::new(Function::new(
443 "INSTR".to_string(),
444 vec![string, substring],
445 ))))
446 }
447
448 "CHARINDEX" if f.args.len() >= 2 => {
450 let mut args = f.args;
451 let substring = args.remove(0);
452 let string = args.remove(0);
453 Ok(Expression::Function(Box::new(Function::new(
455 "INSTR".to_string(),
456 vec![string, substring],
457 ))))
458 }
459
460 "LEVENSHTEIN" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
462 Function::new("EDITDIST3".to_string(), f.args),
463 ))),
464
465 "LEAST" if !f.args.is_empty() => Ok(Self::function("MIN", f.args)),
467 "GREATEST" if !f.args.is_empty() => Ok(Self::function("MAX", f.args)),
468 "JSON_BUILD_ARRAY" => Ok(Self::function("JSON_ARRAY", f.args)),
469 "JSON_BUILD_OBJECT" => Ok(Self::function("JSON_OBJECT", f.args)),
470 "JSON_AGG" | "JSONB_AGG" if f.args.len() == 1 => {
471 Ok(Self::function("JSON_GROUP_ARRAY", f.args))
472 }
473 "JSON_OBJECT_AGG" if f.args.len() == 2 => {
474 Ok(Self::function("JSON_GROUP_OBJECT", f.args))
475 }
476
477 "GETDATE" => Ok(Expression::CurrentTimestamp(
479 crate::expressions::CurrentTimestamp {
480 precision: None,
481 sysdate: false,
482 },
483 )),
484
485 "NOW" => Ok(Expression::CurrentTimestamp(
487 crate::expressions::CurrentTimestamp {
488 precision: None,
489 sysdate: false,
490 },
491 )),
492
493 "CEILING" if f.args.len() == 1 => Ok(Expression::Ceil(Box::new(CeilFunc {
495 this: f.args.into_iter().next().unwrap(),
496 decimals: None,
497 to: None,
498 }))),
499
500 "LEN" if f.args.len() == 1 => Ok(Expression::Length(Box::new(UnaryFunc::new(
502 f.args.into_iter().next().unwrap(),
503 )))),
504
505 "SUBSTRING" => Ok(Self::function("SUBSTRING", f.args)),
507
508 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
510 Function::new("GROUP_CONCAT".to_string(), f.args),
511 ))),
512
513 "LISTAGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
515 "GROUP_CONCAT".to_string(),
516 f.args,
517 )))),
518
519 "DATE_PART" if f.args.len() == 2 => {
520 let mut args = f.args;
521 let unit = args.remove(0);
522 let expr = args.remove(0);
523 if let Some(field) = Self::datetime_field_from_expr(&unit) {
524 Self::transform_extract(ExtractFunc { this: expr, field })
525 } else {
526 Ok(Self::function("DATE_PART", vec![unit, expr]))
527 }
528 }
529
530 "DATE_TRUNC" if f.args.len() == 2 => {
531 let mut args = f.args;
532 let unit = args.remove(0);
533 let expr = args.remove(0);
534 if let Some(unit) = Self::datetime_field_from_expr(&unit) {
535 Self::transform_date_trunc(DateTruncFunc { this: expr, unit })
536 } else {
537 Ok(Self::function("DATE_TRUNC", vec![unit, expr]))
538 }
539 }
540
541 "DATEDIFF" | "DATE_DIFF" if f.args.len() == 3 => {
543 let mut args = f.args;
544 let first = args.remove(0); let second = args.remove(0); let unit_expr = args.remove(0); let unit_str = match &unit_expr {
550 Expression::Literal(lit)
551 if matches!(lit.as_ref(), crate::expressions::Literal::String(_)) =>
552 {
553 let crate::expressions::Literal::String(s) = lit.as_ref() else {
554 unreachable!()
555 };
556 s.to_lowercase()
557 }
558 Expression::Identifier(id) => id.name.to_lowercase(),
559 Expression::Var(v) => v.this.to_lowercase(),
560 Expression::Column(col) if col.table.is_none() => col.name.name.to_lowercase(),
561 _ => "day".to_string(),
562 };
563
564 let jd_first = Expression::Function(Box::new(Function::new(
566 "JULIANDAY".to_string(),
567 vec![first],
568 )));
569 let jd_second = Expression::Function(Box::new(Function::new(
570 "JULIANDAY".to_string(),
571 vec![second],
572 )));
573 let diff = Expression::Sub(Box::new(BinaryOp::new(jd_first, jd_second)));
574 let paren_diff = Expression::Paren(Box::new(crate::expressions::Paren {
575 this: diff,
576 trailing_comments: Vec::new(),
577 }));
578
579 let adjusted = match unit_str.as_str() {
581 "hour" => Expression::Mul(Box::new(BinaryOp::new(
582 paren_diff,
583 Expression::Literal(Box::new(crate::expressions::Literal::Number(
584 "24.0".to_string(),
585 ))),
586 ))),
587 "minute" => Expression::Mul(Box::new(BinaryOp::new(
588 paren_diff,
589 Expression::Literal(Box::new(crate::expressions::Literal::Number(
590 "1440.0".to_string(),
591 ))),
592 ))),
593 "second" => Expression::Mul(Box::new(BinaryOp::new(
594 paren_diff,
595 Expression::Literal(Box::new(crate::expressions::Literal::Number(
596 "86400.0".to_string(),
597 ))),
598 ))),
599 "month" => Expression::Div(Box::new(BinaryOp::new(
600 paren_diff,
601 Expression::Literal(Box::new(crate::expressions::Literal::Number(
602 "30.0".to_string(),
603 ))),
604 ))),
605 "year" => Expression::Div(Box::new(BinaryOp::new(
606 paren_diff,
607 Expression::Literal(Box::new(crate::expressions::Literal::Number(
608 "365.0".to_string(),
609 ))),
610 ))),
611 _ => paren_diff, };
613
614 Ok(Expression::Cast(Box::new(Cast {
616 this: adjusted,
617 to: crate::expressions::DataType::Int {
618 length: None,
619 integer_spelling: true,
620 },
621 trailing_comments: Vec::new(),
622 double_colon_syntax: false,
623 format: None,
624 default: None,
625 inferred_type: None,
626 })))
627 }
628
629 "STRFTIME" if f.args.len() == 1 => {
631 let mut args = f.args;
632 args.push(Expression::CurrentTimestamp(
633 crate::expressions::CurrentTimestamp {
634 precision: None,
635 sysdate: false,
636 },
637 ));
638 Ok(Expression::Function(Box::new(Function::new(
639 "STRFTIME".to_string(),
640 args,
641 ))))
642 }
643
644 "CONCAT" if f.args.len() >= 2 => {
646 let mut args = f.args;
647 let mut result = args.remove(0);
648 for arg in args {
649 result = Expression::DPipe(Box::new(crate::expressions::DPipe {
650 this: Box::new(result),
651 expression: Box::new(arg),
652 safe: None,
653 }));
654 }
655 Ok(result)
656 }
657
658 "TRUNC" if f.args.len() > 1 => Ok(Expression::Function(Box::new(Function::new(
660 "TRUNC".to_string(),
661 vec![f.args[0].clone()],
662 )))),
663
664 _ => Ok(Expression::Function(Box::new(f))),
666 }
667 }
668
669 fn transform_aggregate_function(
670 &self,
671 f: Box<crate::expressions::AggregateFunction>,
672 ) -> Result<Expression> {
673 let name_upper = f.name.to_uppercase();
674 match name_upper.as_str() {
675 "COUNT_IF" if !f.args.is_empty() => {
677 let condition = f.args.into_iter().next().unwrap();
678 let case_expr = Expression::Case(Box::new(Case {
679 operand: None,
680 whens: vec![(condition, Expression::number(1))],
681 else_: Some(Expression::number(0)),
682 comments: Vec::new(),
683 inferred_type: None,
684 }));
685 Ok(Expression::Sum(Box::new(AggFunc {
686 ignore_nulls: None,
687 having_max: None,
688 this: case_expr,
689 distinct: f.distinct,
690 filter: f.filter,
691 order_by: Vec::new(),
692 name: None,
693 limit: None,
694 inferred_type: None,
695 })))
696 }
697
698 "ANY_VALUE" if !f.args.is_empty() => {
700 let arg = f.args.into_iter().next().unwrap();
701 Ok(Expression::Max(Box::new(AggFunc {
702 ignore_nulls: None,
703 having_max: None,
704 this: arg,
705 distinct: f.distinct,
706 filter: f.filter,
707 order_by: Vec::new(),
708 name: None,
709 limit: None,
710 inferred_type: None,
711 })))
712 }
713
714 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
716 Function::new("GROUP_CONCAT".to_string(), f.args),
717 ))),
718
719 "LISTAGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
721 "GROUP_CONCAT".to_string(),
722 f.args,
723 )))),
724
725 "ARRAY_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
727 "GROUP_CONCAT".to_string(),
728 f.args,
729 )))),
730
731 "JSON_AGG" | "JSONB_AGG" if f.args.len() == 1 => {
732 Ok(Self::function("JSON_GROUP_ARRAY", f.args))
733 }
734
735 "JSON_OBJECT_AGG" if f.args.len() == 2 => {
736 Ok(Self::function("JSON_GROUP_OBJECT", f.args))
737 }
738
739 _ => Ok(Expression::AggregateFunction(f)),
741 }
742 }
743
744 fn transform_cast(&self, c: Cast) -> Result<Expression> {
745 Ok(Expression::Cast(Box::new(c)))
749 }
750}