1use std::collections::HashMap;
2
3use pest::iterators::Pair;
4use prost::Message;
5use substrait::proto::aggregate_rel::Grouping;
6use substrait::proto::expression::literal::LiteralType;
7use substrait::proto::expression::{Literal, RexType, nested};
8use substrait::proto::extensions::AdvancedExtension;
9use substrait::proto::fetch_rel::{CountMode, OffsetMode};
10use substrait::proto::rel::RelType;
11use substrait::proto::rel_common::{Direct, Emit, EmitKind};
12use substrait::proto::sort_field::{SortDirection, SortKind};
13use substrait::proto::{
14 AggregateRel, CrossRel, Expression, FetchRel, FilterRel, JoinRel, NamedStruct, ProjectRel,
15 ReadRel, Rel, RelCommon, SetRel, SortField, SortRel, Type, aggregate_rel, join_rel, read_rel,
16 set_rel, r#type,
17};
18
19use super::{MessageParseError, ParsePair, Rule, RuleIter, ScopedParsePair, unwrap_single_pair};
20use crate::extensions::any::Any;
21use crate::extensions::registry::ExtensionError;
22use crate::extensions::{AddendumKind, ExtensionArgs, ExtensionRegistry, SimpleExtensions};
23use crate::parser::errors::{ParseContext, ParseError};
24use crate::parser::expressions::{FieldIndex, Name};
25
26pub struct RelationParsingContext<'a> {
28 pub registry: &'a ExtensionRegistry,
29 pub line_no: i64,
30 pub line: &'a str,
31}
32
33impl<'a> RelationParsingContext<'a> {
34 pub fn resolve_extension_detail(
36 &self,
37 extension_name: &str,
38 extension_args: &ExtensionArgs,
39 ) -> Result<Option<Any>, ParseError> {
40 let detail = self
41 .registry
42 .parse_extension(extension_name, extension_args);
43
44 match detail {
45 Ok(any) => Ok(Some(any)),
46 Err(ExtensionError::NotFound { .. }) => Err(ParseError::UnregisteredExtension {
47 name: extension_name.to_string(),
48 context: ParseContext::new(self.line_no, self.line.to_string()),
49 }),
50 Err(err) => Err(ParseError::ExtensionDetail(
51 ParseContext::new(self.line_no, self.line.to_string()),
52 err,
53 )),
54 }
55 }
56
57 pub(crate) fn resolve_addendum_detail(
60 &self,
61 kind: AddendumKind,
62 name: &str,
63 args: &ExtensionArgs,
64 ) -> Result<Any, ParseError> {
65 let result = match kind {
66 AddendumKind::Enhancement => self.registry.parse_enhancement(name, args),
67 AddendumKind::Optimization => self.registry.parse_optimization(name, args),
68 AddendumKind::ExtensionTable => self.registry.parse_extension_table(name, args),
69 };
70 result.map_err(|err| match err {
71 ExtensionError::NotFound { .. } => ParseError::UnregisteredExtension {
72 name: name.to_string(),
73 context: ParseContext::new(self.line_no, self.line.to_string()),
74 },
75 err => ParseError::ExtensionDetail(
76 ParseContext::new(self.line_no, self.line.to_string()),
77 err,
78 ),
79 })
80 }
81}
82
83pub trait RelationParsePair: Sized {
85 fn rule() -> Rule;
86 fn message() -> &'static str;
87
88 fn parse_pair_with_context(
94 extensions: &SimpleExtensions,
95 pair: Pair<Rule>,
96 input_children: Vec<Rel>,
97 input_field_count: usize,
98 ) -> Result<(Self, usize), MessageParseError>;
99
100 fn into_rel(self, adv_ext: Option<AdvancedExtension>) -> Rel;
103}
104
105pub struct TableName(Vec<String>);
106
107impl ParsePair for TableName {
108 fn rule() -> Rule {
109 Rule::table_name
110 }
111
112 fn message() -> &'static str {
113 "TableName"
114 }
115
116 fn parse_pair(pair: Pair<Rule>) -> Self {
117 assert_eq!(pair.as_rule(), Self::rule());
118 let pairs = pair.into_inner();
119 let mut names = Vec::with_capacity(pairs.len());
120 let mut iter = RuleIter::from(pairs);
121 while let Some(name) = iter.parse_if_next::<Name>() {
122 names.push(name.0);
123 }
124 iter.done();
125 Self(names)
126 }
127}
128
129#[derive(Debug, Clone)]
130pub struct Column {
131 pub name: String,
132 pub typ: Type,
133}
134
135impl ScopedParsePair for Column {
136 fn rule() -> Rule {
137 Rule::named_column
138 }
139
140 fn message() -> &'static str {
141 "Column"
142 }
143
144 fn parse_pair(
145 extensions: &SimpleExtensions,
146 pair: Pair<Rule>,
147 ) -> Result<Self, MessageParseError> {
148 assert_eq!(pair.as_rule(), Self::rule());
149 let mut iter = RuleIter::from(pair.into_inner());
150 let name = iter.parse_next::<Name>().0;
151 let typ = iter.parse_next_scoped(extensions)?;
152 iter.done();
153 Ok(Self { name, typ })
154 }
155}
156
157pub(crate) struct NamedColumnList(pub(crate) Vec<Column>);
158
159impl ScopedParsePair for NamedColumnList {
160 fn rule() -> Rule {
161 Rule::named_column_list
162 }
163
164 fn message() -> &'static str {
165 "NamedColumnList"
166 }
167
168 fn parse_pair(
169 extensions: &SimpleExtensions,
170 pair: Pair<Rule>,
171 ) -> Result<Self, MessageParseError> {
172 assert_eq!(pair.as_rule(), Self::rule());
173 let mut columns = Vec::new();
174 for col in pair.into_inner() {
175 columns.push(Column::parse_pair(extensions, col)?);
176 }
177 Ok(Self(columns))
178 }
179}
180
181pub(crate) fn expect_one_child(
186 message: &'static str,
187 pair: &Pair<Rule>,
188 mut input_children: Vec<Rel>,
189) -> Result<Box<Rel>, MessageParseError> {
190 match input_children.len() {
191 0 => Err(MessageParseError::invalid(
192 message,
193 pair.as_span(),
194 format!("{message} missing child"),
195 )),
196 1 => Ok(Box::new(input_children.pop().unwrap())),
197 n => Err(MessageParseError::invalid(
198 message,
199 pair.as_span(),
200 format!("{message} should have 1 input child, got {n}"),
201 )),
202 }
203}
204
205fn parse_output_mapping(pair: Pair<Rule>) -> Vec<i32> {
208 assert_eq!(pair.as_rule(), Rule::reference_list);
209 pair.into_inner()
210 .map(|p| FieldIndex::parse_pair(p).0)
211 .collect()
212}
213
214fn make_emit(output_mapping: Vec<i32>, direct_output_count: usize) -> EmitKind {
217 let is_identity = output_mapping.len() == direct_output_count
218 && output_mapping
219 .iter()
220 .enumerate()
221 .all(|(i, &v)| v == i as i32);
222 if is_identity {
223 EmitKind::Direct(Direct {})
224 } else {
225 EmitKind::Emit(Emit { output_mapping })
226 }
227}
228
229fn parse_emit(reference_list: Pair<Rule>, direct_output_count: usize) -> (EmitKind, usize) {
231 let output_mapping = parse_output_mapping(reference_list);
232 let output_count = output_mapping.len();
233 let emit = make_emit(output_mapping, direct_output_count);
234 (emit, output_count)
235}
236
237pub struct ParsedNamedArgs<'a> {
243 map: HashMap<&'a str, Pair<'a, Rule>>,
244}
245
246impl<'a> ParsedNamedArgs<'a> {
247 pub fn new(
248 pairs: pest::iterators::Pairs<'a, Rule>,
249 rule: Rule,
250 ) -> Result<Self, MessageParseError> {
251 let mut map = HashMap::new();
252 for pair in pairs {
253 assert_eq!(pair.as_rule(), rule);
254 let mut inner = pair.clone().into_inner();
255 let name_pair = inner.next().unwrap();
256 let value_pair = inner.next().unwrap();
257 assert_eq!(inner.next(), None);
258 let name = name_pair.as_str();
259 if map.contains_key(name) {
260 return Err(MessageParseError::invalid(
261 "NamedArg",
262 name_pair.as_span(),
263 format!("Duplicate argument: {name}"),
264 ));
265 }
266 map.insert(name, value_pair);
267 }
268 Ok(Self { map })
269 }
270
271 pub fn pop(mut self, name: &str, rule: Rule) -> (Self, Option<Pair<'a, Rule>>) {
275 let pair = self.map.remove(name).inspect(|pair| {
276 assert_eq!(pair.as_rule(), rule, "Rule mismatch for argument {name}");
277 });
278 (self, pair)
279 }
280
281 pub fn done(self) -> Result<(), MessageParseError> {
283 if let Some((name, pair)) = self.map.iter().next() {
284 return Err(MessageParseError::invalid(
285 "NamedArgExtractor",
286 pair.as_span(),
288 format!("Unknown argument: {name}"),
289 ));
290 }
291 Ok(())
292 }
293}
294
295impl RelationParsePair for ReadRel {
296 fn rule() -> Rule {
297 Rule::read_relation
298 }
299
300 fn message() -> &'static str {
301 "ReadRel"
302 }
303
304 fn parse_pair_with_context(
305 extensions: &SimpleExtensions,
306 pair: Pair<Rule>,
307 input_children: Vec<Rel>,
308 input_field_count: usize,
309 ) -> Result<(Self, usize), MessageParseError> {
310 assert_eq!(pair.as_rule(), Self::rule());
311 if !input_children.is_empty() {
313 return Err(MessageParseError::invalid(
314 Self::message(),
315 pair.as_span(),
316 "ReadRel should have no input children",
317 ));
318 }
319 if input_field_count != 0 {
320 return Err(MessageParseError::invalid(
321 "ReadRel",
322 pair.as_span(),
323 "ReadRel should have 0 input fields",
324 ));
325 }
326
327 let mut iter = RuleIter::from(pair.into_inner());
328 let table = iter.parse_next::<TableName>().0;
329 let columns = iter.parse_next_scoped::<NamedColumnList>(extensions)?.0;
330 iter.done();
331
332 let output_count = columns.len();
333 Ok((
334 ReadRel {
335 base_schema: Some(build_named_struct(columns)),
336 read_type: Some(read_rel::ReadType::NamedTable(read_rel::NamedTable {
337 names: table,
338 advanced_extension: None,
339 })),
340 ..Default::default()
341 },
342 output_count,
343 ))
344 }
345
346 fn into_rel(mut self, adv_ext: Option<AdvancedExtension>) -> Rel {
347 self.advanced_extension = adv_ext;
348 Rel {
349 rel_type: Some(RelType::Read(Box::new(self))),
350 }
351 }
352}
353
354pub(crate) struct VirtualReadRel(ReadRel);
358
359impl RelationParsePair for VirtualReadRel {
360 fn rule() -> Rule {
361 Rule::virtual_read_relation
362 }
363
364 fn message() -> &'static str {
365 "VirtualReadRel"
366 }
367
368 fn parse_pair_with_context(
369 extensions: &SimpleExtensions,
370 pair: Pair<Rule>,
371 input_children: Vec<Rel>,
372 _input_field_count: usize,
373 ) -> Result<(Self, usize), MessageParseError> {
374 assert_eq!(pair.as_rule(), Self::rule());
375 if !input_children.is_empty() {
376 return Err(MessageParseError::invalid(
377 Self::message(),
378 pair.as_span(),
379 "Read:Virtual should have no input children",
380 ));
381 }
382
383 let mut iter = RuleIter::from(pair.into_inner());
384 let args_pair = iter.pop(Rule::virtual_read_args);
385 let columns_pair = iter.pop(Rule::named_column_list);
386 iter.done();
387
388 let rows = parse_virtual_read_args(extensions, args_pair)?;
389 let columns = NamedColumnList::parse_pair(extensions, columns_pair)?.0;
390
391 let output_count = columns.len();
396 Ok((
397 VirtualReadRel(ReadRel {
398 base_schema: Some(build_named_struct(columns)),
399 read_type: Some(read_rel::ReadType::VirtualTable(read_rel::VirtualTable {
400 expressions: rows,
401 ..Default::default()
402 })),
403 ..Default::default()
404 }),
405 output_count,
406 ))
407 }
408
409 fn into_rel(mut self, adv_ext: Option<AdvancedExtension>) -> Rel {
410 self.0.advanced_extension = adv_ext;
411 Rel {
412 rel_type: Some(RelType::Read(Box::new(self.0))),
413 }
414 }
415}
416
417pub(crate) struct ExtensionReadRel(ReadRel);
421
422impl ExtensionReadRel {
423 pub(crate) fn parse_pair_with_detail(
424 extensions: &SimpleExtensions,
425 pair: Pair<Rule>,
426 input_children: Vec<Rel>,
427 input_field_count: usize,
428 detail: Any,
429 advanced_extension: Option<AdvancedExtension>,
430 ) -> Result<(Rel, usize), MessageParseError> {
431 assert_eq!(pair.as_rule(), Rule::extension_read_relation);
432 if !input_children.is_empty() {
433 return Err(MessageParseError::invalid(
434 "ExtensionReadRel",
435 pair.as_span(),
436 "Read:Extension should have no input children",
437 ));
438 }
439 if input_field_count != 0 {
440 return Err(MessageParseError::invalid(
441 "ExtensionReadRel",
442 pair.as_span(),
443 "Read:Extension should have 0 input fields",
444 ));
445 }
446
447 let mut iter = RuleIter::from(pair.into_inner());
448 let columns = iter.parse_next_scoped::<NamedColumnList>(extensions)?.0;
449 iter.done();
450
451 let output_count = columns.len();
452 let rel = ExtensionReadRel(ReadRel {
453 base_schema: Some(build_named_struct(columns)),
454 read_type: Some(read_rel::ReadType::ExtensionTable(
455 read_rel::ExtensionTable {
456 detail: Some(detail.into()),
457 },
458 )),
459 advanced_extension,
460 ..Default::default()
461 })
462 .into_rel();
463
464 Ok((rel, output_count))
465 }
466
467 fn into_rel(self) -> Rel {
468 Rel {
469 rel_type: Some(RelType::Read(Box::new(self.0))),
470 }
471 }
472}
473
474pub(crate) fn build_named_struct(columns: Vec<Column>) -> NamedStruct {
476 let (names, types): (Vec<_>, Vec<_>) = columns.into_iter().map(|c| (c.name, c.typ)).unzip();
477 NamedStruct {
478 names,
479 r#struct: Some(r#type::Struct {
480 types,
481 type_variation_reference: 0,
482 nullability: r#type::Nullability::Required as i32,
483 }),
484 }
485}
486
487fn parse_virtual_read_args(
489 extensions: &SimpleExtensions,
490 pair: Pair<Rule>,
491) -> Result<Vec<nested::Struct>, MessageParseError> {
492 assert_eq!(pair.as_rule(), Rule::virtual_read_args);
493 let inner = unwrap_single_pair(pair);
494 match inner.as_rule() {
495 Rule::empty => Ok(vec![]),
496 Rule::virtual_row_list => inner
497 .into_inner()
498 .map(|row| parse_virtual_row(extensions, row))
499 .collect(),
500 _ => unreachable!(
501 "Unexpected rule in virtual_read_args: {:?}",
502 inner.as_rule()
503 ),
504 }
505}
506
507fn parse_virtual_row(
509 extensions: &SimpleExtensions,
510 pair: Pair<Rule>,
511) -> Result<nested::Struct, MessageParseError> {
512 assert_eq!(pair.as_rule(), Rule::virtual_row);
513 let fields = match pair.into_inner().next() {
514 Some(expression_list) => {
515 assert_eq!(expression_list.as_rule(), Rule::expression_list);
516 parse_expression_list(extensions, expression_list)?
517 }
518 None => vec![],
520 };
521 Ok(nested::Struct { fields })
522}
523
524impl RelationParsePair for FilterRel {
525 fn rule() -> Rule {
526 Rule::filter_relation
527 }
528
529 fn message() -> &'static str {
530 "FilterRel"
531 }
532
533 fn into_rel(mut self, adv_ext: Option<AdvancedExtension>) -> Rel {
534 self.advanced_extension = adv_ext;
535 Rel {
536 rel_type: Some(RelType::Filter(Box::new(self))),
537 }
538 }
539
540 fn parse_pair_with_context(
541 extensions: &SimpleExtensions,
542 pair: Pair<Rule>,
543 input_children: Vec<Rel>,
544 input_field_count: usize,
545 ) -> Result<(Self, usize), MessageParseError> {
546 assert_eq!(pair.as_rule(), Self::rule());
547 let input = expect_one_child(Self::message(), &pair, input_children)?;
548 let mut iter = RuleIter::from(pair.into_inner());
549 let condition = iter.parse_next_scoped::<Expression>(extensions)?;
550 let references_pair = iter.pop(Rule::reference_list);
552 iter.done();
553
554 let (emit, output_count) = parse_emit(references_pair, input_field_count);
555 let common = RelCommon {
556 emit_kind: Some(emit),
557 ..Default::default()
558 };
559
560 Ok((
561 FilterRel {
562 input: Some(input),
563 condition: Some(Box::new(condition)),
564 common: Some(common),
565 advanced_extension: None,
566 },
567 output_count,
568 ))
569 }
570}
571
572impl RelationParsePair for ProjectRel {
573 fn rule() -> Rule {
574 Rule::project_relation
575 }
576
577 fn message() -> &'static str {
578 "ProjectRel"
579 }
580
581 fn into_rel(mut self, adv_ext: Option<AdvancedExtension>) -> Rel {
582 self.advanced_extension = adv_ext;
583 Rel {
584 rel_type: Some(RelType::Project(Box::new(self))),
585 }
586 }
587
588 fn parse_pair_with_context(
589 extensions: &SimpleExtensions,
590 pair: Pair<Rule>,
591 input_children: Vec<Rel>,
592 input_field_count: usize,
593 ) -> Result<(Self, usize), MessageParseError> {
594 assert_eq!(pair.as_rule(), Self::rule());
595 let input = expect_one_child(Self::message(), &pair, input_children)?;
596
597 let arguments_pair = unwrap_single_pair(pair);
598
599 let mut expressions = Vec::new();
600 let mut output_mapping = Vec::new();
601
602 for arg in arguments_pair.into_inner() {
603 let inner_arg = unwrap_single_pair(arg);
604 match inner_arg.as_rule() {
605 Rule::reference => {
606 let field_index = FieldIndex::parse_pair(inner_arg);
607 output_mapping.push(field_index.0);
608 }
609 Rule::expression => {
610 let expr = Expression::parse_pair(extensions, inner_arg)?;
611 expressions.push(expr);
612 output_mapping.push(input_field_count as i32 + (expressions.len() as i32 - 1));
614 }
615 _ => panic!("Unexpected inner argument rule: {:?}", inner_arg.as_rule()),
616 }
617 }
618
619 let output_count = output_mapping.len();
620 let direct_count = input_field_count + expressions.len();
621 let emit = make_emit(output_mapping, direct_count);
622 let common = RelCommon {
623 emit_kind: Some(emit),
624 ..Default::default()
625 };
626
627 Ok((
628 ProjectRel {
629 input: Some(input),
630 expressions,
631 common: Some(common),
632 advanced_extension: None,
633 },
634 output_count,
635 ))
636 }
637}
638
639impl RelationParsePair for AggregateRel {
640 fn rule() -> Rule {
641 Rule::aggregate_relation
642 }
643
644 fn message() -> &'static str {
645 "AggregateRel"
646 }
647
648 fn into_rel(mut self, adv_ext: Option<AdvancedExtension>) -> Rel {
649 self.advanced_extension = adv_ext;
650 Rel {
651 rel_type: Some(RelType::Aggregate(Box::new(self))),
652 }
653 }
654
655 fn parse_pair_with_context(
656 extensions: &SimpleExtensions,
657 pair: Pair<Rule>,
658 input_children: Vec<Rel>,
659 _input_field_count: usize,
662 ) -> Result<(Self, usize), MessageParseError> {
663 assert_eq!(pair.as_rule(), Self::rule());
664 let input = expect_one_child(Self::message(), &pair, input_children)?;
665 let mut iter = RuleIter::from(pair.into_inner());
666 let group_by_pair = iter.pop(Rule::aggregate_group_by);
667 let output_pair = iter.pop(Rule::aggregate_output);
668 iter.done();
669
670 let inner = group_by_pair
671 .into_inner()
672 .next()
673 .expect("aggregate_group_by must have one inner item");
674
675 let grouping_sets = parse_grouping_sets(extensions, inner)?;
676 let (groupings, grouping_expressions) = build_grouping_fields(&grouping_sets);
677
678 let (measures, output_mapping) =
679 parse_aggregate_measures(extensions, output_pair, &grouping_expressions)?;
680
681 let output_count = output_mapping.len();
682 let direct_count = grouping_expressions.len() + measures.len();
683 let emit = make_emit(output_mapping, direct_count);
684 let common = RelCommon {
685 emit_kind: Some(emit),
686 ..Default::default()
687 };
688
689 Ok((
690 AggregateRel {
691 input: Some(input),
692 grouping_expressions,
693 groupings,
694 measures,
695 common: Some(common),
696 advanced_extension: None,
697 },
698 output_count,
699 ))
700 }
701}
702
703fn parse_aggregate_measures(
708 extensions: &SimpleExtensions,
709 output_pair: Pair<'_, Rule>,
710 grouping_expressions: &[Expression],
711) -> Result<(Vec<aggregate_rel::Measure>, Vec<i32>), MessageParseError> {
712 assert_eq!(output_pair.as_rule(), Rule::aggregate_output);
713 let mut measures = Vec::new();
714 let mut output_mapping = Vec::new();
715
716 for aggregate_output_item in output_pair.into_inner() {
717 let inner_item = unwrap_single_pair(aggregate_output_item);
718 match inner_item.as_rule() {
719 Rule::reference => {
720 let field_index = FieldIndex::parse_pair(inner_item);
721 output_mapping.push(field_index.0);
722 }
723 Rule::aggregate_measure => {
724 let measure = aggregate_rel::Measure::parse_pair(extensions, inner_item)?;
725 output_mapping.push(grouping_expressions.len() as i32 + measures.len() as i32);
726 measures.push(measure);
727 }
728 _ => panic!(
729 "Unexpected inner output item rule: {:?}",
730 inner_item.as_rule()
731 ),
732 }
733 }
734
735 Ok((measures, output_mapping))
736}
737
738fn parse_grouping_sets(
747 extensions: &SimpleExtensions,
748 inner: Pair<'_, Rule>,
749) -> Result<Vec<Vec<Expression>>, MessageParseError> {
750 assert!(
751 matches!(
752 inner.as_rule(),
753 Rule::expression_list | Rule::grouping_set_list
754 ),
755 "Expected expression_list or grouping_set_list, got {:?}",
756 inner.as_rule()
757 );
758 match inner.as_rule() {
759 Rule::expression_list => Ok(vec![parse_expression_list(extensions, inner)?]),
760 Rule::grouping_set_list => inner
761 .into_inner()
762 .map(|pair| parse_grouping_set(extensions, pair))
763 .collect(),
764 _ => unreachable!(
765 "Unexpected rule in aggregate_group_by: {:?}",
766 inner.as_rule()
767 ),
768 }
769}
770
771fn parse_grouping_set(
775 extensions: &SimpleExtensions,
776 pair: Pair<'_, Rule>,
777) -> Result<Vec<Expression>, MessageParseError> {
778 assert_eq!(pair.as_rule(), Rule::grouping_set);
779 let inner = pair
780 .into_inner()
781 .next()
782 .expect("grouping_set must have one inner item");
783 match inner.as_rule() {
784 Rule::empty => Ok(vec![]),
785 Rule::expression_list => parse_expression_list(extensions, inner),
786 _ => unreachable!("Unexpected item in grouping_set: {:?}", inner.as_rule()),
787 }
788}
789
790pub(crate) fn parse_expression_list(
792 extensions: &SimpleExtensions,
793 pair: Pair<'_, Rule>,
794) -> Result<Vec<Expression>, MessageParseError> {
795 pair.into_inner()
796 .map(|expr_pair| Expression::parse_pair(extensions, expr_pair))
797 .collect()
798}
799
800fn build_grouping_fields(expression_sets: &[Vec<Expression>]) -> (Vec<Grouping>, Vec<Expression>) {
804 let mut expressions: Vec<Expression> = Vec::new();
805 let mut seen: HashMap<Vec<u8>, u32> = HashMap::new();
806
807 let groupings = expression_sets
808 .iter()
809 .map(|set| {
810 let expression_references = set
811 .iter()
812 .map(|exp| {
813 let key = exp.encode_to_vec();
817 let next_idx = expressions.len() as u32;
818 *seen.entry(key).or_insert_with(|| {
819 expressions.push(exp.clone());
820 next_idx
821 })
822 })
823 .collect();
824 Grouping {
825 expression_references,
826 #[allow(deprecated)]
827 grouping_expressions: vec![],
828 }
829 })
830 .collect();
831
832 (groupings, expressions)
833}
834
835impl ScopedParsePair for SortField {
836 fn rule() -> Rule {
837 Rule::sort_field
838 }
839
840 fn message() -> &'static str {
841 "SortField"
842 }
843
844 fn parse_pair(
845 _extensions: &SimpleExtensions,
846 pair: Pair<Rule>,
847 ) -> Result<Self, MessageParseError> {
848 assert_eq!(pair.as_rule(), Self::rule());
849 let mut iter = RuleIter::from(pair.into_inner());
850 let reference_pair = iter.pop(Rule::reference);
851 let field_index = FieldIndex::parse_pair(reference_pair);
852 let direction_pair = iter.pop(Rule::sort_direction);
853 let direction = match direction_pair.as_str().trim_start_matches('&') {
857 "AscNullsFirst" => SortDirection::AscNullsFirst,
858 "AscNullsLast" => SortDirection::AscNullsLast,
859 "DescNullsFirst" => SortDirection::DescNullsFirst,
860 "DescNullsLast" => SortDirection::DescNullsLast,
861 other => {
862 return Err(MessageParseError::invalid(
863 "SortDirection",
864 direction_pair.as_span(),
865 format!("Unknown sort direction: {other}"),
866 ));
867 }
868 };
869 iter.done();
870 Ok(SortField {
871 expr: Some(Expression {
872 rex_type: Some(substrait::proto::expression::RexType::Selection(Box::new(
873 field_index.to_field_reference(),
874 ))),
875 }),
876 sort_kind: Some(SortKind::Direction(direction as i32)),
878 })
879 }
880}
881
882impl RelationParsePair for SortRel {
883 fn rule() -> Rule {
884 Rule::sort_relation
885 }
886
887 fn message() -> &'static str {
888 "SortRel"
889 }
890
891 fn into_rel(mut self, adv_ext: Option<AdvancedExtension>) -> Rel {
892 self.advanced_extension = adv_ext;
893 Rel {
894 rel_type: Some(RelType::Sort(Box::new(self))),
895 }
896 }
897
898 fn parse_pair_with_context(
899 extensions: &SimpleExtensions,
900 pair: Pair<Rule>,
901 input_children: Vec<Rel>,
902 input_field_count: usize,
903 ) -> Result<(Self, usize), MessageParseError> {
904 assert_eq!(pair.as_rule(), Self::rule());
905 let input = expect_one_child(Self::message(), &pair, input_children)?;
906 let mut iter = RuleIter::from(pair.into_inner());
907 let sort_field_list_pair = iter.pop(Rule::sort_field_list);
908 let reference_list_pair = iter.pop(Rule::reference_list);
909 let mut sorts = Vec::new();
910 for sort_field_pair in sort_field_list_pair.into_inner() {
911 let sort_field = SortField::parse_pair(extensions, sort_field_pair)?;
912 sorts.push(sort_field);
913 }
914 let (emit, output_count) = parse_emit(reference_list_pair, input_field_count);
915 let common = RelCommon {
916 emit_kind: Some(emit),
917 ..Default::default()
918 };
919 iter.done();
920 Ok((
921 SortRel {
922 input: Some(input),
923 sorts,
924 common: Some(common),
925 advanced_extension: None,
926 },
927 output_count,
928 ))
929 }
930}
931
932impl ScopedParsePair for CountMode {
933 fn rule() -> Rule {
934 Rule::fetch_value
935 }
936 fn message() -> &'static str {
937 "CountMode"
938 }
939 fn parse_pair(
940 extensions: &SimpleExtensions,
941 pair: Pair<Rule>,
942 ) -> Result<Self, MessageParseError> {
943 assert_eq!(pair.as_rule(), Self::rule());
944 let mut arg_inner = RuleIter::from(pair.into_inner());
945 let value_pair = if let Some(int_pair) = arg_inner.try_pop(Rule::integer) {
946 int_pair
947 } else {
948 arg_inner.pop(Rule::expression)
949 };
950 match value_pair.as_rule() {
951 Rule::integer => {
952 let value = value_pair.as_str().parse::<i64>().map_err(|e| {
953 MessageParseError::invalid(
954 Self::message(),
955 value_pair.as_span(),
956 format!("Invalid integer: {e}"),
957 )
958 })?;
959 if value < 0 {
960 return Err(MessageParseError::invalid(
961 Self::message(),
962 value_pair.as_span(),
963 format!("Fetch limit must be non-negative, got: {value}"),
964 ));
965 }
966 Ok(CountMode::CountExpr(i64_literal_expr(value)))
967 }
968 Rule::expression => {
969 let expr = Expression::parse_pair(extensions, value_pair)?;
970 Ok(CountMode::CountExpr(Box::new(expr)))
971 }
972 _ => Err(MessageParseError::invalid(
973 Self::message(),
974 value_pair.as_span(),
975 format!("Unexpected rule for CountMode: {:?}", value_pair.as_rule()),
976 )),
977 }
978 }
979}
980
981fn i64_literal_expr(value: i64) -> Box<Expression> {
982 Box::new(Expression {
983 rex_type: Some(RexType::Literal(Literal {
984 nullable: false,
985 type_variation_reference: 0,
986 literal_type: Some(LiteralType::I64(value)),
987 })),
988 })
989}
990
991impl ScopedParsePair for OffsetMode {
992 fn rule() -> Rule {
993 Rule::fetch_value
994 }
995 fn message() -> &'static str {
996 "OffsetMode"
997 }
998 fn parse_pair(
999 extensions: &SimpleExtensions,
1000 pair: Pair<Rule>,
1001 ) -> Result<Self, MessageParseError> {
1002 assert_eq!(pair.as_rule(), Self::rule());
1003 let mut arg_inner = RuleIter::from(pair.into_inner());
1004 let value_pair = if let Some(int_pair) = arg_inner.try_pop(Rule::integer) {
1005 int_pair
1006 } else {
1007 arg_inner.pop(Rule::expression)
1008 };
1009 match value_pair.as_rule() {
1010 Rule::integer => {
1011 let value = value_pair.as_str().parse::<i64>().map_err(|e| {
1012 MessageParseError::invalid(
1013 Self::message(),
1014 value_pair.as_span(),
1015 format!("Invalid integer: {e}"),
1016 )
1017 })?;
1018 if value < 0 {
1019 return Err(MessageParseError::invalid(
1020 Self::message(),
1021 value_pair.as_span(),
1022 format!("Fetch offset must be non-negative, got: {value}"),
1023 ));
1024 }
1025 Ok(OffsetMode::OffsetExpr(i64_literal_expr(value)))
1026 }
1027 Rule::expression => {
1028 let expr = Expression::parse_pair(extensions, value_pair)?;
1029 Ok(OffsetMode::OffsetExpr(Box::new(expr)))
1030 }
1031 _ => Err(MessageParseError::invalid(
1032 Self::message(),
1033 value_pair.as_span(),
1034 format!("Unexpected rule for OffsetMode: {:?}", value_pair.as_rule()),
1035 )),
1036 }
1037 }
1038}
1039
1040impl RelationParsePair for FetchRel {
1041 fn rule() -> Rule {
1042 Rule::fetch_relation
1043 }
1044
1045 fn message() -> &'static str {
1046 "FetchRel"
1047 }
1048
1049 fn into_rel(mut self, adv_ext: Option<AdvancedExtension>) -> Rel {
1050 self.advanced_extension = adv_ext;
1051 Rel {
1052 rel_type: Some(RelType::Fetch(Box::new(self))),
1053 }
1054 }
1055
1056 fn parse_pair_with_context(
1057 extensions: &SimpleExtensions,
1058 pair: Pair<Rule>,
1059 input_children: Vec<Rel>,
1060 input_field_count: usize,
1061 ) -> Result<(Self, usize), MessageParseError> {
1062 assert_eq!(pair.as_rule(), Self::rule());
1063 let input = expect_one_child(Self::message(), &pair, input_children)?;
1064 let mut iter = RuleIter::from(pair.into_inner());
1065
1066 let (limit_pair, offset_pair) = match iter.try_pop(Rule::fetch_named_arg_list) {
1070 None => {
1071 iter.pop(Rule::empty);
1072 (None, None)
1073 }
1074 Some(fetch_args_pair) => {
1075 let extractor =
1076 ParsedNamedArgs::new(fetch_args_pair.into_inner(), Rule::fetch_named_arg)?;
1077 let (extractor, limit_pair) = extractor.pop("limit", Rule::fetch_value);
1078 let (extractor, offset_pair) = extractor.pop("offset", Rule::fetch_value);
1079 extractor.done()?;
1080 (limit_pair, offset_pair)
1081 }
1082 };
1083
1084 let reference_list_pair = iter.pop(Rule::reference_list);
1085 let (emit, output_count) = parse_emit(reference_list_pair, input_field_count);
1086 let common = RelCommon {
1087 emit_kind: Some(emit),
1088 ..Default::default()
1089 };
1090 iter.done();
1091
1092 let count_mode = limit_pair
1093 .map(|pair| CountMode::parse_pair(extensions, pair))
1094 .transpose()?;
1095 let offset_mode = offset_pair
1096 .map(|pair| OffsetMode::parse_pair(extensions, pair))
1097 .transpose()?;
1098 Ok((
1099 FetchRel {
1100 input: Some(input),
1101 common: Some(common),
1102 advanced_extension: None,
1103 offset_mode,
1104 count_mode,
1105 },
1106 output_count,
1107 ))
1108 }
1109}
1110
1111impl ParsePair for join_rel::JoinType {
1112 fn rule() -> Rule {
1113 Rule::join_type
1114 }
1115
1116 fn message() -> &'static str {
1117 "JoinType"
1118 }
1119
1120 fn parse_pair(pair: Pair<Rule>) -> Self {
1121 assert_eq!(pair.as_rule(), Self::rule());
1122 let join_type_str = pair.as_str().trim_start_matches('&');
1123 match join_type_str {
1124 "Inner" => join_rel::JoinType::Inner,
1125 "Left" => join_rel::JoinType::Left,
1126 "Right" => join_rel::JoinType::Right,
1127 "Outer" => join_rel::JoinType::Outer,
1128 "LeftSemi" => join_rel::JoinType::LeftSemi,
1129 "RightSemi" => join_rel::JoinType::RightSemi,
1130 "LeftAnti" => join_rel::JoinType::LeftAnti,
1131 "RightAnti" => join_rel::JoinType::RightAnti,
1132 "LeftSingle" => join_rel::JoinType::LeftSingle,
1133 "RightSingle" => join_rel::JoinType::RightSingle,
1134 "LeftMark" => join_rel::JoinType::LeftMark,
1135 "RightMark" => join_rel::JoinType::RightMark,
1136 _ => panic!("Unknown join type: {join_type_str} (this should be caught by grammar)"),
1137 }
1138 }
1139}
1140
1141impl RelationParsePair for JoinRel {
1142 fn rule() -> Rule {
1143 Rule::join_relation
1144 }
1145
1146 fn message() -> &'static str {
1147 "JoinRel"
1148 }
1149
1150 fn into_rel(mut self, adv_ext: Option<AdvancedExtension>) -> Rel {
1151 self.advanced_extension = adv_ext;
1152 Rel {
1153 rel_type: Some(RelType::Join(Box::new(self))),
1154 }
1155 }
1156
1157 fn parse_pair_with_context(
1158 extensions: &SimpleExtensions,
1159 pair: Pair<Rule>,
1160 input_children: Vec<Rel>,
1161 input_field_count: usize,
1162 ) -> Result<(Self, usize), MessageParseError> {
1163 assert_eq!(pair.as_rule(), Self::rule());
1164
1165 if input_children.len() != 2 {
1166 return Err(MessageParseError::invalid(
1167 Self::message(),
1168 pair.as_span(),
1169 format!(
1170 "JoinRel should have exactly 2 input children, got {}",
1171 input_children.len()
1172 ),
1173 ));
1174 }
1175
1176 let mut children_iter = input_children.into_iter();
1177 let left = Box::new(children_iter.next().unwrap());
1178 let right = Box::new(children_iter.next().unwrap());
1179
1180 let mut iter = RuleIter::from(pair.into_inner());
1181 let join_type = iter.parse_next::<join_rel::JoinType>();
1182 let condition = iter.parse_next_scoped::<Expression>(extensions)?;
1183 let reference_list_pair = iter.pop(Rule::reference_list);
1184 iter.done();
1185
1186 let (emit, output_count) = parse_emit(reference_list_pair, input_field_count);
1190 let common = RelCommon {
1191 emit_kind: Some(emit),
1192 ..Default::default()
1193 };
1194
1195 Ok((
1196 JoinRel {
1197 common: Some(common),
1198 left: Some(left),
1199 right: Some(right),
1200 expression: Some(Box::new(condition)),
1201 post_join_filter: None, r#type: join_type as i32,
1203 advanced_extension: None,
1204 },
1205 output_count,
1206 ))
1207 }
1208}
1209
1210impl RelationParsePair for CrossRel {
1211 fn rule() -> Rule {
1212 Rule::cross_relation
1213 }
1214
1215 fn message() -> &'static str {
1216 "CrossRel"
1217 }
1218
1219 fn into_rel(mut self, adv_ext: Option<AdvancedExtension>) -> Rel {
1220 self.advanced_extension = adv_ext;
1221 Rel {
1222 rel_type: Some(RelType::Cross(Box::new(self))),
1223 }
1224 }
1225
1226 fn parse_pair_with_context(
1227 _extensions: &SimpleExtensions,
1228 pair: Pair<Rule>,
1229 input_children: Vec<Rel>,
1230 input_field_count: usize,
1231 ) -> Result<(Self, usize), MessageParseError> {
1232 assert_eq!(pair.as_rule(), Self::rule());
1233
1234 if input_children.len() != 2 {
1235 return Err(MessageParseError::invalid(
1236 Self::message(),
1237 pair.as_span(),
1238 format!(
1239 "CrossRel should have exactly 2 input children, got {}",
1240 input_children.len()
1241 ),
1242 ));
1243 }
1244
1245 let mut children_iter = input_children.into_iter();
1246 let left = Box::new(children_iter.next().unwrap());
1247 let right = Box::new(children_iter.next().unwrap());
1248
1249 let mut iter = RuleIter::from(pair.into_inner());
1250 let reference_list_pair = iter.pop(Rule::reference_list);
1251 iter.done();
1252
1253 let (emit, output_count) = parse_emit(reference_list_pair, input_field_count);
1254 let common = RelCommon {
1255 emit_kind: Some(emit),
1256 ..Default::default()
1257 };
1258
1259 Ok((
1260 CrossRel {
1261 common: Some(common),
1262 left: Some(left),
1263 right: Some(right),
1264 advanced_extension: None,
1265 },
1266 output_count,
1267 ))
1268 }
1269}
1270
1271impl ParsePair for set_rel::SetOp {
1272 fn rule() -> Rule {
1273 Rule::set_op
1274 }
1275
1276 fn message() -> &'static str {
1277 "SetOp"
1278 }
1279
1280 fn parse_pair(pair: Pair<Rule>) -> Self {
1281 assert_eq!(pair.as_rule(), Self::rule());
1282 let set_op_str = pair.as_str().trim_start_matches('&');
1283 match set_op_str {
1284 "MinusPrimary" => set_rel::SetOp::MinusPrimary,
1285 "MinusPrimaryAll" => set_rel::SetOp::MinusPrimaryAll,
1286 "MinusMultiset" => set_rel::SetOp::MinusMultiset,
1287 "IntersectionPrimary" => set_rel::SetOp::IntersectionPrimary,
1288 "IntersectionMultiset" => set_rel::SetOp::IntersectionMultiset,
1289 "IntersectionMultisetAll" => set_rel::SetOp::IntersectionMultisetAll,
1290 "UnionDistinct" => set_rel::SetOp::UnionDistinct,
1291 "UnionAll" => set_rel::SetOp::UnionAll,
1292 _ => panic!("Unknown set op: {set_op_str} (this should be caught by grammar)"),
1293 }
1294 }
1295}
1296
1297pub(crate) fn parse_set_relation_pair(
1300 pair: Pair<Rule>,
1301 input_children: Vec<Rel>,
1302 child_field_counts: &[usize],
1303 advanced_extension: Option<AdvancedExtension>,
1304) -> Result<(Rel, usize), MessageParseError> {
1305 assert_eq!(pair.as_rule(), Rule::set_relation);
1306
1307 if input_children.len() < 2 {
1308 return Err(MessageParseError::invalid(
1309 "SetRel",
1310 pair.as_span(),
1311 format!(
1312 "SetRel should have at least 2 input children, got {}",
1313 input_children.len()
1314 ),
1315 ));
1316 }
1317
1318 let child_width = child_field_counts[0];
1321 if child_field_counts.iter().any(|&w| w != child_width) {
1322 return Err(MessageParseError::invalid(
1323 "SetRel",
1324 pair.as_span(),
1325 format!(
1326 "SetRel inputs must all have the same number of columns, got widths {child_field_counts:?}"
1327 ),
1328 ));
1329 }
1330
1331 let mut iter = RuleIter::from(pair.into_inner());
1332 let op = iter.parse_next::<set_rel::SetOp>();
1333 let reference_list_pair = iter.pop(Rule::reference_list);
1334 iter.done();
1335
1336 let (emit, output_count) = parse_emit(reference_list_pair, child_width);
1337 let common = RelCommon {
1338 emit_kind: Some(emit),
1339 ..Default::default()
1340 };
1341
1342 Ok((
1343 Rel {
1344 rel_type: Some(RelType::Set(SetRel {
1345 common: Some(common),
1346 inputs: input_children,
1347 op: op as i32,
1348 advanced_extension,
1349 })),
1350 },
1351 output_count,
1352 ))
1353}
1354
1355#[cfg(test)]
1356mod tests {
1357 use pest::Parser;
1358
1359 use super::*;
1360 use crate::fixtures::TestContext;
1361 use crate::parser::{ExpressionParser, Rule};
1362
1363 #[test]
1364 fn test_parse_relation() {
1365 }
1367
1368 #[test]
1369 fn test_parse_read_relation() {
1370 let extensions = SimpleExtensions::default();
1371 let read = ReadRel::parse_pair_with_context(
1372 &extensions,
1373 parse_exact(Rule::read_relation, "Read[ab.cd.ef => a:i32, b:string?]"),
1374 vec![],
1375 0,
1376 )
1377 .unwrap()
1378 .0;
1379 let names = match &read.read_type {
1380 Some(read_rel::ReadType::NamedTable(table)) => &table.names,
1381 _ => panic!("Expected NamedTable"),
1382 };
1383 assert_eq!(names, &["ab", "cd", "ef"]);
1384 let columns = &read
1385 .base_schema
1386 .as_ref()
1387 .unwrap()
1388 .r#struct
1389 .as_ref()
1390 .unwrap()
1391 .types;
1392 assert_eq!(columns.len(), 2);
1393 }
1394
1395 fn example_read_relation() -> ReadRel {
1397 let extensions = SimpleExtensions::default();
1398 ReadRel::parse_pair_with_context(
1399 &extensions,
1400 parse_exact(
1401 Rule::read_relation,
1402 "Read[ab.cd.ef => a:i32, b:string?, c:i64]",
1403 ),
1404 vec![],
1405 0,
1406 )
1407 .unwrap()
1408 .0
1409 }
1410
1411 #[test]
1412 fn test_parse_filter_relation() {
1413 let extensions = SimpleExtensions::default();
1414 let filter = FilterRel::parse_pair_with_context(
1415 &extensions,
1416 parse_exact(Rule::filter_relation, "Filter[$1 => $0, $1, $2]"),
1417 vec![example_read_relation().into_rel(None)],
1418 3,
1419 )
1420 .unwrap()
1421 .0;
1422 let emit_kind = filter.common.as_ref().unwrap().emit_kind.as_ref().unwrap();
1424 assert!(
1425 matches!(emit_kind, EmitKind::Direct(_)),
1426 "Expected Direct for identity emit, got {emit_kind:?}"
1427 );
1428 }
1429
1430 #[test]
1431 fn test_parse_project_relation() {
1432 let extensions = SimpleExtensions::default();
1433 let project = ProjectRel::parse_pair_with_context(
1434 &extensions,
1435 parse_exact(Rule::project_relation, "Project[$0, $1, 42]"),
1436 vec![example_read_relation().into_rel(None)],
1437 3,
1438 )
1439 .unwrap()
1440 .0;
1441
1442 assert_eq!(project.expressions.len(), 1);
1444
1445 let emit_kind = &project.common.as_ref().unwrap().emit_kind.as_ref().unwrap();
1446 let emit = match emit_kind {
1447 EmitKind::Emit(emit) => &emit.output_mapping,
1448 _ => panic!("Expected EmitKind::Emit, got {emit_kind:?}"),
1449 };
1450 assert_eq!(emit, &[0, 1, 3]);
1452 }
1453
1454 #[test]
1455 fn test_parse_project_relation_complex() {
1456 let extensions = SimpleExtensions::default();
1457 let project = ProjectRel::parse_pair_with_context(
1458 &extensions,
1459 parse_exact(Rule::project_relation, "Project[42, $0, 100, $2, $1]"),
1460 vec![example_read_relation().into_rel(None)],
1461 5, )
1463 .unwrap()
1464 .0;
1465
1466 assert_eq!(project.expressions.len(), 2);
1468
1469 let emit_kind = &project.common.as_ref().unwrap().emit_kind.as_ref().unwrap();
1470 let emit = match emit_kind {
1471 EmitKind::Emit(emit) => &emit.output_mapping,
1472 _ => panic!("Expected EmitKind::Emit, got {emit_kind:?}"),
1473 };
1474 assert_eq!(emit, &[5, 0, 6, 2, 1]);
1477 }
1478
1479 #[test]
1480 fn test_parse_aggregate_relation() {
1481 let extensions = TestContext::new()
1482 .with_urn(1, "https://github.com/substrait-io/substrait/blob/main/extensions/functions_aggregate.yaml")
1483 .with_function(1, 10, "sum")
1484 .with_function(1, 11, "count")
1485 .extensions;
1486
1487 let aggregate = AggregateRel::parse_pair_with_context(
1488 &extensions,
1489 parse_exact(
1490 Rule::aggregate_relation,
1491 "Aggregate[($0, $1), _ => sum($2):i64, $0, count($2):i64]",
1492 ),
1493 vec![example_read_relation().into_rel(None)],
1494 3,
1495 )
1496 .unwrap()
1497 .0;
1498
1499 assert_eq!(aggregate.grouping_expressions.len(), 2);
1501 assert_eq!(aggregate.groupings[0].expression_references.len(), 2);
1502 assert_eq!(aggregate.groupings.len(), 2);
1503 assert_eq!(aggregate.measures.len(), 2);
1504
1505 let emit_kind = &aggregate
1506 .common
1507 .as_ref()
1508 .unwrap()
1509 .emit_kind
1510 .as_ref()
1511 .unwrap();
1512 let emit = match emit_kind {
1513 EmitKind::Emit(emit) => &emit.output_mapping,
1514 _ => panic!("Expected EmitKind::Emit, got {emit_kind:?}"),
1515 };
1516 assert_eq!(emit, &[2, 0, 3]);
1519 }
1520
1521 #[test]
1522 fn test_parse_aggregate_relation_maintain_column_order() {
1523 let extensions = TestContext::new()
1524 .with_urn(1, "https://github.com/substrait-io/substrait/blob/main/extensions/functions_aggregate.yaml")
1525 .with_function(1, 10, "sum")
1526 .with_function(1, 11, "count")
1527 .extensions;
1528
1529 let aggregate = AggregateRel::parse_pair_with_context(
1530 &extensions,
1531 parse_exact(
1532 Rule::aggregate_relation,
1533 "Aggregate[$0 => sum($1):i64, $0, count($1):i64]",
1534 ),
1535 vec![example_read_relation().into_rel(None)],
1536 3,
1537 )
1538 .unwrap()
1539 .0;
1540
1541 assert_eq!(aggregate.grouping_expressions.len(), 1);
1543 assert_eq!(aggregate.groupings.len(), 1);
1544 assert_eq!(aggregate.measures.len(), 2);
1545
1546 let emit_kind = &aggregate
1547 .common
1548 .as_ref()
1549 .unwrap()
1550 .emit_kind
1551 .as_ref()
1552 .unwrap();
1553 let emit = match emit_kind {
1554 EmitKind::Emit(emit) => &emit.output_mapping,
1555 _ => panic!("Expected EmitKind::Emit, got {emit_kind:?}"),
1556 };
1557 assert_eq!(emit, &[1, 0, 2]);
1559 }
1560
1561 #[test]
1562 fn test_parse_aggregate_relation_simple() {
1563 let extensions = TestContext::new()
1564 .with_urn(1, "https://github.com/substrait-io/substrait/blob/main/extensions/functions_aggregate.yaml")
1565 .with_function(1, 10, "sum")
1566 .extensions;
1567
1568 let aggregate = AggregateRel::parse_pair_with_context(
1569 &extensions,
1570 parse_exact(Rule::aggregate_relation, "Aggregate[$2, $0 => sum($1):i64]"),
1571 vec![example_read_relation().into_rel(None)],
1572 3,
1573 )
1574 .unwrap()
1575 .0;
1576
1577 assert_eq!(aggregate.grouping_expressions.len(), 2);
1578 assert_eq!(aggregate.groupings.len(), 1);
1579 assert_eq!(aggregate.groupings[0].expression_references, vec![0, 1]);
1581 }
1582
1583 #[test]
1584 fn test_parse_aggregate_relation_global_aggregate() {
1585 let extensions = TestContext::new()
1586 .with_urn(1, "https://github.com/substrait-io/substrait/blob/main/extensions/functions_aggregate.yaml")
1587 .with_function(1, 10, "sum")
1588 .with_function(1, 11, "count")
1589 .extensions;
1590
1591 let aggregate = AggregateRel::parse_pair_with_context(
1592 &extensions,
1593 parse_exact(
1594 Rule::aggregate_relation,
1595 "Aggregate[_ => sum($0):i64, count($1):i64]",
1596 ),
1597 vec![example_read_relation().into_rel(None)],
1598 3,
1599 )
1600 .unwrap()
1601 .0;
1602
1603 assert_eq!(aggregate.grouping_expressions.len(), 0);
1605 assert_eq!(aggregate.groupings.len(), 1);
1606 assert_eq!(aggregate.groupings[0].expression_references.len(), 0);
1607 assert_eq!(aggregate.measures.len(), 2);
1608
1609 let emit_kind = aggregate
1611 .common
1612 .as_ref()
1613 .unwrap()
1614 .emit_kind
1615 .as_ref()
1616 .unwrap();
1617 assert!(
1618 matches!(emit_kind, EmitKind::Direct(_)),
1619 "Expected Direct for identity emit, got {emit_kind:?}"
1620 );
1621 }
1622
1623 #[test]
1624 fn test_parse_aggregate_relation_grouping_sets() {
1625 let extensions = TestContext::new()
1626 .with_urn(1, "https://github.com/substrait-io/substrait/blob/main/extensions/functions_aggregate.yaml")
1627 .with_function(1, 11, "count")
1628 .extensions;
1629
1630 let read_rel = ReadRel::parse_pair_with_context(
1631 &extensions,
1632 parse_exact(
1633 Rule::read_relation,
1634 "Read[ab.cd.ef => a:i32, b:string?, c:i64, d:i64]",
1635 ),
1636 vec![],
1637 0,
1638 )
1639 .unwrap()
1640 .0;
1641
1642 let aggregate = AggregateRel::parse_pair_with_context(
1643 &extensions,
1644 parse_exact(
1645 Rule::aggregate_relation,
1646 "Aggregate[($0, $1, $2), ($2, $0), ($1), _ => $0, $1, $2, count($3):i64]",
1647 ),
1648 vec![read_rel.into_rel(None)],
1649 4,
1650 )
1651 .unwrap()
1652 .0;
1653
1654 assert_eq!(aggregate.grouping_expressions.len(), 3);
1655 assert_eq!(aggregate.groupings.len(), 4);
1656 assert_eq!(aggregate.groupings[0].expression_references, vec![0, 1, 2]);
1658 assert_eq!(aggregate.groupings[1].expression_references, vec![2, 0]);
1660 assert_eq!(aggregate.groupings[2].expression_references, vec![1]);
1662 assert!(aggregate.groupings[3].expression_references.is_empty());
1664 assert_eq!(aggregate.measures.len(), 1);
1665 }
1666
1667 #[test]
1668 fn test_fetch_relation_positive_values() {
1669 let extensions = SimpleExtensions::default();
1670
1671 let fetch_rel = FetchRel::parse_pair_with_context(
1673 &extensions,
1674 parse_exact(Rule::fetch_relation, "Fetch[limit=10, offset=5 => $0]"),
1675 vec![example_read_relation().into_rel(None)],
1676 3,
1677 )
1678 .unwrap()
1679 .0;
1680
1681 assert_eq!(
1683 fetch_rel.count_mode,
1684 Some(CountMode::CountExpr(i64_literal_expr(10)))
1685 );
1686 assert_eq!(
1687 fetch_rel.offset_mode,
1688 Some(OffsetMode::OffsetExpr(i64_literal_expr(5)))
1689 );
1690 }
1691
1692 #[test]
1693 fn test_fetch_relation_negative_limit_rejected() {
1694 let extensions = SimpleExtensions::default();
1695
1696 let parsed_result = ExpressionParser::parse(Rule::fetch_relation, "Fetch[limit=-5 => $0]");
1698 if let Ok(mut pairs) = parsed_result {
1699 let pair = pairs.next().unwrap();
1700 if pair.as_str() == "Fetch[limit=-5 => $0]" {
1701 let result = FetchRel::parse_pair_with_context(
1703 &extensions,
1704 pair,
1705 vec![example_read_relation().into_rel(None)],
1706 3,
1707 );
1708 assert!(result.is_err());
1709 let error_msg = result.unwrap_err().to_string();
1710 assert!(error_msg.contains("Fetch limit must be non-negative"));
1711 } else {
1712 println!("Grammar prevents negative limit values at parse time");
1715 }
1716 } else {
1717 println!("Grammar prevents negative limit values at parse time");
1719 }
1720 }
1721
1722 #[test]
1723 fn test_fetch_relation_negative_offset_rejected() {
1724 let extensions = SimpleExtensions::default();
1725
1726 let parsed_result =
1728 ExpressionParser::parse(Rule::fetch_relation, "Fetch[offset=-10 => $0]");
1729 if let Ok(mut pairs) = parsed_result {
1730 let pair = pairs.next().unwrap();
1731 if pair.as_str() == "Fetch[offset=-10 => $0]" {
1732 let result = FetchRel::parse_pair_with_context(
1734 &extensions,
1735 pair,
1736 vec![example_read_relation().into_rel(None)],
1737 3,
1738 );
1739 assert!(result.is_err());
1740 let error_msg = result.unwrap_err().to_string();
1741 assert!(error_msg.contains("Fetch offset must be non-negative"));
1742 } else {
1743 println!("Grammar prevents negative offset values at parse time");
1745 }
1746 } else {
1747 println!("Grammar prevents negative offset values at parse time");
1749 }
1750 }
1751
1752 #[test]
1753 fn test_parse_join_relation() {
1754 let extensions = TestContext::new()
1755 .with_urn(1, "https://github.com/substrait-io/substrait/blob/main/extensions/functions_comparison.yaml")
1756 .with_function(1, 10, "eq")
1757 .extensions;
1758
1759 let left_rel = example_read_relation().into_rel(None);
1760 let right_rel = example_read_relation().into_rel(None);
1761
1762 let join = JoinRel::parse_pair_with_context(
1763 &extensions,
1764 parse_exact(
1765 Rule::join_relation,
1766 "Join[&Inner, eq($0, $3):boolean => $0, $1, $3, $4]",
1767 ),
1768 vec![left_rel, right_rel],
1769 6, )
1771 .unwrap()
1772 .0;
1773
1774 assert_eq!(join.r#type, join_rel::JoinType::Inner as i32);
1776
1777 assert!(join.left.is_some());
1779 assert!(join.right.is_some());
1780
1781 assert!(join.expression.is_some());
1783
1784 let emit_kind = &join.common.as_ref().unwrap().emit_kind.as_ref().unwrap();
1785 let emit = match emit_kind {
1786 EmitKind::Emit(emit) => &emit.output_mapping,
1787 _ => panic!("Expected EmitKind::Emit, got {emit_kind:?}"),
1788 };
1789 assert_eq!(emit, &[0, 1, 3, 4]);
1791 }
1792
1793 #[test]
1794 fn test_parse_join_relation_left_outer() {
1795 let extensions = TestContext::new()
1796 .with_urn(1, "https://github.com/substrait-io/substrait/blob/main/extensions/functions_comparison.yaml")
1797 .with_function(1, 10, "eq")
1798 .extensions;
1799
1800 let left_rel = example_read_relation().into_rel(None);
1801 let right_rel = example_read_relation().into_rel(None);
1802
1803 let join = JoinRel::parse_pair_with_context(
1804 &extensions,
1805 parse_exact(
1806 Rule::join_relation,
1807 "Join[&Left, eq($0, $3):boolean => $0, $1, $2]",
1808 ),
1809 vec![left_rel, right_rel],
1810 6,
1811 )
1812 .unwrap()
1813 .0;
1814
1815 assert_eq!(join.r#type, join_rel::JoinType::Left as i32);
1817
1818 let emit_kind = &join.common.as_ref().unwrap().emit_kind.as_ref().unwrap();
1819 let emit = match emit_kind {
1820 EmitKind::Emit(emit) => &emit.output_mapping,
1821 _ => panic!("Expected EmitKind::Emit, got {emit_kind:?}"),
1822 };
1823 assert_eq!(emit, &[0, 1, 2]);
1825 }
1826
1827 #[test]
1828 fn test_parse_join_relation_left_semi() {
1829 let extensions = TestContext::new()
1830 .with_urn(1, "https://github.com/substrait-io/substrait/blob/main/extensions/functions_comparison.yaml")
1831 .with_function(1, 10, "eq")
1832 .extensions;
1833
1834 let left_rel = example_read_relation().into_rel(None);
1835 let right_rel = example_read_relation().into_rel(None);
1836
1837 let join = JoinRel::parse_pair_with_context(
1838 &extensions,
1839 parse_exact(
1840 Rule::join_relation,
1841 "Join[&LeftSemi, eq($0, $3):boolean => $0, $1]",
1842 ),
1843 vec![left_rel, right_rel],
1844 6,
1845 )
1846 .unwrap()
1847 .0;
1848
1849 assert_eq!(join.r#type, join_rel::JoinType::LeftSemi as i32);
1851
1852 let emit_kind = &join.common.as_ref().unwrap().emit_kind.as_ref().unwrap();
1853 let emit = match emit_kind {
1854 EmitKind::Emit(emit) => &emit.output_mapping,
1855 _ => panic!("Expected EmitKind::Emit, got {emit_kind:?}"),
1856 };
1857 assert_eq!(emit, &[0, 1]);
1859 }
1860
1861 #[test]
1862 fn test_parse_join_relation_requires_two_children() {
1863 let extensions = SimpleExtensions::default();
1864
1865 let result = JoinRel::parse_pair_with_context(
1867 &extensions,
1868 parse_exact(
1869 Rule::join_relation,
1870 "Join[&Inner, eq($0, $1):boolean => $0, $1]",
1871 ),
1872 vec![],
1873 0,
1874 );
1875 assert!(result.is_err());
1876
1877 let result = JoinRel::parse_pair_with_context(
1879 &extensions,
1880 parse_exact(
1881 Rule::join_relation,
1882 "Join[&Inner, eq($0, $1):boolean => $0, $1]",
1883 ),
1884 vec![example_read_relation().into_rel(None)],
1885 3,
1886 );
1887 assert!(result.is_err());
1888
1889 let result = JoinRel::parse_pair_with_context(
1891 &extensions,
1892 parse_exact(
1893 Rule::join_relation,
1894 "Join[&Inner, eq($0, $1):boolean => $0, $1]",
1895 ),
1896 vec![
1897 example_read_relation().into_rel(None),
1898 example_read_relation().into_rel(None),
1899 example_read_relation().into_rel(None),
1900 ],
1901 9,
1902 );
1903 assert!(result.is_err());
1904 }
1905
1906 fn parse_exact(rule: Rule, input: &'_ str) -> pest::iterators::Pair<'_, Rule> {
1907 let mut pairs = ExpressionParser::parse(rule, input).unwrap();
1908 assert_eq!(pairs.as_str(), input);
1909 let pair = pairs.next().unwrap();
1910 assert_eq!(pairs.next(), None);
1911 pair
1912 }
1913}