1use super::{DialectImpl, DialectType};
7use crate::error::Result;
8use crate::expressions::{
9 AggFunc, Case, Cast, DataType, Expression, Function, Limit, RegexpFunc, VarArgFunc,
10};
11#[cfg(feature = "generate")]
12use crate::generator::GeneratorConfig;
13use crate::tokens::TokenizerConfig;
14
15pub struct RedshiftDialect;
17
18impl DialectImpl for RedshiftDialect {
19 fn dialect_type(&self) -> DialectType {
20 DialectType::Redshift
21 }
22
23 fn tokenizer_config(&self) -> TokenizerConfig {
24 use crate::tokens::TokenType;
25 let mut config = TokenizerConfig::default();
26 config.identifiers.insert('"', '"');
28 config.nested_comments = false;
30 config
32 .keywords
33 .insert("MINUS".to_string(), TokenType::Except);
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::Redshift),
45 supports_column_join_marks: true,
46 locking_reads_supported: false,
47 tz_to_with_time_zone: true,
48 single_string_interval: true,
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::IfNull(f) => Ok(Expression::Coalesce(Box::new(VarArgFunc {
59 original_name: None,
60 expressions: vec![f.this, f.expression],
61 inferred_type: None,
62 }))),
63
64 Expression::Nvl(f) => Ok(Expression::Coalesce(Box::new(VarArgFunc {
66 original_name: None,
67 expressions: vec![f.this, f.expression],
68 inferred_type: None,
69 }))),
70
71 Expression::TryCast(c) => Ok(Expression::TryCast(c)),
73
74 Expression::SafeCast(c) => Ok(Expression::TryCast(c)),
76
77 Expression::ILike(op) => Ok(Expression::ILike(op)),
79
80 Expression::CountIf(f) => {
82 let case_expr = Expression::Case(Box::new(Case {
83 operand: None,
84 whens: vec![(f.this.clone(), Expression::number(1))],
85 else_: Some(Expression::number(0)),
86 comments: Vec::new(),
87 inferred_type: None,
88 }));
89 Ok(Expression::Sum(Box::new(AggFunc {
90 ignore_nulls: None,
91 having_max: None,
92 this: case_expr,
93 distinct: f.distinct,
94 filter: f.filter,
95 order_by: Vec::new(),
96 name: None,
97 limit: None,
98 inferred_type: None,
99 })))
100 }
101
102 Expression::Explode(_) => Ok(expr),
104
105 Expression::ExplodeOuter(_) => Ok(expr),
107
108 Expression::Unnest(_) => Ok(expr),
110
111 Expression::Rand(r) => {
113 let _ = r.seed;
114 Ok(Expression::Random(crate::expressions::Random))
115 }
116
117 Expression::DateAdd(f) => {
119 let unit_str = match f.unit {
120 crate::expressions::IntervalUnit::Year => "YEAR",
121 crate::expressions::IntervalUnit::Quarter => "QUARTER",
122 crate::expressions::IntervalUnit::Month => "MONTH",
123 crate::expressions::IntervalUnit::Week => "WEEK",
124 crate::expressions::IntervalUnit::Day => "DAY",
125 crate::expressions::IntervalUnit::Hour => "HOUR",
126 crate::expressions::IntervalUnit::Minute => "MINUTE",
127 crate::expressions::IntervalUnit::Second => "SECOND",
128 crate::expressions::IntervalUnit::Millisecond => "MILLISECOND",
129 crate::expressions::IntervalUnit::Microsecond => "MICROSECOND",
130 crate::expressions::IntervalUnit::Nanosecond => "NANOSECOND",
131 };
132 let unit = Expression::Identifier(crate::expressions::Identifier {
133 name: unit_str.to_string(),
134 quoted: false,
135 trailing_comments: Vec::new(),
136 span: None,
137 });
138 Ok(Expression::Function(Box::new(Function::new(
139 "DATEADD".to_string(),
140 vec![unit, f.interval, f.this],
141 ))))
142 }
143
144 Expression::Function(f) => self.transform_function(*f),
146
147 Expression::AggregateFunction(f) => self.transform_aggregate_function(f),
149
150 Expression::Cast(c) => self.transform_cast(*c),
152
153 Expression::Convert(c) => Ok(Expression::Cast(Box::new(Cast {
155 this: c.this,
156 to: c.to,
157 trailing_comments: Vec::new(),
158 double_colon_syntax: false,
159 format: None,
160 default: None,
161 inferred_type: None,
162 }))),
163
164 Expression::Select(mut select) => {
166 if let Some(top) = select.top.take() {
167 if !top.percent && !top.with_ties {
169 select.limit = Some(Limit {
171 this: top.this,
172 percent: false,
173 comments: Vec::new(),
174 });
175 } else {
176 select.top = Some(top);
178 }
179 }
180 Ok(Expression::Select(select))
181 }
182
183 _ => Ok(expr),
185 }
186 }
187}
188
189#[cfg(feature = "transpile")]
190impl RedshiftDialect {
191 fn transform_function(&self, f: Function) -> Result<Expression> {
192 let name_upper = f.name.to_uppercase();
193 match name_upper.as_str() {
194 "IFNULL" if f.args.len() == 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc {
196 original_name: None,
197 expressions: f.args,
198 inferred_type: None,
199 }))),
200
201 "NVL" if f.args.len() >= 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc {
203 original_name: None,
204 expressions: f.args,
205 inferred_type: None,
206 }))),
207
208 "ISNULL" if f.args.len() == 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc {
210 original_name: None,
211 expressions: f.args,
212 inferred_type: None,
213 }))),
214
215 "GETDATE" => Ok(Expression::Function(Box::new(Function::new(
217 "GETDATE".to_string(),
218 vec![],
219 )))),
220
221 "NOW" => Ok(Expression::Function(Box::new(Function::new(
223 "GETDATE".to_string(),
224 vec![],
225 )))),
226
227 "RAND" => Ok(Expression::Random(crate::expressions::Random)),
229
230 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
232 Function::new("LISTAGG".to_string(), f.args),
233 ))),
234
235 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
237 Function::new("LISTAGG".to_string(), f.args),
238 ))),
239
240 "LISTAGG" => Ok(Expression::Function(Box::new(f))),
242
243 "SUBSTR" => Ok(Expression::Function(Box::new(Function::new(
245 "SUBSTRING".to_string(),
246 f.args,
247 )))),
248
249 "LEN" => Ok(Expression::Function(Box::new(f))),
251
252 "LENGTH" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
254 "LEN".to_string(),
255 f.args,
256 )))),
257
258 "CHARINDEX" => Ok(Expression::Function(Box::new(f))),
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 "CHARINDEX".to_string(),
269 vec![substring, string],
270 ))))
271 }
272
273 "STRPOS" if f.args.len() == 2 => {
275 let args = f.args;
276 let string = args[0].clone();
278 let substring = args[1].clone();
279 Ok(Expression::Function(Box::new(Function::new(
280 "CHARINDEX".to_string(),
281 vec![substring, string],
282 ))))
283 }
284
285 "INSTR" if f.args.len() >= 2 => {
287 let mut args = f.args;
288 let string = args.remove(0);
289 let substring = args.remove(0);
290 Ok(Expression::Function(Box::new(Function::new(
292 "CHARINDEX".to_string(),
293 vec![substring, string],
294 ))))
295 }
296
297 "LOCATE" if f.args.len() >= 2 => {
299 let mut args = f.args;
300 let substring = args.remove(0);
301 let string = args.remove(0);
302 Ok(Expression::Function(Box::new(Function::new(
304 "CHARINDEX".to_string(),
305 vec![substring, string],
306 ))))
307 }
308
309 "ARRAY_LENGTH" => Ok(Expression::Function(Box::new(f))),
312
313 "SIZE" => Ok(Expression::Function(Box::new(f))),
315
316 "TO_DATE" => Ok(Expression::Function(Box::new(f))),
318
319 "TO_TIMESTAMP" => Ok(Expression::Function(Box::new(f))),
321
322 "DATE_FORMAT" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(
324 Function::new("TO_CHAR".to_string(), f.args),
325 ))),
326
327 "STRFTIME" if f.args.len() >= 2 => {
329 let mut args = f.args;
330 let format = args.remove(0);
331 let date = args.remove(0);
332 Ok(Expression::Function(Box::new(Function::new(
333 "TO_CHAR".to_string(),
334 vec![date, format],
335 ))))
336 }
337
338 "TO_CHAR" => Ok(Expression::Function(Box::new(f))),
340
341 "LEVENSHTEIN" => Ok(Expression::Function(Box::new(f))),
343
344 "JSON_EXTRACT" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(
346 Function::new("JSON_EXTRACT_PATH_TEXT".to_string(), f.args),
347 ))),
348
349 "JSON_EXTRACT_SCALAR" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(
351 Function::new("JSON_EXTRACT_PATH_TEXT".to_string(), f.args),
352 ))),
353
354 "GET_JSON_OBJECT" if f.args.len() == 2 => Ok(Expression::Function(Box::new(
356 Function::new("JSON_EXTRACT_PATH_TEXT".to_string(), f.args),
357 ))),
358
359 "COLLECT_LIST" => Ok(Expression::Function(Box::new(f))),
361
362 "COLLECT_SET" => Ok(Expression::Function(Box::new(f))),
364
365 "RLIKE" if f.args.len() == 2 => {
367 let mut args = f.args;
369 let string = args.remove(0);
370 let pattern = args.remove(0);
371 Ok(Expression::RegexpLike(Box::new(RegexpFunc {
372 options: None,
373
374 this: string,
375 pattern,
376 flags: None,
377 })))
378 }
379
380 "REGEXP" if f.args.len() == 2 => {
382 let mut args = f.args;
383 let string = args.remove(0);
384 let pattern = args.remove(0);
385 Ok(Expression::RegexpLike(Box::new(RegexpFunc {
386 options: None,
387
388 this: string,
389 pattern,
390 flags: None,
391 })))
392 }
393
394 "REGEXP_LIKE" => Ok(Expression::Function(Box::new(f))),
396
397 "ADD_MONTHS" if f.args.len() == 2 => {
399 let mut args = f.args;
400 let date = args.remove(0);
401 let months = args.remove(0);
402 Ok(Expression::Function(Box::new(Function::new(
404 "DATEADD".to_string(),
405 vec![Expression::identifier("month"), months, date],
406 ))))
407 }
408
409 "DATEDIFF" => Ok(Expression::Function(Box::new(f))),
411
412 "DATE_DIFF" => Ok(Expression::Function(Box::new(Function::new(
414 "DATEDIFF".to_string(),
415 f.args,
416 )))),
417
418 "DATEADD" => Ok(Expression::Function(Box::new(f))),
420
421 "DATE_ADD" => Ok(Expression::Function(Box::new(Function::new(
423 "DATEADD".to_string(),
424 f.args,
425 )))),
426
427 "SPLIT_TO_ARRAY" => Ok(Expression::Function(Box::new(f))),
429
430 "STRING_TO_ARRAY" if f.args.len() >= 1 => Ok(Expression::Function(Box::new(
432 Function::new("SPLIT_TO_ARRAY".to_string(), f.args),
433 ))),
434
435 "SPLIT" if f.args.len() >= 1 => Ok(Expression::Function(Box::new(Function::new(
437 "SPLIT_TO_ARRAY".to_string(),
438 f.args,
439 )))),
440
441 "STRTOL" => Ok(Expression::Function(Box::new(f))),
443
444 "FROM_BASE" if f.args.len() == 2 => Ok(Expression::Function(Box::new(Function::new(
446 "STRTOL".to_string(),
447 f.args,
448 )))),
449
450 "CONVERT_TIMEZONE" if f.args.len() == 2 => {
452 let mut new_args = vec![Expression::string("UTC")];
453 new_args.extend(f.args);
454 Ok(Expression::Function(Box::new(Function::new(
455 "CONVERT_TIMEZONE".to_string(),
456 new_args,
457 ))))
458 }
459 "CONVERT_TIMEZONE" => Ok(Expression::Function(Box::new(f))),
461
462 "CONVERT" if f.args.len() == 2 => {
464 let type_expr = &f.args[0];
465 let value_expr = f.args[1].clone();
466
467 let type_name = match type_expr {
469 Expression::Column(c) => c.name.name.clone(),
470 Expression::Identifier(i) => i.name.clone(),
471 _ => return Ok(Expression::Function(Box::new(f))), };
473
474 let data_type = match type_name.to_uppercase().as_str() {
476 "INT" | "INTEGER" => DataType::Int {
477 length: None,
478 integer_spelling: false,
479 },
480 "BIGINT" => DataType::BigInt { length: None },
481 "SMALLINT" => DataType::SmallInt { length: None },
482 "TINYINT" => DataType::TinyInt { length: None },
483 "VARCHAR" => DataType::VarChar {
484 length: None,
485 parenthesized_length: false,
486 },
487 "CHAR" => DataType::Char { length: None },
488 "FLOAT" | "REAL" => DataType::Float {
489 precision: None,
490 scale: None,
491 real_spelling: false,
492 },
493 "DOUBLE" => DataType::Double {
494 precision: None,
495 scale: None,
496 },
497 "BOOLEAN" | "BOOL" => DataType::Boolean,
498 "DATE" => DataType::Date,
499 "TIMESTAMP" => DataType::Timestamp {
500 precision: None,
501 timezone: false,
502 },
503 "TEXT" => DataType::Text,
504 "DECIMAL" | "NUMERIC" => DataType::Decimal {
505 precision: None,
506 scale: None,
507 },
508 _ => return Ok(Expression::Function(Box::new(f))), };
510
511 Ok(Expression::Cast(Box::new(Cast {
512 this: value_expr,
513 to: data_type,
514 trailing_comments: Vec::new(),
515 double_colon_syntax: false,
516 format: None,
517 default: None,
518 inferred_type: None,
519 })))
520 }
521
522 _ => Ok(Expression::Function(Box::new(f))),
524 }
525 }
526
527 fn transform_aggregate_function(
528 &self,
529 f: Box<crate::expressions::AggregateFunction>,
530 ) -> Result<Expression> {
531 let name_upper = f.name.to_uppercase();
532 match name_upper.as_str() {
533 "COUNT_IF" if !f.args.is_empty() => {
535 let condition = f.args.into_iter().next().unwrap();
536 let case_expr = Expression::Case(Box::new(Case {
537 operand: None,
538 whens: vec![(condition, Expression::number(1))],
539 else_: Some(Expression::number(0)),
540 comments: Vec::new(),
541 inferred_type: None,
542 }));
543 Ok(Expression::Sum(Box::new(AggFunc {
544 ignore_nulls: None,
545 having_max: None,
546 this: case_expr,
547 distinct: f.distinct,
548 filter: f.filter,
549 order_by: Vec::new(),
550 name: None,
551 limit: None,
552 inferred_type: None,
553 })))
554 }
555
556 "ANY_VALUE" => Ok(Expression::AggregateFunction(f)),
558
559 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
561 Function::new("LISTAGG".to_string(), f.args),
562 ))),
563
564 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
566 Function::new("LISTAGG".to_string(), f.args),
567 ))),
568
569 "LISTAGG" => Ok(Expression::AggregateFunction(f)),
571
572 "STDDEV" => Ok(Expression::AggregateFunction(f)),
574
575 "VARIANCE" => Ok(Expression::AggregateFunction(f)),
577
578 "MEDIAN" => Ok(Expression::AggregateFunction(f)),
580
581 _ => Ok(Expression::AggregateFunction(f)),
583 }
584 }
585
586 fn transform_cast(&self, c: Cast) -> Result<Expression> {
587 Ok(Expression::Cast(Box::new(c)))
589 }
590}