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::any::Any;
17use crate::extensions::{AddendumKind, ExtensionRegistry, SimpleExtensions, simple};
18use crate::parser::chunks::ChunkCursor;
19use crate::parser::common::{MessageParseError, ParsePair, ScopedParsePair};
20use crate::parser::errors::{ParseContext, ParseError, ParseResult};
21use crate::parser::expressions::Name;
22use crate::parser::extensions::{
23 AddendumInvocation, ExtensionInvocation, ExtensionParseError, ExtensionParser,
24};
25use crate::parser::relations::{ExtensionReadRel, RelationParsingContext, VirtualReadRel};
26use crate::parser::{ErrorKind, ExpressionParser, RelationParsePair, Rule, unwrap_single_pair};
27
28pub const PLAN_HEADER: &str = "=== Plan";
29
30#[derive(Debug, Clone, Copy, PartialEq, Eq)]
33pub struct IndentedLine<'a>(pub usize, pub &'a str);
34
35impl<'a> From<&'a str> for IndentedLine<'a> {
36 fn from(line: &'a str) -> Self {
37 let line = line.trim_end();
38 let mut spaces = 0;
39 for c in line.chars() {
40 if c == ' ' {
41 spaces += 1;
42 } else {
43 break;
44 }
45 }
46
47 let indents = spaces / 2;
48
49 let (_, trimmed) = line.split_at(indents * 2);
50
51 IndentedLine(indents, trimmed)
52 }
53}
54
55#[derive(Debug, Clone)]
58pub struct Addendum<'a> {
59 pub pair: Pair<'a, Rule>, pub line_no: i64,
61}
62
63#[derive(Debug, Clone)]
65pub struct RelationNode<'a> {
66 pub pair: Pair<'a, Rule>,
67 pub line_no: i64,
68 pub addenda: Vec<Addendum<'a>>,
69 pub children: Vec<RelationNode<'a>>,
70}
71
72impl<'a> RelationNode<'a> {
73 pub fn context(&self) -> ParseContext {
74 ParseContext {
75 line_no: self.line_no,
76 line: self.pair.as_str().to_string(),
77 }
78 }
79}
80
81#[derive(Debug, Clone)]
87pub enum LineNode<'a> {
88 Relation(RelationNode<'a>),
89 Addendum(Addendum<'a>),
90}
91
92impl<'a> LineNode<'a> {
93 pub fn parse(line: &'a str, line_no: i64) -> Result<Self, ParseError> {
94 let mut pairs: pest::iterators::Pairs<'a, Rule> =
95 <ExpressionParser as pest::Parser<Rule>>::parse(Rule::planNode, line).map_err(|e| {
96 ParseError::Plan(
97 ParseContext {
98 line_no,
99 line: line.to_string(),
100 },
101 MessageParseError::new("planNode", ErrorKind::InvalidValue, Box::new(e)),
102 )
103 })?;
104
105 let outer = pairs.next().unwrap();
106 assert!(pairs.next().is_none()); let inner = unwrap_single_pair(outer);
108
109 Ok(match inner.as_rule() {
110 Rule::addendum => LineNode::Addendum(Addendum {
111 pair: inner,
112 line_no,
113 }),
114 _ => LineNode::Relation(RelationNode {
115 pair: inner,
116 line_no,
117 addenda: Vec::new(),
118 children: Vec::new(),
119 }),
120 })
121 }
122
123 pub fn parse_root(line: &'a str, line_no: i64) -> Result<Self, ParseError> {
125 let mut pairs: pest::iterators::Pairs<'a, Rule> = <ExpressionParser as pest::Parser<
126 Rule,
127 >>::parse(
128 Rule::top_level_relation, line
129 )
130 .map_err(|e| {
131 ParseError::Plan(
132 ParseContext::new(line_no, line.to_string()),
133 MessageParseError::new("top_level_relation", ErrorKind::Syntax, Box::new(e)),
134 )
135 })?;
136
137 let outer = pairs.next().unwrap();
138 assert!(pairs.next().is_none());
139
140 let inner = unwrap_single_pair(outer);
143 let pair = if inner.as_rule() == Rule::planNode {
144 unwrap_single_pair(inner)
145 } else {
146 inner };
148
149 if pair.as_rule() == Rule::addendum {
152 return Ok(LineNode::Addendum(Addendum { pair, line_no }));
153 }
154
155 Ok(LineNode::Relation(RelationNode {
156 pair,
157 line_no,
158 addenda: Vec::new(),
159 children: Vec::new(),
160 }))
161 }
162}
163
164#[derive(Copy, Clone, Debug)]
165pub enum State {
166 Initial,
168 Extensions,
170 Plan,
172}
173
174impl fmt::Display for State {
175 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
176 write!(f, "{self:?}")
177 }
178}
179
180#[derive(Debug, Clone, Default)]
182pub struct TreeBuilder<'a> {
183 current: Option<RelationNode<'a>>,
186 completed: Vec<RelationNode<'a>>,
188}
189
190impl<'a> TreeBuilder<'a> {
191 pub fn get_at_depth(&mut self, depth: usize) -> Option<&mut RelationNode<'a>> {
193 let mut node = self.current.as_mut()?;
194 for _ in 0..depth {
195 node = node.children.last_mut()?;
196 }
197 Some(node)
198 }
199
200 pub fn add_line(&mut self, depth: usize, node: LineNode<'a>) -> Result<(), ParseError> {
201 match node {
202 LineNode::Relation(rel_node) => {
203 if depth == 0 {
204 if let Some(prev) = self.current.take() {
205 self.completed.push(prev);
206 }
207 self.current = Some(rel_node);
208 return Ok(());
209 }
210
211 let parent = match self.get_at_depth(depth - 1) {
212 None => {
213 return Err(ParseError::Plan(
214 rel_node.context(),
215 MessageParseError::invalid(
216 "relation",
217 rel_node.pair.as_span(),
218 format!("No parent found for depth {depth}"),
219 ),
220 ));
221 }
222 Some(parent) => parent,
223 };
224
225 parent.children.push(rel_node);
226 }
227 LineNode::Addendum(addendum) => {
228 let context =
229 ParseContext::new(addendum.line_no, addendum.pair.as_str().to_string());
230 if depth == 0 {
231 return Err(ParseError::ValidationError(
232 context,
233 "addenda (+ Enh: / + Opt: / + Ext:) cannot appear at the top level"
234 .to_string(),
235 ));
236 }
237
238 let parent = match self.get_at_depth(depth - 1) {
239 None => {
240 return Err(ParseError::ValidationError(
241 context,
242 format!("no parent found for addendum at depth {depth}"),
243 ));
244 }
245 Some(parent) => parent,
246 };
247
248 if !parent.children.is_empty() {
249 return Err(ParseError::ValidationError(
250 context,
251 "addenda (+ Enh: / + Opt: / + Ext:) must appear before child relations, \
252 not after"
253 .to_string(),
254 ));
255 }
256
257 parent.addenda.push(addendum);
258 }
259 }
260 Ok(())
261 }
262
263 pub fn finish(&mut self) -> Vec<RelationNode<'a>> {
268 if let Some(node) = self.current.take() {
269 self.completed.push(node);
270 }
271 std::mem::take(&mut self.completed)
272 }
273}
274
275struct RelationContext<'a> {
279 pair: Pair<'a, Rule>,
280 line_no: i64,
281 children: Vec<Rel>,
282 input_field_count: usize,
283 addenda: Addenda<'a>,
284}
285
286#[derive(Debug, Clone)]
288struct ParsedAddendum<'a> {
289 line_no: i64,
290 line: &'a str,
291 invocation: AddendumInvocation,
292}
293
294impl<'a> ParsedAddendum<'a> {
295 fn parse(extensions: &SimpleExtensions, addendum: Addendum<'a>) -> Result<Self, ParseError> {
296 let line_no = addendum.line_no;
297 let line = addendum.pair.as_str();
298 let invocation = AddendumInvocation::parse_pair(extensions, addendum.pair)
299 .map_err(|e| ParseError::Plan(ParseContext::new(line_no, line.to_string()), e))?;
300 Ok(Self {
301 line_no,
302 line,
303 invocation,
304 })
305 }
306
307 fn context(&self) -> ParseContext {
308 ParseContext::new(self.line_no, self.line.to_string())
309 }
310
311 fn relation_context<'b>(
312 &'b self,
313 registry: &'b ExtensionRegistry,
314 ) -> RelationParsingContext<'b> {
315 RelationParsingContext {
316 registry,
317 line_no: self.line_no,
318 line: self.line,
319 }
320 }
321 fn resolve_detail(&self, registry: &ExtensionRegistry) -> Result<Any, ParseError> {
322 self.relation_context(registry).resolve_addendum_detail(
323 self.invocation.kind,
324 &self.invocation.name,
325 &self.invocation.args,
326 )
327 }
328}
329
330#[derive(Debug, Clone, Default)]
332struct Addenda<'a> {
333 items: Vec<ParsedAddendum<'a>>,
334}
335
336impl<'a> Addenda<'a> {
337 fn parse(
338 extensions: &SimpleExtensions,
339 addenda: Vec<Addendum<'a>>,
340 ) -> Result<Self, ParseError> {
341 let items = addenda
342 .into_iter()
343 .map(|addendum| ParsedAddendum::parse(extensions, addendum))
344 .collect::<Result<Vec<_>, ParseError>>()?;
345 Ok(Self { items })
346 }
347
348 fn first(&self) -> Option<&ParsedAddendum<'a>> {
349 self.items.first()
350 }
351
352 fn reject_all(&self, message: &'static str) -> Result<(), ParseError> {
353 if let Some(addendum) = self.first() {
354 return Err(ParseError::ValidationError(
355 addendum.context(),
356 message.to_string(),
357 ));
358 }
359 Ok(())
360 }
361
362 fn into_standard_advanced_extension(
363 self,
364 registry: &ExtensionRegistry,
365 ) -> Result<Option<AdvancedExtension>, ParseError> {
366 let mut enhancement = None;
367 let mut optimizations = Vec::new();
368
369 for addendum in self.items {
370 match addendum.invocation.kind {
371 AddendumKind::Enhancement => {
372 if enhancement.is_some() {
373 return Err(ParseError::ValidationError(
374 addendum.context(),
375 "at most one enhancement per relation is allowed".to_string(),
376 ));
377 }
378 enhancement = Some(addendum.resolve_detail(registry)?.into());
379 }
380 AddendumKind::Optimization => {
381 optimizations.push(addendum.resolve_detail(registry)?.into());
382 }
383 AddendumKind::ExtensionTable => {
384 return Err(ParseError::ValidationError(
385 addendum.context(),
386 "+ Ext addenda can only be used with Read:Extension".to_string(),
387 ));
388 }
389 }
390 }
391
392 if enhancement.is_none() && optimizations.is_empty() {
393 return Ok(None);
394 }
395
396 Ok(Some(AdvancedExtension {
397 enhancement,
398 optimization: optimizations,
399 }))
400 }
401
402 fn into_extension_read_parts(
403 self,
404 registry: &ExtensionRegistry,
405 relation_context: ParseContext,
406 ) -> Result<(Any, Option<AdvancedExtension>), ParseError> {
407 let mut extension_table = None;
408 let mut advanced_addenda = Vec::new();
409
410 for addendum in self.items {
411 match addendum.invocation.kind {
412 AddendumKind::ExtensionTable => {
413 if extension_table.is_some() {
414 return Err(ParseError::ValidationError(
415 addendum.context(),
416 "Read:Extension allows exactly one + Ext addendum".to_string(),
417 ));
418 }
419 extension_table = Some(addendum);
420 }
421 AddendumKind::Enhancement | AddendumKind::Optimization => {
422 advanced_addenda.push(addendum);
423 }
424 }
425 }
426
427 let extension_table = extension_table.ok_or_else(|| {
428 ParseError::ValidationError(
429 relation_context,
430 "Read:Extension requires exactly one + Ext addendum".to_string(),
431 )
432 })?;
433
434 let detail = extension_table.resolve_detail(registry)?;
435 let advanced_extension = Addenda {
436 items: advanced_addenda,
437 }
438 .into_standard_advanced_extension(registry)?;
439
440 Ok((detail, advanced_extension))
441 }
442}
443
444#[derive(Debug, Clone, Default)]
446pub struct RelationParser<'a> {
447 tree: TreeBuilder<'a>,
448}
449
450impl<'a> RelationParser<'a> {
451 fn parse_relation(
456 &self,
457 extensions: &SimpleExtensions,
458 registry: &ExtensionRegistry,
459 ctx: RelationContext,
460 ) -> Result<(Rel, usize), ParseError> {
461 match ctx.pair.as_rule() {
462 Rule::extension_read_relation => {
463 self.parse_extension_read_relation(extensions, registry, ctx)
464 }
465 Rule::virtual_read_relation => {
466 self.parse_rel::<VirtualReadRel>(extensions, registry, ctx)
467 }
468 Rule::read_relation => self.parse_rel::<ReadRel>(extensions, registry, ctx),
469 Rule::filter_relation => self.parse_rel::<FilterRel>(extensions, registry, ctx),
470 Rule::project_relation => self.parse_rel::<ProjectRel>(extensions, registry, ctx),
471 Rule::aggregate_relation => self.parse_rel::<AggregateRel>(extensions, registry, ctx),
472 Rule::sort_relation => self.parse_rel::<SortRel>(extensions, registry, ctx),
473 Rule::fetch_relation => self.parse_rel::<FetchRel>(extensions, registry, ctx),
474 Rule::join_relation => self.parse_rel::<JoinRel>(extensions, registry, ctx),
475 Rule::extension_relation => self.parse_extension_relation(extensions, registry, ctx),
476 _ => unreachable!("unhandled relation rule: {:?}", ctx.pair.as_rule()),
477 }
478 }
479
480 fn parse_rel<T: RelationParsePair>(
485 &self,
486 extensions: &SimpleExtensions,
487 registry: &ExtensionRegistry,
488 ctx: RelationContext,
489 ) -> Result<(Rel, usize), ParseError> {
490 let RelationContext {
491 pair,
492 line_no,
493 children,
494 input_field_count,
495 addenda,
496 } = ctx;
497 assert_eq!(pair.as_rule(), T::rule());
498 let line = pair.as_str();
499 let advanced_extension = addenda.into_standard_advanced_extension(registry)?;
500
501 match T::parse_pair_with_context(extensions, pair, children, input_field_count) {
502 Ok((parsed, count)) => Ok((parsed.into_rel(advanced_extension), count)),
503 Err(e) => Err(ParseError::Plan(
504 ParseContext::new(line_no, line.to_string()),
505 e,
506 )),
507 }
508 }
509
510 fn parse_extension_relation(
514 &self,
515 extensions: &SimpleExtensions,
516 registry: &ExtensionRegistry,
517 ctx: RelationContext,
518 ) -> Result<(Rel, usize), ParseError> {
519 assert_eq!(ctx.pair.as_rule(), Rule::extension_relation);
520 let line_no = ctx.line_no;
521 let line = ctx.pair.as_str().to_string();
522 let pair_span = ctx.pair.as_span();
523
524 ctx.addenda
525 .reject_all("extension relations do not support addenda (+ Enh / + Opt / + Ext)")?;
526
527 let ExtensionInvocation {
528 relation_kind,
529 name,
530 args: extension_args,
531 } = ExtensionInvocation::parse_pair(extensions, ctx.pair.clone())
532 .map_err(|e| ParseError::Plan(ParseContext::new(line_no, line.clone()), e))?;
533
534 let child_count = ctx.children.len();
535 relation_kind
536 .validate_child_count(child_count)
537 .map_err(|e| {
538 ParseError::Plan(
539 ParseContext::new(line_no, line.to_string()),
540 MessageParseError::invalid("extension_relation", pair_span, e),
541 )
542 })?;
543
544 let context = RelationParsingContext {
545 registry,
546 line_no,
547 line: &line,
548 };
549
550 let detail = context.resolve_extension_detail(&name, &extension_args)?;
551 let output_column_count = extension_args.output_columns.len();
552
553 let rel = relation_kind.create_rel(detail, ctx.children);
554
555 Ok((rel, output_column_count))
556 }
557
558 fn parse_extension_read_relation(
561 &self,
562 extensions: &SimpleExtensions,
563 registry: &ExtensionRegistry,
564 ctx: RelationContext,
565 ) -> Result<(Rel, usize), ParseError> {
566 assert_eq!(ctx.pair.as_rule(), Rule::extension_read_relation);
567 let context = ParseContext::new(ctx.line_no, ctx.pair.as_str().to_string());
568 let (detail, advanced_extension) = ctx
569 .addenda
570 .into_extension_read_parts(registry, context.clone())?;
571
572 ExtensionReadRel::parse_pair_with_detail(
573 extensions,
574 ctx.pair,
575 ctx.children,
576 ctx.input_field_count,
577 detail,
578 advanced_extension,
579 )
580 .map_err(|e| ParseError::Plan(context, e))
581 }
582
583 fn build_rel(
588 &self,
589 extensions: &SimpleExtensions,
590 registry: &ExtensionRegistry,
591 node: RelationNode,
592 ) -> Result<(Rel, usize), ParseError> {
593 let mut children: Vec<Rel> = Vec::new();
594 let mut input_field_count: usize = 0;
595 for child in node.children {
596 let (rel, count) = self.build_rel(extensions, registry, child)?;
597 input_field_count += count;
598 children.push(rel);
599 }
600
601 let addenda = Addenda::parse(extensions, node.addenda)?;
602
603 self.parse_relation(
604 extensions,
605 registry,
606 RelationContext {
607 pair: node.pair,
608 line_no: node.line_no,
609 children,
610 input_field_count,
611 addenda,
612 },
613 )
614 }
615
616 fn build_plan_rel(
618 &self,
619 extensions: &SimpleExtensions,
620 registry: &ExtensionRegistry,
621 node: RelationNode,
622 ) -> Result<PlanRel, ParseError> {
623 if node.pair.as_rule() != Rule::root_relation {
625 let (rel, _) = self.build_rel(extensions, registry, node)?;
626 return Ok(PlanRel {
627 rel_type: Some(plan_rel::RelType::Rel(rel)),
628 });
629 }
630
631 if !node.addenda.is_empty() {
633 let first = &node.addenda[0];
634 let context = ParseContext::new(first.line_no, first.pair.as_str().to_string());
635 return Err(ParseError::ValidationError(
636 context,
637 "addenda (+ Enh: / + Opt: / + Ext:) are not supported on Root relations"
638 .to_string(),
639 ));
640 }
641
642 let context = node.context();
644 let span = node.pair.as_span();
645
646 let column_names_pair = unwrap_single_pair(node.pair);
648 assert_eq!(column_names_pair.as_rule(), Rule::root_name_list);
649
650 let names: Vec<String> = column_names_pair
651 .into_inner()
652 .map(|name_pair| {
653 assert_eq!(name_pair.as_rule(), Rule::name);
654 Name::parse_pair(name_pair).0
655 })
656 .collect();
657
658 let mut children = node.children;
659 let child = match children.len() {
660 1 => {
661 let (rel, _) = self.build_rel(extensions, registry, children.pop().unwrap())?;
662 rel
663 }
664 n => {
665 return Err(ParseError::Plan(
666 context,
667 MessageParseError::invalid(
668 "root_relation",
669 span,
670 format!("Root relation must have exactly one child, found {n}"),
671 ),
672 ));
673 }
674 };
675
676 Ok(PlanRel {
677 rel_type: Some(plan_rel::RelType::Root(RelRoot {
678 names,
679 input: Some(child),
680 })),
681 })
682 }
683
684 fn build(
686 mut self,
687 extensions: &SimpleExtensions,
688 registry: &ExtensionRegistry,
689 ) -> Result<Vec<PlanRel>, ParseError> {
690 let nodes = self.tree.finish();
691 nodes
692 .into_iter()
693 .map(|n| self.build_plan_rel(extensions, registry, n))
694 .collect::<Result<Vec<PlanRel>, ParseError>>()
695 }
696}
697
698#[derive(Debug)]
808pub struct Parser<'a> {
809 line_no: i64,
810 state: State,
811 cursor: Option<ChunkCursor<'a>>,
815 extension_parser: ExtensionParser,
816 extension_registry: ExtensionRegistry,
817 relation_parser: RelationParser<'a>,
818}
819impl<'a> Default for Parser<'a> {
820 fn default() -> Self {
821 Self::new()
822 }
823}
824
825impl<'a> Parser<'a> {
826 pub fn parse(input: &str) -> ParseResult {
855 Self::new().parse_plan(input)
856 }
857
858 pub fn new() -> Self {
860 Self {
861 line_no: 1,
862 state: State::Initial,
863 cursor: None,
864 extension_parser: ExtensionParser::default(),
865 extension_registry: ExtensionRegistry::new(),
866 relation_parser: RelationParser::default(),
867 }
868 }
869
870 pub fn with_extension_registry(mut self, registry: ExtensionRegistry) -> Self {
872 self.extension_registry = registry;
873 self
874 }
875
876 pub fn parse_plan(mut self, input: &'a str) -> ParseResult {
878 self.cursor = ChunkCursor::new(input, 1);
879 while self.cursor.is_some() {
880 let (chunk, line_no) = self.next_chunk();
881
882 if chunk.trim().is_empty() {
883 continue;
884 }
885
886 self.line_no = line_no;
887 self.parse_line(chunk)?;
896 }
897
898 let plan = self.build_plan()?;
899 Ok(plan)
900 }
901
902 fn next_chunk(&mut self) -> (&'a str, i64) {
908 let mut c = self
909 .cursor
910 .take()
911 .expect("next_chunk called with no cursor");
912
913 let first = c
915 .peek_line()
916 .expect("a non-exhausted cursor always yields a line");
917 c.merge(first);
918
919 if matches!(self.state, State::Plan) {
920 let base = IndentedLine::from(first.as_str()).0;
921 while let Some(line) = c.peek_line() {
922 let IndentedLine(depth, body) = IndentedLine::from(line.as_str());
923 if depth == base + 1 && body.starts_with("- ") {
924 c.merge(line);
925 } else {
926 break;
927 }
928 }
929 }
930
931 let line_no = c.start_line_no();
932 let (chunk, rest) = c.next();
933 self.cursor = rest;
934 (chunk.trim_end_matches(['\r', '\n']), line_no)
935 }
936
937 fn parse_line(&mut self, line: &'a str) -> Result<(), ParseError> {
939 let indented_line = IndentedLine::from(line);
940 let line_no = self.line_no;
941 let ctx = || ParseContext {
942 line_no,
943 line: line.to_string(),
944 };
945
946 match self.state {
947 State::Initial => self.parse_initial(indented_line),
948 State::Extensions => self
949 .parse_extensions(indented_line)
950 .map_err(|e| ParseError::Extension(ctx(), e)),
951 State::Plan => {
952 let IndentedLine(depth, line_str) = indented_line;
953
954 let node = if depth == 0 {
956 LineNode::parse_root(line_str, line_no)?
957 } else {
958 LineNode::parse(line_str, line_no)?
959 };
960
961 self.relation_parser.tree.add_line(depth, node)
962 }
963 }
964 }
965
966 fn parse_initial(&mut self, line: IndentedLine) -> Result<(), ParseError> {
969 match line {
970 IndentedLine(0, l) if l.trim().is_empty() => {}
971 IndentedLine(0, simple::EXTENSIONS_HEADER) => {
972 self.state = State::Extensions;
973 }
974 IndentedLine(0, PLAN_HEADER) => {
975 self.state = State::Plan;
976 }
977 IndentedLine(n, l) => {
978 return Err(ParseError::Initial(
979 ParseContext::new(n as i64, l.to_string()),
980 MessageParseError::invalid(
981 "initial",
982 pest::Span::new(l, 0, l.len()).expect("Invalid span?!"),
983 format!("Unknown initial line: {l:?}"),
984 ),
985 ));
986 }
987 }
988 Ok(())
989 }
990
991 fn parse_extensions(&mut self, line: IndentedLine<'_>) -> Result<(), ExtensionParseError> {
994 if line == IndentedLine(0, PLAN_HEADER) {
995 self.state = State::Plan;
996 return Ok(());
997 }
998 self.extension_parser.parse_line(line)
999 }
1000
1001 fn build_plan(self) -> Result<Plan, ParseError> {
1003 let Parser {
1004 relation_parser,
1005 extension_parser,
1006 extension_registry,
1007 ..
1008 } = self;
1009
1010 let extensions = extension_parser.extensions();
1011
1012 let root_relations = relation_parser.build(extensions, &extension_registry)?;
1014
1015 Ok(Plan {
1017 extension_urns: extensions.to_extension_urns(),
1018 extensions: extensions.to_extension_declarations(),
1019 relations: root_relations,
1020 ..Default::default()
1021 })
1022 }
1023}
1024
1025#[cfg(test)]
1026mod tests {
1027 use substrait::proto::extensions::simple_extension_declaration::MappingType;
1028 use substrait::proto::rel::RelType;
1029
1030 use super::*;
1031 use crate::extensions::simple::ExtensionKind;
1032 use crate::parser::extensions::ExpectedExtensionLine;
1033
1034 #[test]
1035 fn test_parse_basic_block() {
1036 let mut expected_extensions = SimpleExtensions::new();
1037 expected_extensions
1038 .add_extension_urn("/urn/common".to_string(), 1)
1039 .unwrap();
1040 expected_extensions
1041 .add_extension_urn("/urn/specific_funcs".to_string(), 2)
1042 .unwrap();
1043 expected_extensions
1044 .add_extension(ExtensionKind::Function, 1, 10, "func_a".to_string())
1045 .unwrap();
1046 expected_extensions
1047 .add_extension(ExtensionKind::Function, 2, 11, "func_b_special".to_string())
1048 .unwrap();
1049 expected_extensions
1050 .add_extension(ExtensionKind::Type, 1, 20, "SomeType".to_string())
1051 .unwrap();
1052 expected_extensions
1053 .add_extension(ExtensionKind::TypeVariation, 2, 30, "VarX".to_string())
1054 .unwrap();
1055
1056 let mut parser = ExtensionParser::default();
1057 let input_block = r#"
1058URNs:
1059 @ 1: /urn/common
1060 @ 2: /urn/specific_funcs
1061Functions:
1062 # 10 @ 1: func_a
1063 # 11 @ 2: func_b_special
1064Types:
1065 # 20 @ 1: SomeType
1066Type Variations:
1067 # 30 @ 2: VarX
1068"#;
1069
1070 for line_str in input_block.trim().lines() {
1071 parser
1072 .parse_line(IndentedLine::from(line_str))
1073 .unwrap_or_else(|e| panic!("Failed to parse line \'{line_str}\': {e:?}"));
1074 }
1075
1076 assert_eq!(*parser.extensions(), expected_extensions);
1077
1078 let extensions_str = parser.extensions().to_string(" ");
1079 let expected_str = format!(
1082 "{}\n{}",
1083 simple::EXTENSIONS_HEADER,
1084 input_block.trim_start()
1085 );
1086 assert_eq!(extensions_str.trim(), expected_str.trim());
1087 assert_eq!(
1090 parser.state(),
1091 ExpectedExtensionLine::ExtensionDeclarations(ExtensionKind::TypeVariation)
1092 );
1093
1094 parser.parse_line(IndentedLine(0, "")).unwrap();
1096 assert_eq!(parser.state(), ExpectedExtensionLine::Extensions);
1097 }
1098
1099 #[test]
1101 fn test_parse_complete_extension_block() {
1102 let mut parser = ExtensionParser::default();
1103 let input_block = r#"
1104URNs:
1105 @ 1: /urn/common
1106 @ 2: /urn/specific_funcs
1107 @ 3: /urn/types_lib
1108 @ 4: /urn/variations_lib
1109Functions:
1110 # 10 @ 1: func_a
1111 # 11 @ 2: func_b_special
1112 # 12 @ 1: func_c_common
1113Types:
1114 # 20 @ 1: CommonType
1115 # 21 @ 3: LibraryType
1116 # 22 @ 1: AnotherCommonType
1117Type Variations:
1118 # 30 @ 4: VarX
1119 # 31 @ 4: VarY
1120"#;
1121
1122 for line_str in input_block.trim().lines() {
1123 parser
1124 .parse_line(IndentedLine::from(line_str))
1125 .unwrap_or_else(|e| panic!("Failed to parse line \'{line_str}\': {e:?}"));
1126 }
1127
1128 let extensions_str = parser.extensions().to_string(" ");
1129 let expected_str = format!(
1132 "{}\n{}",
1133 simple::EXTENSIONS_HEADER,
1134 input_block.trim_start()
1135 );
1136 assert_eq!(extensions_str.trim(), expected_str.trim());
1137 }
1138
1139 #[test]
1140 fn test_parse_relation_tree() {
1141 let plan = r#"=== Plan
1143Project[$0, $1, 42, 84]
1144 Filter[$2 => $0, $1]
1145 Read[my.table => a:i32, b:string?, c:boolean]
1146"#;
1147 let mut parser = Parser::default();
1148 for line in plan.lines() {
1149 parser.parse_line(line).unwrap();
1150 }
1151
1152 let plan = parser.build_plan().unwrap();
1154
1155 let root_rel = &plan.relations[0].rel_type;
1156 let first_rel = match root_rel {
1157 Some(plan_rel::RelType::Rel(rel)) => rel,
1158 _ => panic!("Expected Rel type, got {root_rel:?}"),
1159 };
1160 let project = match &first_rel.rel_type {
1162 Some(RelType::Project(p)) => p,
1163 other => panic!("Expected Project at root, got {other:?}"),
1164 };
1165
1166 assert!(project.input.is_some());
1168 let filter_input = project.input.as_ref().unwrap();
1169
1170 match &filter_input.rel_type {
1172 Some(RelType::Filter(_)) => {
1173 match &filter_input.rel_type {
1174 Some(RelType::Filter(filter)) => {
1175 assert!(filter.input.is_some());
1176 let read_input = filter.input.as_ref().unwrap();
1177
1178 match &read_input.rel_type {
1180 Some(RelType::Read(_)) => {}
1181 other => panic!("Expected Read relation, got {other:?}"),
1182 }
1183 }
1184 other => panic!("Expected Filter relation, got {other:?}"),
1185 }
1186 }
1187 other => panic!("Expected Filter relation, got {other:?}"),
1188 }
1189 }
1190
1191 #[test]
1192 fn test_parse_root_relation() {
1193 let plan = r#"=== Plan
1195Root[result]
1196 Project[$0, $1]
1197 Read[my.table => a:i32, b:string?]
1198"#;
1199 let mut parser = Parser::default();
1200 for line in plan.lines() {
1201 parser.parse_line(line).unwrap();
1202 }
1203
1204 let plan = parser.build_plan().unwrap();
1205
1206 assert_eq!(plan.relations.len(), 1);
1208
1209 let root_rel = &plan.relations[0].rel_type;
1210 let rel_root = match root_rel {
1211 Some(plan_rel::RelType::Root(rel_root)) => rel_root,
1212 other => panic!("Expected Root type, got {other:?}"),
1213 };
1214
1215 assert_eq!(rel_root.names, vec!["result"]);
1217
1218 let project_input = match &rel_root.input {
1220 Some(rel) => rel,
1221 None => panic!("Root should have an input"),
1222 };
1223
1224 let project = match &project_input.rel_type {
1225 Some(RelType::Project(p)) => p,
1226 other => panic!("Expected Project as root input, got {other:?}"),
1227 };
1228
1229 let read_input = match &project.input {
1231 Some(rel) => rel,
1232 None => panic!("Project should have an input"),
1233 };
1234
1235 match &read_input.rel_type {
1236 Some(RelType::Read(_)) => {}
1237 other => panic!("Expected Read relation, got {other:?}"),
1238 }
1239 }
1240
1241 #[test]
1242 fn test_parse_root_relation_no_names() {
1243 let plan = r#"=== Plan
1245Root[]
1246 Project[$0, $1]
1247 Read[my.table => a:i32, b:string?]
1248"#;
1249 let mut parser = Parser::default();
1250 for line in plan.lines() {
1251 parser.parse_line(line).unwrap();
1252 }
1253
1254 let plan = parser.build_plan().unwrap();
1255
1256 let root_rel = &plan.relations[0].rel_type;
1257 let rel_root = match root_rel {
1258 Some(plan_rel::RelType::Root(rel_root)) => rel_root,
1259 other => panic!("Expected Root type, got {other:?}"),
1260 };
1261
1262 assert_eq!(rel_root.names, Vec::<String>::new());
1264 }
1265
1266 #[test]
1267 fn test_parse_full_plan() {
1268 let input = r#"
1270=== Extensions
1271URNs:
1272 @ 1: /urn/common
1273 @ 2: /urn/specific_funcs
1274Functions:
1275 # 10 @ 1: func_a
1276 # 11 @ 2: func_b_special
1277Types:
1278 # 20 @ 1: SomeType
1279Type Variations:
1280 # 30 @ 2: VarX
1281
1282=== Plan
1283Project[$0, $1, 42, 84]
1284 Filter[$2 => $0, $1]
1285 Read[my.table => a:i32, b:string?, c:boolean]
1286"#;
1287
1288 let plan = Parser::parse(input).unwrap();
1289
1290 assert_eq!(plan.extension_urns.len(), 2);
1292 assert_eq!(plan.extensions.len(), 4);
1293 assert_eq!(plan.relations.len(), 1);
1294
1295 let urn1 = &plan.extension_urns[0];
1297 assert_eq!(urn1.extension_urn_anchor, 1);
1298 assert_eq!(urn1.urn, "/urn/common");
1299
1300 let urn2 = &plan.extension_urns[1];
1301 assert_eq!(urn2.extension_urn_anchor, 2);
1302 assert_eq!(urn2.urn, "/urn/specific_funcs");
1303
1304 let func1 = &plan.extensions[0];
1306 match &func1.mapping_type {
1307 Some(MappingType::ExtensionFunction(f)) => {
1308 assert_eq!(f.function_anchor, 10);
1309 assert_eq!(f.extension_urn_reference, 1);
1310 assert_eq!(f.name, "func_a");
1311 }
1312 other => panic!("Expected ExtensionFunction, got {other:?}"),
1313 }
1314
1315 let func2 = &plan.extensions[1];
1316 match &func2.mapping_type {
1317 Some(MappingType::ExtensionFunction(f)) => {
1318 assert_eq!(f.function_anchor, 11);
1319 assert_eq!(f.extension_urn_reference, 2);
1320 assert_eq!(f.name, "func_b_special");
1321 }
1322 other => panic!("Expected ExtensionFunction, got {other:?}"),
1323 }
1324
1325 let type1 = &plan.extensions[2];
1326 match &type1.mapping_type {
1327 Some(MappingType::ExtensionType(t)) => {
1328 assert_eq!(t.type_anchor, 20);
1329 assert_eq!(t.extension_urn_reference, 1);
1330 assert_eq!(t.name, "SomeType");
1331 }
1332 other => panic!("Expected ExtensionType, got {other:?}"),
1333 }
1334
1335 let var1 = &plan.extensions[3];
1336 match &var1.mapping_type {
1337 Some(MappingType::ExtensionTypeVariation(v)) => {
1338 assert_eq!(v.type_variation_anchor, 30);
1339 assert_eq!(v.extension_urn_reference, 2);
1340 assert_eq!(v.name, "VarX");
1341 }
1342 other => panic!("Expected ExtensionTypeVariation, got {other:?}"),
1343 }
1344
1345 let root_rel = &plan.relations[0];
1347 match &root_rel.rel_type {
1348 Some(plan_rel::RelType::Rel(rel)) => {
1349 match &rel.rel_type {
1350 Some(RelType::Project(project)) => {
1351 assert_eq!(project.expressions.len(), 2); assert!(project.input.is_some()); let filter_input = project.input.as_ref().unwrap();
1357 match &filter_input.rel_type {
1358 Some(RelType::Filter(filter)) => {
1359 assert!(filter.input.is_some()); let read_input = filter.input.as_ref().unwrap();
1363 match &read_input.rel_type {
1364 Some(RelType::Read(read)) => {
1365 let schema = read.base_schema.as_ref().unwrap();
1367 assert_eq!(schema.names.len(), 3);
1368 assert_eq!(schema.names[0], "a");
1369 assert_eq!(schema.names[1], "b");
1370 assert_eq!(schema.names[2], "c");
1371
1372 let struct_ = schema.r#struct.as_ref().unwrap();
1373 assert_eq!(struct_.types.len(), 3);
1374 }
1375 other => panic!("Expected Read relation, got {other:?}"),
1376 }
1377 }
1378 other => panic!("Expected Filter relation, got {other:?}"),
1379 }
1380 }
1381 other => panic!("Expected Project relation, got {other:?}"),
1382 }
1383 }
1384 other => panic!("Expected Rel type, got {other:?}"),
1385 }
1386 }
1387}