1use super::{
22 dml as arena_dml, expression as arena_expr,
23 interner::{ArenaInterner, Symbol},
24 select as arena_select,
25};
26use crate::{
27 Assignment, BinaryOperator, CaseWhen, CharacterUnit, CommonTableExpr, ConflictClause,
28 DeleteStmt, Expression, FrameBound, FrameUnit, FromClause, FulltextMode, FunctionIdentifier,
29 GroupByClause, GroupingElement, GroupingSet, InsertSource, InsertStmt, IntervalUnit, JoinType,
30 MixedGroupingItem, NullsOrder, OrderByItem, OrderDirection, PseudoTable, Quantifier,
31 SelectItem, SelectStmt, SetOperation, SetOperator, TrimPosition, TruthValue, UpdateStmt,
32 WhereClause, WindowFrame, WindowFunctionSpec, WindowSpec,
33};
34
35pub struct Converter<'a, 'arena> {
40 interner: &'a ArenaInterner<'arena>,
41}
42
43impl<'a, 'arena> Converter<'a, 'arena> {
44 pub fn new(interner: &'a ArenaInterner<'arena>) -> Self {
46 Converter { interner }
47 }
48
49 #[inline]
51 fn resolve(&self, sym: Symbol) -> String {
52 self.interner.resolve(sym).to_string()
53 }
54
55 #[inline]
57 fn resolve_opt(&self, sym: Option<Symbol>) -> Option<String> {
58 sym.map(|s| self.resolve(s))
59 }
60
61 fn build_nested_binary_op(
72 &self,
73 children: &[arena_expr::Expression<'arena>],
74 op: BinaryOperator,
75 ) -> Expression {
76 debug_assert!(children.len() >= 2, "Conjunction/Disjunction must have at least 2 children");
77
78 let mut iter = children.iter();
79
80 let first = iter.next().expect("at least one child");
82 let mut result = self.convert_expression(first);
83
84 for child in iter {
86 result = Expression::BinaryOp {
87 op,
88 left: Box::new(result),
89 right: Box::new(self.convert_expression(child)),
90 };
91 }
92
93 result
94 }
95
96 pub fn convert_expression(&self, expr: &arena_expr::Expression<'arena>) -> Expression {
102 match expr {
103 arena_expr::Expression::Literal(v) => Expression::Literal(v.clone()),
105 arena_expr::Expression::Placeholder(i) => Expression::Placeholder(*i),
106 arena_expr::Expression::NumberedPlaceholder(i) => Expression::NumberedPlaceholder(*i),
107 arena_expr::Expression::NamedPlaceholder(name) => {
108 Expression::NamedPlaceholder(self.resolve(*name))
109 }
110 arena_expr::Expression::ColumnRef {
111 schema,
112 table,
113 column,
114 schema_quoted,
115 table_quoted,
116 column_quoted,
117 } => {
118 let schema_str = self.resolve_opt(*schema);
119 let table_str = self.resolve_opt(*table);
120 let column_str = self.resolve(*column);
121
122 let col_id = match (schema_str, table_str) {
123 (Some(s), Some(t)) => crate::ColumnIdentifier::fully_qualified(
124 &s,
125 *schema_quoted,
126 &t,
127 *table_quoted,
128 &column_str,
129 *column_quoted,
130 ),
131 (None, Some(t)) => crate::ColumnIdentifier::qualified(
132 &t,
133 *table_quoted,
134 &column_str,
135 *column_quoted,
136 ),
137 (_, None) => crate::ColumnIdentifier::simple(&column_str, *column_quoted),
138 };
139 Expression::ColumnRef(col_id)
140 }
141 arena_expr::Expression::BinaryOp { op, left, right } => Expression::BinaryOp {
142 op: *op,
143 left: Box::new(self.convert_expression(left)),
144 right: Box::new(self.convert_expression(right)),
145 },
146 arena_expr::Expression::Conjunction(children) => {
147 self.build_nested_binary_op(children, BinaryOperator::And)
152 }
153 arena_expr::Expression::Disjunction(children) => {
154 self.build_nested_binary_op(children, BinaryOperator::Or)
159 }
160 arena_expr::Expression::UnaryOp { op, expr } => {
161 Expression::UnaryOp { op: *op, expr: Box::new(self.convert_expression(expr)) }
162 }
163 arena_expr::Expression::IsNull { expr, negated } => Expression::IsNull {
164 expr: Box::new(self.convert_expression(expr)),
165 negated: *negated,
166 },
167 arena_expr::Expression::IsDistinctFrom { left, right, negated } => {
168 Expression::IsDistinctFrom {
169 left: Box::new(self.convert_expression(left)),
170 right: Box::new(self.convert_expression(right)),
171 negated: *negated,
172 }
173 }
174 arena_expr::Expression::IsTruthValue { expr, truth_value, negated } => {
175 Expression::IsTruthValue {
176 expr: Box::new(self.convert_expression(expr)),
177 truth_value: (*truth_value).into(),
178 negated: *negated,
179 }
180 }
181 arena_expr::Expression::Wildcard => Expression::Wildcard,
182 arena_expr::Expression::CurrentDate => Expression::CurrentDate,
183 arena_expr::Expression::CurrentTime { precision } => {
184 Expression::CurrentTime { precision: *precision }
185 }
186 arena_expr::Expression::CurrentTimestamp { precision } => {
187 Expression::CurrentTimestamp { precision: *precision }
188 }
189 arena_expr::Expression::Default => Expression::Default,
190
191 arena_expr::Expression::Extended(ext) => self.convert_extended_expr(ext),
193 }
194 }
195
196 fn convert_extended_expr(&self, ext: &arena_expr::ExtendedExpr<'arena>) -> Expression {
198 match ext {
199 arena_expr::ExtendedExpr::Function { name, args, character_unit } => {
200 Expression::Function {
201 name: FunctionIdentifier::new(&self.resolve(*name)),
202 args: args.iter().map(|e| self.convert_expression(e)).collect(),
203 character_unit: character_unit.map(|u| u.into()),
204 }
205 }
206 arena_expr::ExtendedExpr::AggregateFunction { name, distinct, args } => {
207 Expression::AggregateFunction {
208 name: FunctionIdentifier::new(&self.resolve(*name)),
209 distinct: *distinct,
210 args: args.iter().map(|e| self.convert_expression(e)).collect(),
211 order_by: None, filter: None, }
214 }
215 arena_expr::ExtendedExpr::Case { operand, when_clauses, else_result } => {
216 Expression::Case {
217 operand: operand.map(|e| Box::new(self.convert_expression(e))),
218 when_clauses: when_clauses
219 .iter()
220 .map(|cw| self.convert_case_when(cw))
221 .collect(),
222 else_result: else_result.map(|e| Box::new(self.convert_expression(e))),
223 }
224 }
225 arena_expr::ExtendedExpr::ScalarSubquery(subquery) => {
226 Expression::ScalarSubquery(Box::new(self.convert_select(subquery)))
227 }
228 arena_expr::ExtendedExpr::In { expr, subquery, negated } => Expression::In {
229 expr: Box::new(self.convert_expression(expr)),
230 subquery: Box::new(self.convert_select(subquery)),
231 negated: *negated,
232 },
233 arena_expr::ExtendedExpr::InList { expr, values, negated } => Expression::InList {
234 expr: Box::new(self.convert_expression(expr)),
235 values: values.iter().map(|e| self.convert_expression(e)).collect(),
236 negated: *negated,
237 },
238 arena_expr::ExtendedExpr::Between { expr, low, high, negated, symmetric } => {
239 Expression::Between {
240 expr: Box::new(self.convert_expression(expr)),
241 low: Box::new(self.convert_expression(low)),
242 high: Box::new(self.convert_expression(high)),
243 negated: *negated,
244 symmetric: *symmetric,
245 }
246 }
247 arena_expr::ExtendedExpr::Cast { expr, data_type } => Expression::Cast {
248 expr: Box::new(self.convert_expression(expr)),
249 data_type: data_type.clone(),
250 },
251 arena_expr::ExtendedExpr::Position { substring, string, character_unit } => {
252 Expression::Position {
253 substring: Box::new(self.convert_expression(substring)),
254 string: Box::new(self.convert_expression(string)),
255 character_unit: character_unit.map(|u| u.into()),
256 }
257 }
258 arena_expr::ExtendedExpr::Trim { position, removal_char, string } => Expression::Trim {
259 position: position.map(|p| p.into()),
260 removal_char: removal_char.map(|e| Box::new(self.convert_expression(e))),
261 string: Box::new(self.convert_expression(string)),
262 },
263 arena_expr::ExtendedExpr::Extract { field, expr } => Expression::Extract {
264 field: (*field).into(),
265 expr: Box::new(self.convert_expression(expr)),
266 },
267 arena_expr::ExtendedExpr::Like { expr, pattern, negated, escape } => Expression::Like {
268 expr: Box::new(self.convert_expression(expr)),
269 pattern: Box::new(self.convert_expression(pattern)),
270 negated: *negated,
271 escape: escape.map(|e| Box::new(self.convert_expression(e))),
272 },
273 arena_expr::ExtendedExpr::Glob { expr, pattern, negated, escape } => Expression::Glob {
274 expr: Box::new(self.convert_expression(expr)),
275 pattern: Box::new(self.convert_expression(pattern)),
276 negated: *negated,
277 escape: escape.map(|e| Box::new(self.convert_expression(e))),
278 },
279 arena_expr::ExtendedExpr::Exists { subquery, negated } => Expression::Exists {
280 subquery: Box::new(self.convert_select(subquery)),
281 negated: *negated,
282 },
283 arena_expr::ExtendedExpr::QuantifiedComparison { expr, op, quantifier, subquery } => {
284 Expression::QuantifiedComparison {
285 expr: Box::new(self.convert_expression(expr)),
286 op: *op,
287 quantifier: (*quantifier).into(),
288 subquery: Box::new(self.convert_select(subquery)),
289 }
290 }
291 arena_expr::ExtendedExpr::Interval {
292 value,
293 unit,
294 leading_precision,
295 fractional_precision,
296 } => Expression::Interval {
297 value: Box::new(self.convert_expression(value)),
298 unit: (*unit).into(),
299 leading_precision: *leading_precision,
300 fractional_precision: *fractional_precision,
301 },
302 arena_expr::ExtendedExpr::DuplicateKeyValue { column } => {
303 Expression::DuplicateKeyValue { column: self.resolve(*column) }
304 }
305 arena_expr::ExtendedExpr::WindowFunction { function, over } => {
306 Expression::WindowFunction {
307 function: self.convert_window_function_spec(function),
308 over: self.convert_window_spec(over),
309 }
310 }
311 arena_expr::ExtendedExpr::NextValue { sequence_name } => {
312 Expression::NextValue { sequence_name: self.resolve(*sequence_name) }
313 }
314 arena_expr::ExtendedExpr::MatchAgainst { columns, search_modifier, mode } => {
315 Expression::MatchAgainst {
316 columns: columns.iter().map(|s| self.resolve(*s)).collect(),
317 search_modifier: Box::new(self.convert_expression(search_modifier)),
318 mode: (*mode).into(),
319 }
320 }
321 arena_expr::ExtendedExpr::PseudoVariable { pseudo_table, column } => {
322 Expression::PseudoVariable {
323 pseudo_table: (*pseudo_table).into(),
324 column: self.resolve(*column),
325 }
326 }
327 arena_expr::ExtendedExpr::SessionVariable { name } => {
328 Expression::SessionVariable { name: self.resolve(*name) }
329 }
330 arena_expr::ExtendedExpr::RowValueConstructor(values) => {
331 Expression::RowValueConstructor(
332 values.iter().map(|e| self.convert_expression(e)).collect(),
333 )
334 }
335 }
336 }
337
338 fn convert_case_when(&self, cw: &arena_expr::CaseWhen<'arena>) -> CaseWhen {
339 CaseWhen {
340 conditions: cw.conditions.iter().map(|e| self.convert_expression(e)).collect(),
341 result: self.convert_expression(&cw.result),
342 }
343 }
344
345 fn convert_window_function_spec(
346 &self,
347 spec: &arena_expr::WindowFunctionSpec<'arena>,
348 ) -> WindowFunctionSpec {
349 match spec {
350 arena_expr::WindowFunctionSpec::Aggregate { name, args } => {
351 WindowFunctionSpec::Aggregate {
352 name: FunctionIdentifier::new(&self.resolve(*name)),
353 args: args.iter().map(|e| self.convert_expression(e)).collect(),
354 filter: None, }
356 }
357 arena_expr::WindowFunctionSpec::Ranking { name, args } => WindowFunctionSpec::Ranking {
358 name: FunctionIdentifier::new(&self.resolve(*name)),
359 args: args.iter().map(|e| self.convert_expression(e)).collect(),
360 },
361 arena_expr::WindowFunctionSpec::Value { name, args } => WindowFunctionSpec::Value {
362 name: FunctionIdentifier::new(&self.resolve(*name)),
363 args: args.iter().map(|e| self.convert_expression(e)).collect(),
364 },
365 }
366 }
367
368 fn convert_window_spec(&self, spec: &arena_expr::WindowSpec<'arena>) -> WindowSpec {
369 WindowSpec {
370 partition_by: spec
371 .partition_by
372 .as_ref()
373 .map(|v| v.iter().map(|e| self.convert_expression(e)).collect()),
374 order_by: spec
375 .order_by
376 .as_ref()
377 .map(|v| v.iter().map(|item| self.convert_order_by_item(item)).collect()),
378 frame: spec.frame.as_ref().map(|f| self.convert_window_frame(f)),
379 }
380 }
381
382 fn convert_window_frame(&self, f: &arena_expr::WindowFrame<'arena>) -> WindowFrame {
383 WindowFrame {
384 unit: f.unit.into(),
385 start: self.convert_frame_bound(&f.start),
386 end: f.end.as_ref().map(|b| self.convert_frame_bound(b)),
387 exclude: f.exclude.map(|e| match e {
388 arena_expr::FrameExclude::NoOthers => crate::FrameExclude::NoOthers,
389 arena_expr::FrameExclude::CurrentRow => crate::FrameExclude::CurrentRow,
390 arena_expr::FrameExclude::Group => crate::FrameExclude::Group,
391 arena_expr::FrameExclude::Ties => crate::FrameExclude::Ties,
392 }),
393 }
394 }
395
396 fn convert_frame_bound(&self, b: &arena_expr::FrameBound<'arena>) -> FrameBound {
397 match b {
398 arena_expr::FrameBound::UnboundedPreceding => FrameBound::UnboundedPreceding,
399 arena_expr::FrameBound::Preceding(e) => {
400 FrameBound::Preceding(Box::new(self.convert_expression(e)))
401 }
402 arena_expr::FrameBound::CurrentRow => FrameBound::CurrentRow,
403 arena_expr::FrameBound::Following(e) => {
404 FrameBound::Following(Box::new(self.convert_expression(e)))
405 }
406 arena_expr::FrameBound::UnboundedFollowing => FrameBound::UnboundedFollowing,
407 }
408 }
409
410 fn convert_order_by_item(&self, item: &arena_expr::OrderByItem<'arena>) -> OrderByItem {
411 OrderByItem {
412 expr: self.convert_expression(&item.expr),
413 direction: item.direction.into(),
414 nulls_order: item.nulls_order.map(|no| match no {
415 arena_expr::NullsOrder::First => NullsOrder::First,
416 arena_expr::NullsOrder::Last => NullsOrder::Last,
417 }),
418 }
419 }
420
421 pub fn convert_select(&self, stmt: &arena_select::SelectStmt<'arena>) -> SelectStmt {
427 SelectStmt {
428 with_clause: stmt
429 .with_clause
430 .as_ref()
431 .map(|ctes| ctes.iter().map(|cte| self.convert_cte(cte)).collect()),
432 distinct: stmt.distinct,
433 select_list: stmt
434 .select_list
435 .iter()
436 .map(|item| self.convert_select_item(item))
437 .collect(),
438 into_table: self.resolve_opt(stmt.into_table),
439 into_variables: stmt
440 .into_variables
441 .as_ref()
442 .map(|v| v.iter().map(|s| self.resolve(*s)).collect()),
443 from: stmt.from.as_ref().map(|f| self.convert_from_clause(f)),
444 where_clause: stmt.where_clause.as_ref().map(|e| self.convert_expression(e)),
445 group_by: stmt.group_by.as_ref().map(|g| self.convert_group_by(g)),
446 having: stmt.having.as_ref().map(|e| self.convert_expression(e)),
447 order_by: stmt
448 .order_by
449 .as_ref()
450 .map(|v| v.iter().map(|item| self.convert_order_by_item(item)).collect()),
451 limit: stmt.limit.as_ref().map(|e| self.convert_expression(e)),
452 offset: stmt.offset.as_ref().map(|e| self.convert_expression(e)),
453 set_operation: stmt.set_operation.as_ref().map(|so| self.convert_set_operation(so)),
454 values: stmt.values.as_ref().map(|rows| {
455 rows.iter()
456 .map(|row| row.iter().map(|e| self.convert_expression(e)).collect())
457 .collect()
458 }),
459 }
460 }
461
462 fn convert_cte(&self, cte: &arena_select::CommonTableExpr<'arena>) -> CommonTableExpr {
463 CommonTableExpr {
464 name: self.resolve(cte.name),
465 columns: cte.columns.as_ref().map(|v| v.iter().map(|s| self.resolve(*s)).collect()),
466 query: Box::new(self.convert_select(cte.query)),
467 recursive: cte.recursive,
468 materialization: cte.materialization,
469 }
470 }
471
472 fn convert_select_item(&self, item: &arena_select::SelectItem<'arena>) -> SelectItem {
473 match item {
474 arena_select::SelectItem::Wildcard { alias } => SelectItem::Wildcard {
475 alias: alias.as_ref().map(|v| v.iter().map(|s| self.resolve(*s)).collect()),
476 },
477 arena_select::SelectItem::QualifiedWildcard { qualifier, alias } => {
478 SelectItem::QualifiedWildcard {
479 qualifier: self.resolve(*qualifier),
480 alias: alias.as_ref().map(|v| v.iter().map(|s| self.resolve(*s)).collect()),
481 }
482 }
483 arena_select::SelectItem::Expression { expr, alias, source_text } => {
484 SelectItem::Expression {
485 expr: self.convert_expression(expr),
486 alias: self.resolve_opt(*alias),
487 source_text: source_text.map(|s| s.to_string()),
488 }
489 }
490 }
491 }
492
493 fn convert_from_clause(&self, from: &arena_select::FromClause<'arena>) -> FromClause {
494 match from {
495 arena_select::FromClause::Table { name, alias, column_aliases, quoted } => {
496 FromClause::Table {
497 name: self.resolve(*name),
498 alias: self.resolve_opt(*alias),
499 column_aliases: column_aliases
500 .as_ref()
501 .map(|cols| cols.iter().map(|s| self.resolve(*s)).collect()),
502 quoted: *quoted,
503 }
504 }
505 arena_select::FromClause::Join {
506 left,
507 right,
508 join_type,
509 condition,
510 using_columns,
511 natural,
512 alias,
513 } => FromClause::Join {
514 left: Box::new(self.convert_from_clause(left)),
515 right: Box::new(self.convert_from_clause(right)),
516 join_type: (*join_type).into(),
517 condition: condition.as_ref().map(|e| self.convert_expression(e)),
518 using_columns: using_columns
519 .as_ref()
520 .map(|cols| cols.iter().map(|s| self.resolve(*s)).collect()),
521 natural: *natural,
522 alias: alias.map(|s| self.resolve(s)),
523 },
524 arena_select::FromClause::Subquery { query, alias, column_aliases } => {
525 FromClause::Subquery {
526 query: Box::new(self.convert_select(query)),
527 alias: self.resolve(*alias),
528 column_aliases: column_aliases
529 .as_ref()
530 .map(|cols| cols.iter().map(|s| self.resolve(*s)).collect()),
531 }
532 }
533 }
534 }
535
536 fn convert_group_by(&self, gb: &arena_select::GroupByClause<'arena>) -> GroupByClause {
537 match gb {
538 arena_select::GroupByClause::Simple(exprs) => {
539 GroupByClause::Simple(exprs.iter().map(|e| self.convert_expression(e)).collect())
540 }
541 arena_select::GroupByClause::Rollup(elements) => GroupByClause::Rollup(
542 elements.iter().map(|e| self.convert_grouping_element(e)).collect(),
543 ),
544 arena_select::GroupByClause::Cube(elements) => GroupByClause::Cube(
545 elements.iter().map(|e| self.convert_grouping_element(e)).collect(),
546 ),
547 arena_select::GroupByClause::GroupingSets(sets) => GroupByClause::GroupingSets(
548 sets.iter().map(|s| self.convert_grouping_set(s)).collect(),
549 ),
550 arena_select::GroupByClause::Mixed(items) => GroupByClause::Mixed(
551 items.iter().map(|i| self.convert_mixed_grouping_item(i)).collect(),
552 ),
553 }
554 }
555
556 fn convert_grouping_element(
557 &self,
558 ge: &arena_select::GroupingElement<'arena>,
559 ) -> GroupingElement {
560 match ge {
561 arena_select::GroupingElement::Single(expr) => {
562 GroupingElement::Single(self.convert_expression(expr))
563 }
564 arena_select::GroupingElement::Composite(exprs) => GroupingElement::Composite(
565 exprs.iter().map(|e| self.convert_expression(e)).collect(),
566 ),
567 }
568 }
569
570 fn convert_grouping_set(&self, gs: &arena_select::GroupingSet<'arena>) -> GroupingSet {
571 GroupingSet { columns: gs.columns.iter().map(|e| self.convert_expression(e)).collect() }
572 }
573
574 fn convert_mixed_grouping_item(
575 &self,
576 mgi: &arena_select::MixedGroupingItem<'arena>,
577 ) -> MixedGroupingItem {
578 match mgi {
579 arena_select::MixedGroupingItem::Simple(expr) => {
580 MixedGroupingItem::Simple(self.convert_expression(expr))
581 }
582 arena_select::MixedGroupingItem::Rollup(elements) => MixedGroupingItem::Rollup(
583 elements.iter().map(|e| self.convert_grouping_element(e)).collect(),
584 ),
585 arena_select::MixedGroupingItem::Cube(elements) => MixedGroupingItem::Cube(
586 elements.iter().map(|e| self.convert_grouping_element(e)).collect(),
587 ),
588 arena_select::MixedGroupingItem::GroupingSets(sets) => MixedGroupingItem::GroupingSets(
589 sets.iter().map(|s| self.convert_grouping_set(s)).collect(),
590 ),
591 }
592 }
593
594 fn convert_set_operation(&self, so: &arena_select::SetOperation<'arena>) -> SetOperation {
595 SetOperation {
596 op: so.op.into(),
597 all: so.all,
598 right: Box::new(self.convert_select(so.right)),
599 }
600 }
601
602 pub fn convert_insert(&self, stmt: &arena_dml::InsertStmt<'arena>) -> InsertStmt {
608 InsertStmt {
609 with_clause: stmt.with_clause.as_ref().map(|ctes| {
610 ctes.iter().map(|cte| self.convert_cte(cte)).collect()
611 }),
612 schema_name: stmt.schema_name.map(|s| self.resolve(s)),
613 schema_quoted: stmt.schema_quoted,
614 table_name: self.resolve(stmt.table_name),
615 table_quoted: stmt.table_quoted,
616 columns: stmt.columns.iter().map(|s| self.resolve(*s)).collect(),
617 source: self.convert_insert_source(&stmt.source),
618 conflict_clause: stmt.conflict_clause.map(ConflictClause::from),
619 on_conflict: stmt.on_conflict.as_ref().map(|c| self.convert_on_conflict_clause(c)),
620 on_duplicate_key_update: stmt.on_duplicate_key_update.as_ref().map(|assignments| {
621 assignments.iter().map(|a| self.convert_assignment(a)).collect()
622 }),
623 }
624 }
625
626 fn convert_on_conflict_clause(
627 &self,
628 clause: &arena_dml::OnConflictClause<'arena>,
629 ) -> crate::OnConflictClause {
630 crate::OnConflictClause {
631 conflict_target: clause
632 .conflict_target
633 .as_ref()
634 .map(|cols| cols.iter().map(|s| self.resolve(*s)).collect()),
635 action: match &clause.action {
636 arena_dml::OnConflictAction::DoNothing => crate::OnConflictAction::DoNothing,
637 arena_dml::OnConflictAction::DoUpdate { assignments, where_clause } => {
638 crate::OnConflictAction::DoUpdate {
639 assignments: assignments
640 .iter()
641 .map(|a| self.convert_assignment(a))
642 .collect(),
643 where_clause: where_clause.as_ref().map(|e| self.convert_expression(e)),
644 }
645 }
646 },
647 }
648 }
649
650 fn convert_insert_source(&self, source: &arena_dml::InsertSource<'arena>) -> InsertSource {
651 match source {
652 arena_dml::InsertSource::Values(rows) => InsertSource::Values(
653 rows.iter()
654 .map(|row| row.iter().map(|e| self.convert_expression(e)).collect())
655 .collect(),
656 ),
657 arena_dml::InsertSource::Select(query) => {
658 InsertSource::Select(Box::new(self.convert_select(query)))
659 }
660 arena_dml::InsertSource::DefaultValues => InsertSource::DefaultValues,
661 }
662 }
663
664 fn convert_assignment(&self, a: &arena_dml::Assignment<'arena>) -> Assignment {
665 Assignment { column: self.resolve(a.column), value: self.convert_expression(&a.value) }
666 }
667
668 pub fn convert_update(&self, stmt: &arena_dml::UpdateStmt<'arena>) -> UpdateStmt {
670 UpdateStmt {
671 with_clause: stmt.with_clause.as_ref().map(|ctes| {
672 ctes.iter().map(|cte| self.convert_cte(cte)).collect()
673 }),
674 table_name: self.resolve(stmt.table_name),
675 quoted: stmt.quoted,
676 alias: stmt.alias.map(|a| self.resolve(a)),
677 assignments: stmt.assignments.iter().map(|a| self.convert_assignment(a)).collect(),
678 from_clause: stmt.from_clause.as_ref().map(|froms| {
679 froms.iter().map(|f| self.convert_from_clause(f)).collect()
680 }),
681 where_clause: stmt.where_clause.as_ref().map(|wc| self.convert_where_clause(wc)),
682 conflict_clause: stmt.conflict_clause.map(ConflictClause::from),
683 }
684 }
685
686 fn convert_where_clause(&self, wc: &arena_dml::WhereClause<'arena>) -> WhereClause {
687 match wc {
688 arena_dml::WhereClause::Condition(expr) => {
689 WhereClause::Condition(self.convert_expression(expr))
690 }
691 arena_dml::WhereClause::CurrentOf(cursor) => {
692 WhereClause::CurrentOf(self.resolve(*cursor))
693 }
694 }
695 }
696
697 pub fn convert_delete(&self, stmt: &arena_dml::DeleteStmt<'arena>) -> DeleteStmt {
699 DeleteStmt {
700 with_clause: stmt.with_clause.as_ref().map(|ctes| {
701 ctes.iter().map(|cte| self.convert_cte(cte)).collect()
702 }),
703 only: stmt.only,
704 table_name: self.resolve(stmt.table_name),
705 quoted: stmt.quoted,
706 where_clause: stmt.where_clause.as_ref().map(|wc| self.convert_where_clause(wc)),
707 order_by: stmt
708 .order_by
709 .as_ref()
710 .map(|v| v.iter().map(|item| self.convert_order_by_item(item)).collect()),
711 limit: stmt.limit.as_ref().map(|e| self.convert_expression(e)),
712 offset: stmt.offset.as_ref().map(|e| self.convert_expression(e)),
713 }
714 }
715}
716
717impl From<arena_expr::CharacterUnit> for CharacterUnit {
722 fn from(u: arena_expr::CharacterUnit) -> Self {
723 match u {
724 arena_expr::CharacterUnit::Characters => CharacterUnit::Characters,
725 arena_expr::CharacterUnit::Octets => CharacterUnit::Octets,
726 }
727 }
728}
729
730impl From<arena_expr::TrimPosition> for TrimPosition {
731 fn from(p: arena_expr::TrimPosition) -> Self {
732 match p {
733 arena_expr::TrimPosition::Both => TrimPosition::Both,
734 arena_expr::TrimPosition::Leading => TrimPosition::Leading,
735 arena_expr::TrimPosition::Trailing => TrimPosition::Trailing,
736 }
737 }
738}
739
740impl From<arena_expr::IntervalUnit> for IntervalUnit {
741 fn from(u: arena_expr::IntervalUnit) -> Self {
742 match u {
743 arena_expr::IntervalUnit::Microsecond => IntervalUnit::Microsecond,
744 arena_expr::IntervalUnit::Second => IntervalUnit::Second,
745 arena_expr::IntervalUnit::Minute => IntervalUnit::Minute,
746 arena_expr::IntervalUnit::Hour => IntervalUnit::Hour,
747 arena_expr::IntervalUnit::Day => IntervalUnit::Day,
748 arena_expr::IntervalUnit::Week => IntervalUnit::Week,
749 arena_expr::IntervalUnit::Month => IntervalUnit::Month,
750 arena_expr::IntervalUnit::Quarter => IntervalUnit::Quarter,
751 arena_expr::IntervalUnit::Year => IntervalUnit::Year,
752 arena_expr::IntervalUnit::SecondMicrosecond => IntervalUnit::SecondMicrosecond,
753 arena_expr::IntervalUnit::MinuteMicrosecond => IntervalUnit::MinuteMicrosecond,
754 arena_expr::IntervalUnit::MinuteSecond => IntervalUnit::MinuteSecond,
755 arena_expr::IntervalUnit::HourMicrosecond => IntervalUnit::HourMicrosecond,
756 arena_expr::IntervalUnit::HourSecond => IntervalUnit::HourSecond,
757 arena_expr::IntervalUnit::HourMinute => IntervalUnit::HourMinute,
758 arena_expr::IntervalUnit::DayMicrosecond => IntervalUnit::DayMicrosecond,
759 arena_expr::IntervalUnit::DaySecond => IntervalUnit::DaySecond,
760 arena_expr::IntervalUnit::DayMinute => IntervalUnit::DayMinute,
761 arena_expr::IntervalUnit::DayHour => IntervalUnit::DayHour,
762 arena_expr::IntervalUnit::YearMonth => IntervalUnit::YearMonth,
763 }
764 }
765}
766
767impl From<arena_expr::Quantifier> for Quantifier {
768 fn from(q: arena_expr::Quantifier) -> Self {
769 match q {
770 arena_expr::Quantifier::All => Quantifier::All,
771 arena_expr::Quantifier::Any => Quantifier::Any,
772 arena_expr::Quantifier::Some => Quantifier::Some,
773 }
774 }
775}
776
777impl From<arena_expr::TruthValue> for TruthValue {
778 fn from(tv: arena_expr::TruthValue) -> Self {
779 match tv {
780 arena_expr::TruthValue::True => TruthValue::True,
781 arena_expr::TruthValue::False => TruthValue::False,
782 arena_expr::TruthValue::Unknown => TruthValue::Unknown,
783 }
784 }
785}
786
787impl From<arena_expr::FulltextMode> for FulltextMode {
788 fn from(m: arena_expr::FulltextMode) -> Self {
789 match m {
790 arena_expr::FulltextMode::NaturalLanguage => FulltextMode::NaturalLanguage,
791 arena_expr::FulltextMode::Boolean => FulltextMode::Boolean,
792 arena_expr::FulltextMode::QueryExpansion => FulltextMode::QueryExpansion,
793 }
794 }
795}
796
797impl From<arena_expr::PseudoTable> for PseudoTable {
798 fn from(p: arena_expr::PseudoTable) -> Self {
799 match p {
800 arena_expr::PseudoTable::Old => PseudoTable::Old,
801 arena_expr::PseudoTable::New => PseudoTable::New,
802 }
803 }
804}
805
806impl From<arena_expr::FrameUnit> for FrameUnit {
807 fn from(u: arena_expr::FrameUnit) -> Self {
808 match u {
809 arena_expr::FrameUnit::Rows => FrameUnit::Rows,
810 arena_expr::FrameUnit::Range => FrameUnit::Range,
811 }
812 }
813}
814
815impl From<arena_expr::OrderDirection> for OrderDirection {
816 fn from(d: arena_expr::OrderDirection) -> Self {
817 match d {
818 arena_expr::OrderDirection::Asc => OrderDirection::Asc,
819 arena_expr::OrderDirection::Desc => OrderDirection::Desc,
820 }
821 }
822}
823
824impl From<arena_select::JoinType> for JoinType {
825 fn from(jt: arena_select::JoinType) -> Self {
826 match jt {
827 arena_select::JoinType::Inner => JoinType::Inner,
828 arena_select::JoinType::LeftOuter => JoinType::LeftOuter,
829 arena_select::JoinType::RightOuter => JoinType::RightOuter,
830 arena_select::JoinType::FullOuter => JoinType::FullOuter,
831 arena_select::JoinType::Cross => JoinType::Cross,
832 arena_select::JoinType::Semi => JoinType::Semi,
833 arena_select::JoinType::Anti => JoinType::Anti,
834 }
835 }
836}
837
838impl From<arena_select::SetOperator> for SetOperator {
839 fn from(op: arena_select::SetOperator) -> Self {
840 match op {
841 arena_select::SetOperator::Union => SetOperator::Union,
842 arena_select::SetOperator::Intersect => SetOperator::Intersect,
843 arena_select::SetOperator::Except => SetOperator::Except,
844 }
845 }
846}
847
848impl From<arena_dml::ConflictClause> for ConflictClause {
849 fn from(cc: arena_dml::ConflictClause) -> Self {
850 match cc {
851 arena_dml::ConflictClause::Abort => ConflictClause::Abort,
852 arena_dml::ConflictClause::Fail => ConflictClause::Fail,
853 arena_dml::ConflictClause::Ignore => ConflictClause::Ignore,
854 arena_dml::ConflictClause::Replace => ConflictClause::Replace,
855 arena_dml::ConflictClause::Rollback => ConflictClause::Rollback,
856 }
857 }
858}
859
860#[cfg(test)]
861mod tests {
862 use bumpalo::{collections::Vec as BumpVec, Bump};
863
864 use super::*;
865
866 fn make_conjunction<'arena>(
868 arena: &'arena Bump,
869 exprs: Vec<arena_expr::Expression<'arena>>,
870 ) -> arena_expr::Expression<'arena> {
871 let mut children = BumpVec::new_in(arena);
872 for e in exprs {
873 children.push(e);
874 }
875 arena_expr::Expression::Conjunction(children)
876 }
877
878 fn make_disjunction<'arena>(
880 arena: &'arena Bump,
881 exprs: Vec<arena_expr::Expression<'arena>>,
882 ) -> arena_expr::Expression<'arena> {
883 let mut children = BumpVec::new_in(arena);
884 for e in exprs {
885 children.push(e);
886 }
887 arena_expr::Expression::Disjunction(children)
888 }
889
890 #[test]
892 fn test_conjunction_normalizes_to_nested_binary_and() {
893 let arena = Bump::new();
894 let interner = ArenaInterner::new(&arena);
895 let converter = Converter::new(&interner);
896
897 let a = arena_expr::Expression::Literal(vibesql_types::SqlValue::Integer(1));
899 let b = arena_expr::Expression::Literal(vibesql_types::SqlValue::Integer(2));
900 let c = arena_expr::Expression::Literal(vibesql_types::SqlValue::Integer(3));
901
902 let conjunction = make_conjunction(&arena, vec![a, b, c]);
903 let result = converter.convert_expression(&conjunction);
904
905 match result {
907 Expression::BinaryOp { op: BinaryOperator::And, left, right } => {
908 assert!(matches!(*right, Expression::Literal(vibesql_types::SqlValue::Integer(3))));
910 match *left {
912 Expression::BinaryOp { op: BinaryOperator::And, left: ll, right: lr } => {
913 assert!(matches!(
914 *ll,
915 Expression::Literal(vibesql_types::SqlValue::Integer(1))
916 ));
917 assert!(matches!(
918 *lr,
919 Expression::Literal(vibesql_types::SqlValue::Integer(2))
920 ));
921 }
922 _ => panic!("Expected nested BinaryOp::And, got {:?}", left),
923 }
924 }
925 _ => panic!("Expected BinaryOp::And, got {:?}", result),
926 }
927 }
928
929 #[test]
931 fn test_disjunction_normalizes_to_nested_binary_or() {
932 let arena = Bump::new();
933 let interner = ArenaInterner::new(&arena);
934 let converter = Converter::new(&interner);
935
936 let a = arena_expr::Expression::Literal(vibesql_types::SqlValue::Integer(1));
938 let b = arena_expr::Expression::Literal(vibesql_types::SqlValue::Integer(2));
939 let c = arena_expr::Expression::Literal(vibesql_types::SqlValue::Integer(3));
940
941 let disjunction = make_disjunction(&arena, vec![a, b, c]);
942 let result = converter.convert_expression(&disjunction);
943
944 match result {
946 Expression::BinaryOp { op: BinaryOperator::Or, left, right } => {
947 assert!(matches!(*right, Expression::Literal(vibesql_types::SqlValue::Integer(3))));
949 match *left {
951 Expression::BinaryOp { op: BinaryOperator::Or, left: ll, right: lr } => {
952 assert!(matches!(
953 *ll,
954 Expression::Literal(vibesql_types::SqlValue::Integer(1))
955 ));
956 assert!(matches!(
957 *lr,
958 Expression::Literal(vibesql_types::SqlValue::Integer(2))
959 ));
960 }
961 _ => panic!("Expected nested BinaryOp::Or, got {:?}", left),
962 }
963 }
964 _ => panic!("Expected BinaryOp::Or, got {:?}", result),
965 }
966 }
967
968 #[test]
970 fn test_two_element_conjunction() {
971 let arena = Bump::new();
972 let interner = ArenaInterner::new(&arena);
973 let converter = Converter::new(&interner);
974
975 let a = arena_expr::Expression::Literal(vibesql_types::SqlValue::Integer(1));
976 let b = arena_expr::Expression::Literal(vibesql_types::SqlValue::Integer(2));
977
978 let conjunction = make_conjunction(&arena, vec![a, b]);
979 let result = converter.convert_expression(&conjunction);
980
981 match result {
983 Expression::BinaryOp { op: BinaryOperator::And, left, right } => {
984 assert!(matches!(*left, Expression::Literal(vibesql_types::SqlValue::Integer(1))));
985 assert!(matches!(*right, Expression::Literal(vibesql_types::SqlValue::Integer(2))));
986 }
987 _ => panic!("Expected BinaryOp::And, got {:?}", result),
988 }
989 }
990
991 #[test]
993 fn test_four_element_conjunction_is_left_associative() {
994 let arena = Bump::new();
995 let interner = ArenaInterner::new(&arena);
996 let converter = Converter::new(&interner);
997
998 let a = arena_expr::Expression::Literal(vibesql_types::SqlValue::Integer(1));
1000 let b = arena_expr::Expression::Literal(vibesql_types::SqlValue::Integer(2));
1001 let c = arena_expr::Expression::Literal(vibesql_types::SqlValue::Integer(3));
1002 let d = arena_expr::Expression::Literal(vibesql_types::SqlValue::Integer(4));
1003
1004 let conjunction = make_conjunction(&arena, vec![a, b, c, d]);
1005 let result = converter.convert_expression(&conjunction);
1006
1007 fn count_left_depth(expr: &Expression) -> usize {
1010 match expr {
1011 Expression::BinaryOp { op: BinaryOperator::And, left, .. } => {
1012 1 + count_left_depth(left)
1013 }
1014 _ => 0,
1015 }
1016 }
1017
1018 assert_eq!(count_left_depth(&result), 3, "Expected 3 levels of nesting for 4 elements");
1019 }
1020}