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 {
69 original_name: None,
70 this: first,
71 expression: second,
72 })))
73 }
74
75 Expression::Nvl(f) => Ok(Expression::Nvl(f)),
77
78 Expression::TryCast(c) => Ok(Expression::Cast(c)),
80
81 Expression::SafeCast(c) => Ok(Expression::Cast(c)),
83
84 Expression::ILike(op) => {
86 let lower_left = Expression::Lower(Box::new(UnaryFunc::new(op.left)));
87 let lower_right = Expression::Lower(Box::new(UnaryFunc::new(op.right)));
88 Ok(Expression::Like(Box::new(LikeOp {
89 left: lower_left,
90 right: lower_right,
91 escape: op.escape,
92 quantifier: op.quantifier,
93 })))
94 }
95
96 Expression::Random(_) => Ok(Expression::Function(Box::new(Function::new(
98 "DBMS_RANDOM.VALUE".to_string(),
99 vec![],
100 )))),
101
102 Expression::Rand(_) => Ok(Expression::Function(Box::new(Function::new(
104 "DBMS_RANDOM.VALUE".to_string(),
105 vec![],
106 )))),
107
108 Expression::Concat(op) => Ok(Expression::Concat(op)),
110
111 Expression::Unnest(f) => Ok(Expression::Function(Box::new(Function::new(
114 "TABLE".to_string(),
115 vec![f.this],
116 )))),
117
118 Expression::Explode(f) => Ok(Expression::Function(Box::new(Function::new(
120 "TABLE".to_string(),
121 vec![f.this],
122 )))),
123
124 Expression::Function(f) => self.transform_function(*f),
126
127 Expression::AggregateFunction(f) => self.transform_aggregate_function(f),
129
130 _ => Ok(expr),
132 }
133 }
134}
135
136impl OracleDialect {
137 fn transform_function(&self, f: Function) -> Result<Expression> {
138 let name_upper = f.name.to_uppercase();
139 match name_upper.as_str() {
140 "IFNULL" if f.args.len() == 2 => {
142 let mut args = f.args;
143 let second = args.pop().unwrap();
144 let first = args.pop().unwrap();
145 Ok(Expression::Nvl(Box::new(BinaryFunc {
146 original_name: None,
147 this: first,
148 expression: second,
149 })))
150 }
151
152 "ISNULL" 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 })))
162 }
163
164 "NVL" if f.args.len() == 2 => {
166 let mut args = f.args;
167 let second = args.pop().unwrap();
168 let first = args.pop().unwrap();
169 Ok(Expression::Nvl(Box::new(BinaryFunc {
170 original_name: None,
171 this: first,
172 expression: second,
173 })))
174 }
175
176 "NVL2" => Ok(Expression::Function(Box::new(f))),
178
179 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
181 Function::new("LISTAGG".to_string(), f.args),
182 ))),
183
184 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
186 Function::new("LISTAGG".to_string(), f.args),
187 ))),
188
189 "LISTAGG" => Ok(Expression::Function(Box::new(f))),
191
192 "SUBSTRING" => Ok(Expression::Function(Box::new(Function::new(
194 "SUBSTR".to_string(),
195 f.args,
196 )))),
197
198 "SUBSTR" => Ok(Expression::Function(Box::new(f))),
200
201 "LENGTH" => Ok(Expression::Function(Box::new(f))),
203
204 "LEN" if f.args.len() == 1 => Ok(Expression::Length(Box::new(UnaryFunc::new(
206 f.args.into_iter().next().unwrap(),
207 )))),
208
209 "RANDOM" | "RAND" => Ok(Expression::Function(Box::new(Function::new(
211 "DBMS_RANDOM.VALUE".to_string(),
212 vec![],
213 )))),
214
215 "NOW" => Ok(Expression::CurrentTimestamp(
217 crate::expressions::CurrentTimestamp {
218 precision: None,
219 sysdate: false,
220 },
221 )),
222
223 "GETDATE" => Ok(Expression::Function(Box::new(Function::new(
225 "SYSDATE".to_string(),
226 vec![],
227 )))),
228
229 "CURRENT_TIMESTAMP" => {
232 if f.args.is_empty() {
233 Ok(Expression::CurrentTimestamp(
234 crate::expressions::CurrentTimestamp {
235 precision: None,
236 sysdate: false,
237 },
238 ))
239 } else if f.args.len() == 1 {
240 if let Expression::Literal(crate::expressions::Literal::Number(n)) = &f.args[0]
242 {
243 if let Ok(precision) = n.parse::<u32>() {
244 return Ok(Expression::CurrentTimestamp(
245 crate::expressions::CurrentTimestamp {
246 precision: Some(precision),
247 sysdate: false,
248 },
249 ));
250 }
251 }
252 Ok(Expression::Function(Box::new(f)))
254 } else {
255 Ok(Expression::Function(Box::new(f)))
257 }
258 }
259
260 "CURRENT_DATE" => Ok(Expression::CurrentDate(crate::expressions::CurrentDate)),
262
263 "TO_DATE" => Ok(Expression::Function(Box::new(f))),
265
266 "TO_TIMESTAMP" => Ok(Expression::Function(Box::new(f))),
268
269 "TO_CHAR" => Ok(Expression::Function(Box::new(f))),
271
272 "DATE_FORMAT" => Ok(Expression::Function(Box::new(Function::new(
274 "TO_CHAR".to_string(),
275 f.args,
276 )))),
277
278 "STRFTIME" => Ok(Expression::Function(Box::new(Function::new(
280 "TO_CHAR".to_string(),
281 f.args,
282 )))),
283
284 "DATE_TRUNC" => Ok(Expression::Function(Box::new(Function::new(
286 "TRUNC".to_string(),
287 f.args,
288 )))),
289
290 "TRUNC" if f.args.len() == 1 => {
294 let mut args = f.args;
295 args.push(Expression::Literal(crate::expressions::Literal::String(
296 "DD".to_string(),
297 )));
298 Ok(Expression::Function(Box::new(Function::new(
299 "TRUNC".to_string(),
300 args,
301 ))))
302 }
303
304 "EXTRACT" => Ok(Expression::Function(Box::new(f))),
306
307 "POSITION" if f.args.len() == 2 => {
310 let mut args = f.args;
311 let first = args.remove(0);
312 let second = args.remove(0);
313 Ok(Expression::Function(Box::new(Function::new(
315 "INSTR".to_string(),
316 vec![second, first],
317 ))))
318 }
319
320 "STRPOS" if f.args.len() == 2 => Ok(Expression::Function(Box::new(Function::new(
322 "INSTR".to_string(),
323 f.args,
324 )))),
325
326 "CHARINDEX" if f.args.len() >= 2 => {
328 let mut args = f.args;
329 let substring = args.remove(0);
330 let string = args.remove(0);
331 let mut instr_args = vec![string, substring];
333 if !args.is_empty() {
334 instr_args.push(args.remove(0));
335 }
336 Ok(Expression::Function(Box::new(Function::new(
337 "INSTR".to_string(),
338 instr_args,
339 ))))
340 }
341
342 "INSTR" => Ok(Expression::Function(Box::new(f))),
344
345 "CEILING" if f.args.len() == 1 => Ok(Expression::Ceil(Box::new(CeilFunc {
347 this: f.args.into_iter().next().unwrap(),
348 decimals: None,
349 to: None,
350 }))),
351
352 "CEIL" if f.args.len() == 1 => Ok(Expression::Ceil(Box::new(CeilFunc {
354 this: f.args.into_iter().next().unwrap(),
355 decimals: None,
356 to: None,
357 }))),
358
359 "LOG" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
362 "LN".to_string(),
363 f.args,
364 )))),
365
366 "LN" => Ok(Expression::Function(Box::new(f))),
368
369 "POWER" | "POW" => Ok(Expression::Function(Box::new(Function::new(
371 "POWER".to_string(),
372 f.args,
373 )))),
374
375 "REGEXP_LIKE" => Ok(Expression::Function(Box::new(f))),
377
378 "JSON_VALUE" => Ok(Expression::Function(Box::new(f))),
380
381 "JSON_QUERY" => Ok(Expression::Function(Box::new(f))),
383
384 "JSON_EXTRACT" => Ok(Expression::Function(Box::new(Function::new(
386 "JSON_VALUE".to_string(),
387 f.args,
388 )))),
389
390 "JSON_EXTRACT_SCALAR" => Ok(Expression::Function(Box::new(Function::new(
392 "JSON_VALUE".to_string(),
393 f.args,
394 )))),
395
396 "SPLIT" => {
399 Ok(Expression::Function(Box::new(Function::new(
401 "REGEXP_SUBSTR".to_string(),
402 f.args,
403 ))))
404 }
405
406 "ADD_MONTHS" => Ok(Expression::Function(Box::new(f))),
408
409 "MONTHS_BETWEEN" => Ok(Expression::Function(Box::new(f))),
411
412 "DATEADD" => {
414 Ok(Expression::Function(Box::new(f)))
416 }
417
418 "DATEDIFF" => Ok(Expression::Function(Box::new(f))),
420
421 "DECODE" => Ok(Expression::Function(Box::new(f))),
423
424 _ => Ok(Expression::Function(Box::new(f))),
426 }
427 }
428
429 fn transform_aggregate_function(
430 &self,
431 f: Box<crate::expressions::AggregateFunction>,
432 ) -> Result<Expression> {
433 let name_upper = f.name.to_uppercase();
434 match name_upper.as_str() {
435 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
437 Function::new("LISTAGG".to_string(), f.args),
438 ))),
439
440 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
442 Function::new("LISTAGG".to_string(), f.args),
443 ))),
444
445 "ARRAY_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
448 "COLLECT".to_string(),
449 f.args,
450 )))),
451
452 _ => Ok(Expression::AggregateFunction(f)),
454 }
455 }
456}