1use super::{DialectImpl, DialectType};
17use crate::error::Result;
18use crate::expressions::{BinaryFunc, CeilFunc, Expression, Function, LikeOp, UnaryFunc};
19#[cfg(feature = "generate")]
20use crate::generator::GeneratorConfig;
21use crate::tokens::TokenizerConfig;
22
23pub struct OracleDialect;
25
26impl DialectImpl for OracleDialect {
27 fn dialect_type(&self) -> DialectType {
28 DialectType::Oracle
29 }
30
31 fn tokenizer_config(&self) -> TokenizerConfig {
32 let mut config = TokenizerConfig::default();
33 config.identifiers.insert('"', '"');
35 config.nested_comments = false;
37 config
38 }
39
40 #[cfg(feature = "generate")]
41
42 fn generator_config(&self) -> GeneratorConfig {
43 use crate::generator::IdentifierQuoteStyle;
44 GeneratorConfig {
45 identifier_quote: '"',
46 identifier_quote_style: IdentifierQuoteStyle::DOUBLE_QUOTE,
47 dialect: Some(DialectType::Oracle),
48 supports_column_join_marks: true,
49 alter_table_include_column_keyword: false,
51 tablesample_keywords: "SAMPLE",
53 alias_post_tablesample: true,
55 tz_to_with_time_zone: true,
57 unpivot_aliases_are_identifiers: false,
59 limit_fetch_style: crate::generator::LimitFetchStyle::FetchFirst,
61 ..Default::default()
62 }
63 }
64
65 #[cfg(feature = "transpile")]
66
67 fn transform_expr(&self, expr: Expression) -> Result<Expression> {
68 match expr {
69 Expression::IfNull(f) => Ok(Expression::Nvl(f)),
71
72 Expression::Coalesce(f) if f.expressions.len() == 2 => {
74 let mut exprs = f.expressions;
75 let second = exprs.pop().unwrap();
76 let first = exprs.pop().unwrap();
77 Ok(Expression::Nvl(Box::new(BinaryFunc {
78 original_name: None,
79 this: first,
80 expression: second,
81 inferred_type: None,
82 })))
83 }
84
85 Expression::Nvl(f) => Ok(Expression::Nvl(f)),
87
88 Expression::TryCast(c) => Ok(Expression::Cast(c)),
90
91 Expression::SafeCast(c) => Ok(Expression::Cast(c)),
93
94 Expression::ILike(op) => {
96 let lower_left = Expression::Lower(Box::new(UnaryFunc::new(op.left)));
97 let lower_right = Expression::Lower(Box::new(UnaryFunc::new(op.right)));
98 Ok(Expression::Like(Box::new(LikeOp {
99 left: lower_left,
100 right: lower_right,
101 escape: op.escape,
102 quantifier: op.quantifier,
103 inferred_type: None,
104 })))
105 }
106
107 Expression::Random(_) => Ok(Expression::Function(Box::new(Function::new(
109 "DBMS_RANDOM.VALUE".to_string(),
110 vec![],
111 )))),
112
113 Expression::Rand(_) => Ok(Expression::Function(Box::new(Function::new(
115 "DBMS_RANDOM.VALUE".to_string(),
116 vec![],
117 )))),
118
119 Expression::Concat(op) => Ok(Expression::Concat(op)),
121
122 Expression::Unnest(f) => Ok(Expression::Function(Box::new(Function::new(
125 "TABLE".to_string(),
126 vec![f.this],
127 )))),
128
129 Expression::Explode(f) => Ok(Expression::Function(Box::new(Function::new(
131 "TABLE".to_string(),
132 vec![f.this],
133 )))),
134
135 Expression::Function(f) => self.transform_function(*f),
137
138 Expression::AggregateFunction(f) => self.transform_aggregate_function(f),
140
141 _ => Ok(expr),
143 }
144 }
145}
146
147#[cfg(feature = "transpile")]
148impl OracleDialect {
149 fn transform_function(&self, f: Function) -> Result<Expression> {
150 let name_upper = f.name.to_uppercase();
151 match name_upper.as_str() {
152 "IFNULL" if f.args.len() == 2 => {
154 let mut args = f.args;
155 let second = args.pop().unwrap();
156 let first = args.pop().unwrap();
157 Ok(Expression::Nvl(Box::new(BinaryFunc {
158 original_name: None,
159 this: first,
160 expression: second,
161 inferred_type: None,
162 })))
163 }
164
165 "ISNULL" if f.args.len() == 2 => {
167 let mut args = f.args;
168 let second = args.pop().unwrap();
169 let first = args.pop().unwrap();
170 Ok(Expression::Nvl(Box::new(BinaryFunc {
171 original_name: None,
172 this: first,
173 expression: second,
174 inferred_type: None,
175 })))
176 }
177
178 "NVL" if f.args.len() == 2 => {
180 let mut args = f.args;
181 let second = args.pop().unwrap();
182 let first = args.pop().unwrap();
183 Ok(Expression::Nvl(Box::new(BinaryFunc {
184 original_name: None,
185 this: first,
186 expression: second,
187 inferred_type: None,
188 })))
189 }
190
191 "NVL2" => Ok(Expression::Function(Box::new(f))),
193
194 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
196 Function::new("LISTAGG".to_string(), f.args),
197 ))),
198
199 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
201 Function::new("LISTAGG".to_string(), f.args),
202 ))),
203
204 "LISTAGG" => Ok(Expression::Function(Box::new(f))),
206
207 "SUBSTRING" => Ok(Expression::Function(Box::new(Function::new(
209 "SUBSTR".to_string(),
210 f.args,
211 )))),
212
213 "SUBSTR" => Ok(Expression::Function(Box::new(f))),
215
216 "LENGTH" => Ok(Expression::Function(Box::new(f))),
218
219 "LEN" if f.args.len() == 1 => Ok(Expression::Length(Box::new(UnaryFunc::new(
221 f.args.into_iter().next().unwrap(),
222 )))),
223
224 "RANDOM" | "RAND" => Ok(Expression::Function(Box::new(Function::new(
226 "DBMS_RANDOM.VALUE".to_string(),
227 vec![],
228 )))),
229
230 "NOW" => Ok(Expression::CurrentTimestamp(
232 crate::expressions::CurrentTimestamp {
233 precision: None,
234 sysdate: false,
235 },
236 )),
237
238 "GETDATE" => Ok(Expression::Function(Box::new(Function::new(
240 "SYSDATE".to_string(),
241 vec![],
242 )))),
243
244 "CURRENT_TIMESTAMP" => {
247 if f.args.is_empty() {
248 Ok(Expression::CurrentTimestamp(
249 crate::expressions::CurrentTimestamp {
250 precision: None,
251 sysdate: false,
252 },
253 ))
254 } else if f.args.len() == 1 {
255 if let Expression::Literal(lit) = &f.args[0] {
257 if let crate::expressions::Literal::Number(n) = lit.as_ref() {
258 if let Ok(precision) = n.parse::<u32>() {
259 return Ok(Expression::CurrentTimestamp(
260 crate::expressions::CurrentTimestamp {
261 precision: Some(precision),
262 sysdate: false,
263 },
264 ));
265 }
266 }
267 }
268 Ok(Expression::Function(Box::new(f)))
270 } else {
271 Ok(Expression::Function(Box::new(f)))
273 }
274 }
275
276 "CURRENT_DATE" => Ok(Expression::CurrentDate(crate::expressions::CurrentDate)),
278
279 "TO_DATE" => Ok(Expression::Function(Box::new(f))),
281
282 "TO_TIMESTAMP" => Ok(Expression::Function(Box::new(f))),
284
285 "TO_CHAR" => Ok(Expression::Function(Box::new(f))),
287
288 "DATE_FORMAT" => Ok(Expression::Function(Box::new(Function::new(
290 "TO_CHAR".to_string(),
291 f.args,
292 )))),
293
294 "STRFTIME" => Ok(Expression::Function(Box::new(Function::new(
296 "TO_CHAR".to_string(),
297 f.args,
298 )))),
299
300 "DATE_TRUNC" => Ok(Expression::Function(Box::new(Function::new(
302 "TRUNC".to_string(),
303 f.args,
304 )))),
305
306 "TRUNC" if f.args.len() == 1 && Self::is_temporal_expr(&f.args[0]) => {
309 let mut args = f.args;
310 args.push(Expression::Literal(Box::new(
311 crate::expressions::Literal::String("DD".to_string()),
312 )));
313 Ok(Expression::Function(Box::new(Function::new(
314 "TRUNC".to_string(),
315 args,
316 ))))
317 }
318 "TRUNC" => Ok(Expression::Function(Box::new(f))),
319
320 "EXTRACT" => Ok(Expression::Function(Box::new(f))),
322
323 "POSITION" if f.args.len() == 2 => {
326 let mut args = f.args;
327 let first = args.remove(0);
328 let second = args.remove(0);
329 Ok(Expression::Function(Box::new(Function::new(
331 "INSTR".to_string(),
332 vec![second, first],
333 ))))
334 }
335
336 "STRPOS" if f.args.len() == 2 => Ok(Expression::Function(Box::new(Function::new(
338 "INSTR".to_string(),
339 f.args,
340 )))),
341
342 "CHARINDEX" if f.args.len() >= 2 => {
344 let mut args = f.args;
345 let substring = args.remove(0);
346 let string = args.remove(0);
347 let mut instr_args = vec![string, substring];
349 if !args.is_empty() {
350 instr_args.push(args.remove(0));
351 }
352 Ok(Expression::Function(Box::new(Function::new(
353 "INSTR".to_string(),
354 instr_args,
355 ))))
356 }
357
358 "INSTR" => Ok(Expression::Function(Box::new(f))),
360
361 "CEILING" if f.args.len() == 1 => Ok(Expression::Ceil(Box::new(CeilFunc {
363 this: f.args.into_iter().next().unwrap(),
364 decimals: None,
365 to: None,
366 }))),
367
368 "CEIL" if f.args.len() == 1 => Ok(Expression::Ceil(Box::new(CeilFunc {
370 this: f.args.into_iter().next().unwrap(),
371 decimals: None,
372 to: None,
373 }))),
374
375 "LOG" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
378 "LN".to_string(),
379 f.args,
380 )))),
381
382 "LN" => Ok(Expression::Function(Box::new(f))),
384
385 "POWER" | "POW" => Ok(Expression::Function(Box::new(Function::new(
387 "POWER".to_string(),
388 f.args,
389 )))),
390
391 "REGEXP_LIKE" => Ok(Expression::Function(Box::new(f))),
393
394 "JSON_VALUE" => Ok(Expression::Function(Box::new(f))),
396
397 "JSON_QUERY" => Ok(Expression::Function(Box::new(f))),
399
400 "JSON_EXTRACT" => Ok(Expression::Function(Box::new(Function::new(
402 "JSON_VALUE".to_string(),
403 f.args,
404 )))),
405
406 "JSON_EXTRACT_SCALAR" => Ok(Expression::Function(Box::new(Function::new(
408 "JSON_VALUE".to_string(),
409 f.args,
410 )))),
411
412 "SPLIT" => {
415 Ok(Expression::Function(Box::new(Function::new(
417 "REGEXP_SUBSTR".to_string(),
418 f.args,
419 ))))
420 }
421
422 "ADD_MONTHS" => Ok(Expression::Function(Box::new(f))),
424
425 "MONTHS_BETWEEN" => Ok(Expression::Function(Box::new(f))),
427
428 "DATEADD" => {
430 Ok(Expression::Function(Box::new(f)))
432 }
433
434 "DATEDIFF" => Ok(Expression::Function(Box::new(f))),
436
437 "DECODE" => Ok(Expression::Function(Box::new(f))),
439
440 _ => Ok(Expression::Function(Box::new(f))),
442 }
443 }
444
445 fn transform_aggregate_function(
446 &self,
447 f: Box<crate::expressions::AggregateFunction>,
448 ) -> Result<Expression> {
449 let name_upper = f.name.to_uppercase();
450 match name_upper.as_str() {
451 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
453 Function::new("LISTAGG".to_string(), f.args),
454 ))),
455
456 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
458 Function::new("LISTAGG".to_string(), f.args),
459 ))),
460
461 "ARRAY_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
464 "COLLECT".to_string(),
465 f.args,
466 )))),
467
468 _ => Ok(Expression::AggregateFunction(f)),
470 }
471 }
472
473 fn is_temporal_expr(expr: &Expression) -> bool {
475 matches!(
476 expr,
477 Expression::CurrentTimestamp(_)
478 | Expression::CurrentDate(_)
479 | Expression::CurrentTime(_)
480 | Expression::Localtimestamp(_)
481 ) || matches!(expr, Expression::Function(f) if {
482 let name = f.name.to_uppercase();
483 name == "SYSDATE" || name == "SYSTIMESTAMP" || name == "TO_DATE" || name == "TO_TIMESTAMP"
484 })
485 }
486}