1use super::{DialectImpl, DialectType};
7use crate::error::Result;
8use crate::expressions::{
9 AggFunc, Case, Cast, DataType, Expression, Function, Limit, RegexpFunc, VarArgFunc,
10};
11use crate::generator::GeneratorConfig;
12use crate::tokens::TokenizerConfig;
13
14pub struct RedshiftDialect;
16
17impl DialectImpl for RedshiftDialect {
18 fn dialect_type(&self) -> DialectType {
19 DialectType::Redshift
20 }
21
22 fn tokenizer_config(&self) -> TokenizerConfig {
23 use crate::tokens::TokenType;
24 let mut config = TokenizerConfig::default();
25 config.identifiers.insert('"', '"');
27 config.nested_comments = false;
29 config
31 .keywords
32 .insert("MINUS".to_string(), TokenType::Except);
33 config
34 }
35
36 fn generator_config(&self) -> GeneratorConfig {
37 use crate::generator::IdentifierQuoteStyle;
38 GeneratorConfig {
39 identifier_quote: '"',
40 identifier_quote_style: IdentifierQuoteStyle::DOUBLE_QUOTE,
41 dialect: Some(DialectType::Redshift),
42 supports_column_join_marks: true,
43 locking_reads_supported: false,
44 tz_to_with_time_zone: true,
45 ..Default::default()
46 }
47 }
48
49 fn transform_expr(&self, expr: Expression) -> Result<Expression> {
50 match expr {
51 Expression::IfNull(f) => Ok(Expression::Coalesce(Box::new(VarArgFunc {
53 original_name: None,
54 expressions: vec![f.this, f.expression],
55 }))),
56
57 Expression::Nvl(f) => Ok(Expression::Coalesce(Box::new(VarArgFunc {
59 original_name: None,
60 expressions: vec![f.this, f.expression],
61 }))),
62
63 Expression::TryCast(c) => Ok(Expression::TryCast(c)),
65
66 Expression::SafeCast(c) => Ok(Expression::TryCast(c)),
68
69 Expression::ILike(op) => Ok(Expression::ILike(op)),
71
72 Expression::CountIf(f) => {
74 let case_expr = Expression::Case(Box::new(Case {
75 operand: None,
76 whens: vec![(f.this.clone(), Expression::number(1))],
77 else_: Some(Expression::number(0)),
78 comments: Vec::new(),
79 }));
80 Ok(Expression::Sum(Box::new(AggFunc {
81 ignore_nulls: None,
82 having_max: None,
83 this: case_expr,
84 distinct: f.distinct,
85 filter: f.filter,
86 order_by: Vec::new(),
87 name: None,
88 limit: None,
89 })))
90 }
91
92 Expression::Explode(_) => Ok(expr),
94
95 Expression::ExplodeOuter(_) => Ok(expr),
97
98 Expression::Unnest(_) => Ok(expr),
100
101 Expression::Rand(r) => {
103 let _ = r.seed;
104 Ok(Expression::Random(crate::expressions::Random))
105 }
106
107 Expression::DateAdd(f) => {
109 let unit_str = match f.unit {
110 crate::expressions::IntervalUnit::Year => "YEAR",
111 crate::expressions::IntervalUnit::Quarter => "QUARTER",
112 crate::expressions::IntervalUnit::Month => "MONTH",
113 crate::expressions::IntervalUnit::Week => "WEEK",
114 crate::expressions::IntervalUnit::Day => "DAY",
115 crate::expressions::IntervalUnit::Hour => "HOUR",
116 crate::expressions::IntervalUnit::Minute => "MINUTE",
117 crate::expressions::IntervalUnit::Second => "SECOND",
118 crate::expressions::IntervalUnit::Millisecond => "MILLISECOND",
119 crate::expressions::IntervalUnit::Microsecond => "MICROSECOND",
120 crate::expressions::IntervalUnit::Nanosecond => "NANOSECOND",
121 };
122 let unit = Expression::Identifier(crate::expressions::Identifier {
123 name: unit_str.to_string(),
124 quoted: false,
125 trailing_comments: Vec::new(),
126 span: None,
127 });
128 Ok(Expression::Function(Box::new(Function::new(
129 "DATEADD".to_string(),
130 vec![unit, f.interval, f.this],
131 ))))
132 }
133
134 Expression::Function(f) => self.transform_function(*f),
136
137 Expression::AggregateFunction(f) => self.transform_aggregate_function(f),
139
140 Expression::Cast(c) => self.transform_cast(*c),
142
143 Expression::Convert(c) => Ok(Expression::Cast(Box::new(Cast {
145 this: c.this,
146 to: c.to,
147 trailing_comments: Vec::new(),
148 double_colon_syntax: false,
149 format: None,
150 default: None,
151 }))),
152
153 Expression::Select(mut select) => {
155 if let Some(top) = select.top.take() {
156 if !top.percent && !top.with_ties {
158 select.limit = Some(Limit {
160 this: top.this,
161 percent: false,
162 comments: Vec::new(),
163 });
164 } else {
165 select.top = Some(top);
167 }
168 }
169 Ok(Expression::Select(select))
170 }
171
172 _ => Ok(expr),
174 }
175 }
176}
177
178impl RedshiftDialect {
179 fn transform_function(&self, f: Function) -> Result<Expression> {
180 let name_upper = f.name.to_uppercase();
181 match name_upper.as_str() {
182 "IFNULL" if f.args.len() == 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc {
184 original_name: None,
185 expressions: f.args,
186 }))),
187
188 "NVL" if f.args.len() >= 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc {
190 original_name: None,
191 expressions: f.args,
192 }))),
193
194 "ISNULL" if f.args.len() == 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc {
196 original_name: None,
197 expressions: f.args,
198 }))),
199
200 "GETDATE" => Ok(Expression::Function(Box::new(Function::new(
202 "GETDATE".to_string(),
203 vec![],
204 )))),
205
206 "NOW" => Ok(Expression::Function(Box::new(Function::new(
208 "GETDATE".to_string(),
209 vec![],
210 )))),
211
212 "RAND" => Ok(Expression::Random(crate::expressions::Random)),
214
215 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
217 Function::new("LISTAGG".to_string(), f.args),
218 ))),
219
220 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
222 Function::new("LISTAGG".to_string(), f.args),
223 ))),
224
225 "LISTAGG" => Ok(Expression::Function(Box::new(f))),
227
228 "SUBSTR" => Ok(Expression::Function(Box::new(Function::new(
230 "SUBSTRING".to_string(),
231 f.args,
232 )))),
233
234 "LEN" => Ok(Expression::Function(Box::new(f))),
236
237 "LENGTH" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
239 "LEN".to_string(),
240 f.args,
241 )))),
242
243 "CHARINDEX" => Ok(Expression::Function(Box::new(f))),
245
246 "POSITION" if f.args.len() == 2 => {
248 let mut args = f.args;
249 let substring = args.remove(0);
250 let string = args.remove(0);
251 Ok(Expression::Function(Box::new(Function::new(
253 "CHARINDEX".to_string(),
254 vec![substring, string],
255 ))))
256 }
257
258 "STRPOS" if f.args.len() == 2 => {
260 let args = f.args;
261 let string = args[0].clone();
263 let substring = args[1].clone();
264 Ok(Expression::Function(Box::new(Function::new(
265 "CHARINDEX".to_string(),
266 vec![substring, string],
267 ))))
268 }
269
270 "INSTR" if f.args.len() >= 2 => {
272 let mut args = f.args;
273 let string = args.remove(0);
274 let substring = args.remove(0);
275 Ok(Expression::Function(Box::new(Function::new(
277 "CHARINDEX".to_string(),
278 vec![substring, string],
279 ))))
280 }
281
282 "LOCATE" if f.args.len() >= 2 => {
284 let mut args = f.args;
285 let substring = args.remove(0);
286 let string = args.remove(0);
287 Ok(Expression::Function(Box::new(Function::new(
289 "CHARINDEX".to_string(),
290 vec![substring, string],
291 ))))
292 }
293
294 "ARRAY_LENGTH" => Ok(Expression::Function(Box::new(f))),
297
298 "SIZE" => Ok(Expression::Function(Box::new(f))),
300
301 "TO_DATE" => Ok(Expression::Function(Box::new(f))),
303
304 "TO_TIMESTAMP" => Ok(Expression::Function(Box::new(f))),
306
307 "DATE_FORMAT" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(
309 Function::new("TO_CHAR".to_string(), f.args),
310 ))),
311
312 "STRFTIME" if f.args.len() >= 2 => {
314 let mut args = f.args;
315 let format = args.remove(0);
316 let date = args.remove(0);
317 Ok(Expression::Function(Box::new(Function::new(
318 "TO_CHAR".to_string(),
319 vec![date, format],
320 ))))
321 }
322
323 "TO_CHAR" => Ok(Expression::Function(Box::new(f))),
325
326 "LEVENSHTEIN" => Ok(Expression::Function(Box::new(f))),
328
329 "JSON_EXTRACT" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(
331 Function::new("JSON_EXTRACT_PATH_TEXT".to_string(), f.args),
332 ))),
333
334 "JSON_EXTRACT_SCALAR" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(
336 Function::new("JSON_EXTRACT_PATH_TEXT".to_string(), f.args),
337 ))),
338
339 "GET_JSON_OBJECT" if f.args.len() == 2 => Ok(Expression::Function(Box::new(
341 Function::new("JSON_EXTRACT_PATH_TEXT".to_string(), f.args),
342 ))),
343
344 "COLLECT_LIST" => Ok(Expression::Function(Box::new(f))),
346
347 "COLLECT_SET" => Ok(Expression::Function(Box::new(f))),
349
350 "RLIKE" if f.args.len() == 2 => {
352 let mut args = f.args;
354 let string = args.remove(0);
355 let pattern = args.remove(0);
356 Ok(Expression::RegexpLike(Box::new(RegexpFunc {
357 this: string,
358 pattern,
359 flags: None,
360 })))
361 }
362
363 "REGEXP" if f.args.len() == 2 => {
365 let mut args = f.args;
366 let string = args.remove(0);
367 let pattern = args.remove(0);
368 Ok(Expression::RegexpLike(Box::new(RegexpFunc {
369 this: string,
370 pattern,
371 flags: None,
372 })))
373 }
374
375 "REGEXP_LIKE" => Ok(Expression::Function(Box::new(f))),
377
378 "ADD_MONTHS" if f.args.len() == 2 => {
380 let mut args = f.args;
381 let date = args.remove(0);
382 let months = args.remove(0);
383 Ok(Expression::Function(Box::new(Function::new(
385 "DATEADD".to_string(),
386 vec![Expression::identifier("month"), months, date],
387 ))))
388 }
389
390 "DATEDIFF" => Ok(Expression::Function(Box::new(f))),
392
393 "DATE_DIFF" => Ok(Expression::Function(Box::new(Function::new(
395 "DATEDIFF".to_string(),
396 f.args,
397 )))),
398
399 "DATEADD" => Ok(Expression::Function(Box::new(f))),
401
402 "DATE_ADD" => Ok(Expression::Function(Box::new(Function::new(
404 "DATEADD".to_string(),
405 f.args,
406 )))),
407
408 "SPLIT_TO_ARRAY" => Ok(Expression::Function(Box::new(f))),
410
411 "STRING_TO_ARRAY" if f.args.len() >= 1 => Ok(Expression::Function(Box::new(
413 Function::new("SPLIT_TO_ARRAY".to_string(), f.args),
414 ))),
415
416 "SPLIT" if f.args.len() >= 1 => Ok(Expression::Function(Box::new(Function::new(
418 "SPLIT_TO_ARRAY".to_string(),
419 f.args,
420 )))),
421
422 "STRTOL" => Ok(Expression::Function(Box::new(f))),
424
425 "FROM_BASE" if f.args.len() == 2 => Ok(Expression::Function(Box::new(Function::new(
427 "STRTOL".to_string(),
428 f.args,
429 )))),
430
431 "CONVERT_TIMEZONE" if f.args.len() == 2 => {
433 let mut new_args = vec![Expression::string("UTC")];
434 new_args.extend(f.args);
435 Ok(Expression::Function(Box::new(Function::new(
436 "CONVERT_TIMEZONE".to_string(),
437 new_args,
438 ))))
439 }
440 "CONVERT_TIMEZONE" => Ok(Expression::Function(Box::new(f))),
442
443 "CONVERT" if f.args.len() == 2 => {
445 let type_expr = &f.args[0];
446 let value_expr = f.args[1].clone();
447
448 let type_name = match type_expr {
450 Expression::Column(c) => c.name.name.clone(),
451 Expression::Identifier(i) => i.name.clone(),
452 _ => return Ok(Expression::Function(Box::new(f))), };
454
455 let data_type = match type_name.to_uppercase().as_str() {
457 "INT" | "INTEGER" => DataType::Int {
458 length: None,
459 integer_spelling: false,
460 },
461 "BIGINT" => DataType::BigInt { length: None },
462 "SMALLINT" => DataType::SmallInt { length: None },
463 "TINYINT" => DataType::TinyInt { length: None },
464 "VARCHAR" => DataType::VarChar {
465 length: None,
466 parenthesized_length: false,
467 },
468 "CHAR" => DataType::Char { length: None },
469 "FLOAT" | "REAL" => DataType::Float {
470 precision: None,
471 scale: None,
472 real_spelling: false,
473 },
474 "DOUBLE" => DataType::Double {
475 precision: None,
476 scale: None,
477 },
478 "BOOLEAN" | "BOOL" => DataType::Boolean,
479 "DATE" => DataType::Date,
480 "TIMESTAMP" => DataType::Timestamp {
481 precision: None,
482 timezone: false,
483 },
484 "TEXT" => DataType::Text,
485 "DECIMAL" | "NUMERIC" => DataType::Decimal {
486 precision: None,
487 scale: None,
488 },
489 _ => return Ok(Expression::Function(Box::new(f))), };
491
492 Ok(Expression::Cast(Box::new(Cast {
493 this: value_expr,
494 to: data_type,
495 trailing_comments: Vec::new(),
496 double_colon_syntax: false,
497 format: None,
498 default: None,
499 })))
500 }
501
502 _ => Ok(Expression::Function(Box::new(f))),
504 }
505 }
506
507 fn transform_aggregate_function(
508 &self,
509 f: Box<crate::expressions::AggregateFunction>,
510 ) -> Result<Expression> {
511 let name_upper = f.name.to_uppercase();
512 match name_upper.as_str() {
513 "COUNT_IF" if !f.args.is_empty() => {
515 let condition = f.args.into_iter().next().unwrap();
516 let case_expr = Expression::Case(Box::new(Case {
517 operand: None,
518 whens: vec![(condition, Expression::number(1))],
519 else_: Some(Expression::number(0)),
520 comments: Vec::new(),
521 }));
522 Ok(Expression::Sum(Box::new(AggFunc {
523 ignore_nulls: None,
524 having_max: None,
525 this: case_expr,
526 distinct: f.distinct,
527 filter: f.filter,
528 order_by: Vec::new(),
529 name: None,
530 limit: None,
531 })))
532 }
533
534 "ANY_VALUE" => Ok(Expression::AggregateFunction(f)),
536
537 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
539 Function::new("LISTAGG".to_string(), f.args),
540 ))),
541
542 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
544 Function::new("LISTAGG".to_string(), f.args),
545 ))),
546
547 "LISTAGG" => Ok(Expression::AggregateFunction(f)),
549
550 "STDDEV" => Ok(Expression::AggregateFunction(f)),
552
553 "VARIANCE" => Ok(Expression::AggregateFunction(f)),
555
556 "MEDIAN" => Ok(Expression::AggregateFunction(f)),
558
559 _ => Ok(Expression::AggregateFunction(f)),
561 }
562 }
563
564 fn transform_cast(&self, c: Cast) -> Result<Expression> {
565 Ok(Expression::Cast(Box::new(c)))
567 }
568}