1use chrono::{DateTime, NaiveDate, NaiveDateTime, NaiveTime};
2use substrait::proto::aggregate_rel::Measure;
3use substrait::proto::expression::field_reference::{ReferenceType, RootReference, RootType};
4use substrait::proto::expression::if_then::IfClause;
5use substrait::proto::expression::literal::LiteralType;
6use substrait::proto::expression::{
7 Cast, FieldReference, IfThen, Literal, ReferenceSegment, RexType, ScalarFunction, cast,
8 reference_segment,
9};
10use substrait::proto::function_argument::ArgType;
11use substrait::proto::r#type::{Fp64, I64, Kind, Nullability};
12use substrait::proto::{AggregateFunction, Expression, FunctionArgument, Type};
13
14use super::types::get_and_validate_anchor;
15use super::{
16 MessageParseError, ParsePair, Rule, RuleIter, ScopedParsePair, unescape_string,
17 unwrap_single_pair,
18};
19use crate::extensions::SimpleExtensions;
20use crate::extensions::simple::{CompoundName, ExtensionKind};
21use crate::parser::ErrorKind;
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
25pub struct FieldIndex(pub i32);
26
27impl FieldIndex {
28 pub fn to_field_reference(self) -> FieldReference {
30 FieldReference {
33 reference_type: Some(ReferenceType::DirectReference(ReferenceSegment {
34 reference_type: Some(reference_segment::ReferenceType::StructField(Box::new(
35 reference_segment::StructField {
36 field: self.0,
37 child: None,
38 },
39 ))),
40 })),
41 root_type: Some(RootType::RootReference(RootReference {})),
42 }
43 }
44}
45
46impl ParsePair for FieldIndex {
47 fn rule() -> Rule {
48 Rule::reference
49 }
50
51 fn message() -> &'static str {
52 "FieldIndex"
53 }
54
55 fn parse_pair(pair: pest::iterators::Pair<Rule>) -> Self {
56 assert_eq!(pair.as_rule(), Self::rule());
57 let inner = unwrap_single_pair(pair);
58 let index: i32 = inner.as_str().parse().unwrap();
59 FieldIndex(index)
60 }
61}
62
63impl ParsePair for FieldReference {
64 fn rule() -> Rule {
65 Rule::reference
66 }
67
68 fn message() -> &'static str {
69 "FieldReference"
70 }
71
72 fn parse_pair(pair: pest::iterators::Pair<Rule>) -> Self {
73 assert_eq!(pair.as_rule(), Self::rule());
74
75 FieldIndex::parse_pair(pair).to_field_reference()
77 }
78}
79
80fn to_int_literal(
81 value: pest::iterators::Pair<Rule>,
82 typ: Option<Type>,
83) -> Result<Literal, MessageParseError> {
84 assert_eq!(value.as_rule(), Rule::integer);
85 let parsed_value: i64 = value.as_str().parse().unwrap();
86
87 const DEFAULT_KIND: Kind = Kind::I64(I64 {
88 type_variation_reference: 0,
89 nullability: Nullability::Required as i32,
90 });
91
92 let kind = typ.and_then(|t| t.kind).unwrap_or(DEFAULT_KIND);
94
95 let (lit, nullability, tvar) = match &kind {
96 Kind::I8(i) => (
98 LiteralType::I8(parsed_value as i32),
99 i.nullability,
100 i.type_variation_reference,
101 ),
102 Kind::I16(i) => (
103 LiteralType::I16(parsed_value as i32),
104 i.nullability,
105 i.type_variation_reference,
106 ),
107 Kind::I32(i) => (
108 LiteralType::I32(parsed_value as i32),
109 i.nullability,
110 i.type_variation_reference,
111 ),
112 Kind::I64(i) => (
113 LiteralType::I64(parsed_value),
114 i.nullability,
115 i.type_variation_reference,
116 ),
117 k => {
118 let pest_error = pest::error::Error::new_from_span(
119 pest::error::ErrorVariant::CustomError {
120 message: format!("Invalid type for integer literal: {k:?}"),
121 },
122 value.as_span(),
123 );
124 let error = MessageParseError {
125 message: "int_literal_type",
126 kind: ErrorKind::InvalidValue,
127 error: Box::new(pest_error),
128 };
129 return Err(error);
130 }
131 };
132
133 Ok(Literal {
134 literal_type: Some(lit),
135 nullable: nullability != Nullability::Required as i32,
136 type_variation_reference: tvar,
137 })
138}
139
140fn to_float_literal(
141 value: pest::iterators::Pair<Rule>,
142 typ: Option<Type>,
143) -> Result<Literal, MessageParseError> {
144 assert_eq!(value.as_rule(), Rule::float);
145 let parsed_value: f64 = value.as_str().parse().unwrap();
146
147 const DEFAULT_KIND: Kind = Kind::Fp64(Fp64 {
148 type_variation_reference: 0,
149 nullability: Nullability::Required as i32,
150 });
151
152 let kind = typ.and_then(|t| t.kind).unwrap_or(DEFAULT_KIND);
154
155 let (lit, nullability, tvar) = match &kind {
156 Kind::Fp32(f) => (
157 LiteralType::Fp32(parsed_value as f32),
158 f.nullability,
159 f.type_variation_reference,
160 ),
161 Kind::Fp64(f) => (
162 LiteralType::Fp64(parsed_value),
163 f.nullability,
164 f.type_variation_reference,
165 ),
166 k => {
167 let pest_error = pest::error::Error::new_from_span(
168 pest::error::ErrorVariant::CustomError {
169 message: format!("Invalid type for float literal: {k:?}"),
170 },
171 value.as_span(),
172 );
173 let error = MessageParseError {
174 message: "float_literal_type",
175 kind: ErrorKind::InvalidValue,
176 error: Box::new(pest_error),
177 };
178 return Err(error);
179 }
180 };
181
182 Ok(Literal {
183 literal_type: Some(lit),
184 nullable: nullability != Nullability::Required as i32,
185 type_variation_reference: tvar,
186 })
187}
188
189fn to_boolean_literal(
190 value: pest::iterators::Pair<Rule>,
191 typ: Option<Type>,
192) -> Result<Literal, MessageParseError> {
193 assert_eq!(value.as_rule(), Rule::boolean);
194 let parsed_value: bool = value.as_str().parse().unwrap();
195
196 let (nullable, tvar) = match typ.and_then(|t| t.kind) {
197 Some(Kind::Bool(b)) => (
198 b.nullability != Nullability::Required as i32,
199 b.type_variation_reference,
200 ),
201 None => (false, 0),
202 Some(k) => {
203 let pest_error = pest::error::Error::new_from_span(
204 pest::error::ErrorVariant::CustomError {
205 message: format!("Invalid type for boolean literal: {k:?}"),
206 },
207 value.as_span(),
208 );
209 return Err(MessageParseError {
210 message: "bool_literal_type",
211 kind: ErrorKind::InvalidValue,
212 error: Box::new(pest_error),
213 });
214 }
215 };
216
217 Ok(Literal {
218 literal_type: Some(LiteralType::Boolean(parsed_value)),
219 nullable,
220 type_variation_reference: tvar,
221 })
222}
223
224fn to_string_literal(
225 value: pest::iterators::Pair<Rule>,
226 typ: Option<Type>,
227) -> Result<Literal, MessageParseError> {
228 assert_eq!(value.as_rule(), Rule::string_literal);
229 let string_value = unescape_string(value.clone());
230
231 let Some(typ) = typ else {
233 return Ok(Literal {
234 literal_type: Some(LiteralType::String(string_value)),
235 nullable: false,
236 type_variation_reference: 0,
237 });
238 };
239
240 let Some(kind) = typ.kind else {
241 return Ok(Literal {
242 literal_type: Some(LiteralType::String(string_value)),
243 nullable: false,
244 type_variation_reference: 0,
245 });
246 };
247
248 match &kind {
249 Kind::Date(d) => {
250 let date_days = parse_date_to_days(&string_value, value.as_span())?;
252 Ok(Literal {
253 literal_type: Some(LiteralType::Date(date_days)),
254 nullable: d.nullability != Nullability::Required as i32,
255 type_variation_reference: d.type_variation_reference,
256 })
257 }
258 #[allow(deprecated)]
259 Kind::Time(t) => {
260 let time_microseconds = parse_time_to_microseconds(&string_value, value.as_span())?;
262 Ok(Literal {
263 literal_type: Some(LiteralType::Time(time_microseconds)),
264 nullable: t.nullability != Nullability::Required as i32,
265 type_variation_reference: t.type_variation_reference,
266 })
267 }
268 #[allow(deprecated)]
269 Kind::Timestamp(ts) => {
270 let timestamp_microseconds =
272 parse_timestamp_to_microseconds(&string_value, value.as_span())?;
273 Ok(Literal {
274 literal_type: Some(LiteralType::Timestamp(timestamp_microseconds)),
275 nullable: ts.nullability != Nullability::Required as i32,
276 type_variation_reference: ts.type_variation_reference,
277 })
278 }
279 _ => {
280 Ok(Literal {
282 literal_type: Some(LiteralType::String(string_value)),
283 nullable: false,
284 type_variation_reference: 0,
285 })
286 }
287 }
288}
289
290fn parse_date_to_days(date_str: &str, span: pest::Span) -> Result<i32, MessageParseError> {
292 let formats = ["%Y-%m-%d", "%Y/%m/%d"];
294
295 for format in &formats {
296 if let Ok(date) = NaiveDate::parse_from_str(date_str, format) {
297 let epoch = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
299 let days = date.signed_duration_since(epoch).num_days();
300 return Ok(days as i32);
301 }
302 }
303
304 Err(MessageParseError {
305 message: "date_parse_format",
306 kind: ErrorKind::InvalidValue,
307 error: Box::new(pest::error::Error::new_from_span(
308 pest::error::ErrorVariant::CustomError {
309 message: format!(
310 "Invalid date format: '{date_str}'. Expected YYYY-MM-DD or YYYY/MM/DD"
311 ),
312 },
313 span,
314 )),
315 })
316}
317
318fn parse_time_to_microseconds(time_str: &str, span: pest::Span) -> Result<i64, MessageParseError> {
320 let formats = ["%H:%M:%S%.f", "%H:%M:%S"];
322
323 for format in &formats {
324 if let Ok(time) = NaiveTime::parse_from_str(time_str, format) {
325 let midnight = NaiveTime::from_hms_opt(0, 0, 0).unwrap();
327 let duration = time.signed_duration_since(midnight);
328 return Ok(duration.num_microseconds().unwrap_or(0));
329 }
330 }
331
332 Err(MessageParseError {
333 message: "time_parse_format",
334 kind: ErrorKind::InvalidValue,
335 error: Box::new(pest::error::Error::new_from_span(
336 pest::error::ErrorVariant::CustomError {
337 message: format!(
338 "Invalid time format: '{time_str}'. Expected HH:MM:SS or HH:MM:SS.fff"
339 ),
340 },
341 span,
342 )),
343 })
344}
345
346fn parse_timestamp_to_microseconds(
348 timestamp_str: &str,
349 span: pest::Span,
350) -> Result<i64, MessageParseError> {
351 let formats = [
353 "%Y-%m-%dT%H:%M:%S%.f", "%Y-%m-%dT%H:%M:%S", "%Y-%m-%d %H:%M:%S%.f", "%Y-%m-%d %H:%M:%S", "%Y/%m/%dT%H:%M:%S%.f", "%Y/%m/%dT%H:%M:%S", "%Y/%m/%d %H:%M:%S%.f", "%Y/%m/%d %H:%M:%S", ];
362
363 for format in &formats {
364 if let Ok(datetime) = NaiveDateTime::parse_from_str(timestamp_str, format) {
365 let epoch = DateTime::from_timestamp(0, 0).unwrap().naive_utc();
367 let duration = datetime.signed_duration_since(epoch);
368 return Ok(duration.num_microseconds().unwrap_or(0));
369 }
370 }
371
372 Err(MessageParseError {
373 message: "timestamp_parse_format",
374 kind: ErrorKind::InvalidValue,
375 error: Box::new(pest::error::Error::new_from_span(
376 pest::error::ErrorVariant::CustomError {
377 message: format!(
378 "Invalid timestamp format: '{timestamp_str}'. Expected YYYY-MM-DDTHH:MM:SS or YYYY-MM-DD HH:MM:SS"
379 ),
380 },
381 span,
382 )),
383 })
384}
385
386impl ScopedParsePair for Literal {
387 fn rule() -> Rule {
388 Rule::literal
389 }
390
391 fn message() -> &'static str {
392 "Literal"
393 }
394
395 fn parse_pair(
396 extensions: &SimpleExtensions,
397 pair: pest::iterators::Pair<Rule>,
398 ) -> Result<Self, MessageParseError> {
399 assert_eq!(pair.as_rule(), Self::rule());
400 let mut pairs = pair.into_inner();
401 let value = pairs.next().unwrap(); let typ = pairs.next(); assert!(pairs.next().is_none());
404 let typ = match typ {
405 Some(t) => Some(Type::parse_pair(extensions, t)?),
406 None => None,
407 };
408 match value.as_rule() {
409 Rule::integer => to_int_literal(value, typ),
410 Rule::float => to_float_literal(value, typ),
411 Rule::boolean => to_boolean_literal(value, typ),
412 Rule::string_literal => to_string_literal(value, typ),
413 _ => unreachable!("Literal unexpected rule: {:?}", value.as_rule()),
414 }
415 }
416}
417
418impl ScopedParsePair for ScalarFunction {
419 fn rule() -> Rule {
420 Rule::function_call
421 }
422
423 fn message() -> &'static str {
424 "ScalarFunction"
425 }
426
427 fn parse_pair(
428 extensions: &SimpleExtensions,
429 pair: pest::iterators::Pair<Rule>,
430 ) -> Result<Self, MessageParseError> {
431 assert_eq!(pair.as_rule(), Self::rule());
432 let span = pair.as_span();
433 let mut iter = RuleIter::from(pair.into_inner());
434
435 let name = iter.parse_next::<CompoundName>();
437
438 let anchor = iter
440 .try_pop(Rule::anchor)
441 .map(|n| unwrap_single_pair(n).as_str().parse::<u32>().unwrap());
442
443 let _urn_anchor = iter
445 .try_pop(Rule::urn_anchor)
446 .map(|n| unwrap_single_pair(n).as_str().parse::<u32>().unwrap());
447
448 let argument_list = iter.pop(Rule::argument_list);
450 let mut arguments = Vec::new();
451 for e in argument_list.into_inner() {
452 arguments.push(FunctionArgument {
453 arg_type: Some(ArgType::Value(Expression::parse_pair(extensions, e)?)),
454 });
455 }
456
457 let output_type = match iter.try_pop(Rule::r#type) {
459 Some(t) => Some(Type::parse_pair(extensions, t)?),
460 None => None,
461 };
462
463 iter.done();
464 let anchor = get_and_validate_anchor(
465 extensions,
466 ExtensionKind::Function,
467 anchor,
468 name.full(),
469 span,
470 )?;
471 Ok(ScalarFunction {
472 function_reference: anchor,
473 arguments,
474 options: vec![], output_type,
476 #[allow(deprecated)]
477 args: vec![],
478 })
479 }
480}
481
482impl ScopedParsePair for Cast {
483 fn rule() -> Rule {
484 Rule::cast_expression
485 }
486
487 fn message() -> &'static str {
488 "Cast"
489 }
490
491 fn parse_pair(
492 extensions: &SimpleExtensions,
493 pair: pest::iterators::Pair<Rule>,
494 ) -> Result<Self, MessageParseError> {
495 assert_eq!(pair.as_rule(), Self::rule());
496 let mut pairs = pair.into_inner();
497
498 let expr_pair = pairs.next().unwrap();
499
500 let next = pairs.next().unwrap();
502 let (failure_behavior, type_pair) = if next.as_rule() == Rule::cast_failure_behavior {
503 let fb = match next.as_str() {
504 "?" => cast::FailureBehavior::ReturnNull as i32,
505 "!" => cast::FailureBehavior::ThrowException as i32,
506 _ => unreachable!("Grammar guarantees cast_failure_behavior is ? or !"),
507 };
508 (fb, pairs.next().unwrap())
509 } else {
510 (cast::FailureBehavior::Unspecified as i32, next)
511 };
512
513 assert!(pairs.next().is_none());
514
515 let input = Expression::parse_pair(extensions, expr_pair)?;
516 let target_type = Type::parse_pair(extensions, type_pair)?;
517
518 Ok(Cast {
519 r#type: Some(target_type),
520 input: Some(Box::new(input)),
521 failure_behavior,
522 })
523 }
524}
525
526impl ScopedParsePair for Expression {
527 fn rule() -> Rule {
528 Rule::expression
529 }
530
531 fn message() -> &'static str {
532 "Expression"
533 }
534
535 fn parse_pair(
536 extensions: &SimpleExtensions,
537 pair: pest::iterators::Pair<Rule>,
538 ) -> Result<Self, MessageParseError> {
539 assert_eq!(pair.as_rule(), Self::rule());
540 let inner = unwrap_single_pair(pair);
541 match inner.as_rule() {
542 Rule::literal => Ok(Expression {
543 rex_type: Some(RexType::Literal(Literal::parse_pair(extensions, inner)?)),
544 }),
545 Rule::function_call => Ok(Expression {
546 rex_type: Some(RexType::ScalarFunction(ScalarFunction::parse_pair(
547 extensions, inner,
548 )?)),
549 }),
550 Rule::reference => Ok(Expression {
551 rex_type: Some(RexType::Selection(Box::new(FieldReference::parse_pair(
552 inner,
553 )))),
554 }),
555 Rule::if_then => Ok(Expression {
556 rex_type: Some(RexType::IfThen(Box::new(IfThen::parse_pair(
557 extensions, inner,
558 )?))),
559 }),
560 Rule::cast_expression => Ok(Expression {
561 rex_type: Some(RexType::Cast(Box::new(Cast::parse_pair(
562 extensions, inner,
563 )?))),
564 }),
565 _ => unreachable!(
566 "Grammar guarantees expression can only be literal, function_call, reference, if_then, or cast_expression, got: {:?}",
567 inner.as_rule()
568 ),
569 }
570 }
571}
572
573impl ScopedParsePair for IfClause {
574 fn rule() -> Rule {
575 Rule::if_clause
576 }
577
578 fn message() -> &'static str {
579 "IfClause"
580 }
581
582 fn parse_pair(
583 extensions: &SimpleExtensions,
584 pair: pest::iterators::Pair<Rule>,
585 ) -> Result<Self, MessageParseError> {
586 assert_eq!(pair.as_rule(), Self::rule());
587 let mut pairs = pair.into_inner(); let condition = pairs.next().unwrap();
590 let result = pairs.next().unwrap();
591 assert!(pairs.next().is_none());
592
593 let ex1 = Some(Expression::parse_pair(extensions, condition)?);
594 let ex2 = Some(Expression::parse_pair(extensions, result)?);
595
596 Ok(IfClause {
597 r#if: ex1,
598 then: ex2,
599 })
600 }
601}
602
603impl ScopedParsePair for IfThen {
604 fn rule() -> Rule {
605 Rule::if_then
606 }
607 fn message() -> &'static str {
608 "IfThen"
609 }
610
611 fn parse_pair(
612 extensions: &SimpleExtensions,
613 pair: pest::iterators::Pair<Rule>,
614 ) -> Result<Self, MessageParseError> {
615 assert_eq!(pair.as_rule(), Self::rule());
616
617 let mut iter = RuleIter::from(pair.into_inner()); let mut ifs: Vec<IfClause> = Vec::new();
620
621 while let Some(p) = iter.try_pop(Rule::if_clause) {
623 let if_clause = IfClause::parse_pair(extensions, p)?;
624 ifs.push(if_clause);
625 }
626
627 let pair = iter.try_pop(Rule::expression).unwrap(); iter.done();
629 let else_clause = Some(Box::new(Expression::parse_pair(extensions, pair)?));
630
631 Ok(IfThen {
632 ifs,
633 r#else: else_clause,
634 })
635 }
636}
637pub struct Name(pub String);
638
639impl ParsePair for Name {
640 fn rule() -> Rule {
641 Rule::name
642 }
643
644 fn message() -> &'static str {
645 "Name"
646 }
647
648 fn parse_pair(pair: pest::iterators::Pair<Rule>) -> Self {
649 assert_eq!(pair.as_rule(), Self::rule());
650 let inner = unwrap_single_pair(pair);
651 match inner.as_rule() {
652 Rule::identifier => Name(inner.as_str().to_string()),
653 Rule::quoted_name => Name(unescape_string(inner)),
654 _ => unreachable!("Name unexpected rule: {:?}", inner.as_rule()),
655 }
656 }
657}
658
659impl ParsePair for CompoundName {
660 fn rule() -> Rule {
661 Rule::compound_name
662 }
663
664 fn message() -> &'static str {
665 "CompoundName"
666 }
667
668 fn parse_pair(pair: pest::iterators::Pair<Rule>) -> Self {
669 assert_eq!(pair.as_rule(), Self::rule());
670 CompoundName::new(pair.as_str())
671 }
672}
673
674impl ScopedParsePair for Measure {
675 fn rule() -> Rule {
676 Rule::aggregate_measure
677 }
678
679 fn message() -> &'static str {
680 "Measure"
681 }
682
683 fn parse_pair(
684 extensions: &SimpleExtensions,
685 pair: pest::iterators::Pair<Rule>,
686 ) -> Result<Self, MessageParseError> {
687 assert_eq!(pair.as_rule(), Self::rule());
688
689 let function_call_pair = unwrap_single_pair(pair);
691 assert_eq!(function_call_pair.as_rule(), Rule::function_call);
692
693 let scalar = ScalarFunction::parse_pair(extensions, function_call_pair)?;
695 Ok(Measure {
696 measure: Some(AggregateFunction {
697 function_reference: scalar.function_reference,
698 arguments: scalar.arguments,
699 options: scalar.options,
700 output_type: scalar.output_type,
701 invocation: 0, phase: 0, sorts: vec![], #[allow(deprecated)]
705 args: scalar.args,
706 }),
707 filter: None, })
709 }
710}
711
712#[cfg(test)]
713mod tests {
714 use pest::Parser as PestParser;
715
716 use super::*;
717 use crate::parser::ExpressionParser;
718
719 fn parse_exact(rule: Rule, input: &'_ str) -> pest::iterators::Pair<'_, Rule> {
720 let mut pairs = ExpressionParser::parse(rule, input).unwrap();
721 assert_eq!(pairs.as_str(), input);
722 let pair = pairs.next().unwrap();
723 assert_eq!(pairs.next(), None);
724 pair
725 }
726
727 fn assert_parses_to<T: ParsePair + PartialEq + std::fmt::Debug>(input: &str, expected: T) {
728 let pair = parse_exact(T::rule(), input);
729 let actual = T::parse_pair(pair);
730 assert_eq!(actual, expected);
731 }
732
733 fn assert_parses_with<T: ScopedParsePair + PartialEq + std::fmt::Debug>(
734 ext: &SimpleExtensions,
735 input: &str,
736 expected: T,
737 ) {
738 let pair = parse_exact(T::rule(), input);
739 let actual = T::parse_pair(ext, pair).unwrap();
740 assert_eq!(actual, expected);
741 }
742
743 #[test]
744 fn test_parse_field_reference() {
745 assert_parses_to("$1", FieldIndex(1).to_field_reference());
746 }
747
748 #[test]
749 fn test_parse_integer_literal() {
750 let extensions = SimpleExtensions::default();
751 let expected = Literal {
752 literal_type: Some(LiteralType::I64(1)),
753 nullable: false,
754 type_variation_reference: 0,
755 };
756 assert_parses_with(&extensions, "1", expected);
757 }
758
759 #[test]
760 fn test_parse_float_literal() {
761 let pairs = ExpressionParser::parse(Rule::float, "3.82").unwrap();
763 let parsed_text = pairs.as_str();
764 assert_eq!(parsed_text, "3.82");
765
766 let extensions = SimpleExtensions::default();
767 let expected = Literal {
768 literal_type: Some(LiteralType::Fp64(3.82)),
769 nullable: false,
770 type_variation_reference: 0,
771 };
772 assert_parses_with(&extensions, "3.82", expected);
773 }
774
775 #[test]
776 fn test_parse_negative_float_literal() {
777 let extensions = SimpleExtensions::default();
778 let expected = Literal {
779 literal_type: Some(LiteralType::Fp64(-2.5)),
780 nullable: false,
781 type_variation_reference: 0,
782 };
783 assert_parses_with(&extensions, "-2.5", expected);
784 }
785
786 #[test]
787 fn test_parse_boolean_true_literal() {
788 let extensions = SimpleExtensions::default();
789 let expected = Literal {
790 literal_type: Some(LiteralType::Boolean(true)),
791 nullable: false,
792 type_variation_reference: 0,
793 };
794 assert_parses_with(&extensions, "true", expected);
795 }
796
797 #[test]
798 fn test_parse_boolean_false_literal() {
799 let extensions = SimpleExtensions::default();
800 let expected = Literal {
801 literal_type: Some(LiteralType::Boolean(false)),
802 nullable: false,
803 type_variation_reference: 0,
804 };
805 assert_parses_with(&extensions, "false", expected);
806 }
807
808 #[test]
809 fn test_parse_nullable_boolean_literal() {
810 let extensions = SimpleExtensions::default();
811 let expected_true = Literal {
812 literal_type: Some(LiteralType::Boolean(true)),
813 nullable: true,
814 type_variation_reference: 0,
815 };
816 let expected_false = Literal {
817 literal_type: Some(LiteralType::Boolean(false)),
818 nullable: true,
819 type_variation_reference: 0,
820 };
821 assert_parses_with(&extensions, "true:boolean?", expected_true);
822 assert_parses_with(&extensions, "false:boolean?", expected_false);
823 }
824
825 #[test]
826 fn test_parse_nullable_integer_literal() {
827 let extensions = SimpleExtensions::default();
828 let expected_i32 = Literal {
829 literal_type: Some(LiteralType::I32(78)),
830 nullable: true,
831 type_variation_reference: 0,
832 };
833 let expected_i64 = Literal {
834 literal_type: Some(LiteralType::I64(42)),
835 nullable: true,
836 type_variation_reference: 0,
837 };
838 assert_parses_with(&extensions, "78:i32?", expected_i32);
839 assert_parses_with(&extensions, "42:i64?", expected_i64);
840 }
841
842 #[test]
843 fn test_parse_nullable_float_literal() {
844 let extensions = SimpleExtensions::default();
845 let expected_fp64 = Literal {
846 literal_type: Some(LiteralType::Fp64(3.19)),
847 nullable: true,
848 type_variation_reference: 0,
849 };
850 assert_parses_with(&extensions, "3.19:fp64?", expected_fp64);
851 }
852
853 #[test]
854 fn test_parse_float_literal_with_fp32_type() {
855 let extensions = SimpleExtensions::default();
856 let pair = parse_exact(Rule::literal, "3.82:fp32");
857 let result = Literal::parse_pair(&extensions, pair).unwrap();
858
859 match result.literal_type {
860 Some(LiteralType::Fp32(val)) => assert!((val - 3.82).abs() < f32::EPSILON),
861 _ => panic!("Expected Fp32 literal type"),
862 }
863 }
864
865 #[test]
866 fn test_parse_date_literal() {
867 let extensions = SimpleExtensions::default();
868 let pair = parse_exact(Rule::literal, "'2023-12-25':date");
869 let result = Literal::parse_pair(&extensions, pair).unwrap();
870
871 match result.literal_type {
872 Some(LiteralType::Date(days)) => {
873 assert!(
875 days > 0,
876 "Expected positive days since epoch, got: {}",
877 days
878 );
879 }
880 _ => panic!("Expected Date literal type, got: {:?}", result.literal_type),
881 }
882 }
883
884 #[test]
885 fn test_parse_time_literal() {
886 let extensions = SimpleExtensions::default();
887 let pair = parse_exact(Rule::literal, "'14:30:45':time");
888 let result = Literal::parse_pair(&extensions, pair).unwrap();
889
890 match result.literal_type {
891 #[allow(deprecated)]
892 Some(LiteralType::Time(microseconds)) => {
893 let expected = (14 * 3600 + 30 * 60 + 45) * 1_000_000;
895 assert_eq!(microseconds, expected);
896 }
897 _ => panic!("Expected Time literal type, got: {:?}", result.literal_type),
898 }
899 }
900
901 #[test]
902 fn test_parse_timestamp_literal_with_t() {
903 let extensions = SimpleExtensions::default();
904 let pair = parse_exact(Rule::literal, "'2023-01-01T12:00:00':timestamp");
905 let result = Literal::parse_pair(&extensions, pair).unwrap();
906
907 match result.literal_type {
908 #[allow(deprecated)]
909 Some(LiteralType::Timestamp(microseconds)) => {
910 assert!(
911 microseconds > 0,
912 "Expected positive microseconds since epoch"
913 );
914 }
915 _ => panic!(
916 "Expected Timestamp literal type, got: {:?}",
917 result.literal_type
918 ),
919 }
920 }
921
922 #[test]
923 fn test_parse_timestamp_literal_with_space() {
924 let extensions = SimpleExtensions::default();
925 let pair = parse_exact(Rule::literal, "'2023-01-01 12:00:00':timestamp");
926 let result = Literal::parse_pair(&extensions, pair).unwrap();
927
928 match result.literal_type {
929 #[allow(deprecated)]
930 Some(LiteralType::Timestamp(microseconds)) => {
931 assert!(
932 microseconds > 0,
933 "Expected positive microseconds since epoch"
934 );
935 }
936 _ => panic!(
937 "Expected Timestamp literal type, got: {:?}",
938 result.literal_type
939 ),
940 }
941 }
942
943 fn make_literal_bool(value: bool) -> Expression {
945 Expression {
946 rex_type: Some(RexType::Literal(Literal {
947 literal_type: Some(LiteralType::Boolean(value)),
948 nullable: false,
949 type_variation_reference: 0,
950 })),
951 }
952 }
953
954 #[test]
955 fn test_parse_if_then_single_clause() {
956 let extensions = SimpleExtensions::default();
957 let input = "if_then(true -> 42, _ -> 0)";
958 let pair = parse_exact(Rule::if_then, input);
959 let result = IfThen::parse_pair(&extensions, pair).unwrap();
960
961 assert_eq!(result.ifs.len(), 1);
962 assert!(result.r#else.is_some());
963 }
964
965 #[test]
966 fn test_parse_if_then_with_typed_literals() {
967 let extensions = SimpleExtensions::default();
968 let input = "if_then(true -> 100:i32, _ -> -100:i32)";
969 let pair = parse_exact(Rule::if_then, input);
970 let result = IfThen::parse_pair(&extensions, pair).unwrap();
971
972 assert_eq!(result.ifs.len(), 1);
973 assert!(result.r#else.is_some());
974 }
975
976 #[test]
977 fn test_parse_if_then_with_date_literals() {
978 let extensions = SimpleExtensions::default();
979 let input = "if_then(true -> '2023-12-25':date, _ -> '1970-01-01':date)";
980 let pair = parse_exact(Rule::if_then, input);
981 let result = IfThen::parse_pair(&extensions, pair).unwrap();
982
983 assert_eq!(result.ifs.len(), 1);
984 assert!(result.r#else.is_some());
985 }
986
987 #[test]
988 fn test_parse_if_then_with_time_literals() {
989 let extensions = SimpleExtensions::default();
990 let input = "if_then(true -> '14:30:45':time, _ -> '00:00:00':time)";
991 let pair = parse_exact(Rule::if_then, input);
992 let result = IfThen::parse_pair(&extensions, pair).unwrap();
993
994 assert_eq!(result.ifs.len(), 1);
995 assert!(result.r#else.is_some());
996 }
997
998 #[test]
999 fn test_parse_if_then_with_timestamp_literals() {
1000 let extensions = SimpleExtensions::default();
1001 let input = "if_then(true -> '2023-01-01T12:00:00':timestamp, _ -> '1970-01-01T00:00:00':timestamp)";
1002 let pair = parse_exact(Rule::if_then, input);
1003 let result = IfThen::parse_pair(&extensions, pair).unwrap();
1004
1005 assert_eq!(result.ifs.len(), 1);
1006 assert!(result.r#else.is_some());
1007 }
1008
1009 #[test]
1010 fn test_parse_if_clause_with_whitespace_variations() {
1011 let extensions = SimpleExtensions::default();
1012
1013 let inputs = vec!["true->false", "true -> false", "true -> false"];
1015
1016 for input in inputs {
1017 let pair = parse_exact(Rule::if_clause, input);
1018 let result = IfClause::parse_pair(&extensions, pair).unwrap();
1019 assert!(result.r#if.is_some());
1020 assert!(result.then.is_some());
1021 }
1022 }
1023
1024 #[test]
1025 fn test_if_clause_structure() {
1026 let extensions = SimpleExtensions::default();
1027 let pair = parse_exact(Rule::if_clause, "42 -> 100");
1028 let result = IfClause::parse_pair(&extensions, pair).unwrap();
1029
1030 let if_expr = result.r#if.as_ref().unwrap();
1032 let then_expr = result.then.as_ref().unwrap();
1033
1034 match (&if_expr.rex_type, &then_expr.rex_type) {
1036 (Some(RexType::Literal(_)), Some(RexType::Literal(_))) => {
1037 }
1039 _ => panic!("Expected both if and then to be literals"),
1040 }
1041 }
1042
1043 #[test]
1044 fn test_if_then_structure() {
1045 let extensions = SimpleExtensions::default();
1046 let input = "if_then(true -> 1, false -> 2, _ -> 0)";
1047 let pair = parse_exact(Rule::if_then, input);
1048 let result = IfThen::parse_pair(&extensions, pair).unwrap();
1049
1050 assert_eq!(result.ifs.len(), 2);
1052
1053 for clause in &result.ifs {
1055 assert!(clause.r#if.is_some(), "If clause condition should exist");
1056 assert!(clause.then.is_some(), "If clause result should exist");
1057 }
1058
1059 assert!(result.r#else.is_some(), "Else clause should exist");
1061 }
1062
1063 #[test]
1064 fn test_parse_if_then_mixed_types_in_conditions() {
1065 let extensions = SimpleExtensions::default();
1066 let input = "if_then(true -> 1, true -> 'yes', 'yes' -> true, 42 -> 2, $0 -> 3, _ -> 0)";
1068 let pair = parse_exact(Rule::if_then, input);
1069 let result = IfThen::parse_pair(&extensions, pair).unwrap();
1070
1071 assert_eq!(result.ifs.len(), 5);
1072 assert!(result.r#else.is_some());
1073 }
1074
1075 #[test]
1076 fn test_if_then_preserves_clause_order() {
1077 let extensions = SimpleExtensions::default();
1078 let input = "if_then(1 -> 10, 2 -> 20, 3 -> 30, _ -> 0)";
1079 let pair = parse_exact(Rule::if_then, input);
1080 let result = IfThen::parse_pair(&extensions, pair).unwrap();
1081
1082 assert_eq!(result.ifs.len(), 3);
1083
1084 for (i, clause) in result.ifs.iter().enumerate() {
1086 if let Some(Expression {
1087 rex_type: Some(RexType::Literal(lit)),
1088 }) = &clause.r#if
1089 && let Some(LiteralType::I64(val)) = &lit.literal_type
1090 {
1091 assert_eq!(*val, (i as i64) + 1);
1092 }
1093 }
1094 }
1095
1096 #[test]
1097 fn test_parse_if_then() {
1098 let extensions = SimpleExtensions::default();
1099
1100 let c1 = IfClause {
1101 r#if: Some(make_literal_bool(true)),
1102 then: Some(make_literal_bool(true)),
1103 };
1104
1105 let c2 = IfClause {
1106 r#if: Some(make_literal_bool(false)),
1107 then: Some(make_literal_bool(false)),
1108 };
1109
1110 let if_clause = IfThen {
1111 ifs: vec![c1, c2],
1112 r#else: Some(Box::new(make_literal_bool(false))),
1113 };
1114 assert_parses_with(
1115 &extensions,
1116 "if_then(true -> true , false -> false, _ -> false)",
1117 if_clause,
1118 );
1119 }
1120
1121 fn parse_compound_name(input: &str) -> CompoundName {
1124 let pair = parse_exact(Rule::compound_name, input);
1125 CompoundName::parse_pair(pair)
1126 }
1127
1128 #[test]
1129 fn test_compound_name_plain() {
1130 assert_eq!(parse_compound_name("add").full(), "add");
1131 }
1132
1133 #[test]
1134 fn test_compound_name_with_signature() {
1135 assert_eq!(parse_compound_name("equal:any_any").full(), "equal:any_any");
1136 assert_eq!(
1137 parse_compound_name("regexp_match_substring:str_str_i64").full(),
1138 "regexp_match_substring:str_str_i64"
1139 );
1140 assert_eq!(parse_compound_name("add:i64_i64").full(), "add:i64_i64");
1141 }
1142
1143 #[test]
1144 fn test_compound_name_stops_at_opening_paren() {
1145 let pairs = ExpressionParser::parse(Rule::compound_name, "equal:any_any").unwrap();
1149 assert_eq!(pairs.as_str(), "equal:any_any");
1150 }
1151
1152 fn make_extensions_for_fn_tests() -> SimpleExtensions {
1155 let mut exts = SimpleExtensions::default();
1156 exts.add_extension_urn("urn".to_string(), 1).unwrap();
1157 exts.add_extension(
1158 crate::extensions::simple::ExtensionKind::Function,
1159 1,
1160 1,
1161 "equal:any_any".to_string(),
1162 )
1163 .unwrap();
1164 exts.add_extension(
1165 crate::extensions::simple::ExtensionKind::Function,
1166 1,
1167 2,
1168 "equal:str_str".to_string(),
1169 )
1170 .unwrap();
1171 exts.add_extension(
1172 crate::extensions::simple::ExtensionKind::Function,
1173 1,
1174 3,
1175 "add:i64_i64".to_string(),
1176 )
1177 .unwrap();
1178 exts
1179 }
1180
1181 #[test]
1182 fn test_scalar_function_full_compound_name() {
1183 let exts = make_extensions_for_fn_tests();
1185 let pair = parse_exact(Rule::function_call, "equal:any_any($0, $1)");
1186 let f = ScalarFunction::parse_pair(&exts, pair).unwrap();
1187 assert_eq!(f.function_reference, 1);
1188 assert_eq!(f.arguments.len(), 2);
1189 }
1190
1191 #[test]
1192 fn test_scalar_function_second_overload() {
1193 let exts = make_extensions_for_fn_tests();
1194 let pair = parse_exact(Rule::function_call, "equal:str_str($0, $1)");
1195 let f = ScalarFunction::parse_pair(&exts, pair).unwrap();
1196
1197 assert_eq!(f.arguments.len(), 2);
1198 assert_eq!(f.function_reference, 2);
1199 }
1200
1201 #[test]
1202 fn test_scalar_function_base_name_unique_overload() {
1203 let exts = make_extensions_for_fn_tests();
1205 let pair = parse_exact(Rule::function_call, "add($0, $1)");
1206 let f = ScalarFunction::parse_pair(&exts, pair).unwrap();
1207
1208 assert_eq!(f.arguments.len(), 2);
1209 assert_eq!(f.function_reference, 3);
1210 }
1211
1212 #[test]
1213 fn test_scalar_function_base_name_ambiguous_fails() {
1214 let exts = make_extensions_for_fn_tests();
1216 let pair = parse_exact(Rule::function_call, "equal($0, $1)");
1217 let result = ScalarFunction::parse_pair(&exts, pair);
1218 assert!(result.is_err(), "ambiguous base name should fail");
1219 }
1220
1221 #[test]
1222 fn test_scalar_function_compound_name_with_anchor() {
1223 let exts = make_extensions_for_fn_tests();
1224 let pair = parse_exact(Rule::function_call, "equal:any_any#1($0, $1)");
1225 let f = ScalarFunction::parse_pair(&exts, pair).unwrap();
1226 assert_eq!(f.function_reference, 1);
1227 assert_eq!(f.arguments.len(), 2);
1228 }
1229
1230 #[test]
1231 fn test_scalar_function_base_name_with_anchor() {
1232 let exts = make_extensions_for_fn_tests();
1234 let pair = parse_exact(Rule::function_call, "equal#1($0, $1)");
1235 let f = ScalarFunction::parse_pair(&exts, pair).unwrap();
1236 assert_eq!(f.function_reference, 1);
1237 assert_eq!(f.arguments.len(), 2);
1238 }
1239
1240 #[test]
1241 fn test_scalar_function_wrong_name_for_anchor_fails() {
1242 let exts = make_extensions_for_fn_tests();
1243 let pair = parse_exact(Rule::function_call, "like#1($0)");
1244 let result = ScalarFunction::parse_pair(&exts, pair);
1245 assert!(result.is_err(), "mismatched name/anchor should fail");
1246 }
1247
1248 #[test]
1249 fn test_parse_cast_expression_basic() {
1250 let extensions = SimpleExtensions::default();
1251 let pair = parse_exact(Rule::cast_expression, "(78:i32)::i16");
1252 let result = Cast::parse_pair(&extensions, pair).unwrap();
1253
1254 let input = result.input.as_ref().unwrap();
1256 match &input.rex_type {
1257 Some(RexType::Literal(lit)) => match &lit.literal_type {
1258 Some(LiteralType::I32(v)) => assert_eq!(*v, 78),
1259 other => panic!("Expected I32 literal, got: {:?}", other),
1260 },
1261 other => panic!("Expected literal, got: {:?}", other),
1262 }
1263
1264 let target = result.r#type.as_ref().unwrap();
1266 match &target.kind {
1267 Some(substrait::proto::r#type::Kind::I16(_)) => {}
1268 other => panic!("Expected i16 type, got: {:?}", other),
1269 }
1270
1271 assert_eq!(result.failure_behavior, 0);
1272 }
1273
1274 #[test]
1275 fn test_parse_cast_expression_via_expression_rule() {
1276 let extensions = SimpleExtensions::default();
1277 let pair = parse_exact(Rule::expression, "(78:i32)::i16");
1278 let result = Expression::parse_pair(&extensions, pair).unwrap();
1279
1280 match result.rex_type {
1281 Some(RexType::Cast(_)) => {}
1282 other => panic!("Expected Cast rex type, got: {:?}", other),
1283 }
1284 }
1285
1286 #[test]
1287 fn test_parse_cast_expression_nested() {
1288 let extensions = SimpleExtensions::default();
1289 let pair = parse_exact(Rule::cast_expression, "((78:i32)::i16)::i32");
1290 let result = Cast::parse_pair(&extensions, pair).unwrap();
1291
1292 let input = result.input.as_ref().unwrap();
1294 match &input.rex_type {
1295 Some(RexType::Cast(inner)) => {
1296 let inner_input = inner.input.as_ref().unwrap();
1297 match &inner_input.rex_type {
1298 Some(RexType::Literal(lit)) => match &lit.literal_type {
1299 Some(LiteralType::I32(v)) => assert_eq!(*v, 78),
1300 other => panic!("Expected I32 literal, got: {:?}", other),
1301 },
1302 other => panic!("Expected literal, got: {:?}", other),
1303 }
1304 }
1305 other => panic!("Expected inner Cast, got: {:?}", other),
1306 }
1307
1308 match &result.r#type.as_ref().unwrap().kind {
1309 Some(substrait::proto::r#type::Kind::I32(_)) => {}
1310 other => panic!("Expected i32 outer type, got: {:?}", other),
1311 }
1312 }
1313
1314 #[test]
1315 fn test_parse_cast_expression_with_boolean() {
1316 let extensions = SimpleExtensions::default();
1317 let pair = parse_exact(Rule::cast_expression, "(true)::i32");
1318 let result = Cast::parse_pair(&extensions, pair).unwrap();
1319
1320 let input = result.input.as_ref().unwrap();
1321 match &input.rex_type {
1322 Some(RexType::Literal(lit)) => match &lit.literal_type {
1323 Some(LiteralType::Boolean(v)) => assert!(*v),
1324 other => panic!("Expected Boolean literal, got: {:?}", other),
1325 },
1326 other => panic!("Expected literal, got: {:?}", other),
1327 }
1328 }
1329
1330 #[test]
1331 fn test_parse_cast_expression_with_whitespace() {
1332 let extensions = SimpleExtensions::default();
1333 let pair = parse_exact(Rule::cast_expression, "( 78:i32 ) :: i16");
1335 let result = Cast::parse_pair(&extensions, pair).unwrap();
1336 assert!(result.input.is_some());
1337 assert!(result.r#type.is_some());
1338 }
1339
1340 #[test]
1341 fn test_parse_cast_unspecified_failure_behavior() {
1342 let extensions = SimpleExtensions::default();
1343 let pair = parse_exact(Rule::cast_expression, "(78:i32)::i16");
1344 let result = Cast::parse_pair(&extensions, pair).unwrap();
1345 assert_eq!(
1346 result.failure_behavior,
1347 cast::FailureBehavior::Unspecified as i32
1348 );
1349 }
1350
1351 #[test]
1352 fn test_parse_cast_return_null_failure_behavior() {
1353 let extensions = SimpleExtensions::default();
1354 let pair = parse_exact(Rule::cast_expression, "(78:i32)::?i16");
1355 let result = Cast::parse_pair(&extensions, pair).unwrap();
1356 assert_eq!(
1357 result.failure_behavior,
1358 cast::FailureBehavior::ReturnNull as i32
1359 );
1360 }
1361
1362 #[test]
1363 fn test_parse_cast_throw_exception_failure_behavior() {
1364 let extensions = SimpleExtensions::default();
1365 let pair = parse_exact(Rule::cast_expression, "(78:i32)::!i16");
1366 let result = Cast::parse_pair(&extensions, pair).unwrap();
1367 assert_eq!(
1368 result.failure_behavior,
1369 cast::FailureBehavior::ThrowException as i32
1370 );
1371 }
1372}