1use std::fmt;
8
9use pest::iterators::Pair;
10use substrait::proto::extensions::AdvancedExtension;
11use substrait::proto::{
12 AggregateRel, FetchRel, FilterRel, JoinRel, Plan, PlanRel, ProjectRel, ReadRel, Rel, RelRoot,
13 SortRel, plan_rel,
14};
15
16use crate::extensions::{AddendumKind, ExtensionRegistry, SimpleExtensions, simple};
17use crate::parser::common::{MessageParseError, ParsePair, ScopedParsePair};
18use crate::parser::errors::{ParseContext, ParseError, ParseResult};
19use crate::parser::expressions::Name;
20use crate::parser::extensions::{
21 AddendumInvocation, ExtensionInvocation, ExtensionParseError, ExtensionParser,
22};
23use crate::parser::relations::{RelationParsingContext, VirtualReadRel};
24use crate::parser::{ErrorKind, ExpressionParser, RelationParsePair, Rule, unwrap_single_pair};
25
26pub const PLAN_HEADER: &str = "=== Plan";
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31pub struct IndentedLine<'a>(pub usize, pub &'a str);
32
33impl<'a> From<&'a str> for IndentedLine<'a> {
34 fn from(line: &'a str) -> Self {
35 let line = line.trim_end();
36 let mut spaces = 0;
37 for c in line.chars() {
38 if c == ' ' {
39 spaces += 1;
40 } else {
41 break;
42 }
43 }
44
45 let indents = spaces / 2;
46
47 let (_, trimmed) = line.split_at(indents * 2);
48
49 IndentedLine(indents, trimmed)
50 }
51}
52
53#[derive(Debug, Clone)]
56pub struct Addendum<'a> {
57 pub pair: Pair<'a, Rule>, pub line_no: i64,
59}
60
61#[derive(Debug, Clone)]
63pub struct RelationNode<'a> {
64 pub pair: Pair<'a, Rule>,
65 pub line_no: i64,
66 pub addenda: Vec<Addendum<'a>>,
67 pub children: Vec<RelationNode<'a>>,
68}
69
70impl<'a> RelationNode<'a> {
71 pub fn context(&self) -> ParseContext {
72 ParseContext {
73 line_no: self.line_no,
74 line: self.pair.as_str().to_string(),
75 }
76 }
77}
78
79#[derive(Debug, Clone)]
85pub enum LineNode<'a> {
86 Relation(RelationNode<'a>),
87 Addendum(Addendum<'a>),
88}
89
90impl<'a> LineNode<'a> {
91 pub fn parse(line: &'a str, line_no: i64) -> Result<Self, ParseError> {
92 let mut pairs: pest::iterators::Pairs<'a, Rule> =
93 <ExpressionParser as pest::Parser<Rule>>::parse(Rule::planNode, line).map_err(|e| {
94 ParseError::Plan(
95 ParseContext {
96 line_no,
97 line: line.to_string(),
98 },
99 MessageParseError::new("planNode", ErrorKind::InvalidValue, Box::new(e)),
100 )
101 })?;
102
103 let outer = pairs.next().unwrap();
104 assert!(pairs.next().is_none()); let inner = unwrap_single_pair(outer);
106
107 Ok(match inner.as_rule() {
108 Rule::adv_extension => LineNode::Addendum(Addendum {
109 pair: inner,
110 line_no,
111 }),
112 _ => LineNode::Relation(RelationNode {
113 pair: inner,
114 line_no,
115 addenda: Vec::new(),
116 children: Vec::new(),
117 }),
118 })
119 }
120
121 pub fn parse_root(line: &'a str, line_no: i64) -> Result<Self, ParseError> {
123 let mut pairs: pest::iterators::Pairs<'a, Rule> = <ExpressionParser as pest::Parser<
124 Rule,
125 >>::parse(
126 Rule::top_level_relation, line
127 )
128 .map_err(|e| {
129 ParseError::Plan(
130 ParseContext::new(line_no, line.to_string()),
131 MessageParseError::new("top_level_relation", ErrorKind::Syntax, Box::new(e)),
132 )
133 })?;
134
135 let outer = pairs.next().unwrap();
136 assert!(pairs.next().is_none());
137
138 let inner = unwrap_single_pair(outer);
141 let pair = if inner.as_rule() == Rule::planNode {
142 unwrap_single_pair(inner)
143 } else {
144 inner };
146
147 if pair.as_rule() == Rule::adv_extension {
150 return Ok(LineNode::Addendum(Addendum { pair, line_no }));
151 }
152
153 Ok(LineNode::Relation(RelationNode {
154 pair,
155 line_no,
156 addenda: Vec::new(),
157 children: Vec::new(),
158 }))
159 }
160}
161
162#[derive(Copy, Clone, Debug)]
163pub enum State {
164 Initial,
166 Extensions,
168 Plan,
170}
171
172impl fmt::Display for State {
173 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174 write!(f, "{self:?}")
175 }
176}
177
178#[derive(Debug, Clone, Default)]
180pub struct TreeBuilder<'a> {
181 current: Option<RelationNode<'a>>,
184 completed: Vec<RelationNode<'a>>,
186}
187
188impl<'a> TreeBuilder<'a> {
189 pub fn get_at_depth(&mut self, depth: usize) -> Option<&mut RelationNode<'a>> {
191 let mut node = self.current.as_mut()?;
192 for _ in 0..depth {
193 node = node.children.last_mut()?;
194 }
195 Some(node)
196 }
197
198 pub fn add_line(&mut self, depth: usize, node: LineNode<'a>) -> Result<(), ParseError> {
199 match node {
200 LineNode::Relation(rel_node) => {
201 if depth == 0 {
202 if let Some(prev) = self.current.take() {
203 self.completed.push(prev);
204 }
205 self.current = Some(rel_node);
206 return Ok(());
207 }
208
209 let parent = match self.get_at_depth(depth - 1) {
210 None => {
211 return Err(ParseError::Plan(
212 rel_node.context(),
213 MessageParseError::invalid(
214 "relation",
215 rel_node.pair.as_span(),
216 format!("No parent found for depth {depth}"),
217 ),
218 ));
219 }
220 Some(parent) => parent,
221 };
222
223 parent.children.push(rel_node);
224 }
225 LineNode::Addendum(addendum) => {
226 let context =
227 ParseContext::new(addendum.line_no, addendum.pair.as_str().to_string());
228 if depth == 0 {
229 return Err(ParseError::ValidationError(
230 context,
231 "addenda (+ Enh: / + Opt:) cannot appear at the top level".to_string(),
232 ));
233 }
234
235 let parent = match self.get_at_depth(depth - 1) {
236 None => {
237 return Err(ParseError::ValidationError(
238 context,
239 format!("no parent found for addendum at depth {depth}"),
240 ));
241 }
242 Some(parent) => parent,
243 };
244
245 if !parent.children.is_empty() {
246 return Err(ParseError::ValidationError(
247 context,
248 "addenda (+ Enh: / + Opt:) must appear before child relations, \
249 not after"
250 .to_string(),
251 ));
252 }
253
254 parent.addenda.push(addendum);
255 }
256 }
257 Ok(())
258 }
259
260 pub fn finish(&mut self) -> Vec<RelationNode<'a>> {
265 if let Some(node) = self.current.take() {
266 self.completed.push(node);
267 }
268 std::mem::take(&mut self.completed)
269 }
270}
271
272struct RelationContext<'a> {
276 pair: Pair<'a, Rule>,
277 line_no: i64,
278 #[allow(clippy::vec_box)]
279 children: Vec<Box<Rel>>,
280 input_field_count: usize,
281 advanced_extension: Option<AdvancedExtension>,
282}
283
284#[derive(Debug, Clone, Default)]
286pub struct RelationParser<'a> {
287 tree: TreeBuilder<'a>,
288}
289
290impl<'a> RelationParser<'a> {
291 pub fn parse_line(&mut self, line: IndentedLine<'a>, line_no: i64) -> Result<(), ParseError> {
292 let IndentedLine(depth, line) = line;
293
294 let node = if depth == 0 {
296 LineNode::parse_root(line, line_no)?
297 } else {
298 LineNode::parse(line, line_no)?
299 };
300
301 self.tree.add_line(depth, node)
302 }
303
304 fn parse_relation(
309 &self,
310 extensions: &SimpleExtensions,
311 registry: &ExtensionRegistry,
312 ctx: RelationContext,
313 ) -> Result<(Rel, usize), ParseError> {
314 match ctx.pair.as_rule() {
315 Rule::virtual_read_relation => self.parse_rel::<VirtualReadRel>(extensions, ctx),
316 Rule::read_relation => self.parse_rel::<ReadRel>(extensions, ctx),
317 Rule::filter_relation => self.parse_rel::<FilterRel>(extensions, ctx),
318 Rule::project_relation => self.parse_rel::<ProjectRel>(extensions, ctx),
319 Rule::aggregate_relation => self.parse_rel::<AggregateRel>(extensions, ctx),
320 Rule::sort_relation => self.parse_rel::<SortRel>(extensions, ctx),
321 Rule::fetch_relation => self.parse_rel::<FetchRel>(extensions, ctx),
322 Rule::join_relation => self.parse_rel::<JoinRel>(extensions, ctx),
323 Rule::extension_relation => self.parse_extension_relation(extensions, registry, ctx),
324 _ => unreachable!("unhandled relation rule: {:?}", ctx.pair.as_rule()),
325 }
326 }
327
328 fn parse_rel<T: RelationParsePair>(
333 &self,
334 extensions: &SimpleExtensions,
335 ctx: RelationContext,
336 ) -> Result<(Rel, usize), ParseError> {
337 assert_eq!(ctx.pair.as_rule(), T::rule());
338 let line_no = ctx.line_no;
339 let line = ctx.pair.as_str();
340
341 match T::parse_pair_with_context(extensions, ctx.pair, ctx.children, ctx.input_field_count)
342 {
343 Ok((parsed, count)) => Ok((parsed.into_rel(ctx.advanced_extension), count)),
344 Err(e) => Err(ParseError::Plan(
345 ParseContext::new(line_no, line.to_string()),
346 e,
347 )),
348 }
349 }
350
351 fn parse_extension_relation(
355 &self,
356 extensions: &SimpleExtensions,
357 registry: &ExtensionRegistry,
358 ctx: RelationContext,
359 ) -> Result<(Rel, usize), ParseError> {
360 assert_eq!(ctx.pair.as_rule(), Rule::extension_relation);
361 let line_no = ctx.line_no;
362 let line = ctx.pair.as_str().to_string();
363 let pair_span = ctx.pair.as_span();
364
365 let ExtensionInvocation {
366 relation_kind,
367 name,
368 args: extension_args,
369 } = ExtensionInvocation::parse_pair(extensions, ctx.pair.clone())
370 .map_err(|e| ParseError::Plan(ParseContext::new(line_no, line.clone()), e))?;
371
372 let child_count = ctx.children.len();
373 relation_kind
374 .validate_child_count(child_count)
375 .map_err(|e| {
376 ParseError::Plan(
377 ParseContext::new(line_no, line.to_string()),
378 MessageParseError::invalid("extension_relation", pair_span, e),
379 )
380 })?;
381
382 let context = RelationParsingContext {
383 extensions,
384 registry,
385 line_no,
386 line: &line,
387 };
388
389 let detail = context.resolve_extension_detail(&name, &extension_args)?;
390 let output_column_count = extension_args.output_columns.len();
391
392 let children = ctx.children.into_iter().map(|child| *child).collect();
393 let rel = relation_kind.create_rel(detail, children);
394
395 if ctx.advanced_extension.is_some() {
396 return Err(ParseError::ValidationError(
397 ParseContext::new(line_no, line.to_string()),
398 "extension relations do not support advanced extensions (+ Enh / + Opt)"
399 .to_string(),
400 ));
401 }
402 Ok((rel, output_column_count))
403 }
404
405 fn build_rel(
410 &self,
411 extensions: &SimpleExtensions,
412 registry: &ExtensionRegistry,
413 node: RelationNode,
414 ) -> Result<(Rel, usize), ParseError> {
415 let mut children: Vec<Box<Rel>> = Vec::new();
416 let mut input_field_count: usize = 0;
417 for child in node.children {
418 let (rel, count) = self.build_rel(extensions, registry, child)?;
419 input_field_count += count;
420 children.push(Box::new(rel));
421 }
422
423 let advanced_extension = if node.addenda.is_empty() {
424 None
425 } else {
426 Some(self.build_advanced_extension(extensions, registry, node.addenda)?)
427 };
428
429 self.parse_relation(
430 extensions,
431 registry,
432 RelationContext {
433 pair: node.pair,
434 line_no: node.line_no,
435 children,
436 input_field_count,
437 advanced_extension,
438 },
439 )
440 }
441
442 fn build_advanced_extension(
444 &self,
445 extensions: &SimpleExtensions,
446 registry: &ExtensionRegistry,
447 addenda: Vec<Addendum>,
448 ) -> Result<AdvancedExtension, ParseError> {
449 let mut enhancement = None;
450 let mut optimizations = Vec::new();
451
452 for addendum in addenda {
453 let line_no = addendum.line_no;
454 let line = addendum.pair.as_str().to_string();
455 let invocation = AddendumInvocation::parse_pair(extensions, addendum.pair)
456 .map_err(|e| ParseError::Plan(ParseContext::new(line_no, line.clone()), e))?;
457 let context = RelationParsingContext {
458 extensions,
459 registry,
460 line_no,
461 line: &line,
462 };
463
464 match invocation.kind {
465 AddendumKind::Enhancement => {
466 let detail = context.resolve_adv_ext_detail(
467 AddendumKind::Enhancement,
468 &invocation.name,
469 &invocation.args,
470 )?;
471 if enhancement.is_some() {
472 return Err(ParseError::ValidationError(
473 ParseContext::new(line_no, line.clone()),
474 "at most one enhancement per relation is allowed".to_string(),
475 ));
476 }
477 enhancement = Some(detail.into());
478 }
479 AddendumKind::Optimization => {
480 let detail = context.resolve_adv_ext_detail(
481 AddendumKind::Optimization,
482 &invocation.name,
483 &invocation.args,
484 )?;
485 optimizations.push(detail.into());
486 }
487 }
488 }
489
490 Ok(AdvancedExtension {
491 enhancement,
492 optimization: optimizations,
493 })
494 }
495
496 fn build_plan_rel(
498 &self,
499 extensions: &SimpleExtensions,
500 registry: &ExtensionRegistry,
501 node: RelationNode,
502 ) -> Result<PlanRel, ParseError> {
503 if node.pair.as_rule() != Rule::root_relation {
505 let (rel, _) = self.build_rel(extensions, registry, node)?;
506 return Ok(PlanRel {
507 rel_type: Some(plan_rel::RelType::Rel(rel)),
508 });
509 }
510
511 if !node.addenda.is_empty() {
513 let first = &node.addenda[0];
514 let context = ParseContext::new(first.line_no, first.pair.as_str().to_string());
515 return Err(ParseError::ValidationError(
516 context,
517 "addenda (+ Enh: / + Opt:) are not supported on Root relations".to_string(),
518 ));
519 }
520
521 let context = node.context();
523 let span = node.pair.as_span();
524
525 let column_names_pair = unwrap_single_pair(node.pair);
527 assert_eq!(column_names_pair.as_rule(), Rule::root_name_list);
528
529 let names: Vec<String> = column_names_pair
530 .into_inner()
531 .map(|name_pair| {
532 assert_eq!(name_pair.as_rule(), Rule::name);
533 Name::parse_pair(name_pair).0
534 })
535 .collect();
536
537 let mut children = node.children;
538 let child = match children.len() {
539 1 => {
540 let (rel, _) = self.build_rel(extensions, registry, children.pop().unwrap())?;
541 rel
542 }
543 n => {
544 return Err(ParseError::Plan(
545 context,
546 MessageParseError::invalid(
547 "root_relation",
548 span,
549 format!("Root relation must have exactly one child, found {n}"),
550 ),
551 ));
552 }
553 };
554
555 Ok(PlanRel {
556 rel_type: Some(plan_rel::RelType::Root(RelRoot {
557 names,
558 input: Some(child),
559 })),
560 })
561 }
562
563 fn build(
565 mut self,
566 extensions: &SimpleExtensions,
567 registry: &ExtensionRegistry,
568 ) -> Result<Vec<PlanRel>, ParseError> {
569 let nodes = self.tree.finish();
570 nodes
571 .into_iter()
572 .map(|n| self.build_plan_rel(extensions, registry, n))
573 .collect::<Result<Vec<PlanRel>, ParseError>>()
574 }
575}
576
577#[derive(Debug)]
687pub struct Parser<'a> {
688 line_no: i64,
689 state: State,
690 extension_parser: ExtensionParser,
691 extension_registry: ExtensionRegistry,
692 relation_parser: RelationParser<'a>,
693}
694impl<'a> Default for Parser<'a> {
695 fn default() -> Self {
696 Self::new()
697 }
698}
699
700impl<'a> Parser<'a> {
701 pub fn parse(input: &str) -> ParseResult {
730 Self::new().parse_plan(input)
731 }
732
733 pub fn new() -> Self {
735 Self {
736 line_no: 1,
737 state: State::Initial,
738 extension_parser: ExtensionParser::default(),
739 extension_registry: ExtensionRegistry::new(),
740 relation_parser: RelationParser::default(),
741 }
742 }
743
744 pub fn with_extension_registry(mut self, registry: ExtensionRegistry) -> Self {
746 self.extension_registry = registry;
747 self
748 }
749
750 pub fn parse_plan(mut self, input: &'a str) -> ParseResult {
752 for line in input.lines() {
753 if line.trim().is_empty() {
754 self.line_no += 1;
755 continue;
756 }
757
758 self.parse_line(line)?;
759 self.line_no += 1;
760 }
761
762 let plan = self.build_plan()?;
763 Ok(plan)
764 }
765
766 fn parse_line(&mut self, line: &'a str) -> Result<(), ParseError> {
768 let indented_line = IndentedLine::from(line);
769 let line_no = self.line_no;
770 let ctx = || ParseContext {
771 line_no,
772 line: line.to_string(),
773 };
774
775 match self.state {
776 State::Initial => self.parse_initial(indented_line),
777 State::Extensions => self
778 .parse_extensions(indented_line)
779 .map_err(|e| ParseError::Extension(ctx(), e)),
780 State::Plan => {
781 let IndentedLine(depth, line_str) = indented_line;
782
783 let node = if depth == 0 {
785 LineNode::parse_root(line_str, line_no)?
786 } else {
787 LineNode::parse(line_str, line_no)?
788 };
789
790 self.relation_parser.tree.add_line(depth, node)
791 }
792 }
793 }
794
795 fn parse_initial(&mut self, line: IndentedLine) -> Result<(), ParseError> {
798 match line {
799 IndentedLine(0, l) if l.trim().is_empty() => {}
800 IndentedLine(0, simple::EXTENSIONS_HEADER) => {
801 self.state = State::Extensions;
802 }
803 IndentedLine(0, PLAN_HEADER) => {
804 self.state = State::Plan;
805 }
806 IndentedLine(n, l) => {
807 return Err(ParseError::Initial(
808 ParseContext::new(n as i64, l.to_string()),
809 MessageParseError::invalid(
810 "initial",
811 pest::Span::new(l, 0, l.len()).expect("Invalid span?!"),
812 format!("Unknown initial line: {l:?}"),
813 ),
814 ));
815 }
816 }
817 Ok(())
818 }
819
820 fn parse_extensions(&mut self, line: IndentedLine<'_>) -> Result<(), ExtensionParseError> {
823 if line == IndentedLine(0, PLAN_HEADER) {
824 self.state = State::Plan;
825 return Ok(());
826 }
827 self.extension_parser.parse_line(line)
828 }
829
830 fn build_plan(self) -> Result<Plan, ParseError> {
832 let Parser {
833 relation_parser,
834 extension_parser,
835 extension_registry,
836 ..
837 } = self;
838
839 let extensions = extension_parser.extensions();
840
841 let root_relations = relation_parser.build(extensions, &extension_registry)?;
843
844 Ok(Plan {
846 extension_urns: extensions.to_extension_urns(),
847 extensions: extensions.to_extension_declarations(),
848 relations: root_relations,
849 ..Default::default()
850 })
851 }
852}
853
854#[cfg(test)]
855mod tests {
856 use substrait::proto::extensions::simple_extension_declaration::MappingType;
857 use substrait::proto::rel::RelType;
858
859 use super::*;
860 use crate::extensions::simple::ExtensionKind;
861 use crate::parser::extensions::ExtensionParserState;
862
863 #[test]
864 fn test_parse_basic_block() {
865 let mut expected_extensions = SimpleExtensions::new();
866 expected_extensions
867 .add_extension_urn("/urn/common".to_string(), 1)
868 .unwrap();
869 expected_extensions
870 .add_extension_urn("/urn/specific_funcs".to_string(), 2)
871 .unwrap();
872 expected_extensions
873 .add_extension(ExtensionKind::Function, 1, 10, "func_a".to_string())
874 .unwrap();
875 expected_extensions
876 .add_extension(ExtensionKind::Function, 2, 11, "func_b_special".to_string())
877 .unwrap();
878 expected_extensions
879 .add_extension(ExtensionKind::Type, 1, 20, "SomeType".to_string())
880 .unwrap();
881 expected_extensions
882 .add_extension(ExtensionKind::TypeVariation, 2, 30, "VarX".to_string())
883 .unwrap();
884
885 let mut parser = ExtensionParser::default();
886 let input_block = r#"
887URNs:
888 @ 1: /urn/common
889 @ 2: /urn/specific_funcs
890Functions:
891 # 10 @ 1: func_a
892 # 11 @ 2: func_b_special
893Types:
894 # 20 @ 1: SomeType
895Type Variations:
896 # 30 @ 2: VarX
897"#;
898
899 for line_str in input_block.trim().lines() {
900 parser
901 .parse_line(IndentedLine::from(line_str))
902 .unwrap_or_else(|e| panic!("Failed to parse line \'{line_str}\': {e:?}"));
903 }
904
905 assert_eq!(*parser.extensions(), expected_extensions);
906
907 let extensions_str = parser.extensions().to_string(" ");
908 let expected_str = format!(
911 "{}\n{}",
912 simple::EXTENSIONS_HEADER,
913 input_block.trim_start()
914 );
915 assert_eq!(extensions_str.trim(), expected_str.trim());
916 assert_eq!(
919 parser.state(),
920 ExtensionParserState::ExtensionDeclarations(ExtensionKind::TypeVariation)
921 );
922
923 parser.parse_line(IndentedLine(0, "")).unwrap();
925 assert_eq!(parser.state(), ExtensionParserState::Extensions);
926 }
927
928 #[test]
930 fn test_parse_complete_extension_block() {
931 let mut parser = ExtensionParser::default();
932 let input_block = r#"
933URNs:
934 @ 1: /urn/common
935 @ 2: /urn/specific_funcs
936 @ 3: /urn/types_lib
937 @ 4: /urn/variations_lib
938Functions:
939 # 10 @ 1: func_a
940 # 11 @ 2: func_b_special
941 # 12 @ 1: func_c_common
942Types:
943 # 20 @ 1: CommonType
944 # 21 @ 3: LibraryType
945 # 22 @ 1: AnotherCommonType
946Type Variations:
947 # 30 @ 4: VarX
948 # 31 @ 4: VarY
949"#;
950
951 for line_str in input_block.trim().lines() {
952 parser
953 .parse_line(IndentedLine::from(line_str))
954 .unwrap_or_else(|e| panic!("Failed to parse line \'{line_str}\': {e:?}"));
955 }
956
957 let extensions_str = parser.extensions().to_string(" ");
958 let expected_str = format!(
961 "{}\n{}",
962 simple::EXTENSIONS_HEADER,
963 input_block.trim_start()
964 );
965 assert_eq!(extensions_str.trim(), expected_str.trim());
966 }
967
968 #[test]
969 fn test_parse_relation_tree() {
970 let plan = r#"=== Plan
972Project[$0, $1, 42, 84]
973 Filter[$2 => $0, $1]
974 Read[my.table => a:i32, b:string?, c:boolean]
975"#;
976 let mut parser = Parser::default();
977 for line in plan.lines() {
978 parser.parse_line(line).unwrap();
979 }
980
981 let plan = parser.build_plan().unwrap();
983
984 let root_rel = &plan.relations[0].rel_type;
985 let first_rel = match root_rel {
986 Some(plan_rel::RelType::Rel(rel)) => rel,
987 _ => panic!("Expected Rel type, got {root_rel:?}"),
988 };
989 let project = match &first_rel.rel_type {
991 Some(RelType::Project(p)) => p,
992 other => panic!("Expected Project at root, got {other:?}"),
993 };
994
995 assert!(project.input.is_some());
997 let filter_input = project.input.as_ref().unwrap();
998
999 match &filter_input.rel_type {
1001 Some(RelType::Filter(_)) => {
1002 match &filter_input.rel_type {
1003 Some(RelType::Filter(filter)) => {
1004 assert!(filter.input.is_some());
1005 let read_input = filter.input.as_ref().unwrap();
1006
1007 match &read_input.rel_type {
1009 Some(RelType::Read(_)) => {}
1010 other => panic!("Expected Read relation, got {other:?}"),
1011 }
1012 }
1013 other => panic!("Expected Filter relation, got {other:?}"),
1014 }
1015 }
1016 other => panic!("Expected Filter relation, got {other:?}"),
1017 }
1018 }
1019
1020 #[test]
1021 fn test_parse_root_relation() {
1022 let plan = r#"=== Plan
1024Root[result]
1025 Project[$0, $1]
1026 Read[my.table => a:i32, b:string?]
1027"#;
1028 let mut parser = Parser::default();
1029 for line in plan.lines() {
1030 parser.parse_line(line).unwrap();
1031 }
1032
1033 let plan = parser.build_plan().unwrap();
1034
1035 assert_eq!(plan.relations.len(), 1);
1037
1038 let root_rel = &plan.relations[0].rel_type;
1039 let rel_root = match root_rel {
1040 Some(plan_rel::RelType::Root(rel_root)) => rel_root,
1041 other => panic!("Expected Root type, got {other:?}"),
1042 };
1043
1044 assert_eq!(rel_root.names, vec!["result"]);
1046
1047 let project_input = match &rel_root.input {
1049 Some(rel) => rel,
1050 None => panic!("Root should have an input"),
1051 };
1052
1053 let project = match &project_input.rel_type {
1054 Some(RelType::Project(p)) => p,
1055 other => panic!("Expected Project as root input, got {other:?}"),
1056 };
1057
1058 let read_input = match &project.input {
1060 Some(rel) => rel,
1061 None => panic!("Project should have an input"),
1062 };
1063
1064 match &read_input.rel_type {
1065 Some(RelType::Read(_)) => {}
1066 other => panic!("Expected Read relation, got {other:?}"),
1067 }
1068 }
1069
1070 #[test]
1071 fn test_parse_root_relation_no_names() {
1072 let plan = r#"=== Plan
1074Root[]
1075 Project[$0, $1]
1076 Read[my.table => a:i32, b:string?]
1077"#;
1078 let mut parser = Parser::default();
1079 for line in plan.lines() {
1080 parser.parse_line(line).unwrap();
1081 }
1082
1083 let plan = parser.build_plan().unwrap();
1084
1085 let root_rel = &plan.relations[0].rel_type;
1086 let rel_root = match root_rel {
1087 Some(plan_rel::RelType::Root(rel_root)) => rel_root,
1088 other => panic!("Expected Root type, got {other:?}"),
1089 };
1090
1091 assert_eq!(rel_root.names, Vec::<String>::new());
1093 }
1094
1095 #[test]
1096 fn test_parse_full_plan() {
1097 let input = r#"
1099=== Extensions
1100URNs:
1101 @ 1: /urn/common
1102 @ 2: /urn/specific_funcs
1103Functions:
1104 # 10 @ 1: func_a
1105 # 11 @ 2: func_b_special
1106Types:
1107 # 20 @ 1: SomeType
1108Type Variations:
1109 # 30 @ 2: VarX
1110
1111=== Plan
1112Project[$0, $1, 42, 84]
1113 Filter[$2 => $0, $1]
1114 Read[my.table => a:i32, b:string?, c:boolean]
1115"#;
1116
1117 let plan = Parser::parse(input).unwrap();
1118
1119 assert_eq!(plan.extension_urns.len(), 2);
1121 assert_eq!(plan.extensions.len(), 4);
1122 assert_eq!(plan.relations.len(), 1);
1123
1124 let urn1 = &plan.extension_urns[0];
1126 assert_eq!(urn1.extension_urn_anchor, 1);
1127 assert_eq!(urn1.urn, "/urn/common");
1128
1129 let urn2 = &plan.extension_urns[1];
1130 assert_eq!(urn2.extension_urn_anchor, 2);
1131 assert_eq!(urn2.urn, "/urn/specific_funcs");
1132
1133 let func1 = &plan.extensions[0];
1135 match &func1.mapping_type {
1136 Some(MappingType::ExtensionFunction(f)) => {
1137 assert_eq!(f.function_anchor, 10);
1138 assert_eq!(f.extension_urn_reference, 1);
1139 assert_eq!(f.name, "func_a");
1140 }
1141 other => panic!("Expected ExtensionFunction, got {other:?}"),
1142 }
1143
1144 let func2 = &plan.extensions[1];
1145 match &func2.mapping_type {
1146 Some(MappingType::ExtensionFunction(f)) => {
1147 assert_eq!(f.function_anchor, 11);
1148 assert_eq!(f.extension_urn_reference, 2);
1149 assert_eq!(f.name, "func_b_special");
1150 }
1151 other => panic!("Expected ExtensionFunction, got {other:?}"),
1152 }
1153
1154 let type1 = &plan.extensions[2];
1155 match &type1.mapping_type {
1156 Some(MappingType::ExtensionType(t)) => {
1157 assert_eq!(t.type_anchor, 20);
1158 assert_eq!(t.extension_urn_reference, 1);
1159 assert_eq!(t.name, "SomeType");
1160 }
1161 other => panic!("Expected ExtensionType, got {other:?}"),
1162 }
1163
1164 let var1 = &plan.extensions[3];
1165 match &var1.mapping_type {
1166 Some(MappingType::ExtensionTypeVariation(v)) => {
1167 assert_eq!(v.type_variation_anchor, 30);
1168 assert_eq!(v.extension_urn_reference, 2);
1169 assert_eq!(v.name, "VarX");
1170 }
1171 other => panic!("Expected ExtensionTypeVariation, got {other:?}"),
1172 }
1173
1174 let root_rel = &plan.relations[0];
1176 match &root_rel.rel_type {
1177 Some(plan_rel::RelType::Rel(rel)) => {
1178 match &rel.rel_type {
1179 Some(RelType::Project(project)) => {
1180 assert_eq!(project.expressions.len(), 2); assert!(project.input.is_some()); let filter_input = project.input.as_ref().unwrap();
1186 match &filter_input.rel_type {
1187 Some(RelType::Filter(filter)) => {
1188 assert!(filter.input.is_some()); let read_input = filter.input.as_ref().unwrap();
1192 match &read_input.rel_type {
1193 Some(RelType::Read(read)) => {
1194 let schema = read.base_schema.as_ref().unwrap();
1196 assert_eq!(schema.names.len(), 3);
1197 assert_eq!(schema.names[0], "a");
1198 assert_eq!(schema.names[1], "b");
1199 assert_eq!(schema.names[2], "c");
1200
1201 let struct_ = schema.r#struct.as_ref().unwrap();
1202 assert_eq!(struct_.types.len(), 3);
1203 }
1204 other => panic!("Expected Read relation, got {other:?}"),
1205 }
1206 }
1207 other => panic!("Expected Filter relation, got {other:?}"),
1208 }
1209 }
1210 other => panic!("Expected Project relation, got {other:?}"),
1211 }
1212 }
1213 other => panic!("Expected Rel type, got {other:?}"),
1214 }
1215 }
1216}