1use super::{DialectImpl, DialectType};
17use crate::error::Result;
18use crate::expressions::{BinaryFunc, CeilFunc, Expression, Function, LikeOp, UnaryFunc};
19use crate::generator::GeneratorConfig;
20use crate::tokens::TokenizerConfig;
21
22pub struct OracleDialect;
24
25impl DialectImpl for OracleDialect {
26 fn dialect_type(&self) -> DialectType {
27 DialectType::Oracle
28 }
29
30 fn tokenizer_config(&self) -> TokenizerConfig {
31 let mut config = TokenizerConfig::default();
32 config.identifiers.insert('"', '"');
34 config.nested_comments = false;
36 config
37 }
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::Oracle),
45 supports_column_join_marks: true,
46 alter_table_include_column_keyword: false,
48 tablesample_keywords: "SAMPLE",
50 alias_post_tablesample: true,
52 tz_to_with_time_zone: true,
54 ..Default::default()
55 }
56 }
57
58 fn transform_expr(&self, expr: Expression) -> Result<Expression> {
59 match expr {
60 Expression::IfNull(f) => Ok(Expression::Nvl(f)),
62
63 Expression::Coalesce(f) if f.expressions.len() == 2 => {
65 let mut exprs = f.expressions;
66 let second = exprs.pop().unwrap();
67 let first = exprs.pop().unwrap();
68 Ok(Expression::Nvl(Box::new(BinaryFunc { original_name: None,
69 this: first,
70 expression: second,
71 })))
72 }
73
74 Expression::Nvl(f) => Ok(Expression::Nvl(f)),
76
77 Expression::TryCast(c) => Ok(Expression::Cast(c)),
79
80 Expression::SafeCast(c) => Ok(Expression::Cast(c)),
82
83 Expression::ILike(op) => {
85 let lower_left = Expression::Lower(Box::new(UnaryFunc::new(op.left)));
86 let lower_right = Expression::Lower(Box::new(UnaryFunc::new(op.right)));
87 Ok(Expression::Like(Box::new(LikeOp {
88 left: lower_left,
89 right: lower_right,
90 escape: op.escape,
91 quantifier: op.quantifier,
92 })))
93 }
94
95 Expression::Random(_) => Ok(Expression::Function(Box::new(Function::new(
97 "DBMS_RANDOM.VALUE".to_string(),
98 vec![],
99 )))),
100
101 Expression::Rand(_) => Ok(Expression::Function(Box::new(Function::new(
103 "DBMS_RANDOM.VALUE".to_string(),
104 vec![],
105 )))),
106
107 Expression::Concat(op) => Ok(Expression::Concat(op)),
109
110 Expression::Unnest(f) => Ok(Expression::Function(Box::new(Function::new(
113 "TABLE".to_string(),
114 vec![f.this],
115 )))),
116
117 Expression::Explode(f) => Ok(Expression::Function(Box::new(Function::new(
119 "TABLE".to_string(),
120 vec![f.this],
121 )))),
122
123 Expression::Function(f) => self.transform_function(*f),
125
126 Expression::AggregateFunction(f) => self.transform_aggregate_function(f),
128
129 _ => Ok(expr),
131 }
132 }
133}
134
135impl OracleDialect {
136 fn transform_function(&self, f: Function) -> Result<Expression> {
137 let name_upper = f.name.to_uppercase();
138 match name_upper.as_str() {
139 "IFNULL" if f.args.len() == 2 => {
141 let mut args = f.args;
142 let second = args.pop().unwrap();
143 let first = args.pop().unwrap();
144 Ok(Expression::Nvl(Box::new(BinaryFunc { original_name: None,
145 this: first,
146 expression: second,
147 })))
148 }
149
150 "ISNULL" if f.args.len() == 2 => {
152 let mut args = f.args;
153 let second = args.pop().unwrap();
154 let first = args.pop().unwrap();
155 Ok(Expression::Nvl(Box::new(BinaryFunc { original_name: None,
156 this: first,
157 expression: second,
158 })))
159 }
160
161 "NVL" if f.args.len() == 2 => {
163 let mut args = f.args;
164 let second = args.pop().unwrap();
165 let first = args.pop().unwrap();
166 Ok(Expression::Nvl(Box::new(BinaryFunc { original_name: None,
167 this: first,
168 expression: second,
169 })))
170 }
171
172 "NVL2" => Ok(Expression::Function(Box::new(f))),
174
175 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
177 Function::new("LISTAGG".to_string(), f.args),
178 ))),
179
180 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
182 "LISTAGG".to_string(),
183 f.args,
184 )))),
185
186 "LISTAGG" => Ok(Expression::Function(Box::new(f))),
188
189 "SUBSTRING" => Ok(Expression::Function(Box::new(Function::new(
191 "SUBSTR".to_string(),
192 f.args,
193 )))),
194
195 "SUBSTR" => Ok(Expression::Function(Box::new(f))),
197
198 "LENGTH" => Ok(Expression::Function(Box::new(f))),
200
201 "LEN" if f.args.len() == 1 => Ok(Expression::Length(Box::new(UnaryFunc::new(
203 f.args.into_iter().next().unwrap(),
204 )))),
205
206 "RANDOM" | "RAND" => Ok(Expression::Function(Box::new(Function::new(
208 "DBMS_RANDOM.VALUE".to_string(),
209 vec![],
210 )))),
211
212 "NOW" => Ok(Expression::CurrentTimestamp(
214 crate::expressions::CurrentTimestamp { precision: None, sysdate: false },
215 )),
216
217 "GETDATE" => Ok(Expression::Function(Box::new(Function::new(
219 "SYSDATE".to_string(),
220 vec![],
221 )))),
222
223 "CURRENT_TIMESTAMP" => {
226 if f.args.is_empty() {
227 Ok(Expression::CurrentTimestamp(
228 crate::expressions::CurrentTimestamp { precision: None, sysdate: false },
229 ))
230 } else if f.args.len() == 1 {
231 if let Expression::Literal(crate::expressions::Literal::Number(n)) = &f.args[0] {
233 if let Ok(precision) = n.parse::<u32>() {
234 return Ok(Expression::CurrentTimestamp(
235 crate::expressions::CurrentTimestamp { precision: Some(precision), sysdate: false },
236 ));
237 }
238 }
239 Ok(Expression::Function(Box::new(f)))
241 } else {
242 Ok(Expression::Function(Box::new(f)))
244 }
245 }
246
247 "CURRENT_DATE" => Ok(Expression::CurrentDate(crate::expressions::CurrentDate)),
249
250 "TO_DATE" => Ok(Expression::Function(Box::new(f))),
252
253 "TO_TIMESTAMP" => Ok(Expression::Function(Box::new(f))),
255
256 "TO_CHAR" => Ok(Expression::Function(Box::new(f))),
258
259 "DATE_FORMAT" => Ok(Expression::Function(Box::new(Function::new(
261 "TO_CHAR".to_string(),
262 f.args,
263 )))),
264
265 "STRFTIME" => Ok(Expression::Function(Box::new(Function::new(
267 "TO_CHAR".to_string(),
268 f.args,
269 )))),
270
271 "DATE_TRUNC" => Ok(Expression::Function(Box::new(Function::new(
273 "TRUNC".to_string(),
274 f.args,
275 )))),
276
277 "TRUNC" if f.args.len() == 1 => {
281 let mut args = f.args;
282 args.push(Expression::Literal(crate::expressions::Literal::String("DD".to_string())));
283 Ok(Expression::Function(Box::new(Function::new(
284 "TRUNC".to_string(),
285 args,
286 ))))
287 }
288
289 "EXTRACT" => Ok(Expression::Function(Box::new(f))),
291
292 "POSITION" if f.args.len() == 2 => {
295 let mut args = f.args;
296 let first = args.remove(0);
297 let second = args.remove(0);
298 Ok(Expression::Function(Box::new(Function::new(
300 "INSTR".to_string(),
301 vec![second, first],
302 ))))
303 }
304
305 "STRPOS" if f.args.len() == 2 => Ok(Expression::Function(Box::new(Function::new(
307 "INSTR".to_string(),
308 f.args,
309 )))),
310
311 "CHARINDEX" if f.args.len() >= 2 => {
313 let mut args = f.args;
314 let substring = args.remove(0);
315 let string = args.remove(0);
316 let mut instr_args = vec![string, substring];
318 if !args.is_empty() {
319 instr_args.push(args.remove(0));
320 }
321 Ok(Expression::Function(Box::new(Function::new(
322 "INSTR".to_string(),
323 instr_args,
324 ))))
325 }
326
327 "INSTR" => Ok(Expression::Function(Box::new(f))),
329
330 "CEILING" if f.args.len() == 1 => Ok(Expression::Ceil(Box::new(CeilFunc {
332 this: f.args.into_iter().next().unwrap(),
333 decimals: None,
334 to: None,
335 }))),
336
337 "CEIL" if f.args.len() == 1 => Ok(Expression::Ceil(Box::new(CeilFunc {
339 this: f.args.into_iter().next().unwrap(),
340 decimals: None,
341 to: None,
342 }))),
343
344 "LOG" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
347 "LN".to_string(),
348 f.args,
349 )))),
350
351 "LN" => Ok(Expression::Function(Box::new(f))),
353
354 "POWER" | "POW" => Ok(Expression::Function(Box::new(Function::new(
356 "POWER".to_string(),
357 f.args,
358 )))),
359
360 "REGEXP_LIKE" => Ok(Expression::Function(Box::new(f))),
362
363 "JSON_VALUE" => Ok(Expression::Function(Box::new(f))),
365
366 "JSON_QUERY" => Ok(Expression::Function(Box::new(f))),
368
369 "JSON_EXTRACT" => Ok(Expression::Function(Box::new(Function::new(
371 "JSON_VALUE".to_string(),
372 f.args,
373 )))),
374
375 "JSON_EXTRACT_SCALAR" => Ok(Expression::Function(Box::new(Function::new(
377 "JSON_VALUE".to_string(),
378 f.args,
379 )))),
380
381 "SPLIT" => {
384 Ok(Expression::Function(Box::new(Function::new(
386 "REGEXP_SUBSTR".to_string(),
387 f.args,
388 ))))
389 }
390
391 "ADD_MONTHS" => Ok(Expression::Function(Box::new(f))),
393
394 "MONTHS_BETWEEN" => Ok(Expression::Function(Box::new(f))),
396
397 "DATEADD" => {
399 Ok(Expression::Function(Box::new(f)))
401 }
402
403 "DATEDIFF" => Ok(Expression::Function(Box::new(f))),
405
406 "DECODE" => Ok(Expression::Function(Box::new(f))),
408
409 _ => Ok(Expression::Function(Box::new(f))),
411 }
412 }
413
414 fn transform_aggregate_function(
415 &self,
416 f: Box<crate::expressions::AggregateFunction>,
417 ) -> Result<Expression> {
418 let name_upper = f.name.to_uppercase();
419 match name_upper.as_str() {
420 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
422 Function::new("LISTAGG".to_string(), f.args),
423 ))),
424
425 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
427 "LISTAGG".to_string(),
428 f.args,
429 )))),
430
431 "ARRAY_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
434 "COLLECT".to_string(),
435 f.args,
436 )))),
437
438 _ => Ok(Expression::AggregateFunction(f)),
440 }
441 }
442}