1use super::{DialectImpl, DialectType};
6use crate::error::Result;
7use crate::expressions::{
8 AggFunc, BinaryFunc, BinaryOp, Case, Cast, CeilFunc, Expression, Function, LikeOp, UnaryFunc, VarArgFunc,
9};
10use crate::generator::GeneratorConfig;
11use crate::tokens::TokenizerConfig;
12
13pub struct SQLiteDialect;
15
16impl DialectImpl for SQLiteDialect {
17 fn dialect_type(&self) -> DialectType {
18 DialectType::SQLite
19 }
20
21 fn tokenizer_config(&self) -> TokenizerConfig {
22 let mut config = TokenizerConfig::default();
23 config.identifiers.insert('"', '"');
25 config.identifiers.insert('[', ']');
26 config.identifiers.insert('`', '`');
27 config.nested_comments = false;
29 config.hex_number_strings = true;
31 config
32 }
33
34 fn generator_config(&self) -> GeneratorConfig {
35 use crate::generator::IdentifierQuoteStyle;
36 GeneratorConfig {
37 identifier_quote: '"',
38 identifier_quote_style: IdentifierQuoteStyle::DOUBLE_QUOTE,
39 dialect: Some(DialectType::SQLite),
40 json_key_value_pair_sep: ",",
42 supports_table_alias_columns: false,
44 ..Default::default()
45 }
46 }
47
48 fn transform_expr(&self, expr: Expression) -> Result<Expression> {
49 match expr {
50 Expression::Nvl(f) => Ok(Expression::IfNull(f)),
52
53 Expression::TryCast(c) => Ok(Expression::Cast(c)),
55
56 Expression::SafeCast(c) => Ok(Expression::Cast(c)),
58
59 Expression::Rand(r) => {
61 let _ = r.seed; Ok(Expression::Function(Box::new(Function::new(
64 "RANDOM".to_string(),
65 vec![],
66 ))))
67 }
68
69 Expression::Random(_) => Ok(Expression::Function(Box::new(Function::new(
71 "RANDOM".to_string(),
72 vec![],
73 )))),
74
75 Expression::ILike(op) => {
77 let lower_left = Expression::Lower(Box::new(UnaryFunc::new(op.left.clone())));
78 let lower_right = Expression::Lower(Box::new(UnaryFunc::new(op.right.clone())));
79 Ok(Expression::Like(Box::new(LikeOp {
80 left: lower_left,
81 right: lower_right,
82 escape: op.escape,
83 quantifier: op.quantifier.clone(),
84 })))
85 }
86
87 Expression::CountIf(f) => {
89 let case_expr = Expression::Case(Box::new(Case {
90 operand: None,
91 whens: vec![(f.this.clone(), Expression::number(1))],
92 else_: Some(Expression::number(0)),
93 }));
94 Ok(Expression::Sum(Box::new(AggFunc { ignore_nulls: None, having_max: None,
95 this: case_expr,
96 distinct: f.distinct,
97 filter: f.filter,
98 order_by: Vec::new(),
99 name: None,
100 limit: None,
101 })))
102 }
103
104 Expression::Unnest(_) => Ok(expr),
106
107 Expression::Explode(_) => Ok(expr),
109
110 Expression::Concat(c) => {
112 Ok(Expression::Concat(c))
115 }
116
117 Expression::IfFunc(f) => {
119 let mut args = vec![f.condition, f.true_value];
120 if let Some(false_val) = f.false_value {
121 args.push(false_val);
122 }
123 Ok(Expression::Function(Box::new(Function::new(
124 "IIF".to_string(),
125 args,
126 ))))
127 }
128
129 Expression::Function(f) => self.transform_function(*f),
131
132 Expression::AggregateFunction(f) => self.transform_aggregate_function(f),
134
135 Expression::Cast(c) => self.transform_cast(*c),
137
138 Expression::Div(mut op) => {
140 let right_is_float = matches!(&op.right, Expression::Literal(crate::expressions::Literal::Number(n)) if n.contains('.'));
142 let right_is_float_cast = Self::is_float_cast(&op.right);
143 if !Self::is_float_cast(&op.left) && !right_is_float && !right_is_float_cast {
144 op.left = Expression::Cast(Box::new(crate::expressions::Cast {
145 this: op.left,
146 to: crate::expressions::DataType::Float { precision: None, scale: None, real_spelling: true },
147 trailing_comments: Vec::new(),
148 double_colon_syntax: false,
149 format: None,
150 default: None,
151 }));
152 }
153 Ok(Expression::Div(op))
154 }
155
156 _ => Ok(expr),
158 }
159 }
160}
161
162impl SQLiteDialect {
163 fn is_float_cast(expr: &Expression) -> bool {
165 if let Expression::Cast(cast) = expr {
166 match &cast.to {
167 crate::expressions::DataType::Double { .. }
168 | crate::expressions::DataType::Float { .. } => true,
169 crate::expressions::DataType::Custom { name } => {
170 name.eq_ignore_ascii_case("REAL") || name.eq_ignore_ascii_case("DOUBLE")
171 }
172 _ => false,
173 }
174 } else {
175 false
176 }
177 }
178
179 fn transform_function(&self, f: Function) -> Result<Expression> {
180 let name_upper = f.name.to_uppercase();
181 match name_upper.as_str() {
182 "LIKE" if f.args.len() == 2 => {
184 let mut args = f.args;
185 let pattern = args.remove(0);
186 let string = args.remove(0);
187 Ok(Expression::Like(Box::new(LikeOp::new(string, pattern))))
189 }
190 "LIKE" if f.args.len() == 3 => {
192 let mut args = f.args;
193 let pattern = args.remove(0);
194 let string = args.remove(0);
195 let escape = args.remove(0);
196 Ok(Expression::Like(Box::new(LikeOp {
197 left: string,
198 right: pattern,
199 escape: Some(escape),
200 quantifier: None,
201 })))
202 }
203 "GLOB" if f.args.len() == 2 => {
205 let mut args = f.args;
206 let pattern = args.remove(0);
207 let string = args.remove(0);
208 Ok(Expression::Glob(Box::new(BinaryOp::new(string, pattern))))
210 }
211 "NVL" if f.args.len() == 2 => {
213 let mut args = f.args;
214 let expr1 = args.remove(0);
215 let expr2 = args.remove(0);
216 Ok(Expression::IfNull(Box::new(BinaryFunc { original_name: None,
217 this: expr1,
218 expression: expr2,
219 })))
220 }
221
222 "COALESCE" => Ok(Expression::Coalesce(Box::new(VarArgFunc { original_name: None,
224 expressions: f.args,
225 }))),
226
227 "RAND" => Ok(Expression::Function(Box::new(Function::new(
229 "RANDOM".to_string(),
230 vec![],
231 )))),
232
233 "CHR" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
235 "CHAR".to_string(),
236 f.args,
237 )))),
238
239 "POSITION" if f.args.len() == 2 => {
241 let mut args = f.args;
242 let substring = args.remove(0);
243 let string = args.remove(0);
244 Ok(Expression::Function(Box::new(Function::new(
246 "INSTR".to_string(),
247 vec![string, substring],
248 ))))
249 }
250
251 "STRPOS" if f.args.len() == 2 => {
253 let mut args = f.args;
254 let string = args.remove(0);
255 let substring = args.remove(0);
256 Ok(Expression::Function(Box::new(Function::new(
258 "INSTR".to_string(),
259 vec![string, substring],
260 ))))
261 }
262
263 "CHARINDEX" if f.args.len() >= 2 => {
265 let mut args = f.args;
266 let substring = args.remove(0);
267 let string = args.remove(0);
268 Ok(Expression::Function(Box::new(Function::new(
270 "INSTR".to_string(),
271 vec![string, substring],
272 ))))
273 }
274
275 "LEVENSHTEIN" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
277 Function::new("EDITDIST3".to_string(), f.args),
278 ))),
279
280 "GETDATE" => Ok(Expression::CurrentTimestamp(
282 crate::expressions::CurrentTimestamp { precision: None, sysdate: false },
283 )),
284
285 "NOW" => Ok(Expression::CurrentTimestamp(
287 crate::expressions::CurrentTimestamp { precision: None, sysdate: false },
288 )),
289
290 "CEILING" if f.args.len() == 1 => Ok(Expression::Ceil(Box::new(CeilFunc {
292 this: f.args.into_iter().next().unwrap(),
293 decimals: None,
294 to: None,
295 }))),
296
297 "LEN" if f.args.len() == 1 => Ok(Expression::Length(Box::new(UnaryFunc::new(
299 f.args.into_iter().next().unwrap(),
300 )))),
301
302 "SUBSTRING" => Ok(Expression::Function(Box::new(Function::new(
304 "SUBSTR".to_string(),
305 f.args,
306 )))),
307
308 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
310 Function::new("GROUP_CONCAT".to_string(), f.args),
311 ))),
312
313 "LISTAGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
315 Function::new("GROUP_CONCAT".to_string(), f.args),
316 ))),
317
318 "DATEDIFF" | "DATE_DIFF" if f.args.len() == 3 => {
320 let mut args = f.args;
321 let first = args.remove(0); let second = args.remove(0); let unit_expr = args.remove(0); let unit_str = match &unit_expr {
327 Expression::Literal(crate::expressions::Literal::String(s)) => s.to_lowercase(),
328 Expression::Identifier(id) => id.name.to_lowercase(),
329 _ => "day".to_string(),
330 };
331
332 let jd_first = Expression::Function(Box::new(Function::new(
334 "JULIANDAY".to_string(),
335 vec![first],
336 )));
337 let jd_second = Expression::Function(Box::new(Function::new(
338 "JULIANDAY".to_string(),
339 vec![second],
340 )));
341 let diff = Expression::Sub(Box::new(BinaryOp::new(jd_first, jd_second)));
342 let paren_diff = Expression::Paren(Box::new(crate::expressions::Paren {
343 this: diff,
344 trailing_comments: Vec::new(),
345 }));
346
347 let adjusted = match unit_str.as_str() {
349 "hour" => Expression::Mul(Box::new(BinaryOp::new(
350 paren_diff,
351 Expression::Literal(crate::expressions::Literal::Number("24.0".to_string())),
352 ))),
353 "minute" => Expression::Mul(Box::new(BinaryOp::new(
354 paren_diff,
355 Expression::Literal(crate::expressions::Literal::Number("1440.0".to_string())),
356 ))),
357 "second" => Expression::Mul(Box::new(BinaryOp::new(
358 paren_diff,
359 Expression::Literal(crate::expressions::Literal::Number("86400.0".to_string())),
360 ))),
361 "month" => Expression::Div(Box::new(BinaryOp::new(
362 paren_diff,
363 Expression::Literal(crate::expressions::Literal::Number("30.0".to_string())),
364 ))),
365 "year" => Expression::Div(Box::new(BinaryOp::new(
366 paren_diff,
367 Expression::Literal(crate::expressions::Literal::Number("365.0".to_string())),
368 ))),
369 _ => paren_diff, };
371
372 Ok(Expression::Cast(Box::new(Cast {
374 this: adjusted,
375 to: crate::expressions::DataType::Int { length: None, integer_spelling: true },
376 trailing_comments: Vec::new(),
377 double_colon_syntax: false,
378 format: None,
379 default: None,
380 })))
381 }
382
383 "STRFTIME" if f.args.len() == 1 => {
385 let mut args = f.args;
386 args.push(Expression::CurrentTimestamp(
387 crate::expressions::CurrentTimestamp { precision: None, sysdate: false },
388 ));
389 Ok(Expression::Function(Box::new(Function::new(
390 "STRFTIME".to_string(),
391 args,
392 ))))
393 }
394
395 _ => Ok(Expression::Function(Box::new(f))),
397 }
398 }
399
400 fn transform_aggregate_function(
401 &self,
402 f: Box<crate::expressions::AggregateFunction>,
403 ) -> Result<Expression> {
404 let name_upper = f.name.to_uppercase();
405 match name_upper.as_str() {
406 "COUNT_IF" if !f.args.is_empty() => {
408 let condition = f.args.into_iter().next().unwrap();
409 let case_expr = Expression::Case(Box::new(Case {
410 operand: None,
411 whens: vec![(condition, Expression::number(1))],
412 else_: Some(Expression::number(0)),
413 }));
414 Ok(Expression::Sum(Box::new(AggFunc { ignore_nulls: None, having_max: None,
415 this: case_expr,
416 distinct: f.distinct,
417 filter: f.filter,
418 order_by: Vec::new(),
419 name: None,
420 limit: None,
421 })))
422 }
423
424 "ANY_VALUE" if !f.args.is_empty() => {
426 let arg = f.args.into_iter().next().unwrap();
427 Ok(Expression::Max(Box::new(AggFunc { ignore_nulls: None, having_max: None,
428 this: arg,
429 distinct: f.distinct,
430 filter: f.filter,
431 order_by: Vec::new(),
432 name: None,
433 limit: None,
434 })))
435 }
436
437 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
439 Function::new("GROUP_CONCAT".to_string(), f.args),
440 ))),
441
442 "LISTAGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
444 Function::new("GROUP_CONCAT".to_string(), f.args),
445 ))),
446
447 "ARRAY_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
449 Function::new("GROUP_CONCAT".to_string(), f.args),
450 ))),
451
452 _ => Ok(Expression::AggregateFunction(f)),
454 }
455 }
456
457 fn transform_cast(&self, c: Cast) -> Result<Expression> {
458 Ok(Expression::Cast(Box::new(c)))
462 }
463}