1use std::fmt;
8
9use substrait::proto::rel::RelType;
10use substrait::proto::{
11 AggregateRel, FetchRel, FilterRel, JoinRel, Plan, PlanRel, ProjectRel, ReadRel, Rel, RelRoot,
12 SortRel, plan_rel,
13};
14
15use crate::extensions::{ExtensionRegistry, SimpleExtensions, simple};
16use crate::parser::common::{MessageParseError, ParsePair};
17use crate::parser::errors::{ParseContext, ParseError, ParseResult};
18use crate::parser::expressions::Name;
19use crate::parser::extensions::{ExtensionInvocation, ExtensionParseError, ExtensionParser};
20use crate::parser::relations::RelationParsingContext;
21use crate::parser::{ErrorKind, ExpressionParser, RelationParsePair, Rule, unwrap_single_pair};
22
23pub const PLAN_HEADER: &str = "=== Plan";
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub struct IndentedLine<'a>(pub usize, pub &'a str);
29
30impl<'a> From<&'a str> for IndentedLine<'a> {
31 fn from(line: &'a str) -> Self {
32 let line = line.trim_end();
33 let mut spaces = 0;
34 for c in line.chars() {
35 if c == ' ' {
36 spaces += 1;
37 } else {
38 break;
39 }
40 }
41
42 let indents = spaces / 2;
43
44 let (_, trimmed) = line.split_at(indents * 2);
45
46 IndentedLine(indents, trimmed)
47 }
48}
49
50#[derive(Debug, Clone)]
54pub struct LineNode<'a> {
55 pub pair: pest::iterators::Pair<'a, Rule>,
56 pub line_no: i64,
57 pub children: Vec<LineNode<'a>>,
58}
59
60impl<'a> LineNode<'a> {
61 pub fn context(&self) -> ParseContext {
62 ParseContext {
63 line_no: self.line_no,
64 line: self.pair.as_str().to_string(),
65 }
66 }
67
68 pub fn parse(line: &'a str, line_no: i64) -> Result<Self, ParseError> {
69 let mut pairs: pest::iterators::Pairs<'a, Rule> =
71 <ExpressionParser as pest::Parser<Rule>>::parse(Rule::relation, line).map_err(|e| {
72 ParseError::Plan(
73 ParseContext {
74 line_no,
75 line: line.to_string(),
76 },
77 MessageParseError::new("relation", ErrorKind::InvalidValue, Box::new(e)),
78 )
79 })?;
80
81 let pair = pairs.next().unwrap();
82 assert!(pairs.next().is_none()); Ok(Self {
85 pair,
86 line_no,
87 children: Vec::new(),
88 })
89 }
90
91 pub fn parse_root(line: &'a str, line_no: i64) -> Result<Self, ParseError> {
93 let mut pairs: pest::iterators::Pairs<'a, Rule> = <ExpressionParser as pest::Parser<
95 Rule,
96 >>::parse(
97 Rule::top_level_relation, line
98 )
99 .map_err(|e| {
100 ParseError::Plan(
101 ParseContext::new(line_no, line.to_string()),
102 MessageParseError::new("top_level_relation", ErrorKind::Syntax, Box::new(e)),
103 )
104 })?;
105
106 let pair = pairs.next().unwrap();
107 assert!(pairs.next().is_none());
108
109 let inner_pair = unwrap_single_pair(pair);
111
112 Ok(Self {
113 pair: inner_pair,
114 line_no,
115 children: Vec::new(),
116 })
117 }
118}
119
120fn get_input_field_count(rel: &Rel) -> usize {
123 match &rel.rel_type {
124 Some(RelType::Read(read_rel)) => {
125 read_rel
127 .base_schema
128 .as_ref()
129 .and_then(|schema| schema.r#struct.as_ref())
130 .map(|struct_| struct_.types.len())
131 .unwrap_or(0)
132 }
133 Some(RelType::Filter(filter_rel)) => {
134 filter_rel
136 .input
137 .as_ref()
138 .map(|input| get_input_field_count(input))
139 .unwrap_or(0)
140 }
141 Some(RelType::Project(project_rel)) => {
142 project_rel
144 .input
145 .as_ref()
146 .map(|input| get_input_field_count(input))
147 .unwrap_or(0)
148 }
149 _ => 0,
150 }
151}
152
153#[derive(Copy, Clone, Debug)]
154pub enum State {
155 Initial,
157 Extensions,
159 Plan,
161}
162
163impl fmt::Display for State {
164 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
165 write!(f, "{self:?}")
166 }
167}
168
169#[derive(Debug, Clone, Default)]
171pub struct TreeBuilder<'a> {
172 current: Option<LineNode<'a>>,
175 completed: Vec<LineNode<'a>>,
177}
178
179impl<'a> TreeBuilder<'a> {
180 pub fn get_at_depth(&mut self, depth: usize) -> Option<&mut LineNode<'a>> {
182 let mut node = self.current.as_mut()?;
183 for _ in 0..depth {
184 node = node.children.last_mut()?;
185 }
186 Some(node)
187 }
188
189 pub fn add_line(&mut self, depth: usize, node: LineNode<'a>) -> Result<(), ParseError> {
190 if depth == 0 {
191 if let Some(prev) = self.current.take() {
192 self.completed.push(prev)
193 }
194 self.current = Some(node);
195 return Ok(());
196 }
197
198 let parent = match self.get_at_depth(depth - 1) {
199 None => {
200 return Err(ParseError::Plan(
201 node.context(),
202 MessageParseError::invalid(
203 "relation",
204 node.pair.as_span(),
205 format!("No parent found for depth {depth}"),
206 ),
207 ));
208 }
209 Some(parent) => parent,
210 };
211
212 parent.children.push(node.clone());
213 Ok(())
214 }
215
216 pub fn finish(&mut self) -> Vec<LineNode<'a>> {
220 if let Some(node) = self.current.take() {
222 self.completed.push(node);
223 }
224 std::mem::take(&mut self.completed)
225 }
226}
227
228#[derive(Debug, Clone, Default)]
230pub struct RelationParser<'a> {
231 tree: TreeBuilder<'a>,
232}
233
234impl<'a> RelationParser<'a> {
235 pub fn parse_line(&mut self, line: IndentedLine<'a>, line_no: i64) -> Result<(), ParseError> {
236 let IndentedLine(depth, line) = line;
237
238 let node = if depth == 0 {
240 LineNode::parse_root(line, line_no)?
241 } else {
242 LineNode::parse(line, line_no)?
243 };
244
245 self.tree.add_line(depth, node)
246 }
247
248 #[allow(clippy::vec_box)]
254 fn parse_relation(
255 &self,
256 extensions: &SimpleExtensions,
257 registry: &ExtensionRegistry,
258 line_no: i64,
259 pair: pest::iterators::Pair<Rule>,
260 child_relations: Vec<Box<substrait::proto::Rel>>,
261 input_field_count: usize,
262 ) -> Result<substrait::proto::Rel, ParseError> {
263 assert_eq!(pair.as_rule(), Rule::relation);
264 let p = unwrap_single_pair(pair);
265
266 let (e, r, l, p_inner, cr, ic) = (
267 extensions,
268 registry,
269 line_no,
270 p,
271 child_relations,
272 input_field_count,
273 );
274
275 match p_inner.as_rule() {
276 Rule::read_relation => self.parse_rel::<ReadRel>(e, l, p_inner, cr, ic),
277 Rule::filter_relation => self.parse_rel::<FilterRel>(e, l, p_inner, cr, ic),
278 Rule::project_relation => self.parse_rel::<ProjectRel>(e, l, p_inner, cr, ic),
279 Rule::aggregate_relation => self.parse_rel::<AggregateRel>(e, l, p_inner, cr, ic),
280 Rule::sort_relation => self.parse_rel::<SortRel>(e, l, p_inner, cr, ic),
281 Rule::fetch_relation => self.parse_rel::<FetchRel>(e, l, p_inner, cr, ic),
282 Rule::join_relation => self.parse_rel::<JoinRel>(e, l, p_inner, cr, ic),
283 Rule::extension_relation => self.parse_extension_relation(e, r, l, p_inner, cr),
284 _ => todo!(),
285 }
286 }
287
288 #[allow(clippy::vec_box)]
292 fn parse_rel<T: RelationParsePair>(
293 &self,
294 extensions: &SimpleExtensions,
295 line_no: i64,
296 pair: pest::iterators::Pair<Rule>,
297 child_relations: Vec<Box<substrait::proto::Rel>>,
298 input_field_count: usize,
299 ) -> Result<substrait::proto::Rel, ParseError> {
300 assert_eq!(pair.as_rule(), T::rule());
301
302 let line = pair.as_str();
303
304 let rel_type =
305 T::parse_pair_with_context(extensions, pair, child_relations, input_field_count);
306
307 match rel_type {
308 Ok(rel) => Ok(rel.into_rel()),
309 Err(e) => Err(ParseError::Plan(
310 ParseContext::new(line_no, line.to_string()),
311 e,
312 )),
313 }
314 }
315
316 #[allow(clippy::vec_box)]
321 fn parse_extension_relation(
322 &self,
323 extensions: &SimpleExtensions,
324 registry: &ExtensionRegistry,
325 line_no: i64,
326 pair: pest::iterators::Pair<Rule>,
327 child_relations: Vec<Box<substrait::proto::Rel>>,
328 ) -> Result<substrait::proto::Rel, ParseError> {
329 assert_eq!(pair.as_rule(), Rule::extension_relation);
330
331 let line = pair.as_str();
332 let pair_span = pair.as_span();
333
334 let ExtensionInvocation {
336 name,
337 args: extension_args,
338 } = ExtensionInvocation::parse_pair(pair);
339
340 let child_count = child_relations.len();
342 extension_args
343 .relation_type
344 .validate_child_count(child_count)
345 .map_err(|e| {
346 ParseError::Plan(
347 ParseContext::new(line_no, line.to_string()),
348 MessageParseError::invalid("extension_relation", pair_span, e),
349 )
350 })?;
351
352 let context = RelationParsingContext {
353 extensions,
354 registry,
355 line_no,
356 line,
357 };
358
359 let detail = context.resolve_extension_detail(&name, &extension_args)?;
360
361 extension_args
362 .relation_type
363 .create_rel(detail, child_relations)
364 .map_err(|e| {
365 ParseError::Plan(
366 ParseContext::new(line_no, line.to_string()),
367 MessageParseError::invalid("extension_relation", pair_span, e),
368 )
369 })
370 }
371
372 fn build_rel(
374 &self,
375 extensions: &SimpleExtensions,
376 registry: &ExtensionRegistry,
377 node: LineNode,
378 ) -> Result<substrait::proto::Rel, ParseError> {
379 let child_relations = node
381 .children
382 .into_iter()
383 .map(|c| self.build_rel(extensions, registry, c).map(Box::new))
384 .collect::<Result<Vec<Box<Rel>>, ParseError>>()?;
385
386 let input_field_count = child_relations
388 .iter()
389 .map(|r| get_input_field_count(r.as_ref()))
390 .reduce(|a, b| a + b)
391 .unwrap_or(0);
392
393 self.parse_relation(
395 extensions,
396 registry,
397 node.line_no,
398 node.pair,
399 child_relations,
400 input_field_count,
401 )
402 }
403
404 fn build_plan_rel(
406 &self,
407 extensions: &SimpleExtensions,
408 registry: &ExtensionRegistry,
409 mut node: LineNode,
410 ) -> Result<PlanRel, ParseError> {
411 if node.pair.as_rule() == Rule::relation {
413 let rel = self.build_rel(extensions, registry, node)?;
414 return Ok(PlanRel {
415 rel_type: Some(plan_rel::RelType::Rel(rel)),
416 });
417 }
418
419 assert_eq!(node.pair.as_rule(), Rule::root_relation);
421 let context = node.context();
422 let span = node.pair.as_span();
423
424 let column_names_pair = unwrap_single_pair(node.pair);
426 assert_eq!(column_names_pair.as_rule(), Rule::root_name_list);
427
428 let names: Vec<String> = column_names_pair
429 .into_inner()
430 .map(|name_pair| {
431 assert_eq!(name_pair.as_rule(), Rule::name);
432 Name::parse_pair(name_pair).0
433 })
434 .collect();
435
436 let child = match node.children.len() {
437 1 => self.build_rel(extensions, registry, node.children.pop().unwrap())?,
438 n => {
439 return Err(ParseError::Plan(
440 context,
441 MessageParseError::invalid(
442 "root_relation",
443 span,
444 format!("Root relation must have exactly one child, found {n}"),
445 ),
446 ));
447 }
448 };
449
450 let rel_root = RelRoot {
451 names,
452 input: Some(child),
453 };
454
455 Ok(PlanRel {
456 rel_type: Some(plan_rel::RelType::Root(rel_root)),
457 })
458 }
459
460 fn build(
462 mut self,
463 extensions: &SimpleExtensions,
464 registry: &ExtensionRegistry,
465 ) -> Result<Vec<PlanRel>, ParseError> {
466 let nodes = self.tree.finish();
467 nodes
468 .into_iter()
469 .map(|n| self.build_plan_rel(extensions, registry, n))
470 .collect::<Result<Vec<PlanRel>, ParseError>>()
471 }
472}
473
474#[derive(Debug)]
584pub struct Parser<'a> {
585 line_no: i64,
586 state: State,
587 extension_parser: ExtensionParser,
588 extension_registry: ExtensionRegistry,
589 relation_parser: RelationParser<'a>,
590}
591impl<'a> Default for Parser<'a> {
592 fn default() -> Self {
593 Self::new()
594 }
595}
596
597impl<'a> Parser<'a> {
598 pub fn parse(input: &str) -> ParseResult {
627 Self::new().parse_plan(input)
628 }
629
630 pub fn new() -> Self {
632 Self {
633 line_no: 1,
634 state: State::Initial,
635 extension_parser: ExtensionParser::default(),
636 extension_registry: ExtensionRegistry::new(),
637 relation_parser: RelationParser::default(),
638 }
639 }
640
641 pub fn with_extension_registry(mut self, registry: ExtensionRegistry) -> Self {
643 self.extension_registry = registry;
644 self
645 }
646
647 pub fn parse_plan(mut self, input: &'a str) -> ParseResult {
649 for line in input.lines() {
650 if line.trim().is_empty() {
651 self.line_no += 1;
652 continue;
653 }
654
655 self.parse_line(line)?;
656 self.line_no += 1;
657 }
658
659 let plan = self.build_plan()?;
660 Ok(plan)
661 }
662
663 fn parse_line(&mut self, line: &'a str) -> Result<(), ParseError> {
665 let indented_line = IndentedLine::from(line);
666 let line_no = self.line_no;
667 let ctx = || ParseContext {
668 line_no,
669 line: line.to_string(),
670 };
671
672 match self.state {
673 State::Initial => self.parse_initial(indented_line),
674 State::Extensions => self
675 .parse_extensions(indented_line)
676 .map_err(|e| ParseError::Extension(ctx(), e)),
677 State::Plan => {
678 let IndentedLine(depth, line_str) = indented_line;
679
680 let node = if depth == 0 {
682 LineNode::parse_root(line_str, line_no)?
683 } else {
684 LineNode::parse(line_str, line_no)?
685 };
686
687 self.relation_parser.tree.add_line(depth, node)
688 }
689 }
690 }
691
692 fn parse_initial(&mut self, line: IndentedLine) -> Result<(), ParseError> {
695 match line {
696 IndentedLine(0, l) if l.trim().is_empty() => {}
697 IndentedLine(0, simple::EXTENSIONS_HEADER) => {
698 self.state = State::Extensions;
699 }
700 IndentedLine(0, PLAN_HEADER) => {
701 self.state = State::Plan;
702 }
703 IndentedLine(n, l) => {
704 return Err(ParseError::Initial(
705 ParseContext::new(n as i64, l.to_string()),
706 MessageParseError::invalid(
707 "initial",
708 pest::Span::new(l, 0, l.len()).expect("Invalid span?!"),
709 format!("Unknown initial line: {l:?}"),
710 ),
711 ));
712 }
713 }
714 Ok(())
715 }
716
717 fn parse_extensions(&mut self, line: IndentedLine<'_>) -> Result<(), ExtensionParseError> {
720 if line == IndentedLine(0, PLAN_HEADER) {
721 self.state = State::Plan;
722 return Ok(());
723 }
724 self.extension_parser.parse_line(line)
725 }
726
727 fn build_plan(self) -> Result<Plan, ParseError> {
729 let Parser {
730 relation_parser,
731 extension_parser,
732 extension_registry,
733 ..
734 } = self;
735
736 let extensions = extension_parser.extensions();
737
738 let root_relations = relation_parser.build(extensions, &extension_registry)?;
740
741 Ok(Plan {
743 extension_urns: extensions.to_extension_urns(),
744 extensions: extensions.to_extension_declarations(),
745 relations: root_relations,
746 ..Default::default()
747 })
748 }
749}
750
751#[cfg(test)]
752mod tests {
753 use substrait::proto::extensions::simple_extension_declaration::MappingType;
754
755 use super::*;
756 use crate::extensions::simple::ExtensionKind;
757 use crate::parser::extensions::ExtensionParserState;
758
759 #[test]
760 fn test_parse_basic_block() {
761 let mut expected_extensions = SimpleExtensions::new();
762 expected_extensions
763 .add_extension_urn("/urn/common".to_string(), 1)
764 .unwrap();
765 expected_extensions
766 .add_extension_urn("/urn/specific_funcs".to_string(), 2)
767 .unwrap();
768 expected_extensions
769 .add_extension(ExtensionKind::Function, 1, 10, "func_a".to_string())
770 .unwrap();
771 expected_extensions
772 .add_extension(ExtensionKind::Function, 2, 11, "func_b_special".to_string())
773 .unwrap();
774 expected_extensions
775 .add_extension(ExtensionKind::Type, 1, 20, "SomeType".to_string())
776 .unwrap();
777 expected_extensions
778 .add_extension(ExtensionKind::TypeVariation, 2, 30, "VarX".to_string())
779 .unwrap();
780
781 let mut parser = ExtensionParser::default();
782 let input_block = r#"
783URNs:
784 @ 1: /urn/common
785 @ 2: /urn/specific_funcs
786Functions:
787 # 10 @ 1: func_a
788 # 11 @ 2: func_b_special
789Types:
790 # 20 @ 1: SomeType
791Type Variations:
792 # 30 @ 2: VarX
793"#;
794
795 for line_str in input_block.trim().lines() {
796 parser
797 .parse_line(IndentedLine::from(line_str))
798 .unwrap_or_else(|e| panic!("Failed to parse line \'{line_str}\': {e:?}"));
799 }
800
801 assert_eq!(*parser.extensions(), expected_extensions);
802
803 let extensions_str = parser.extensions().to_string(" ");
804 let expected_str = format!(
807 "{}\n{}",
808 simple::EXTENSIONS_HEADER,
809 input_block.trim_start()
810 );
811 assert_eq!(extensions_str.trim(), expected_str.trim());
812 assert_eq!(
815 parser.state(),
816 ExtensionParserState::ExtensionDeclarations(ExtensionKind::TypeVariation)
817 );
818
819 parser.parse_line(IndentedLine(0, "")).unwrap();
821 assert_eq!(parser.state(), ExtensionParserState::Extensions);
822 }
823
824 #[test]
826 fn test_parse_complete_extension_block() {
827 let mut parser = ExtensionParser::default();
828 let input_block = r#"
829URNs:
830 @ 1: /urn/common
831 @ 2: /urn/specific_funcs
832 @ 3: /urn/types_lib
833 @ 4: /urn/variations_lib
834Functions:
835 # 10 @ 1: func_a
836 # 11 @ 2: func_b_special
837 # 12 @ 1: func_c_common
838Types:
839 # 20 @ 1: CommonType
840 # 21 @ 3: LibraryType
841 # 22 @ 1: AnotherCommonType
842Type Variations:
843 # 30 @ 4: VarX
844 # 31 @ 4: VarY
845"#;
846
847 for line_str in input_block.trim().lines() {
848 parser
849 .parse_line(IndentedLine::from(line_str))
850 .unwrap_or_else(|e| panic!("Failed to parse line \'{line_str}\': {e:?}"));
851 }
852
853 let extensions_str = parser.extensions().to_string(" ");
854 let expected_str = format!(
857 "{}\n{}",
858 simple::EXTENSIONS_HEADER,
859 input_block.trim_start()
860 );
861 assert_eq!(extensions_str.trim(), expected_str.trim());
862 }
863
864 #[test]
865 fn test_parse_relation_tree() {
866 let plan = r#"=== Plan
868Project[$0, $1, 42, 84]
869 Filter[$2 => $0, $1]
870 Read[my.table => a:i32, b:string?, c:boolean]
871"#;
872 let mut parser = Parser::default();
873 for line in plan.lines() {
874 parser.parse_line(line).unwrap();
875 }
876
877 let plan = parser.build_plan().unwrap();
879
880 let root_rel = &plan.relations[0].rel_type;
881 let first_rel = match root_rel {
882 Some(plan_rel::RelType::Rel(rel)) => rel,
883 _ => panic!("Expected Rel type, got {root_rel:?}"),
884 };
885 let project = match &first_rel.rel_type {
887 Some(RelType::Project(p)) => p,
888 other => panic!("Expected Project at root, got {other:?}"),
889 };
890
891 assert!(project.input.is_some());
893 let filter_input = project.input.as_ref().unwrap();
894
895 match &filter_input.rel_type {
897 Some(RelType::Filter(_)) => {
898 match &filter_input.rel_type {
899 Some(RelType::Filter(filter)) => {
900 assert!(filter.input.is_some());
901 let read_input = filter.input.as_ref().unwrap();
902
903 match &read_input.rel_type {
905 Some(RelType::Read(_)) => {}
906 other => panic!("Expected Read relation, got {other:?}"),
907 }
908 }
909 other => panic!("Expected Filter relation, got {other:?}"),
910 }
911 }
912 other => panic!("Expected Filter relation, got {other:?}"),
913 }
914 }
915
916 #[test]
917 fn test_parse_root_relation() {
918 let plan = r#"=== Plan
920Root[result]
921 Project[$0, $1]
922 Read[my.table => a:i32, b:string?]
923"#;
924 let mut parser = Parser::default();
925 for line in plan.lines() {
926 parser.parse_line(line).unwrap();
927 }
928
929 let plan = parser.build_plan().unwrap();
930
931 assert_eq!(plan.relations.len(), 1);
933
934 let root_rel = &plan.relations[0].rel_type;
935 let rel_root = match root_rel {
936 Some(plan_rel::RelType::Root(rel_root)) => rel_root,
937 other => panic!("Expected Root type, got {other:?}"),
938 };
939
940 assert_eq!(rel_root.names, vec!["result"]);
942
943 let project_input = match &rel_root.input {
945 Some(rel) => rel,
946 None => panic!("Root should have an input"),
947 };
948
949 let project = match &project_input.rel_type {
950 Some(RelType::Project(p)) => p,
951 other => panic!("Expected Project as root input, got {other:?}"),
952 };
953
954 let read_input = match &project.input {
956 Some(rel) => rel,
957 None => panic!("Project should have an input"),
958 };
959
960 match &read_input.rel_type {
961 Some(RelType::Read(_)) => {}
962 other => panic!("Expected Read relation, got {other:?}"),
963 }
964 }
965
966 #[test]
967 fn test_parse_root_relation_no_names() {
968 let plan = r#"=== Plan
970Root[]
971 Project[$0, $1]
972 Read[my.table => a:i32, b:string?]
973"#;
974 let mut parser = Parser::default();
975 for line in plan.lines() {
976 parser.parse_line(line).unwrap();
977 }
978
979 let plan = parser.build_plan().unwrap();
980
981 let root_rel = &plan.relations[0].rel_type;
982 let rel_root = match root_rel {
983 Some(plan_rel::RelType::Root(rel_root)) => rel_root,
984 other => panic!("Expected Root type, got {other:?}"),
985 };
986
987 assert_eq!(rel_root.names, Vec::<String>::new());
989 }
990
991 #[test]
992 fn test_parse_full_plan() {
993 let input = r#"
995=== Extensions
996URNs:
997 @ 1: /urn/common
998 @ 2: /urn/specific_funcs
999Functions:
1000 # 10 @ 1: func_a
1001 # 11 @ 2: func_b_special
1002Types:
1003 # 20 @ 1: SomeType
1004Type Variations:
1005 # 30 @ 2: VarX
1006
1007=== Plan
1008Project[$0, $1, 42, 84]
1009 Filter[$2 => $0, $1]
1010 Read[my.table => a:i32, b:string?, c:boolean]
1011"#;
1012
1013 let plan = Parser::parse(input).unwrap();
1014
1015 assert_eq!(plan.extension_urns.len(), 2);
1017 assert_eq!(plan.extensions.len(), 4);
1018 assert_eq!(plan.relations.len(), 1);
1019
1020 let urn1 = &plan.extension_urns[0];
1022 assert_eq!(urn1.extension_urn_anchor, 1);
1023 assert_eq!(urn1.urn, "/urn/common");
1024
1025 let urn2 = &plan.extension_urns[1];
1026 assert_eq!(urn2.extension_urn_anchor, 2);
1027 assert_eq!(urn2.urn, "/urn/specific_funcs");
1028
1029 let func1 = &plan.extensions[0];
1031 match &func1.mapping_type {
1032 Some(MappingType::ExtensionFunction(f)) => {
1033 assert_eq!(f.function_anchor, 10);
1034 assert_eq!(f.extension_urn_reference, 1);
1035 assert_eq!(f.name, "func_a");
1036 }
1037 other => panic!("Expected ExtensionFunction, got {other:?}"),
1038 }
1039
1040 let func2 = &plan.extensions[1];
1041 match &func2.mapping_type {
1042 Some(MappingType::ExtensionFunction(f)) => {
1043 assert_eq!(f.function_anchor, 11);
1044 assert_eq!(f.extension_urn_reference, 2);
1045 assert_eq!(f.name, "func_b_special");
1046 }
1047 other => panic!("Expected ExtensionFunction, got {other:?}"),
1048 }
1049
1050 let type1 = &plan.extensions[2];
1051 match &type1.mapping_type {
1052 Some(MappingType::ExtensionType(t)) => {
1053 assert_eq!(t.type_anchor, 20);
1054 assert_eq!(t.extension_urn_reference, 1);
1055 assert_eq!(t.name, "SomeType");
1056 }
1057 other => panic!("Expected ExtensionType, got {other:?}"),
1058 }
1059
1060 let var1 = &plan.extensions[3];
1061 match &var1.mapping_type {
1062 Some(MappingType::ExtensionTypeVariation(v)) => {
1063 assert_eq!(v.type_variation_anchor, 30);
1064 assert_eq!(v.extension_urn_reference, 2);
1065 assert_eq!(v.name, "VarX");
1066 }
1067 other => panic!("Expected ExtensionTypeVariation, got {other:?}"),
1068 }
1069
1070 let root_rel = &plan.relations[0];
1072 match &root_rel.rel_type {
1073 Some(plan_rel::RelType::Rel(rel)) => {
1074 match &rel.rel_type {
1075 Some(RelType::Project(project)) => {
1076 assert_eq!(project.expressions.len(), 2); assert!(project.input.is_some()); let filter_input = project.input.as_ref().unwrap();
1082 match &filter_input.rel_type {
1083 Some(RelType::Filter(filter)) => {
1084 assert!(filter.input.is_some()); let read_input = filter.input.as_ref().unwrap();
1088 match &read_input.rel_type {
1089 Some(RelType::Read(read)) => {
1090 let schema = read.base_schema.as_ref().unwrap();
1092 assert_eq!(schema.names.len(), 3);
1093 assert_eq!(schema.names[0], "a");
1094 assert_eq!(schema.names[1], "b");
1095 assert_eq!(schema.names[2], "c");
1096
1097 let struct_ = schema.r#struct.as_ref().unwrap();
1098 assert_eq!(struct_.types.len(), 3);
1099 }
1100 other => panic!("Expected Read relation, got {other:?}"),
1101 }
1102 }
1103 other => panic!("Expected Filter relation, got {other:?}"),
1104 }
1105 }
1106 other => panic!("Expected Project relation, got {other:?}"),
1107 }
1108 }
1109 other => panic!("Expected Rel type, got {other:?}"),
1110 }
1111 }
1112}