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
237fn parse_output(
238 extensions: &SimpleExtensions,
239 output: Pair<Rule>,
240) -> Result<(Vec<Column>, Option<RelCommon>, usize), MessageParseError> {
241 assert_eq!(output.as_rule(), Rule::output);
242 let output = unwrap_single_pair(output);
243 match output.as_rule() {
244 Rule::implicit_output => {
245 let mut iter = RuleIter::from(output.into_inner());
246 let columns = iter.parse_next_scoped::<NamedColumnList>(extensions)?.0;
247 iter.done();
248 let output_count = columns.len();
249 Ok((columns, None, output_count))
250 }
251 Rule::direct_output => {
252 let mut iter = RuleIter::from(output.into_inner());
253 let columns = iter.parse_next_scoped::<NamedColumnList>(extensions)?.0;
254 let emit_suffix = iter.pop(Rule::emit_suffix);
255 iter.done();
256
257 let direct_output_count = columns.len();
258 let (emit, output_count) = parse_emit_suffix(emit_suffix)
259 .unwrap_or((EmitKind::Direct(Direct {}), direct_output_count));
260 let common = Some(RelCommon {
261 emit_kind: Some(emit),
262 ..Default::default()
263 });
264 Ok((columns, common, output_count))
265 }
266 other => unreachable!("Unexpected rule in output: {other:?}"),
267 }
268}
269
270fn parse_emit_suffix(suffix: Pair<Rule>) -> Option<(EmitKind, usize)> {
271 assert_eq!(suffix.as_rule(), Rule::emit_suffix);
272 let reference_list = suffix.into_inner().next()?;
273 assert_eq!(reference_list.as_rule(), Rule::reference_list);
274 let output_mapping = parse_output_mapping(reference_list);
275 let output_count = output_mapping.len();
276 Some((EmitKind::Emit(Emit { output_mapping }), output_count))
277}
278
279pub struct ParsedNamedArgs<'a> {
285 map: HashMap<&'a str, Pair<'a, Rule>>,
286}
287
288impl<'a> ParsedNamedArgs<'a> {
289 pub fn new(
290 pairs: pest::iterators::Pairs<'a, Rule>,
291 rule: Rule,
292 ) -> Result<Self, MessageParseError> {
293 let mut map = HashMap::new();
294 for pair in pairs {
295 assert_eq!(pair.as_rule(), rule);
296 let mut inner = pair.clone().into_inner();
297 let name_pair = inner.next().unwrap();
298 let value_pair = inner.next().unwrap();
299 assert_eq!(inner.next(), None);
300 let name = name_pair.as_str();
301 if map.contains_key(name) {
302 return Err(MessageParseError::invalid(
303 "NamedArg",
304 name_pair.as_span(),
305 format!("Duplicate argument: {name}"),
306 ));
307 }
308 map.insert(name, value_pair);
309 }
310 Ok(Self { map })
311 }
312
313 pub fn pop(mut self, name: &str, rule: Rule) -> (Self, Option<Pair<'a, Rule>>) {
317 let pair = self.map.remove(name).inspect(|pair| {
318 assert_eq!(pair.as_rule(), rule, "Rule mismatch for argument {name}");
319 });
320 (self, pair)
321 }
322
323 pub fn done(self) -> Result<(), MessageParseError> {
325 if let Some((name, pair)) = self.map.iter().next() {
326 return Err(MessageParseError::invalid(
327 "NamedArgExtractor",
328 pair.as_span(),
330 format!("Unknown argument: {name}"),
331 ));
332 }
333 Ok(())
334 }
335}
336
337impl RelationParsePair for ReadRel {
338 fn rule() -> Rule {
339 Rule::read_relation
340 }
341
342 fn message() -> &'static str {
343 "ReadRel"
344 }
345
346 fn parse_pair_with_context(
347 extensions: &SimpleExtensions,
348 pair: Pair<Rule>,
349 input_children: Vec<Rel>,
350 input_field_count: usize,
351 ) -> Result<(Self, usize), MessageParseError> {
352 assert_eq!(pair.as_rule(), Self::rule());
353 if !input_children.is_empty() {
355 return Err(MessageParseError::invalid(
356 Self::message(),
357 pair.as_span(),
358 "ReadRel should have no input children",
359 ));
360 }
361 if input_field_count != 0 {
362 return Err(MessageParseError::invalid(
363 "ReadRel",
364 pair.as_span(),
365 "ReadRel should have 0 input fields",
366 ));
367 }
368
369 let mut iter = RuleIter::from(pair.into_inner());
370 let table = iter.parse_next::<TableName>().0;
371 let output_pair = iter.pop(Rule::output);
372 iter.done();
373
374 let (columns, common, output_count) = parse_output(extensions, output_pair)?;
375
376 Ok((
377 ReadRel {
378 base_schema: Some(build_named_struct(columns)),
379 read_type: Some(read_rel::ReadType::NamedTable(read_rel::NamedTable {
380 names: table,
381 advanced_extension: None,
382 })),
383 common,
384 ..Default::default()
385 },
386 output_count,
387 ))
388 }
389
390 fn into_rel(mut self, adv_ext: Option<AdvancedExtension>) -> Rel {
391 self.advanced_extension = adv_ext;
392 Rel {
393 rel_type: Some(RelType::Read(Box::new(self))),
394 }
395 }
396}
397
398pub(crate) struct VirtualReadRel(ReadRel);
402
403impl RelationParsePair for VirtualReadRel {
404 fn rule() -> Rule {
405 Rule::virtual_read_relation
406 }
407
408 fn message() -> &'static str {
409 "VirtualReadRel"
410 }
411
412 fn parse_pair_with_context(
413 extensions: &SimpleExtensions,
414 pair: Pair<Rule>,
415 input_children: Vec<Rel>,
416 _input_field_count: usize,
417 ) -> Result<(Self, usize), MessageParseError> {
418 assert_eq!(pair.as_rule(), Self::rule());
419 if !input_children.is_empty() {
420 return Err(MessageParseError::invalid(
421 Self::message(),
422 pair.as_span(),
423 "Read:Virtual should have no input children",
424 ));
425 }
426
427 let mut iter = RuleIter::from(pair.into_inner());
428 let rows_pair = iter.pop(Rule::virtual_read_rows);
429 let filter = iter
430 .try_pop(Rule::virtual_read_filter)
431 .map(|pair| {
432 let expression_pair = unwrap_single_pair(pair);
433 Expression::parse_pair(extensions, expression_pair).map(Box::new)
434 })
435 .transpose()?;
436 let columns_pair = iter.pop(Rule::named_column_list);
437 iter.done();
438
439 let rows = parse_virtual_read_rows(extensions, rows_pair)?;
440 let columns = NamedColumnList::parse_pair(extensions, columns_pair)?.0;
441
442 let output_count = columns.len();
447 Ok((
448 VirtualReadRel(ReadRel {
449 base_schema: Some(build_named_struct(columns)),
450 read_type: Some(read_rel::ReadType::VirtualTable(read_rel::VirtualTable {
451 expressions: rows,
452 ..Default::default()
453 })),
454 filter,
455 ..Default::default()
456 }),
457 output_count,
458 ))
459 }
460
461 fn into_rel(mut self, adv_ext: Option<AdvancedExtension>) -> Rel {
462 self.0.advanced_extension = adv_ext;
463 Rel {
464 rel_type: Some(RelType::Read(Box::new(self.0))),
465 }
466 }
467}
468
469pub(crate) struct ExtensionReadRel(ReadRel);
473
474impl ExtensionReadRel {
475 pub(crate) fn parse_pair_with_detail(
476 extensions: &SimpleExtensions,
477 pair: Pair<Rule>,
478 input_children: Vec<Rel>,
479 input_field_count: usize,
480 detail: Any,
481 advanced_extension: Option<AdvancedExtension>,
482 ) -> Result<(Rel, usize), MessageParseError> {
483 assert_eq!(pair.as_rule(), Rule::extension_read_relation);
484 if !input_children.is_empty() {
485 return Err(MessageParseError::invalid(
486 "ExtensionReadRel",
487 pair.as_span(),
488 "Read:Extension should have no input children",
489 ));
490 }
491 if input_field_count != 0 {
492 return Err(MessageParseError::invalid(
493 "ExtensionReadRel",
494 pair.as_span(),
495 "Read:Extension should have 0 input fields",
496 ));
497 }
498
499 let mut iter = RuleIter::from(pair.into_inner());
500 let columns = iter.parse_next_scoped::<NamedColumnList>(extensions)?.0;
501 iter.done();
502
503 let output_count = columns.len();
504 let rel = ExtensionReadRel(ReadRel {
505 base_schema: Some(build_named_struct(columns)),
506 read_type: Some(read_rel::ReadType::ExtensionTable(
507 read_rel::ExtensionTable {
508 detail: Some(detail.into()),
509 },
510 )),
511 advanced_extension,
512 ..Default::default()
513 })
514 .into_rel();
515
516 Ok((rel, output_count))
517 }
518
519 fn into_rel(self) -> Rel {
520 Rel {
521 rel_type: Some(RelType::Read(Box::new(self.0))),
522 }
523 }
524}
525
526pub(crate) fn build_named_struct(columns: Vec<Column>) -> NamedStruct {
528 let (names, types): (Vec<_>, Vec<_>) = columns.into_iter().map(|c| (c.name, c.typ)).unzip();
529 NamedStruct {
530 names,
531 r#struct: Some(r#type::Struct {
532 types,
533 type_variation_reference: 0,
534 nullability: r#type::Nullability::Required as i32,
535 }),
536 }
537}
538
539fn parse_virtual_read_rows(
541 extensions: &SimpleExtensions,
542 pair: Pair<Rule>,
543) -> Result<Vec<nested::Struct>, MessageParseError> {
544 assert_eq!(pair.as_rule(), Rule::virtual_read_rows);
545 let inner = unwrap_single_pair(pair);
546 match inner.as_rule() {
547 Rule::empty => Ok(vec![]),
548 Rule::virtual_row_list => inner
549 .into_inner()
550 .map(|row| parse_virtual_row(extensions, row))
551 .collect(),
552 _ => unreachable!(
553 "Unexpected rule in virtual_read_rows: {:?}",
554 inner.as_rule()
555 ),
556 }
557}
558
559fn parse_virtual_row(
561 extensions: &SimpleExtensions,
562 pair: Pair<Rule>,
563) -> Result<nested::Struct, MessageParseError> {
564 assert_eq!(pair.as_rule(), Rule::virtual_row);
565 let fields = match pair.into_inner().next() {
566 Some(expression_list) => {
567 assert_eq!(expression_list.as_rule(), Rule::expression_list);
568 parse_expression_list(extensions, expression_list)?
569 }
570 None => vec![],
572 };
573 Ok(nested::Struct { fields })
574}
575
576impl RelationParsePair for FilterRel {
577 fn rule() -> Rule {
578 Rule::filter_relation
579 }
580
581 fn message() -> &'static str {
582 "FilterRel"
583 }
584
585 fn into_rel(mut self, adv_ext: Option<AdvancedExtension>) -> Rel {
586 self.advanced_extension = adv_ext;
587 Rel {
588 rel_type: Some(RelType::Filter(Box::new(self))),
589 }
590 }
591
592 fn parse_pair_with_context(
593 extensions: &SimpleExtensions,
594 pair: Pair<Rule>,
595 input_children: Vec<Rel>,
596 input_field_count: usize,
597 ) -> Result<(Self, usize), MessageParseError> {
598 assert_eq!(pair.as_rule(), Self::rule());
599 let input = expect_one_child(Self::message(), &pair, input_children)?;
600 let mut iter = RuleIter::from(pair.into_inner());
601 let condition = iter.parse_next_scoped::<Expression>(extensions)?;
602 let references_pair = iter.pop(Rule::reference_list);
603 iter.done();
604
605 let (emit, output_count) = parse_emit(references_pair, input_field_count);
606 let common = RelCommon {
607 emit_kind: Some(emit),
608 ..Default::default()
609 };
610
611 Ok((
612 FilterRel {
613 input: Some(input),
614 condition: Some(Box::new(condition)),
615 common: Some(common),
616 advanced_extension: None,
617 },
618 output_count,
619 ))
620 }
621}
622
623impl RelationParsePair for ProjectRel {
624 fn rule() -> Rule {
625 Rule::project_relation
626 }
627
628 fn message() -> &'static str {
629 "ProjectRel"
630 }
631
632 fn into_rel(mut self, adv_ext: Option<AdvancedExtension>) -> Rel {
633 self.advanced_extension = adv_ext;
634 Rel {
635 rel_type: Some(RelType::Project(Box::new(self))),
636 }
637 }
638
639 fn parse_pair_with_context(
640 extensions: &SimpleExtensions,
641 pair: Pair<Rule>,
642 input_children: Vec<Rel>,
643 input_field_count: usize,
644 ) -> Result<(Self, usize), MessageParseError> {
645 assert_eq!(pair.as_rule(), Self::rule());
646 let input = expect_one_child(Self::message(), &pair, input_children)?;
647
648 let arguments_pair = unwrap_single_pair(pair);
649
650 let mut expressions = Vec::new();
651 let mut output_mapping = Vec::new();
652
653 for arg in arguments_pair.into_inner() {
654 let inner_arg = unwrap_single_pair(arg);
655 match inner_arg.as_rule() {
656 Rule::reference => {
657 let field_index = FieldIndex::parse_pair(inner_arg);
658 output_mapping.push(field_index.0);
659 }
660 Rule::expression => {
661 let expr = Expression::parse_pair(extensions, inner_arg)?;
662 expressions.push(expr);
663 output_mapping.push(input_field_count as i32 + (expressions.len() as i32 - 1));
665 }
666 _ => panic!("Unexpected inner argument rule: {:?}", inner_arg.as_rule()),
667 }
668 }
669
670 let output_count = output_mapping.len();
671 let direct_count = input_field_count + expressions.len();
672 let emit = make_emit(output_mapping, direct_count);
673 let common = RelCommon {
674 emit_kind: Some(emit),
675 ..Default::default()
676 };
677
678 Ok((
679 ProjectRel {
680 input: Some(input),
681 expressions,
682 common: Some(common),
683 advanced_extension: None,
684 },
685 output_count,
686 ))
687 }
688}
689
690impl RelationParsePair for AggregateRel {
691 fn rule() -> Rule {
692 Rule::aggregate_relation
693 }
694
695 fn message() -> &'static str {
696 "AggregateRel"
697 }
698
699 fn into_rel(mut self, adv_ext: Option<AdvancedExtension>) -> Rel {
700 self.advanced_extension = adv_ext;
701 Rel {
702 rel_type: Some(RelType::Aggregate(Box::new(self))),
703 }
704 }
705
706 fn parse_pair_with_context(
707 extensions: &SimpleExtensions,
708 pair: Pair<Rule>,
709 input_children: Vec<Rel>,
710 _input_field_count: usize,
713 ) -> Result<(Self, usize), MessageParseError> {
714 assert_eq!(pair.as_rule(), Self::rule());
715 let input = expect_one_child(Self::message(), &pair, input_children)?;
716 let mut iter = RuleIter::from(pair.into_inner());
717 let group_by_pair = iter.pop(Rule::aggregate_group_by);
718 let output_pair = iter.pop(Rule::aggregate_output);
719 iter.done();
720
721 let inner = group_by_pair
722 .into_inner()
723 .next()
724 .expect("aggregate_group_by must have one inner item");
725
726 let grouping_sets = parse_grouping_sets(extensions, inner)?;
727 let (groupings, grouping_expressions) = build_grouping_fields(&grouping_sets);
728
729 let (measures, output_mapping) =
730 parse_aggregate_output(extensions, output_pair, &grouping_expressions)?;
731
732 let output_count = output_mapping.len();
733 let direct_count = grouping_expressions.len() + measures.len();
734 let emit = make_emit(output_mapping, direct_count);
735 let common = RelCommon {
736 emit_kind: Some(emit),
737 ..Default::default()
738 };
739
740 Ok((
741 AggregateRel {
742 input: Some(input),
743 grouping_expressions,
744 groupings,
745 measures,
746 common: Some(common),
747 advanced_extension: None,
748 },
749 output_count,
750 ))
751 }
752}
753
754fn expression_key(expression: &Expression) -> Vec<u8> {
759 expression.encode_to_vec()
760}
761
762fn parse_aggregate_output(
767 extensions: &SimpleExtensions,
768 output_pair: Pair<'_, Rule>,
769 grouping_expressions: &[Expression],
770) -> Result<(Vec<aggregate_rel::Measure>, Vec<i32>), MessageParseError> {
771 assert_eq!(output_pair.as_rule(), Rule::aggregate_output);
772
773 let grouping_positions: HashMap<Vec<u8>, usize> = grouping_expressions
784 .iter()
785 .enumerate()
786 .map(|(index, expression)| (expression_key(expression), index))
787 .collect();
788
789 let mut measures = Vec::new();
790 let mut output_mapping = Vec::new();
791
792 for output_item in output_pair.into_inner() {
793 assert_eq!(output_item.as_rule(), Rule::expression);
794 let span = output_item.as_span();
795 let inner_item = unwrap_single_pair(output_item.clone());
796
797 if inner_item.as_rule() == Rule::function_call {
798 let expression = Expression::parse_pair(extensions, output_item)?;
799 if let Some(&index) = grouping_positions.get(&expression_key(&expression)) {
800 output_mapping.push(index as i32);
801 continue;
802 }
803
804 let measure = aggregate_rel::Measure::parse_pair(extensions, inner_item)?;
805 output_mapping.push(grouping_expressions.len() as i32 + measures.len() as i32);
806 measures.push(measure);
807 continue;
808 }
809
810 let expression = Expression::parse_pair(extensions, output_item)?;
811 match grouping_positions.get(&expression_key(&expression)) {
812 Some(&index) => output_mapping.push(index as i32),
813 None => {
814 return Err(MessageParseError::invalid(
815 "AggregateRel",
816 span,
817 "output expression is not an aggregate measure and does not match any grouping expression",
818 ));
819 }
820 }
821 }
822
823 Ok((measures, output_mapping))
824}
825
826fn parse_grouping_sets(
835 extensions: &SimpleExtensions,
836 inner: Pair<'_, Rule>,
837) -> Result<Vec<Vec<Expression>>, MessageParseError> {
838 assert!(
839 matches!(
840 inner.as_rule(),
841 Rule::expression_list | Rule::grouping_set_list
842 ),
843 "Expected expression_list or grouping_set_list, got {:?}",
844 inner.as_rule()
845 );
846 match inner.as_rule() {
847 Rule::expression_list => Ok(vec![parse_expression_list(extensions, inner)?]),
848 Rule::grouping_set_list => inner
849 .into_inner()
850 .map(|pair| parse_grouping_set(extensions, pair))
851 .collect(),
852 _ => unreachable!(
853 "Unexpected rule in aggregate_group_by: {:?}",
854 inner.as_rule()
855 ),
856 }
857}
858
859fn parse_grouping_set(
863 extensions: &SimpleExtensions,
864 pair: Pair<'_, Rule>,
865) -> Result<Vec<Expression>, MessageParseError> {
866 assert_eq!(pair.as_rule(), Rule::grouping_set);
867 let inner = pair
868 .into_inner()
869 .next()
870 .expect("grouping_set must have one inner item");
871 match inner.as_rule() {
872 Rule::empty => Ok(vec![]),
873 Rule::expression_list => parse_expression_list(extensions, inner),
874 _ => unreachable!("Unexpected item in grouping_set: {:?}", inner.as_rule()),
875 }
876}
877
878pub(crate) fn parse_expression_list(
880 extensions: &SimpleExtensions,
881 pair: Pair<'_, Rule>,
882) -> Result<Vec<Expression>, MessageParseError> {
883 pair.into_inner()
884 .map(|expr_pair| Expression::parse_pair(extensions, expr_pair))
885 .collect()
886}
887
888fn build_grouping_fields(expression_sets: &[Vec<Expression>]) -> (Vec<Grouping>, Vec<Expression>) {
892 let mut expressions: Vec<Expression> = Vec::new();
893 let mut seen: HashMap<Vec<u8>, u32> = HashMap::new();
894
895 let groupings = expression_sets
896 .iter()
897 .map(|set| {
898 let expression_references = set
899 .iter()
900 .map(|exp| {
901 let key = expression_key(exp);
902 let next_idx = expressions.len() as u32;
903 *seen.entry(key).or_insert_with(|| {
904 expressions.push(exp.clone());
905 next_idx
906 })
907 })
908 .collect();
909 Grouping {
910 expression_references,
911 #[allow(deprecated)]
912 grouping_expressions: vec![],
913 }
914 })
915 .collect();
916
917 (groupings, expressions)
918}
919
920impl ScopedParsePair for SortField {
921 fn rule() -> Rule {
922 Rule::sort_field
923 }
924
925 fn message() -> &'static str {
926 "SortField"
927 }
928
929 fn parse_pair(
930 _extensions: &SimpleExtensions,
931 pair: Pair<Rule>,
932 ) -> Result<Self, MessageParseError> {
933 assert_eq!(pair.as_rule(), Self::rule());
934 let mut iter = RuleIter::from(pair.into_inner());
935 let reference_pair = iter.pop(Rule::reference);
936 let field_index = FieldIndex::parse_pair(reference_pair);
937 let direction_pair = iter.pop(Rule::sort_direction);
938 let direction = match direction_pair.as_str().trim_start_matches('&') {
942 "AscNullsFirst" => SortDirection::AscNullsFirst,
943 "AscNullsLast" => SortDirection::AscNullsLast,
944 "DescNullsFirst" => SortDirection::DescNullsFirst,
945 "DescNullsLast" => SortDirection::DescNullsLast,
946 other => {
947 return Err(MessageParseError::invalid(
948 "SortDirection",
949 direction_pair.as_span(),
950 format!("Unknown sort direction: {other}"),
951 ));
952 }
953 };
954 iter.done();
955 Ok(SortField {
956 expr: Some(Expression {
957 rex_type: Some(substrait::proto::expression::RexType::Selection(Box::new(
958 field_index.to_field_reference(),
959 ))),
960 }),
961 sort_kind: Some(SortKind::Direction(direction as i32)),
963 })
964 }
965}
966
967impl RelationParsePair for SortRel {
968 fn rule() -> Rule {
969 Rule::sort_relation
970 }
971
972 fn message() -> &'static str {
973 "SortRel"
974 }
975
976 fn into_rel(mut self, adv_ext: Option<AdvancedExtension>) -> Rel {
977 self.advanced_extension = adv_ext;
978 Rel {
979 rel_type: Some(RelType::Sort(Box::new(self))),
980 }
981 }
982
983 fn parse_pair_with_context(
984 extensions: &SimpleExtensions,
985 pair: Pair<Rule>,
986 input_children: Vec<Rel>,
987 input_field_count: usize,
988 ) -> Result<(Self, usize), MessageParseError> {
989 assert_eq!(pair.as_rule(), Self::rule());
990 let input = expect_one_child(Self::message(), &pair, input_children)?;
991 let mut iter = RuleIter::from(pair.into_inner());
992 let sort_field_list_pair = iter.pop(Rule::sort_field_list);
993 let references_pair = iter.pop(Rule::reference_list);
994 let mut sorts = Vec::new();
995 for sort_field_pair in sort_field_list_pair.into_inner() {
996 let sort_field = SortField::parse_pair(extensions, sort_field_pair)?;
997 sorts.push(sort_field);
998 }
999 let (emit, output_count) = parse_emit(references_pair, input_field_count);
1000 let common = RelCommon {
1001 emit_kind: Some(emit),
1002 ..Default::default()
1003 };
1004 iter.done();
1005 Ok((
1006 SortRel {
1007 input: Some(input),
1008 sorts,
1009 common: Some(common),
1010 advanced_extension: None,
1011 },
1012 output_count,
1013 ))
1014 }
1015}
1016
1017impl ScopedParsePair for CountMode {
1018 fn rule() -> Rule {
1019 Rule::fetch_value
1020 }
1021 fn message() -> &'static str {
1022 "CountMode"
1023 }
1024 fn parse_pair(
1025 extensions: &SimpleExtensions,
1026 pair: Pair<Rule>,
1027 ) -> Result<Self, MessageParseError> {
1028 assert_eq!(pair.as_rule(), Self::rule());
1029 let mut arg_inner = RuleIter::from(pair.into_inner());
1030 let value_pair = if let Some(int_pair) = arg_inner.try_pop(Rule::integer) {
1031 int_pair
1032 } else {
1033 arg_inner.pop(Rule::expression)
1034 };
1035 match value_pair.as_rule() {
1036 Rule::integer => {
1037 let value = value_pair.as_str().parse::<i64>().map_err(|e| {
1038 MessageParseError::invalid(
1039 Self::message(),
1040 value_pair.as_span(),
1041 format!("Invalid integer: {e}"),
1042 )
1043 })?;
1044 if value < 0 {
1045 return Err(MessageParseError::invalid(
1046 Self::message(),
1047 value_pair.as_span(),
1048 format!("Fetch limit must be non-negative, got: {value}"),
1049 ));
1050 }
1051 Ok(CountMode::CountExpr(i64_literal_expr(value)))
1052 }
1053 Rule::expression => {
1054 let expr = Expression::parse_pair(extensions, value_pair)?;
1055 Ok(CountMode::CountExpr(Box::new(expr)))
1056 }
1057 _ => Err(MessageParseError::invalid(
1058 Self::message(),
1059 value_pair.as_span(),
1060 format!("Unexpected rule for CountMode: {:?}", value_pair.as_rule()),
1061 )),
1062 }
1063 }
1064}
1065
1066fn i64_literal_expr(value: i64) -> Box<Expression> {
1067 Box::new(Expression {
1068 rex_type: Some(RexType::Literal(Literal {
1069 nullable: false,
1070 type_variation_reference: 0,
1071 literal_type: Some(LiteralType::I64(value)),
1072 })),
1073 })
1074}
1075
1076impl ScopedParsePair for OffsetMode {
1077 fn rule() -> Rule {
1078 Rule::fetch_value
1079 }
1080 fn message() -> &'static str {
1081 "OffsetMode"
1082 }
1083 fn parse_pair(
1084 extensions: &SimpleExtensions,
1085 pair: Pair<Rule>,
1086 ) -> Result<Self, MessageParseError> {
1087 assert_eq!(pair.as_rule(), Self::rule());
1088 let mut arg_inner = RuleIter::from(pair.into_inner());
1089 let value_pair = if let Some(int_pair) = arg_inner.try_pop(Rule::integer) {
1090 int_pair
1091 } else {
1092 arg_inner.pop(Rule::expression)
1093 };
1094 match value_pair.as_rule() {
1095 Rule::integer => {
1096 let value = value_pair.as_str().parse::<i64>().map_err(|e| {
1097 MessageParseError::invalid(
1098 Self::message(),
1099 value_pair.as_span(),
1100 format!("Invalid integer: {e}"),
1101 )
1102 })?;
1103 if value < 0 {
1104 return Err(MessageParseError::invalid(
1105 Self::message(),
1106 value_pair.as_span(),
1107 format!("Fetch offset must be non-negative, got: {value}"),
1108 ));
1109 }
1110 Ok(OffsetMode::OffsetExpr(i64_literal_expr(value)))
1111 }
1112 Rule::expression => {
1113 let expr = Expression::parse_pair(extensions, value_pair)?;
1114 Ok(OffsetMode::OffsetExpr(Box::new(expr)))
1115 }
1116 _ => Err(MessageParseError::invalid(
1117 Self::message(),
1118 value_pair.as_span(),
1119 format!("Unexpected rule for OffsetMode: {:?}", value_pair.as_rule()),
1120 )),
1121 }
1122 }
1123}
1124
1125impl RelationParsePair for FetchRel {
1126 fn rule() -> Rule {
1127 Rule::fetch_relation
1128 }
1129
1130 fn message() -> &'static str {
1131 "FetchRel"
1132 }
1133
1134 fn into_rel(mut self, adv_ext: Option<AdvancedExtension>) -> Rel {
1135 self.advanced_extension = adv_ext;
1136 Rel {
1137 rel_type: Some(RelType::Fetch(Box::new(self))),
1138 }
1139 }
1140
1141 fn parse_pair_with_context(
1142 extensions: &SimpleExtensions,
1143 pair: Pair<Rule>,
1144 input_children: Vec<Rel>,
1145 input_field_count: usize,
1146 ) -> Result<(Self, usize), MessageParseError> {
1147 assert_eq!(pair.as_rule(), Self::rule());
1148 let input = expect_one_child(Self::message(), &pair, input_children)?;
1149 let mut iter = RuleIter::from(pair.into_inner());
1150
1151 let (limit_pair, offset_pair) = match iter.try_pop(Rule::fetch_named_arg_list) {
1155 None => {
1156 iter.pop(Rule::empty);
1157 (None, None)
1158 }
1159 Some(fetch_args_pair) => {
1160 let extractor =
1161 ParsedNamedArgs::new(fetch_args_pair.into_inner(), Rule::fetch_named_arg)?;
1162 let (extractor, limit_pair) = extractor.pop("limit", Rule::fetch_value);
1163 let (extractor, offset_pair) = extractor.pop("offset", Rule::fetch_value);
1164 extractor.done()?;
1165 (limit_pair, offset_pair)
1166 }
1167 };
1168
1169 let references_pair = iter.pop(Rule::reference_list);
1170 let (emit, output_count) = parse_emit(references_pair, input_field_count);
1171 let common = RelCommon {
1172 emit_kind: Some(emit),
1173 ..Default::default()
1174 };
1175 iter.done();
1176
1177 let count_mode = limit_pair
1178 .map(|pair| CountMode::parse_pair(extensions, pair))
1179 .transpose()?;
1180 let offset_mode = offset_pair
1181 .map(|pair| OffsetMode::parse_pair(extensions, pair))
1182 .transpose()?;
1183 Ok((
1184 FetchRel {
1185 input: Some(input),
1186 common: Some(common),
1187 advanced_extension: None,
1188 offset_mode,
1189 count_mode,
1190 },
1191 output_count,
1192 ))
1193 }
1194}
1195
1196impl ParsePair for join_rel::JoinType {
1197 fn rule() -> Rule {
1198 Rule::join_type
1199 }
1200
1201 fn message() -> &'static str {
1202 "JoinType"
1203 }
1204
1205 fn parse_pair(pair: Pair<Rule>) -> Self {
1206 assert_eq!(pair.as_rule(), Self::rule());
1207 let join_type_str = pair.as_str().trim_start_matches('&');
1208 match join_type_str {
1209 "Inner" => join_rel::JoinType::Inner,
1210 "Left" => join_rel::JoinType::Left,
1211 "Right" => join_rel::JoinType::Right,
1212 "Outer" => join_rel::JoinType::Outer,
1213 "LeftSemi" => join_rel::JoinType::LeftSemi,
1214 "RightSemi" => join_rel::JoinType::RightSemi,
1215 "LeftAnti" => join_rel::JoinType::LeftAnti,
1216 "RightAnti" => join_rel::JoinType::RightAnti,
1217 "LeftSingle" => join_rel::JoinType::LeftSingle,
1218 "RightSingle" => join_rel::JoinType::RightSingle,
1219 "LeftMark" => join_rel::JoinType::LeftMark,
1220 "RightMark" => join_rel::JoinType::RightMark,
1221 _ => panic!("Unknown join type: {join_type_str} (this should be caught by grammar)"),
1222 }
1223 }
1224}
1225
1226impl RelationParsePair for JoinRel {
1227 fn rule() -> Rule {
1228 Rule::join_relation
1229 }
1230
1231 fn message() -> &'static str {
1232 "JoinRel"
1233 }
1234
1235 fn into_rel(mut self, adv_ext: Option<AdvancedExtension>) -> Rel {
1236 self.advanced_extension = adv_ext;
1237 Rel {
1238 rel_type: Some(RelType::Join(Box::new(self))),
1239 }
1240 }
1241
1242 fn parse_pair_with_context(
1243 extensions: &SimpleExtensions,
1244 pair: Pair<Rule>,
1245 input_children: Vec<Rel>,
1246 input_field_count: usize,
1247 ) -> Result<(Self, usize), MessageParseError> {
1248 assert_eq!(pair.as_rule(), Self::rule());
1249
1250 if input_children.len() != 2 {
1251 return Err(MessageParseError::invalid(
1252 Self::message(),
1253 pair.as_span(),
1254 format!(
1255 "JoinRel should have exactly 2 input children, got {}",
1256 input_children.len()
1257 ),
1258 ));
1259 }
1260
1261 let mut children_iter = input_children.into_iter();
1262 let left = Box::new(children_iter.next().unwrap());
1263 let right = Box::new(children_iter.next().unwrap());
1264
1265 let mut iter = RuleIter::from(pair.into_inner());
1266 let join_type = iter.parse_next::<join_rel::JoinType>();
1267 let condition = iter.parse_next_scoped::<Expression>(extensions)?;
1268 let post_join_filter = iter
1269 .try_pop(Rule::join_post_join_filter)
1270 .map(|pair| {
1271 let expression_pair = unwrap_single_pair(pair);
1272 Expression::parse_pair(extensions, expression_pair).map(Box::new)
1273 })
1274 .transpose()?;
1275 let references_pair = iter.pop(Rule::reference_list);
1276 iter.done();
1277
1278 let (emit, output_count) = parse_emit(references_pair, input_field_count);
1282 let common = RelCommon {
1283 emit_kind: Some(emit),
1284 ..Default::default()
1285 };
1286
1287 Ok((
1288 JoinRel {
1289 common: Some(common),
1290 left: Some(left),
1291 right: Some(right),
1292 expression: Some(Box::new(condition)),
1293 post_join_filter,
1294 r#type: join_type as i32,
1295 advanced_extension: None,
1296 },
1297 output_count,
1298 ))
1299 }
1300}
1301
1302impl RelationParsePair for CrossRel {
1303 fn rule() -> Rule {
1304 Rule::cross_relation
1305 }
1306
1307 fn message() -> &'static str {
1308 "CrossRel"
1309 }
1310
1311 fn into_rel(mut self, adv_ext: Option<AdvancedExtension>) -> Rel {
1312 self.advanced_extension = adv_ext;
1313 Rel {
1314 rel_type: Some(RelType::Cross(Box::new(self))),
1315 }
1316 }
1317
1318 fn parse_pair_with_context(
1319 _extensions: &SimpleExtensions,
1320 pair: Pair<Rule>,
1321 input_children: Vec<Rel>,
1322 input_field_count: usize,
1323 ) -> Result<(Self, usize), MessageParseError> {
1324 assert_eq!(pair.as_rule(), Self::rule());
1325
1326 if input_children.len() != 2 {
1327 return Err(MessageParseError::invalid(
1328 Self::message(),
1329 pair.as_span(),
1330 format!(
1331 "CrossRel should have exactly 2 input children, got {}",
1332 input_children.len()
1333 ),
1334 ));
1335 }
1336
1337 let mut children_iter = input_children.into_iter();
1338 let left = Box::new(children_iter.next().unwrap());
1339 let right = Box::new(children_iter.next().unwrap());
1340
1341 let mut iter = RuleIter::from(pair.into_inner());
1342 let reference_list_pair = iter.pop(Rule::reference_list);
1343 iter.done();
1344
1345 let (emit, output_count) = parse_emit(reference_list_pair, input_field_count);
1346 let common = RelCommon {
1347 emit_kind: Some(emit),
1348 ..Default::default()
1349 };
1350
1351 Ok((
1352 CrossRel {
1353 common: Some(common),
1354 left: Some(left),
1355 right: Some(right),
1356 advanced_extension: None,
1357 },
1358 output_count,
1359 ))
1360 }
1361}
1362
1363impl ParsePair for set_rel::SetOp {
1364 fn rule() -> Rule {
1365 Rule::set_op
1366 }
1367
1368 fn message() -> &'static str {
1369 "SetOp"
1370 }
1371
1372 fn parse_pair(pair: Pair<Rule>) -> Self {
1373 assert_eq!(pair.as_rule(), Self::rule());
1374 let set_op_str = pair.as_str().trim_start_matches('&');
1375 match set_op_str {
1376 "MinusPrimary" => set_rel::SetOp::MinusPrimary,
1377 "MinusPrimaryAll" => set_rel::SetOp::MinusPrimaryAll,
1378 "MinusMultiset" => set_rel::SetOp::MinusMultiset,
1379 "IntersectionPrimary" => set_rel::SetOp::IntersectionPrimary,
1380 "IntersectionMultiset" => set_rel::SetOp::IntersectionMultiset,
1381 "IntersectionMultisetAll" => set_rel::SetOp::IntersectionMultisetAll,
1382 "UnionDistinct" => set_rel::SetOp::UnionDistinct,
1383 "UnionAll" => set_rel::SetOp::UnionAll,
1384 _ => panic!("Unknown set op: {set_op_str} (this should be caught by grammar)"),
1385 }
1386 }
1387}
1388
1389pub(crate) fn parse_set_relation_pair(
1392 pair: Pair<Rule>,
1393 input_children: Vec<Rel>,
1394 child_field_counts: &[usize],
1395 advanced_extension: Option<AdvancedExtension>,
1396) -> Result<(Rel, usize), MessageParseError> {
1397 assert_eq!(pair.as_rule(), Rule::set_relation);
1398
1399 if input_children.len() < 2 {
1400 return Err(MessageParseError::invalid(
1401 "SetRel",
1402 pair.as_span(),
1403 format!(
1404 "SetRel should have at least 2 input children, got {}",
1405 input_children.len()
1406 ),
1407 ));
1408 }
1409
1410 let child_width = child_field_counts[0];
1413 if child_field_counts.iter().any(|&w| w != child_width) {
1414 return Err(MessageParseError::invalid(
1415 "SetRel",
1416 pair.as_span(),
1417 format!(
1418 "SetRel inputs must all have the same number of columns, got widths {child_field_counts:?}"
1419 ),
1420 ));
1421 }
1422
1423 let mut iter = RuleIter::from(pair.into_inner());
1424 let op = iter.parse_next::<set_rel::SetOp>();
1425 let reference_list_pair = iter.pop(Rule::reference_list);
1426 iter.done();
1427
1428 let (emit, output_count) = parse_emit(reference_list_pair, child_width);
1429 let common = RelCommon {
1430 emit_kind: Some(emit),
1431 ..Default::default()
1432 };
1433
1434 Ok((
1435 Rel {
1436 rel_type: Some(RelType::Set(SetRel {
1437 common: Some(common),
1438 inputs: input_children,
1439 op: op as i32,
1440 advanced_extension,
1441 })),
1442 },
1443 output_count,
1444 ))
1445}
1446
1447#[cfg(test)]
1448mod tests {
1449 use pest::Parser;
1450
1451 use super::*;
1452 use crate::fixtures::TestContext;
1453 use crate::parser::{ExpressionParser, Rule};
1454
1455 #[test]
1456 fn test_parse_relation() {
1457 }
1459
1460 #[test]
1461 fn test_parse_read_relation() {
1462 let extensions = SimpleExtensions::default();
1463 let read = ReadRel::parse_pair_with_context(
1464 &extensions,
1465 parse_exact(Rule::read_relation, "Read[ab.cd.ef => a:i32, b:string?]"),
1466 vec![],
1467 0,
1468 )
1469 .unwrap()
1470 .0;
1471 let names = match &read.read_type {
1472 Some(read_rel::ReadType::NamedTable(table)) => &table.names,
1473 _ => panic!("Expected NamedTable"),
1474 };
1475 assert_eq!(names, &["ab", "cd", "ef"]);
1476 let columns = &read
1477 .base_schema
1478 .as_ref()
1479 .unwrap()
1480 .r#struct
1481 .as_ref()
1482 .unwrap()
1483 .types;
1484 assert_eq!(columns.len(), 2);
1485 assert!(read.common.is_none());
1486 }
1487
1488 #[test]
1489 fn test_parse_read_relation_explicit_emit() {
1490 let extensions = SimpleExtensions::default();
1491 let read = ReadRel::parse_pair_with_context(
1492 &extensions,
1493 parse_exact(
1494 Rule::read_relation,
1495 "Read[ab.cd.ef +> a:i32, b:string?, c:i64 |> $2, $0]",
1496 ),
1497 vec![],
1498 0,
1499 )
1500 .unwrap();
1501 let (read, output_count) = read;
1502 assert_eq!(output_count, 2);
1503 let emit_kind = read.common.as_ref().unwrap().emit_kind.as_ref().unwrap();
1504 match emit_kind {
1505 EmitKind::Emit(emit) => assert_eq!(emit.output_mapping, vec![2, 0]),
1506 other => panic!("Expected EmitKind::Emit, got {other:?}"),
1507 }
1508 }
1509
1510 #[test]
1511 fn test_parse_read_relation_explicit_identity_emit_not_collapsed() {
1512 let extensions = SimpleExtensions::default();
1515 let read = ReadRel::parse_pair_with_context(
1516 &extensions,
1517 parse_exact(
1518 Rule::read_relation,
1519 "Read[ab.cd.ef +> a:i32, b:string? |> $0, $1]",
1520 ),
1521 vec![],
1522 0,
1523 )
1524 .unwrap()
1525 .0;
1526 let emit_kind = read.common.as_ref().unwrap().emit_kind.as_ref().unwrap();
1527 assert!(
1528 matches!(emit_kind, EmitKind::Emit(_)),
1529 "Expected explicit Emit to survive even with an identity mapping, got {emit_kind:?}"
1530 );
1531 }
1532
1533 #[test]
1534 fn test_parse_read_relation_explicit_direct() {
1535 let extensions = SimpleExtensions::default();
1536 let (read, output_count) = ReadRel::parse_pair_with_context(
1537 &extensions,
1538 parse_exact(Rule::read_relation, "Read[ab.cd.ef +> a:i32, b:string?]"),
1539 vec![],
1540 0,
1541 )
1542 .unwrap();
1543 assert_eq!(output_count, 2);
1544 let emit_kind = read.common.as_ref().unwrap().emit_kind.as_ref().unwrap();
1545 assert!(
1546 matches!(emit_kind, EmitKind::Direct(_)),
1547 "Expected +> without |> to produce Direct, got {emit_kind:?}"
1548 );
1549 }
1550
1551 #[test]
1552 fn test_parse_virtual_read_relation_filter() {
1553 let extensions = TestContext::new()
1554 .with_urn(1, "https://github.com/substrait-io/substrait/blob/main/extensions/functions_comparison.yaml")
1555 .with_function(1, 10, "gt")
1556 .extensions;
1557
1558 let read = VirtualReadRel::parse_pair_with_context(
1559 &extensions,
1560 parse_exact(
1561 Rule::virtual_read_relation,
1562 "Read:Virtual[(1, 'alice'), filter=gt($0, 0:i64):boolean => id:i64, name:string]",
1563 ),
1564 vec![],
1565 0,
1566 )
1567 .unwrap()
1568 .0
1569 .0;
1570
1571 match read.read_type {
1572 Some(read_rel::ReadType::VirtualTable(table)) => {
1573 assert_eq!(table.expressions.len(), 1);
1574 }
1575 other => panic!("Expected VirtualTable, got {other:?}"),
1576 }
1577 assert!(read.filter.is_some());
1578 }
1579
1580 #[test]
1581 fn test_parse_read_relation_rejects_arrow_with_emit() {
1582 let parsed = ExpressionParser::parse(
1583 Rule::read_relation,
1584 "Read[ab.cd.ef => a:i32, b:string? |> $0, $1]",
1585 );
1586 assert!(
1587 parsed.is_err(),
1588 "Read cannot combine legacy => output with explicit |>"
1589 );
1590 }
1591
1592 fn example_read_relation() -> ReadRel {
1594 let extensions = SimpleExtensions::default();
1595 ReadRel::parse_pair_with_context(
1596 &extensions,
1597 parse_exact(
1598 Rule::read_relation,
1599 "Read[ab.cd.ef => a:i32, b:string?, c:i64]",
1600 ),
1601 vec![],
1602 0,
1603 )
1604 .unwrap()
1605 .0
1606 }
1607
1608 #[test]
1609 fn test_parse_filter_relation() {
1610 let extensions = SimpleExtensions::default();
1611 let filter = FilterRel::parse_pair_with_context(
1612 &extensions,
1613 parse_exact(Rule::filter_relation, "Filter[$1 => $0, $1, $2]"),
1614 vec![example_read_relation().into_rel(None)],
1615 3,
1616 )
1617 .unwrap()
1618 .0;
1619 let emit_kind = filter.common.as_ref().unwrap().emit_kind.as_ref().unwrap();
1621 assert!(
1622 matches!(emit_kind, EmitKind::Direct(_)),
1623 "Expected Direct for identity emit, got {emit_kind:?}"
1624 );
1625 }
1626
1627 #[test]
1628 fn test_parse_project_relation() {
1629 let extensions = SimpleExtensions::default();
1630 let project = ProjectRel::parse_pair_with_context(
1631 &extensions,
1632 parse_exact(Rule::project_relation, "Project[$0, $1, 42]"),
1633 vec![example_read_relation().into_rel(None)],
1634 3,
1635 )
1636 .unwrap()
1637 .0;
1638
1639 assert_eq!(project.expressions.len(), 1);
1641
1642 let emit_kind = &project.common.as_ref().unwrap().emit_kind.as_ref().unwrap();
1643 let emit = match emit_kind {
1644 EmitKind::Emit(emit) => &emit.output_mapping,
1645 _ => panic!("Expected EmitKind::Emit, got {emit_kind:?}"),
1646 };
1647 assert_eq!(emit, &[0, 1, 3]);
1649 }
1650
1651 #[test]
1652 fn test_parse_project_relation_complex() {
1653 let extensions = SimpleExtensions::default();
1654 let project = ProjectRel::parse_pair_with_context(
1655 &extensions,
1656 parse_exact(Rule::project_relation, "Project[42, $0, 100, $2, $1]"),
1657 vec![example_read_relation().into_rel(None)],
1658 5, )
1660 .unwrap()
1661 .0;
1662
1663 assert_eq!(project.expressions.len(), 2);
1665
1666 let emit_kind = &project.common.as_ref().unwrap().emit_kind.as_ref().unwrap();
1667 let emit = match emit_kind {
1668 EmitKind::Emit(emit) => &emit.output_mapping,
1669 _ => panic!("Expected EmitKind::Emit, got {emit_kind:?}"),
1670 };
1671 assert_eq!(emit, &[5, 0, 6, 2, 1]);
1674 }
1675
1676 #[test]
1677 fn test_parse_aggregate_relation() {
1678 let extensions = TestContext::new()
1679 .with_urn(1, "https://github.com/substrait-io/substrait/blob/main/extensions/functions_aggregate.yaml")
1680 .with_function(1, 10, "sum")
1681 .with_function(1, 11, "count")
1682 .extensions;
1683
1684 let aggregate = AggregateRel::parse_pair_with_context(
1685 &extensions,
1686 parse_exact(
1687 Rule::aggregate_relation,
1688 "Aggregate[($0, $1), _ => sum($2):i64, $0, count($2):i64]",
1689 ),
1690 vec![example_read_relation().into_rel(None)],
1691 3,
1692 )
1693 .unwrap()
1694 .0;
1695
1696 assert_eq!(aggregate.grouping_expressions.len(), 2);
1698 assert_eq!(aggregate.groupings[0].expression_references.len(), 2);
1699 assert_eq!(aggregate.groupings.len(), 2);
1700 assert_eq!(aggregate.measures.len(), 2);
1701
1702 let emit_kind = &aggregate
1703 .common
1704 .as_ref()
1705 .unwrap()
1706 .emit_kind
1707 .as_ref()
1708 .unwrap();
1709 let emit = match emit_kind {
1710 EmitKind::Emit(emit) => &emit.output_mapping,
1711 _ => panic!("Expected EmitKind::Emit, got {emit_kind:?}"),
1712 };
1713 assert_eq!(emit, &[2, 0, 3]);
1716 }
1717
1718 #[test]
1719 fn test_parse_aggregate_relation_maintain_column_order() {
1720 let extensions = TestContext::new()
1721 .with_urn(1, "https://github.com/substrait-io/substrait/blob/main/extensions/functions_aggregate.yaml")
1722 .with_function(1, 10, "sum")
1723 .with_function(1, 11, "count")
1724 .extensions;
1725
1726 let aggregate = AggregateRel::parse_pair_with_context(
1727 &extensions,
1728 parse_exact(
1729 Rule::aggregate_relation,
1730 "Aggregate[$0 => sum($1):i64, $0, count($1):i64]",
1731 ),
1732 vec![example_read_relation().into_rel(None)],
1733 3,
1734 )
1735 .unwrap()
1736 .0;
1737
1738 assert_eq!(aggregate.grouping_expressions.len(), 1);
1740 assert_eq!(aggregate.groupings.len(), 1);
1741 assert_eq!(aggregate.measures.len(), 2);
1742
1743 let emit_kind = &aggregate
1744 .common
1745 .as_ref()
1746 .unwrap()
1747 .emit_kind
1748 .as_ref()
1749 .unwrap();
1750 let emit = match emit_kind {
1751 EmitKind::Emit(emit) => &emit.output_mapping,
1752 _ => panic!("Expected EmitKind::Emit, got {emit_kind:?}"),
1753 };
1754 assert_eq!(emit, &[1, 0, 2]);
1756 }
1757
1758 #[test]
1759 fn test_parse_aggregate_relation_simple() {
1760 let extensions = TestContext::new()
1761 .with_urn(1, "https://github.com/substrait-io/substrait/blob/main/extensions/functions_aggregate.yaml")
1762 .with_function(1, 10, "sum")
1763 .extensions;
1764
1765 let aggregate = AggregateRel::parse_pair_with_context(
1766 &extensions,
1767 parse_exact(Rule::aggregate_relation, "Aggregate[$2, $0 => sum($1):i64]"),
1768 vec![example_read_relation().into_rel(None)],
1769 3,
1770 )
1771 .unwrap()
1772 .0;
1773
1774 assert_eq!(aggregate.grouping_expressions.len(), 2);
1775 assert_eq!(aggregate.groupings.len(), 1);
1776 assert_eq!(aggregate.groupings[0].expression_references, vec![0, 1]);
1778 }
1779
1780 #[test]
1781 fn test_parse_aggregate_relation_output_reference_uses_grouping_position() {
1782 let extensions = TestContext::new()
1783 .with_urn(1, "https://github.com/substrait-io/substrait/blob/main/extensions/functions_aggregate.yaml")
1784 .with_function(1, 10, "sum")
1785 .extensions;
1786
1787 let aggregate = AggregateRel::parse_pair_with_context(
1794 &extensions,
1795 parse_exact(
1796 Rule::aggregate_relation,
1797 "Aggregate[$2, $0 => $0, $2, sum($1):i64]",
1798 ),
1799 vec![example_read_relation().into_rel(None)],
1800 3,
1801 )
1802 .unwrap()
1803 .0;
1804
1805 assert_eq!(aggregate.grouping_expressions.len(), 2);
1806 let emit_kind = &aggregate
1807 .common
1808 .as_ref()
1809 .unwrap()
1810 .emit_kind
1811 .as_ref()
1812 .unwrap();
1813 let emit = match emit_kind {
1814 EmitKind::Emit(emit) => &emit.output_mapping,
1815 _ => panic!("Expected EmitKind::Emit, got {emit_kind:?}"),
1816 };
1817 assert_eq!(emit, &[1, 0, 2]);
1819 }
1820
1821 #[test]
1822 fn test_parse_aggregate_relation_output_not_in_grouping_expressions_errors() {
1823 let extensions = TestContext::new()
1824 .with_urn(1, "https://github.com/substrait-io/substrait/blob/main/extensions/functions_aggregate.yaml")
1825 .with_function(1, 10, "sum")
1826 .extensions;
1827
1828 let result = AggregateRel::parse_pair_with_context(
1831 &extensions,
1832 parse_exact(Rule::aggregate_relation, "Aggregate[$0 => $1, sum($1):i64]"),
1833 vec![example_read_relation().into_rel(None)],
1834 3,
1835 );
1836
1837 let error = result.unwrap_err();
1838 assert!(error.to_string().contains(
1839 "output expression is not an aggregate measure and does not match any grouping expression"
1840 ));
1841 }
1842
1843 #[test]
1844 fn test_parse_aggregate_relation_output_with_literal_expression() {
1845 let extensions = TestContext::new()
1846 .with_urn(1, "https://github.com/substrait-io/substrait/blob/main/extensions/functions_aggregate.yaml")
1847 .with_function(1, 10, "sum")
1848 .extensions;
1849
1850 let aggregate = AggregateRel::parse_pair_with_context(
1854 &extensions,
1855 parse_exact(
1856 Rule::aggregate_relation,
1857 "Aggregate[42, $0 => $0, 42, sum($1):i64]",
1858 ),
1859 vec![example_read_relation().into_rel(None)],
1860 3,
1861 )
1862 .unwrap()
1863 .0;
1864
1865 assert_eq!(aggregate.grouping_expressions.len(), 2);
1866 let emit_kind = &aggregate
1867 .common
1868 .as_ref()
1869 .unwrap()
1870 .emit_kind
1871 .as_ref()
1872 .unwrap();
1873 let emit = match emit_kind {
1874 EmitKind::Emit(emit) => &emit.output_mapping,
1875 _ => panic!("Expected EmitKind::Emit, got {emit_kind:?}"),
1876 };
1877 assert_eq!(emit, &[1, 0, 2]);
1879 }
1880
1881 #[test]
1882 fn test_parse_aggregate_relation_function_call_is_not_a_measure() {
1883 let extensions = TestContext::new()
1884 .with_urn(1, "https://github.com/substrait-io/substrait/blob/main/extensions/functions_comparison.yaml")
1885 .with_urn(2, "https://github.com/substrait-io/substrait/blob/main/extensions/functions_aggregate.yaml")
1886 .with_function(1, 10, "eq")
1887 .with_function(2, 11, "sum")
1888 .extensions;
1889
1890 let aggregate = AggregateRel::parse_pair_with_context(
1895 &extensions,
1896 parse_exact(
1897 Rule::aggregate_relation,
1898 "Aggregate[eq($0, $1):boolean => eq($0, $1):boolean, sum($2):i64]",
1899 ),
1900 vec![example_read_relation().into_rel(None)],
1901 3,
1902 )
1903 .unwrap()
1904 .0;
1905
1906 assert_eq!(aggregate.grouping_expressions.len(), 1);
1907 assert_eq!(aggregate.measures.len(), 1);
1908 let emit_kind = &aggregate
1909 .common
1910 .as_ref()
1911 .unwrap()
1912 .emit_kind
1913 .as_ref()
1914 .unwrap();
1915 assert!(matches!(emit_kind, EmitKind::Direct(_)));
1916 }
1917
1918 #[test]
1919 fn test_parse_aggregate_relation_global_aggregate() {
1920 let extensions = TestContext::new()
1921 .with_urn(1, "https://github.com/substrait-io/substrait/blob/main/extensions/functions_aggregate.yaml")
1922 .with_function(1, 10, "sum")
1923 .with_function(1, 11, "count")
1924 .extensions;
1925
1926 let aggregate = AggregateRel::parse_pair_with_context(
1927 &extensions,
1928 parse_exact(
1929 Rule::aggregate_relation,
1930 "Aggregate[_ => sum($0):i64, count($1):i64]",
1931 ),
1932 vec![example_read_relation().into_rel(None)],
1933 3,
1934 )
1935 .unwrap()
1936 .0;
1937
1938 assert_eq!(aggregate.grouping_expressions.len(), 0);
1940 assert_eq!(aggregate.groupings.len(), 1);
1941 assert_eq!(aggregate.groupings[0].expression_references.len(), 0);
1942 assert_eq!(aggregate.measures.len(), 2);
1943
1944 let emit_kind = aggregate
1946 .common
1947 .as_ref()
1948 .unwrap()
1949 .emit_kind
1950 .as_ref()
1951 .unwrap();
1952 assert!(
1953 matches!(emit_kind, EmitKind::Direct(_)),
1954 "Expected Direct for identity emit, got {emit_kind:?}"
1955 );
1956 }
1957
1958 #[test]
1959 fn test_parse_aggregate_relation_grouping_sets() {
1960 let extensions = TestContext::new()
1961 .with_urn(1, "https://github.com/substrait-io/substrait/blob/main/extensions/functions_aggregate.yaml")
1962 .with_function(1, 11, "count")
1963 .extensions;
1964
1965 let read_rel = ReadRel::parse_pair_with_context(
1966 &extensions,
1967 parse_exact(
1968 Rule::read_relation,
1969 "Read[ab.cd.ef => a:i32, b:string?, c:i64, d:i64]",
1970 ),
1971 vec![],
1972 0,
1973 )
1974 .unwrap()
1975 .0;
1976
1977 let aggregate = AggregateRel::parse_pair_with_context(
1978 &extensions,
1979 parse_exact(
1980 Rule::aggregate_relation,
1981 "Aggregate[($0, $1, $2), ($2, $0), ($1), _ => $0, $1, $2, count($3):i64]",
1982 ),
1983 vec![read_rel.into_rel(None)],
1984 4,
1985 )
1986 .unwrap()
1987 .0;
1988
1989 assert_eq!(aggregate.grouping_expressions.len(), 3);
1990 assert_eq!(aggregate.groupings.len(), 4);
1991 assert_eq!(aggregate.groupings[0].expression_references, vec![0, 1, 2]);
1993 assert_eq!(aggregate.groupings[1].expression_references, vec![2, 0]);
1995 assert_eq!(aggregate.groupings[2].expression_references, vec![1]);
1997 assert!(aggregate.groupings[3].expression_references.is_empty());
1999 assert_eq!(aggregate.measures.len(), 1);
2000 }
2001
2002 #[test]
2003 fn test_fetch_relation_positive_values() {
2004 let extensions = SimpleExtensions::default();
2005
2006 let fetch_rel = FetchRel::parse_pair_with_context(
2008 &extensions,
2009 parse_exact(Rule::fetch_relation, "Fetch[limit=10, offset=5 => $0]"),
2010 vec![example_read_relation().into_rel(None)],
2011 3,
2012 )
2013 .unwrap()
2014 .0;
2015
2016 assert_eq!(
2018 fetch_rel.count_mode,
2019 Some(CountMode::CountExpr(i64_literal_expr(10)))
2020 );
2021 assert_eq!(
2022 fetch_rel.offset_mode,
2023 Some(OffsetMode::OffsetExpr(i64_literal_expr(5)))
2024 );
2025 }
2026
2027 #[test]
2028 fn test_fetch_relation_negative_limit_rejected() {
2029 let extensions = SimpleExtensions::default();
2030
2031 let parsed_result = ExpressionParser::parse(Rule::fetch_relation, "Fetch[limit=-5 => $0]");
2033 if let Ok(mut pairs) = parsed_result {
2034 let pair = pairs.next().unwrap();
2035 if pair.as_str() == "Fetch[limit=-5 => $0]" {
2036 let result = FetchRel::parse_pair_with_context(
2038 &extensions,
2039 pair,
2040 vec![example_read_relation().into_rel(None)],
2041 3,
2042 );
2043 assert!(result.is_err());
2044 let error_msg = result.unwrap_err().to_string();
2045 assert!(error_msg.contains("Fetch limit must be non-negative"));
2046 } else {
2047 println!("Grammar prevents negative limit values at parse time");
2050 }
2051 } else {
2052 println!("Grammar prevents negative limit values at parse time");
2054 }
2055 }
2056
2057 #[test]
2058 fn test_fetch_relation_negative_offset_rejected() {
2059 let extensions = SimpleExtensions::default();
2060
2061 let parsed_result =
2063 ExpressionParser::parse(Rule::fetch_relation, "Fetch[offset=-10 => $0]");
2064 if let Ok(mut pairs) = parsed_result {
2065 let pair = pairs.next().unwrap();
2066 if pair.as_str() == "Fetch[offset=-10 => $0]" {
2067 let result = FetchRel::parse_pair_with_context(
2069 &extensions,
2070 pair,
2071 vec![example_read_relation().into_rel(None)],
2072 3,
2073 );
2074 assert!(result.is_err());
2075 let error_msg = result.unwrap_err().to_string();
2076 assert!(error_msg.contains("Fetch offset must be non-negative"));
2077 } else {
2078 println!("Grammar prevents negative offset values at parse time");
2080 }
2081 } else {
2082 println!("Grammar prevents negative offset values at parse time");
2084 }
2085 }
2086
2087 #[test]
2088 fn test_parse_join_relation() {
2089 let extensions = TestContext::new()
2090 .with_urn(1, "https://github.com/substrait-io/substrait/blob/main/extensions/functions_comparison.yaml")
2091 .with_function(1, 10, "eq")
2092 .extensions;
2093
2094 let left_rel = example_read_relation().into_rel(None);
2095 let right_rel = example_read_relation().into_rel(None);
2096
2097 let join = JoinRel::parse_pair_with_context(
2098 &extensions,
2099 parse_exact(
2100 Rule::join_relation,
2101 "Join[&Inner, eq($0, $3):boolean => $0, $1, $3, $4]",
2102 ),
2103 vec![left_rel, right_rel],
2104 6, )
2106 .unwrap()
2107 .0;
2108
2109 assert_eq!(join.r#type, join_rel::JoinType::Inner as i32);
2111
2112 assert!(join.left.is_some());
2114 assert!(join.right.is_some());
2115
2116 assert!(join.expression.is_some());
2118 assert!(join.post_join_filter.is_none());
2119
2120 let emit_kind = &join.common.as_ref().unwrap().emit_kind.as_ref().unwrap();
2121 let emit = match emit_kind {
2122 EmitKind::Emit(emit) => &emit.output_mapping,
2123 _ => panic!("Expected EmitKind::Emit, got {emit_kind:?}"),
2124 };
2125 assert_eq!(emit, &[0, 1, 3, 4]);
2127 }
2128
2129 #[test]
2130 fn test_parse_join_relation_post_join_filter() {
2131 let extensions = TestContext::new()
2132 .with_urn(1, "https://github.com/substrait-io/substrait/blob/main/extensions/functions_comparison.yaml")
2133 .with_function(1, 10, "eq")
2134 .with_function(1, 11, "gt")
2135 .extensions;
2136
2137 let left_rel = example_read_relation().into_rel(None);
2138 let right_rel = example_read_relation().into_rel(None);
2139
2140 let join = JoinRel::parse_pair_with_context(
2141 &extensions,
2142 parse_exact(
2143 Rule::join_relation,
2144 "Join[&RightSemi, eq($0, $3):boolean, post_filter=gt($1, 100:i32):boolean => $0, $1]",
2145 ),
2146 vec![left_rel, right_rel],
2147 6,
2148 )
2149 .unwrap()
2150 .0;
2151
2152 assert_eq!(join.r#type, join_rel::JoinType::RightSemi as i32);
2153 assert!(join.expression.is_some());
2154 assert!(join.post_join_filter.is_some());
2155
2156 let emit_kind = &join.common.as_ref().unwrap().emit_kind.as_ref().unwrap();
2157 let emit = match emit_kind {
2158 EmitKind::Emit(emit) => &emit.output_mapping,
2159 _ => panic!("Expected EmitKind::Emit, got {emit_kind:?}"),
2160 };
2161 assert_eq!(emit, &[0, 1]);
2162 }
2163
2164 #[test]
2165 fn test_parse_join_relation_left_outer() {
2166 let extensions = TestContext::new()
2167 .with_urn(1, "https://github.com/substrait-io/substrait/blob/main/extensions/functions_comparison.yaml")
2168 .with_function(1, 10, "eq")
2169 .extensions;
2170
2171 let left_rel = example_read_relation().into_rel(None);
2172 let right_rel = example_read_relation().into_rel(None);
2173
2174 let join = JoinRel::parse_pair_with_context(
2175 &extensions,
2176 parse_exact(
2177 Rule::join_relation,
2178 "Join[&Left, eq($0, $3):boolean => $0, $1, $2]",
2179 ),
2180 vec![left_rel, right_rel],
2181 6,
2182 )
2183 .unwrap()
2184 .0;
2185
2186 assert_eq!(join.r#type, join_rel::JoinType::Left as i32);
2188
2189 let emit_kind = &join.common.as_ref().unwrap().emit_kind.as_ref().unwrap();
2190 let emit = match emit_kind {
2191 EmitKind::Emit(emit) => &emit.output_mapping,
2192 _ => panic!("Expected EmitKind::Emit, got {emit_kind:?}"),
2193 };
2194 assert_eq!(emit, &[0, 1, 2]);
2196 }
2197
2198 #[test]
2199 fn test_parse_join_relation_left_semi() {
2200 let extensions = TestContext::new()
2201 .with_urn(1, "https://github.com/substrait-io/substrait/blob/main/extensions/functions_comparison.yaml")
2202 .with_function(1, 10, "eq")
2203 .extensions;
2204
2205 let left_rel = example_read_relation().into_rel(None);
2206 let right_rel = example_read_relation().into_rel(None);
2207
2208 let join = JoinRel::parse_pair_with_context(
2209 &extensions,
2210 parse_exact(
2211 Rule::join_relation,
2212 "Join[&LeftSemi, eq($0, $3):boolean => $0, $1]",
2213 ),
2214 vec![left_rel, right_rel],
2215 6,
2216 )
2217 .unwrap()
2218 .0;
2219
2220 assert_eq!(join.r#type, join_rel::JoinType::LeftSemi as i32);
2222
2223 let emit_kind = &join.common.as_ref().unwrap().emit_kind.as_ref().unwrap();
2224 let emit = match emit_kind {
2225 EmitKind::Emit(emit) => &emit.output_mapping,
2226 _ => panic!("Expected EmitKind::Emit, got {emit_kind:?}"),
2227 };
2228 assert_eq!(emit, &[0, 1]);
2230 }
2231
2232 #[test]
2233 fn test_parse_join_relation_right_semi() {
2234 let extensions = TestContext::new()
2235 .with_urn(1, "https://github.com/substrait-io/substrait/blob/main/extensions/functions_comparison.yaml")
2236 .with_function(1, 10, "eq")
2237 .extensions;
2238
2239 let left_rel = example_read_relation().into_rel(None);
2240 let right_rel = example_read_relation().into_rel(None);
2241
2242 let join = JoinRel::parse_pair_with_context(
2243 &extensions,
2244 parse_exact(
2245 Rule::join_relation,
2246 "Join[&RightSemi, eq($0, $3):boolean => $0, $1]",
2247 ),
2248 vec![left_rel, right_rel],
2249 6,
2250 )
2251 .unwrap()
2252 .0;
2253
2254 assert_eq!(join.r#type, join_rel::JoinType::RightSemi as i32);
2256
2257 let emit_kind = &join.common.as_ref().unwrap().emit_kind.as_ref().unwrap();
2258 let emit = match emit_kind {
2259 EmitKind::Emit(emit) => &emit.output_mapping,
2260 _ => panic!("Expected EmitKind::Emit, got {emit_kind:?}"),
2261 };
2262 assert_eq!(emit, &[0, 1]);
2264 }
2265
2266 #[test]
2267 fn test_parse_join_relation_requires_two_children() {
2268 let extensions = SimpleExtensions::default();
2269
2270 let result = JoinRel::parse_pair_with_context(
2272 &extensions,
2273 parse_exact(
2274 Rule::join_relation,
2275 "Join[&Inner, eq($0, $1):boolean => $0, $1]",
2276 ),
2277 vec![],
2278 0,
2279 );
2280 assert!(result.is_err());
2281
2282 let result = JoinRel::parse_pair_with_context(
2284 &extensions,
2285 parse_exact(
2286 Rule::join_relation,
2287 "Join[&Inner, eq($0, $1):boolean => $0, $1]",
2288 ),
2289 vec![example_read_relation().into_rel(None)],
2290 3,
2291 );
2292 assert!(result.is_err());
2293
2294 let result = JoinRel::parse_pair_with_context(
2296 &extensions,
2297 parse_exact(
2298 Rule::join_relation,
2299 "Join[&Inner, eq($0, $1):boolean => $0, $1]",
2300 ),
2301 vec![
2302 example_read_relation().into_rel(None),
2303 example_read_relation().into_rel(None),
2304 example_read_relation().into_rel(None),
2305 ],
2306 9,
2307 );
2308 assert!(result.is_err());
2309 }
2310
2311 fn parse_exact(rule: Rule, input: &'_ str) -> pest::iterators::Pair<'_, Rule> {
2312 let mut pairs = ExpressionParser::parse(rule, input).unwrap();
2313 assert_eq!(pairs.as_str(), input);
2314 let pair = pairs.next().unwrap();
2315 assert_eq!(pairs.next(), None);
2316 pair
2317 }
2318}