Skip to main content

substrait_explain/parser/
expressions.rs

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::{
6    LiteralType, PrecisionTime as LitPrecisionTime, PrecisionTimestamp as LitPrecisionTimestamp,
7};
8use substrait::proto::expression::{
9    Cast, FieldReference, IfThen, Literal, ReferenceSegment, RexType, ScalarFunction, cast,
10    reference_segment,
11};
12use substrait::proto::function_argument::ArgType;
13use substrait::proto::r#type::{Fp64, I64, Kind, Nullability};
14use substrait::proto::{AggregateFunction, Expression, FunctionArgument, Type};
15
16use super::types::get_and_validate_anchor;
17use super::{
18    MessageParseError, ParsePair, Rule, RuleIter, ScopedParsePair, unescape_string,
19    unwrap_single_pair,
20};
21use crate::extensions::SimpleExtensions;
22use crate::extensions::simple::{CompoundName, ExtensionKind};
23
24/// A field index (e.g., parsed from "$0" -> 0).
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26pub struct FieldIndex(pub i32);
27
28impl FieldIndex {
29    /// Convert this field index to a FieldReference for use in expressions.
30    pub fn to_field_reference(self) -> FieldReference {
31        // XXX: Why is it so many layers to make a struct field reference? This is
32        // surprisingly complex
33        FieldReference {
34            reference_type: Some(ReferenceType::DirectReference(ReferenceSegment {
35                reference_type: Some(reference_segment::ReferenceType::StructField(Box::new(
36                    reference_segment::StructField {
37                        field: self.0,
38                        child: None,
39                    },
40                ))),
41            })),
42            root_type: Some(RootType::RootReference(RootReference {})),
43        }
44    }
45}
46
47impl ParsePair for FieldIndex {
48    fn rule() -> Rule {
49        Rule::reference
50    }
51
52    fn message() -> &'static str {
53        "FieldIndex"
54    }
55
56    fn parse_pair(pair: pest::iterators::Pair<Rule>) -> Self {
57        assert_eq!(pair.as_rule(), Self::rule());
58        let inner = unwrap_single_pair(pair);
59        let index: i32 = inner.as_str().parse().unwrap();
60        FieldIndex(index)
61    }
62}
63
64impl ParsePair for FieldReference {
65    fn rule() -> Rule {
66        Rule::reference
67    }
68
69    fn message() -> &'static str {
70        "FieldReference"
71    }
72
73    fn parse_pair(pair: pest::iterators::Pair<Rule>) -> Self {
74        assert_eq!(pair.as_rule(), Self::rule());
75
76        // TODO: Other types of references.
77        FieldIndex::parse_pair(pair).to_field_reference()
78    }
79}
80
81fn to_int_literal(
82    value: pest::iterators::Pair<Rule>,
83    typ: Option<Type>,
84) -> Result<Literal, MessageParseError> {
85    assert_eq!(value.as_rule(), Rule::integer);
86    let parsed_value: i64 = value.as_str().parse().unwrap();
87
88    const DEFAULT_KIND: Kind = Kind::I64(I64 {
89        type_variation_reference: 0,
90        nullability: Nullability::Required as i32,
91    });
92
93    // If no type is provided, we assume i64, Nullability::Required.
94    let kind = typ.and_then(|t| t.kind).unwrap_or(DEFAULT_KIND);
95
96    let (lit, nullability, tvar) = match &kind {
97        // If no type is provided, we assume i64, Nullability::Required.
98        Kind::I8(i) => (
99            LiteralType::I8(parsed_value as i32),
100            i.nullability,
101            i.type_variation_reference,
102        ),
103        Kind::I16(i) => (
104            LiteralType::I16(parsed_value as i32),
105            i.nullability,
106            i.type_variation_reference,
107        ),
108        Kind::I32(i) => (
109            LiteralType::I32(parsed_value as i32),
110            i.nullability,
111            i.type_variation_reference,
112        ),
113        Kind::I64(i) => (
114            LiteralType::I64(parsed_value),
115            i.nullability,
116            i.type_variation_reference,
117        ),
118        k => {
119            return Err(MessageParseError::invalid(
120                "int_literal_type",
121                value.as_span(),
122                format!("Invalid type for integer literal: {k:?}"),
123            ));
124        }
125    };
126
127    Ok(Literal {
128        literal_type: Some(lit),
129        nullable: nullability != Nullability::Required as i32,
130        type_variation_reference: tvar,
131    })
132}
133
134fn to_float_literal(
135    value: pest::iterators::Pair<Rule>,
136    typ: Option<Type>,
137) -> Result<Literal, MessageParseError> {
138    assert_eq!(value.as_rule(), Rule::float);
139    let parsed_value: f64 = value.as_str().parse().unwrap();
140
141    const DEFAULT_KIND: Kind = Kind::Fp64(Fp64 {
142        type_variation_reference: 0,
143        nullability: Nullability::Required as i32,
144    });
145
146    // If no type is provided, we assume fp64, Nullability::Required.
147    let kind = typ.and_then(|t| t.kind).unwrap_or(DEFAULT_KIND);
148
149    let (lit, nullability, tvar) = match &kind {
150        Kind::Fp32(f) => (
151            LiteralType::Fp32(parsed_value as f32),
152            f.nullability,
153            f.type_variation_reference,
154        ),
155        Kind::Fp64(f) => (
156            LiteralType::Fp64(parsed_value),
157            f.nullability,
158            f.type_variation_reference,
159        ),
160        k => {
161            return Err(MessageParseError::invalid(
162                "float_literal_type",
163                value.as_span(),
164                format!("Invalid type for float literal: {k:?}"),
165            ));
166        }
167    };
168
169    Ok(Literal {
170        literal_type: Some(lit),
171        nullable: nullability != Nullability::Required as i32,
172        type_variation_reference: tvar,
173    })
174}
175
176fn to_boolean_literal(
177    value: pest::iterators::Pair<Rule>,
178    typ: Option<Type>,
179) -> Result<Literal, MessageParseError> {
180    assert_eq!(value.as_rule(), Rule::boolean);
181    let parsed_value: bool = value.as_str().parse().unwrap();
182
183    let (nullable, tvar) = match typ.and_then(|t| t.kind) {
184        Some(Kind::Bool(b)) => (
185            b.nullability != Nullability::Required as i32,
186            b.type_variation_reference,
187        ),
188        None => (false, 0),
189        Some(k) => {
190            return Err(MessageParseError::invalid(
191                "bool_literal_type",
192                value.as_span(),
193                format!("Invalid type for boolean literal: {k:?}"),
194            ));
195        }
196    };
197
198    Ok(Literal {
199        literal_type: Some(LiteralType::Boolean(parsed_value)),
200        nullable,
201        type_variation_reference: tvar,
202    })
203}
204
205fn to_string_literal(
206    value: pest::iterators::Pair<Rule>,
207    typ: Option<Type>,
208) -> Result<Literal, MessageParseError> {
209    assert_eq!(value.as_rule(), Rule::string_literal);
210    let string_value = unescape_string(value.clone());
211
212    // If no type is provided, default to string
213    let Some(typ) = typ else {
214        return Ok(Literal {
215            literal_type: Some(LiteralType::String(string_value)),
216            nullable: false,
217            type_variation_reference: 0,
218        });
219    };
220
221    let Some(kind) = typ.kind else {
222        return Ok(Literal {
223            literal_type: Some(LiteralType::String(string_value)),
224            nullable: false,
225            type_variation_reference: 0,
226        });
227    };
228
229    match &kind {
230        Kind::Date(d) => {
231            // Parse date in ISO 8601 format: YYYY-MM-DD
232            let date_days = parse_date_to_days(&string_value, value.as_span())?;
233            Ok(Literal {
234                literal_type: Some(LiteralType::Date(date_days)),
235                nullable: d.nullability != Nullability::Required as i32,
236                type_variation_reference: d.type_variation_reference,
237            })
238        }
239        #[allow(deprecated)]
240        Kind::Time(t) => {
241            // Parse time in ISO 8601 format: HH:MM:SS[.fff]
242            let time_microseconds = parse_time_to_microseconds(&string_value, value.as_span())?;
243            Ok(Literal {
244                literal_type: Some(LiteralType::Time(time_microseconds)),
245                nullable: t.nullability != Nullability::Required as i32,
246                type_variation_reference: t.type_variation_reference,
247            })
248        }
249        #[allow(deprecated)]
250        Kind::Timestamp(ts) => {
251            // Parse timestamp in ISO 8601 format: YYYY-MM-DDTHH:MM:SS[.fff] or YYYY-MM-DD HH:MM:SS[.fff]
252            let timestamp_microseconds =
253                parse_timestamp_to_microseconds(&string_value, value.as_span())?;
254            Ok(Literal {
255                literal_type: Some(LiteralType::Timestamp(timestamp_microseconds)),
256                nullable: ts.nullability != Nullability::Required as i32,
257                type_variation_reference: ts.type_variation_reference,
258            })
259        }
260        Kind::PrecisionTimestamp(pt) => {
261            let precision = pt.precision;
262            let timestamp_value = parse_timestamp_to_precision_units(
263                &string_value,
264                precision,
265                "precisiontimestamp",
266                value.as_span(),
267            )?;
268            Ok(Literal {
269                literal_type: Some(LiteralType::PrecisionTimestamp(LitPrecisionTimestamp {
270                    precision,
271                    value: timestamp_value,
272                })),
273                nullable: pt.nullability != Nullability::Required as i32,
274                type_variation_reference: pt.type_variation_reference,
275            })
276        }
277        Kind::PrecisionTimestampTz(pt) => {
278            let precision = pt.precision;
279            let timestamp_value = parse_timestamp_to_precision_units(
280                &string_value,
281                precision,
282                "precisiontimestamptz",
283                value.as_span(),
284            )?;
285            Ok(Literal {
286                literal_type: Some(LiteralType::PrecisionTimestampTz(LitPrecisionTimestamp {
287                    precision,
288                    value: timestamp_value,
289                })),
290                nullable: pt.nullability != Nullability::Required as i32,
291                type_variation_reference: pt.type_variation_reference,
292            })
293        }
294        Kind::PrecisionTime(pt) => {
295            let precision = pt.precision;
296            let time_value = parse_time_to_precision_units(
297                &string_value,
298                precision,
299                "precisiontime",
300                value.as_span(),
301            )?;
302            Ok(Literal {
303                literal_type: Some(LiteralType::PrecisionTime(LitPrecisionTime {
304                    precision,
305                    value: time_value,
306                })),
307                nullable: pt.nullability != Nullability::Required as i32,
308                type_variation_reference: pt.type_variation_reference,
309            })
310        }
311        _ => {
312            // For other types, treat as string
313            Ok(Literal {
314                literal_type: Some(LiteralType::String(string_value)),
315                nullable: false,
316                type_variation_reference: 0,
317            })
318        }
319    }
320}
321
322fn to_null_literal(
323    value: pest::iterators::Pair<Rule>,
324    typ: Option<Type>,
325) -> Result<Literal, MessageParseError> {
326    assert_eq!(value.as_rule(), Rule::null);
327    let typ = typ.ok_or_else(|| {
328        MessageParseError::invalid(
329            "null_literal_type",
330            value.as_span(),
331            "Null literals require an explicit type annotation, e.g. null:i64?",
332        )
333    })?;
334
335    Ok(Literal {
336        literal_type: Some(LiteralType::Null(typ)),
337        nullable: false,
338        type_variation_reference: 0,
339    })
340}
341
342/// Parse a date string using chrono to days since Unix epoch
343fn parse_date_to_days(date_str: &str, span: pest::Span) -> Result<i32, MessageParseError> {
344    // Try multiple date formats for flexibility
345    let formats = ["%Y-%m-%d", "%Y/%m/%d"];
346
347    for format in &formats {
348        if let Ok(date) = NaiveDate::parse_from_str(date_str, format) {
349            // Calculate days since Unix epoch (1970-01-01)
350            let epoch = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
351            let days = date.signed_duration_since(epoch).num_days();
352            return Ok(days as i32);
353        }
354    }
355
356    Err(MessageParseError::invalid(
357        "date_parse_format",
358        span,
359        format!("Invalid date format: '{date_str}'. Expected YYYY-MM-DD or YYYY/MM/DD"),
360    ))
361}
362
363/// Parse a time string to microseconds(precision 6) since midnight.
364fn parse_time_to_microseconds(time_str: &str, span: pest::Span) -> Result<i64, MessageParseError> {
365    parse_time_to_precision_units(time_str, 6, "time", span)
366}
367
368/// Parse a timestamp string to microseconds since Unix epoch.
369fn parse_timestamp_to_microseconds(
370    timestamp_str: &str,
371    span: pest::Span,
372) -> Result<i64, MessageParseError> {
373    parse_timestamp_to_precision_units(timestamp_str, 6, "timestamp", span)
374}
375
376#[derive(Debug, Clone, Copy)]
377enum SupportedPrecision {
378    Seconds,      // 0
379    Milliseconds, // 3
380    Microseconds, // 6
381    Nanoseconds,  // 9
382}
383
384impl SupportedPrecision {
385    /// The Substrait precision unit exponent (`0`, `3`, `6`, or `9`).
386    fn units(self) -> i32 {
387        match self {
388            SupportedPrecision::Seconds => 0,
389            SupportedPrecision::Milliseconds => 3,
390            SupportedPrecision::Microseconds => 6,
391            SupportedPrecision::Nanoseconds => 9,
392        }
393    }
394}
395
396/// Convert a `chrono::Duration` to the units implied by `precision`.
397/// Errors if `duration` overflows the target unit's i64 range, or if `duration`
398/// carries a fractional component finer than `precision` can represent (e.g.
399/// `.999` seconds can't be represented exactly at precision 0).
400fn duration_to_precision_units(
401    duration: chrono::Duration,
402    precision: SupportedPrecision,
403    literal_kind: &'static str,
404    span: pest::Span,
405) -> Result<i64, MessageParseError> {
406    let out_of_range = || {
407        MessageParseError::invalid(
408            "precision_literal_out_of_range",
409            span,
410            format!(
411                "value is out of range for a {literal_kind} literal at precision {}",
412                precision.units()
413            ),
414        )
415    };
416    let fractional_truncated = || {
417        MessageParseError::invalid(
418            "precision_literal_fractional_truncated",
419            span,
420            format!(
421                "value has a fractional component finer than precision {} can represent for a {literal_kind} literal",
422                precision.units()
423            ),
424        )
425    };
426
427    match precision {
428        SupportedPrecision::Seconds => {
429            let value = duration.num_seconds();
430            if chrono::Duration::seconds(value) != duration {
431                return Err(fractional_truncated());
432            }
433            Ok(value)
434        }
435        SupportedPrecision::Milliseconds => {
436            let value = duration.num_milliseconds();
437            if chrono::Duration::milliseconds(value) != duration {
438                return Err(fractional_truncated());
439            }
440            Ok(value)
441        }
442        SupportedPrecision::Microseconds => {
443            let value = duration.num_microseconds().ok_or_else(out_of_range)?;
444            if chrono::Duration::microseconds(value) != duration {
445                return Err(fractional_truncated());
446            }
447            Ok(value)
448        }
449        // Nanoseconds is the finest precision chrono can represent, so there's
450        // no finer fractional component that could be silently dropped here.
451        SupportedPrecision::Nanoseconds => duration.num_nanoseconds().ok_or_else(out_of_range),
452    }
453}
454
455fn check_supported_precision(
456    precision: i32,
457    literal_kind: &'static str,
458    span: pest::Span,
459) -> Result<SupportedPrecision, MessageParseError> {
460    match precision {
461        0 => return Ok(SupportedPrecision::Seconds),
462        3 => return Ok(SupportedPrecision::Milliseconds),
463        6 => return Ok(SupportedPrecision::Microseconds),
464        9 => return Ok(SupportedPrecision::Nanoseconds),
465        _ => {}
466    }
467    if precision == 12 {
468        return Err(MessageParseError::invalid(
469            "precision_literal_unsupported_precision",
470            span,
471            format!(
472                "precision 12 (picoseconds) is not supported for {literal_kind} literals; chrono only supports nanosecond (precision 9) resolution"
473            ),
474        ));
475    }
476    Err(MessageParseError::invalid(
477        "precision_literal_invalid_precision",
478        span,
479        format!(
480            "Invalid precision {precision} for a {literal_kind} literal; expected one of 0 (seconds), 3 (milliseconds), 6 (microseconds), or 9 (nanoseconds)"
481        ),
482    ))
483}
484
485/// Parse a timestamp string using chrono to a value in the given precision's units since the Unix epoch.
486fn parse_timestamp_to_precision_units(
487    timestamp_str: &str,
488    precision: i32,
489    literal_kind: &'static str,
490    span: pest::Span,
491) -> Result<i64, MessageParseError> {
492    let precision = check_supported_precision(precision, literal_kind, span)?;
493
494    // Try multiple timestamp formats for flexibility
495    let formats = [
496        "%Y-%m-%dT%H:%M:%S%.f", // ISO 8601 with T and fractional seconds
497        "%Y-%m-%dT%H:%M:%S",    // ISO 8601 with T
498        "%Y-%m-%d %H:%M:%S%.f", // Space separator with fractional seconds
499        "%Y-%m-%d %H:%M:%S",    // Space separator
500        "%Y/%m/%dT%H:%M:%S%.f", // Alternative date format with T
501        "%Y/%m/%dT%H:%M:%S",    // Alternative date format with T
502        "%Y/%m/%d %H:%M:%S%.f", // Alternative date format with space
503        "%Y/%m/%d %H:%M:%S",    // Alternative date format with space
504    ];
505
506    for format in &formats {
507        if let Ok(datetime) = NaiveDateTime::parse_from_str(timestamp_str, format) {
508            let epoch = DateTime::from_timestamp(0, 0).unwrap().naive_utc();
509            let duration = datetime.signed_duration_since(epoch);
510            return duration_to_precision_units(duration, precision, literal_kind, span);
511        }
512    }
513
514    Err(MessageParseError::invalid(
515        "timestamp_parse_format",
516        span,
517        format!(
518            "Invalid timestamp format: '{timestamp_str}'. Expected YYYY-MM-DDTHH:MM:SS or YYYY-MM-DD HH:MM:SS"
519        ),
520    ))
521}
522
523/// Parse a time-of-day string using chrono to a value in the given precision's units since midnight.
524fn parse_time_to_precision_units(
525    time_str: &str,
526    precision: i32,
527    literal_kind: &'static str,
528    span: pest::Span,
529) -> Result<i64, MessageParseError> {
530    let precision = check_supported_precision(precision, literal_kind, span)?;
531
532    // Try multiple time formats for flexibility
533    let formats = ["%H:%M:%S%.f", "%H:%M:%S"];
534
535    for format in &formats {
536        if let Ok(time) = NaiveTime::parse_from_str(time_str, format) {
537            let midnight = NaiveTime::from_hms_opt(0, 0, 0).unwrap();
538            let duration = time.signed_duration_since(midnight);
539            return duration_to_precision_units(duration, precision, literal_kind, span);
540        }
541    }
542
543    Err(MessageParseError::invalid(
544        "time_parse_format",
545        span,
546        format!("Invalid time format: '{time_str}'. Expected HH:MM:SS or HH:MM:SS.fff"),
547    ))
548}
549
550impl ScopedParsePair for Literal {
551    fn rule() -> Rule {
552        Rule::literal
553    }
554
555    fn message() -> &'static str {
556        "Literal"
557    }
558
559    fn parse_pair(
560        extensions: &SimpleExtensions,
561        pair: pest::iterators::Pair<Rule>,
562    ) -> Result<Self, MessageParseError> {
563        assert_eq!(pair.as_rule(), Self::rule());
564        let mut pairs = pair.into_inner();
565        let value = pairs.next().unwrap(); // First item is always the value
566        let typ = pairs.next(); // Second item is optional type
567        assert!(pairs.next().is_none());
568        let typ = match typ {
569            Some(t) => Some(Type::parse_pair(extensions, t)?),
570            None => None,
571        };
572        match value.as_rule() {
573            Rule::integer => to_int_literal(value, typ),
574            Rule::float => to_float_literal(value, typ),
575            Rule::boolean => to_boolean_literal(value, typ),
576            Rule::string_literal => to_string_literal(value, typ),
577            Rule::null => to_null_literal(value, typ),
578            _ => unreachable!("Literal unexpected rule: {:?}", value.as_rule()),
579        }
580    }
581}
582
583impl ScopedParsePair for ScalarFunction {
584    fn rule() -> Rule {
585        Rule::function_call
586    }
587
588    fn message() -> &'static str {
589        "ScalarFunction"
590    }
591
592    fn parse_pair(
593        extensions: &SimpleExtensions,
594        pair: pest::iterators::Pair<Rule>,
595    ) -> Result<Self, MessageParseError> {
596        assert_eq!(pair.as_rule(), Self::rule());
597        let span = pair.as_span();
598        let mut iter = RuleIter::from(pair.into_inner());
599
600        // Parse compound function name (required) — e.g. "equal" or "equal:any_any"
601        let name = iter.parse_next::<CompoundName>();
602
603        // Parse optional anchor (e.g., #1)
604        let anchor = iter
605            .try_pop(Rule::anchor)
606            .map(|n| unwrap_single_pair(n).as_str().parse::<u32>().unwrap());
607
608        // Parse optional URN anchor (e.g., @1)
609        let _urn_anchor = iter
610            .try_pop(Rule::urn_anchor)
611            .map(|n| unwrap_single_pair(n).as_str().parse::<u32>().unwrap());
612
613        // Parse argument list (required)
614        let argument_list = iter.pop(Rule::argument_list);
615        let mut arguments = Vec::new();
616        for e in argument_list.into_inner() {
617            arguments.push(FunctionArgument {
618                arg_type: Some(ArgType::Value(Expression::parse_pair(extensions, e)?)),
619            });
620        }
621
622        // Parse required output type (e.g., :i64). pop is safe here because
623        // the grammar guarantees the type token is always present.
624        let output_type = Some(Type::parse_pair(extensions, iter.pop(Rule::r#type))?);
625
626        iter.done();
627        let anchor = get_and_validate_anchor(
628            extensions,
629            ExtensionKind::Function,
630            anchor,
631            name.full(),
632            span,
633        )?;
634        Ok(ScalarFunction {
635            function_reference: anchor,
636            arguments,
637            options: vec![], // TODO: Function Options
638            output_type,
639            #[allow(deprecated)]
640            args: vec![],
641        })
642    }
643}
644
645impl ScopedParsePair for Cast {
646    fn rule() -> Rule {
647        Rule::cast_expression
648    }
649
650    fn message() -> &'static str {
651        "Cast"
652    }
653
654    fn parse_pair(
655        extensions: &SimpleExtensions,
656        pair: pest::iterators::Pair<Rule>,
657    ) -> Result<Self, MessageParseError> {
658        assert_eq!(pair.as_rule(), Self::rule());
659        let mut pairs = pair.into_inner();
660
661        let expr_pair = pairs.next().unwrap();
662
663        // Optional failure behavior prefix: ? = RETURN_NULL, ! = THROW_EXCEPTION
664        let next = pairs.next().unwrap();
665        let (failure_behavior, type_pair) = if next.as_rule() == Rule::cast_failure_behavior {
666            let fb = match next.as_str() {
667                "?" => cast::FailureBehavior::ReturnNull as i32,
668                "!" => cast::FailureBehavior::ThrowException as i32,
669                _ => unreachable!("Grammar guarantees cast_failure_behavior is ? or !"),
670            };
671            (fb, pairs.next().unwrap())
672        } else {
673            (cast::FailureBehavior::Unspecified as i32, next)
674        };
675
676        assert!(pairs.next().is_none());
677
678        let input = Expression::parse_pair(extensions, expr_pair)?;
679        let target_type = Type::parse_pair(extensions, type_pair)?;
680
681        Ok(Cast {
682            r#type: Some(target_type),
683            input: Some(Box::new(input)),
684            failure_behavior,
685        })
686    }
687}
688
689impl ScopedParsePair for Expression {
690    fn rule() -> Rule {
691        Rule::expression
692    }
693
694    fn message() -> &'static str {
695        "Expression"
696    }
697
698    fn parse_pair(
699        extensions: &SimpleExtensions,
700        pair: pest::iterators::Pair<Rule>,
701    ) -> Result<Self, MessageParseError> {
702        assert_eq!(pair.as_rule(), Self::rule());
703        let inner = unwrap_single_pair(pair);
704        match inner.as_rule() {
705            Rule::literal => Ok(Expression {
706                rex_type: Some(RexType::Literal(Literal::parse_pair(extensions, inner)?)),
707            }),
708            Rule::function_call => Ok(Expression {
709                rex_type: Some(RexType::ScalarFunction(ScalarFunction::parse_pair(
710                    extensions, inner,
711                )?)),
712            }),
713            Rule::reference => Ok(Expression {
714                rex_type: Some(RexType::Selection(Box::new(FieldReference::parse_pair(
715                    inner,
716                )))),
717            }),
718            Rule::if_then => Ok(Expression {
719                rex_type: Some(RexType::IfThen(Box::new(IfThen::parse_pair(
720                    extensions, inner,
721                )?))),
722            }),
723            Rule::cast_expression => Ok(Expression {
724                rex_type: Some(RexType::Cast(Box::new(Cast::parse_pair(
725                    extensions, inner,
726                )?))),
727            }),
728            _ => unreachable!(
729                "Grammar guarantees expression can only be literal, function_call, reference, if_then, or cast_expression, got: {:?}",
730                inner.as_rule()
731            ),
732        }
733    }
734}
735
736impl ScopedParsePair for IfClause {
737    fn rule() -> Rule {
738        Rule::if_clause
739    }
740
741    fn message() -> &'static str {
742        "IfClause"
743    }
744
745    fn parse_pair(
746        extensions: &SimpleExtensions,
747        pair: pest::iterators::Pair<Rule>,
748    ) -> Result<Self, MessageParseError> {
749        assert_eq!(pair.as_rule(), Self::rule());
750        let mut pairs = pair.into_inner(); // should have 2 children, 2 expressions
751
752        let condition = pairs.next().unwrap();
753        let result = pairs.next().unwrap();
754        assert!(pairs.next().is_none());
755
756        let ex1 = Some(Expression::parse_pair(extensions, condition)?);
757        let ex2 = Some(Expression::parse_pair(extensions, result)?);
758
759        Ok(IfClause {
760            r#if: ex1,
761            then: ex2,
762        })
763    }
764}
765
766impl ScopedParsePair for IfThen {
767    fn rule() -> Rule {
768        Rule::if_then
769    }
770    fn message() -> &'static str {
771        "IfThen"
772    }
773
774    fn parse_pair(
775        extensions: &SimpleExtensions,
776        pair: pest::iterators::Pair<Rule>,
777    ) -> Result<Self, MessageParseError> {
778        assert_eq!(pair.as_rule(), Self::rule());
779
780        let mut iter = RuleIter::from(pair.into_inner()); // should have 2 or more children
781
782        let mut ifs: Vec<IfClause> = Vec::new();
783
784        // gets all of the if clauses
785        while let Some(p) = iter.try_pop(Rule::if_clause) {
786            let if_clause = IfClause::parse_pair(extensions, p)?;
787            ifs.push(if_clause);
788        }
789
790        let pair = iter.try_pop(Rule::expression).unwrap(); // should be else expression
791        iter.done();
792        let else_clause = Some(Box::new(Expression::parse_pair(extensions, pair)?));
793
794        Ok(IfThen {
795            ifs,
796            r#else: else_clause,
797        })
798    }
799}
800pub struct Name(pub String);
801
802impl ParsePair for Name {
803    fn rule() -> Rule {
804        Rule::name
805    }
806
807    fn message() -> &'static str {
808        "Name"
809    }
810
811    fn parse_pair(pair: pest::iterators::Pair<Rule>) -> Self {
812        assert_eq!(pair.as_rule(), Self::rule());
813        let inner = unwrap_single_pair(pair);
814        match inner.as_rule() {
815            Rule::identifier => Name(inner.as_str().to_string()),
816            Rule::quoted_name => Name(unescape_string(inner)),
817            _ => unreachable!("Name unexpected rule: {:?}", inner.as_rule()),
818        }
819    }
820}
821
822impl ParsePair for CompoundName {
823    fn rule() -> Rule {
824        Rule::function_signature
825    }
826
827    fn message() -> &'static str {
828        "CompoundName"
829    }
830
831    fn parse_pair(pair: pest::iterators::Pair<Rule>) -> Self {
832        assert_eq!(pair.as_rule(), Self::rule());
833        CompoundName::new(pair.as_str())
834    }
835}
836
837impl ScopedParsePair for Measure {
838    fn rule() -> Rule {
839        Rule::function_call
840    }
841
842    fn message() -> &'static str {
843        "Measure"
844    }
845
846    fn parse_pair(
847        extensions: &SimpleExtensions,
848        pair: pest::iterators::Pair<Rule>,
849    ) -> Result<Self, MessageParseError> {
850        assert_eq!(pair.as_rule(), Self::rule());
851
852        // Parse as ScalarFunction, then convert to AggregateFunction
853        let scalar = ScalarFunction::parse_pair(extensions, pair)?;
854        Ok(Measure {
855            measure: Some(AggregateFunction {
856                function_reference: scalar.function_reference,
857                arguments: scalar.arguments,
858                options: scalar.options,
859                output_type: scalar.output_type,
860                invocation: 0, // TODO: support invocation (ALL, DISTINCT, etc.)
861                phase: 0, // TODO: support phase (INITIAL_TO_RESULT, PARTIAL_TO_INTERMEDIATE, etc.)
862                sorts: vec![], // TODO: support sorts for ordered aggregates
863                #[allow(deprecated)]
864                args: scalar.args,
865            }),
866            filter: None, // TODO: support filter conditions on aggregate measures
867        })
868    }
869}
870
871#[cfg(test)]
872mod tests {
873    use pest::Parser as PestParser;
874
875    use super::*;
876    use crate::parser::ExpressionParser;
877
878    fn parse_exact(rule: Rule, input: &'_ str) -> pest::iterators::Pair<'_, Rule> {
879        let mut pairs = ExpressionParser::parse(rule, input).unwrap();
880        assert_eq!(pairs.as_str(), input);
881        let pair = pairs.next().unwrap();
882        assert_eq!(pairs.next(), None);
883        pair
884    }
885
886    fn assert_parses_to<T: ParsePair + PartialEq + std::fmt::Debug>(input: &str, expected: T) {
887        let pair = parse_exact(T::rule(), input);
888        let actual = T::parse_pair(pair);
889        assert_eq!(actual, expected);
890    }
891
892    fn assert_parses_with<T: ScopedParsePair + PartialEq + std::fmt::Debug>(
893        ext: &SimpleExtensions,
894        input: &str,
895        expected: T,
896    ) {
897        let pair = parse_exact(T::rule(), input);
898        let actual = T::parse_pair(ext, pair).unwrap();
899        assert_eq!(actual, expected);
900    }
901
902    #[test]
903    fn test_parse_field_reference() {
904        assert_parses_to("$1", FieldIndex(1).to_field_reference());
905    }
906
907    #[test]
908    fn test_parse_integer_literal() {
909        let extensions = SimpleExtensions::default();
910        let expected = Literal {
911            literal_type: Some(LiteralType::I64(1)),
912            nullable: false,
913            type_variation_reference: 0,
914        };
915        assert_parses_with(&extensions, "1", expected);
916    }
917
918    #[test]
919    fn test_parse_float_literal() {
920        // First test that the grammar can parse floats
921        let pairs = ExpressionParser::parse(Rule::float, "3.82").unwrap();
922        let parsed_text = pairs.as_str();
923        assert_eq!(parsed_text, "3.82");
924
925        let extensions = SimpleExtensions::default();
926        let expected = Literal {
927            literal_type: Some(LiteralType::Fp64(3.82)),
928            nullable: false,
929            type_variation_reference: 0,
930        };
931        assert_parses_with(&extensions, "3.82", expected);
932    }
933
934    #[test]
935    fn test_parse_negative_float_literal() {
936        let extensions = SimpleExtensions::default();
937        let expected = Literal {
938            literal_type: Some(LiteralType::Fp64(-2.5)),
939            nullable: false,
940            type_variation_reference: 0,
941        };
942        assert_parses_with(&extensions, "-2.5", expected);
943    }
944
945    #[test]
946    fn test_parse_boolean_true_literal() {
947        let extensions = SimpleExtensions::default();
948        let expected = Literal {
949            literal_type: Some(LiteralType::Boolean(true)),
950            nullable: false,
951            type_variation_reference: 0,
952        };
953        assert_parses_with(&extensions, "true", expected);
954    }
955
956    #[test]
957    fn test_parse_boolean_false_literal() {
958        let extensions = SimpleExtensions::default();
959        let expected = Literal {
960            literal_type: Some(LiteralType::Boolean(false)),
961            nullable: false,
962            type_variation_reference: 0,
963        };
964        assert_parses_with(&extensions, "false", expected);
965    }
966
967    #[test]
968    fn test_parse_nullable_boolean_literal() {
969        let extensions = SimpleExtensions::default();
970        let expected_true = Literal {
971            literal_type: Some(LiteralType::Boolean(true)),
972            nullable: true,
973            type_variation_reference: 0,
974        };
975        let expected_false = Literal {
976            literal_type: Some(LiteralType::Boolean(false)),
977            nullable: true,
978            type_variation_reference: 0,
979        };
980        assert_parses_with(&extensions, "true:boolean?", expected_true);
981        assert_parses_with(&extensions, "false:boolean?", expected_false);
982    }
983
984    #[test]
985    fn test_parse_nullable_integer_literal() {
986        let extensions = SimpleExtensions::default();
987        let expected_i32 = Literal {
988            literal_type: Some(LiteralType::I32(78)),
989            nullable: true,
990            type_variation_reference: 0,
991        };
992        let expected_i64 = Literal {
993            literal_type: Some(LiteralType::I64(42)),
994            nullable: true,
995            type_variation_reference: 0,
996        };
997        assert_parses_with(&extensions, "78:i32?", expected_i32);
998        assert_parses_with(&extensions, "42:i64?", expected_i64);
999    }
1000
1001    #[test]
1002    fn test_parse_nullable_float_literal() {
1003        let extensions = SimpleExtensions::default();
1004        let expected_fp64 = Literal {
1005            literal_type: Some(LiteralType::Fp64(3.19)),
1006            nullable: true,
1007            type_variation_reference: 0,
1008        };
1009        assert_parses_with(&extensions, "3.19:fp64?", expected_fp64);
1010    }
1011
1012    #[test]
1013    fn test_parse_float_literal_with_fp32_type() {
1014        let extensions = SimpleExtensions::default();
1015        let pair = parse_exact(Rule::literal, "3.82:fp32");
1016        let result = Literal::parse_pair(&extensions, pair).unwrap();
1017
1018        match result.literal_type {
1019            Some(LiteralType::Fp32(val)) => assert!((val - 3.82).abs() < f32::EPSILON),
1020            _ => panic!("Expected Fp32 literal type"),
1021        }
1022    }
1023
1024    #[test]
1025    fn test_parse_date_literal() {
1026        let extensions = SimpleExtensions::default();
1027        let pair = parse_exact(Rule::literal, "'2023-12-25':date");
1028        let result = Literal::parse_pair(&extensions, pair).unwrap();
1029
1030        match result.literal_type {
1031            Some(LiteralType::Date(days)) => {
1032                // 2023-12-25 should be a positive number of days since 1970-01-01
1033                assert!(
1034                    days > 0,
1035                    "Expected positive days since epoch, got: {}",
1036                    days
1037                );
1038            }
1039            _ => panic!("Expected Date literal type, got: {:?}", result.literal_type),
1040        }
1041    }
1042
1043    #[test]
1044    fn test_parse_time_literal() {
1045        let extensions = SimpleExtensions::default();
1046        let pair = parse_exact(Rule::literal, "'14:30:45':time");
1047        let result = Literal::parse_pair(&extensions, pair).unwrap();
1048
1049        match result.literal_type {
1050            #[allow(deprecated)]
1051            Some(LiteralType::Time(microseconds)) => {
1052                // 14:30:45 = (14*3600 + 30*60 + 45) * 1_000_000 microseconds
1053                let expected = (14 * 3600 + 30 * 60 + 45) * 1_000_000;
1054                assert_eq!(microseconds, expected);
1055            }
1056            _ => panic!("Expected Time literal type, got: {:?}", result.literal_type),
1057        }
1058    }
1059
1060    #[test]
1061    fn test_parse_timestamp_literal_with_t() {
1062        let extensions = SimpleExtensions::default();
1063        let pair = parse_exact(Rule::literal, "'2023-01-01T12:00:00':timestamp");
1064        let result = Literal::parse_pair(&extensions, pair).unwrap();
1065
1066        match result.literal_type {
1067            #[allow(deprecated)]
1068            Some(LiteralType::Timestamp(microseconds)) => {
1069                assert!(
1070                    microseconds > 0,
1071                    "Expected positive microseconds since epoch"
1072                );
1073            }
1074            _ => panic!(
1075                "Expected Timestamp literal type, got: {:?}",
1076                result.literal_type
1077            ),
1078        }
1079    }
1080
1081    #[test]
1082    fn test_parse_timestamp_literal_with_space() {
1083        let extensions = SimpleExtensions::default();
1084        let pair = parse_exact(Rule::literal, "'2023-01-01 12:00:00':timestamp");
1085        let result = Literal::parse_pair(&extensions, pair).unwrap();
1086
1087        match result.literal_type {
1088            #[allow(deprecated)]
1089            Some(LiteralType::Timestamp(microseconds)) => {
1090                assert!(
1091                    microseconds > 0,
1092                    "Expected positive microseconds since epoch"
1093                );
1094            }
1095            _ => panic!(
1096                "Expected Timestamp literal type, got: {:?}",
1097                result.literal_type
1098            ),
1099        }
1100    }
1101
1102    #[test]
1103    fn test_parse_precision_timestamp_literal() {
1104        let extensions = SimpleExtensions::default();
1105        let pair = parse_exact(
1106            Rule::literal,
1107            "'2023-01-01T12:00:00.123456789':precisiontimestamp<9>",
1108        );
1109        let result = Literal::parse_pair(&extensions, pair).unwrap();
1110
1111        match result.literal_type {
1112            Some(LiteralType::PrecisionTimestamp(p)) => {
1113                assert_eq!(p.precision, 9);
1114                assert!(p.value > 0, "Expected positive value since epoch");
1115                // p.value is total nanoseconds since epoch; mod 1e9 isolates just
1116                // the sub-second fraction, i.e. the ".123456789" part of the input.
1117                assert_eq!(p.value % 1_000_000_000, 123_456_789);
1118            }
1119            _ => panic!(
1120                "Expected PrecisionTimestamp literal type, got: {:?}",
1121                result.literal_type
1122            ),
1123        }
1124        assert!(!result.nullable);
1125    }
1126
1127    #[test]
1128    fn test_parse_precision_timestamp_tz_literal_nullable() {
1129        let extensions = SimpleExtensions::default();
1130        let pair = parse_exact(
1131            Rule::literal,
1132            "'2023-01-01T12:00:00.123':precisiontimestamptz?<3>",
1133        );
1134        let result = Literal::parse_pair(&extensions, pair).unwrap();
1135
1136        match result.literal_type {
1137            Some(LiteralType::PrecisionTimestampTz(p)) => {
1138                assert_eq!(p.precision, 3);
1139                assert_eq!(p.value % 1000, 123);
1140            }
1141            _ => panic!(
1142                "Expected PrecisionTimestampTz literal type, got: {:?}",
1143                result.literal_type
1144            ),
1145        }
1146        assert!(result.nullable);
1147    }
1148
1149    #[test]
1150    fn test_parse_precision_time_literal() {
1151        let extensions = SimpleExtensions::default();
1152        let pair = parse_exact(Rule::literal, "'14:30:45.123456':precisiontime<6>");
1153        let result = Literal::parse_pair(&extensions, pair).unwrap();
1154
1155        match result.literal_type {
1156            Some(LiteralType::PrecisionTime(p)) => {
1157                assert_eq!(p.precision, 6);
1158                let expected = (14 * 3600 + 30 * 60 + 45) * 1_000_000 + 123_456;
1159                assert_eq!(p.value, expected);
1160            }
1161            _ => panic!(
1162                "Expected PrecisionTime literal type, got: {:?}",
1163                result.literal_type
1164            ),
1165        }
1166    }
1167
1168    #[test]
1169    fn test_parse_precision_timestamp_literal_precision_12_unsupported() {
1170        let extensions = SimpleExtensions::default();
1171        let pair = parse_exact(
1172            Rule::literal,
1173            "'2023-01-01T12:00:00':precisiontimestamp<12>",
1174        );
1175        let err = Literal::parse_pair(&extensions, pair).unwrap_err();
1176        assert!(err.to_string().contains("picoseconds"));
1177    }
1178
1179    #[test]
1180    fn test_parse_precision_timestamp_literal_invalid_precision() {
1181        let extensions = SimpleExtensions::default();
1182        // 5 isn't a recognized precision for precisiontimestamp, so this should error.
1183        let pair = parse_exact(Rule::literal, "'2023-01-01T12:00:00':precisiontimestamp<5>");
1184        let err = Literal::parse_pair(&extensions, pair).unwrap_err();
1185        assert!(err.to_string().contains("Invalid precision 5"));
1186    }
1187
1188    #[test]
1189    fn test_parse_precision_timestamp_literal_nullable() {
1190        let extensions = SimpleExtensions::default();
1191        let pair = parse_exact(
1192            Rule::literal,
1193            "'2023-01-01T12:00:00.123456789':precisiontimestamp?<9>",
1194        );
1195        let result = Literal::parse_pair(&extensions, pair).unwrap();
1196        assert!(result.nullable);
1197    }
1198
1199    #[test]
1200    fn test_parse_precision_time_literal_nullable() {
1201        let extensions = SimpleExtensions::default();
1202        let pair = parse_exact(Rule::literal, "'14:30:45.123456':precisiontime?<6>");
1203        let result = Literal::parse_pair(&extensions, pair).unwrap();
1204        assert!(result.nullable);
1205    }
1206
1207    #[test]
1208    fn test_parse_precision_timestamp_literal_fractional_truncated() {
1209        let extensions = SimpleExtensions::default();
1210        // precisiontimestamp<0> declares second resolution, but the value has a
1211        // fractional second; this must error rather than silently drop the ".999".
1212        let pair = parse_exact(
1213            Rule::literal,
1214            "'2023-01-01T12:00:00.999':precisiontimestamp<0>",
1215        );
1216        let err = Literal::parse_pair(&extensions, pair).unwrap_err();
1217        assert!(err.to_string().contains("fractional"));
1218    }
1219
1220    #[test]
1221    fn test_parse_precision_time_literal_fractional_truncated() {
1222        let extensions = SimpleExtensions::default();
1223        // precisiontime<3> declares millisecond resolution, but the value has
1224        // more fractional digits than that; this must error, not truncate.
1225        let pair = parse_exact(Rule::literal, "'14:30:45.123456':precisiontime<3>");
1226        let err = Literal::parse_pair(&extensions, pair).unwrap_err();
1227        assert!(err.to_string().contains("fractional"));
1228    }
1229
1230    #[test]
1231    fn test_parse_precision_timestamp_literal_nanosecond_overflow() {
1232        let extensions = SimpleExtensions::default();
1233        // 2300 is past chrono's ~292-year-around-1970 nanosecond range,
1234        // so this must error rather than silently parsing to some truncated or zeroed value.
1235        let pair = parse_exact(Rule::literal, "'2300-01-01T00:00:00':precisiontimestamp<9>");
1236        let err = Literal::parse_pair(&extensions, pair).unwrap_err();
1237        assert!(err.to_string().contains("out of range"));
1238    }
1239
1240    /// Helper function to create a literal boolean expression
1241    fn make_literal_bool(value: bool) -> Expression {
1242        Expression {
1243            rex_type: Some(RexType::Literal(Literal {
1244                literal_type: Some(LiteralType::Boolean(value)),
1245                nullable: false,
1246                type_variation_reference: 0,
1247            })),
1248        }
1249    }
1250
1251    #[test]
1252    fn test_parse_if_then_single_clause() {
1253        let extensions = SimpleExtensions::default();
1254        let input = "if_then(true -> 42, _ -> 0)";
1255        let pair = parse_exact(Rule::if_then, input);
1256        let result = IfThen::parse_pair(&extensions, pair).unwrap();
1257
1258        assert_eq!(result.ifs.len(), 1);
1259        assert!(result.r#else.is_some());
1260    }
1261
1262    #[test]
1263    fn test_parse_if_then_with_typed_literals() {
1264        let extensions = SimpleExtensions::default();
1265        let input = "if_then(true -> 100:i32, _ -> -100:i32)";
1266        let pair = parse_exact(Rule::if_then, input);
1267        let result = IfThen::parse_pair(&extensions, pair).unwrap();
1268
1269        assert_eq!(result.ifs.len(), 1);
1270        assert!(result.r#else.is_some());
1271    }
1272
1273    #[test]
1274    fn test_parse_if_then_with_date_literals() {
1275        let extensions = SimpleExtensions::default();
1276        let input = "if_then(true -> '2023-12-25':date, _ -> '1970-01-01':date)";
1277        let pair = parse_exact(Rule::if_then, input);
1278        let result = IfThen::parse_pair(&extensions, pair).unwrap();
1279
1280        assert_eq!(result.ifs.len(), 1);
1281        assert!(result.r#else.is_some());
1282    }
1283
1284    #[test]
1285    fn test_parse_if_then_with_time_literals() {
1286        let extensions = SimpleExtensions::default();
1287        let input = "if_then(true -> '14:30:45':time, _ -> '00:00:00':time)";
1288        let pair = parse_exact(Rule::if_then, input);
1289        let result = IfThen::parse_pair(&extensions, pair).unwrap();
1290
1291        assert_eq!(result.ifs.len(), 1);
1292        assert!(result.r#else.is_some());
1293    }
1294
1295    #[test]
1296    fn test_parse_if_then_with_timestamp_literals() {
1297        let extensions = SimpleExtensions::default();
1298        let input = "if_then(true -> '2023-01-01T12:00:00':timestamp, _ -> '1970-01-01T00:00:00':timestamp)";
1299        let pair = parse_exact(Rule::if_then, input);
1300        let result = IfThen::parse_pair(&extensions, pair).unwrap();
1301
1302        assert_eq!(result.ifs.len(), 1);
1303        assert!(result.r#else.is_some());
1304    }
1305
1306    #[test]
1307    fn test_parse_if_clause_with_whitespace_variations() {
1308        let extensions = SimpleExtensions::default();
1309
1310        // Test with various whitespace patterns
1311        let inputs = vec!["true->false", "true -> false", "true  ->  false"];
1312
1313        for input in inputs {
1314            let pair = parse_exact(Rule::if_clause, input);
1315            let result = IfClause::parse_pair(&extensions, pair).unwrap();
1316            assert!(result.r#if.is_some());
1317            assert!(result.then.is_some());
1318        }
1319    }
1320
1321    #[test]
1322    fn test_if_clause_structure() {
1323        let extensions = SimpleExtensions::default();
1324        let pair = parse_exact(Rule::if_clause, "42 -> 100");
1325        let result = IfClause::parse_pair(&extensions, pair).unwrap();
1326
1327        // Verify the if clause has both condition and result
1328        let if_expr = result.r#if.as_ref().unwrap();
1329        let then_expr = result.then.as_ref().unwrap();
1330
1331        // Check that they are literal expressions
1332        match (&if_expr.rex_type, &then_expr.rex_type) {
1333            (Some(RexType::Literal(_)), Some(RexType::Literal(_))) => {
1334                // Success - both are literals as expected
1335            }
1336            _ => panic!("Expected both if and then to be literals"),
1337        }
1338    }
1339
1340    #[test]
1341    fn test_if_then_structure() {
1342        let extensions = SimpleExtensions::default();
1343        let input = "if_then(true -> 1, false -> 2, _ -> 0)";
1344        let pair = parse_exact(Rule::if_then, input);
1345        let result = IfThen::parse_pair(&extensions, pair).unwrap();
1346
1347        // Verify structure
1348        assert_eq!(result.ifs.len(), 2);
1349
1350        // Check each if clause
1351        for clause in &result.ifs {
1352            assert!(clause.r#if.is_some(), "If clause condition should exist");
1353            assert!(clause.then.is_some(), "If clause result should exist");
1354        }
1355
1356        // Check else clause
1357        assert!(result.r#else.is_some(), "Else clause should exist");
1358    }
1359
1360    #[test]
1361    fn test_parse_if_then_mixed_types_in_conditions() {
1362        let extensions = SimpleExtensions::default();
1363        // Different types in conditions (not results)
1364        let input = "if_then(true -> 1, true -> 'yes', 'yes' -> true, 42 -> 2, $0 -> 3, _ -> 0)";
1365        let pair = parse_exact(Rule::if_then, input);
1366        let result = IfThen::parse_pair(&extensions, pair).unwrap();
1367
1368        assert_eq!(result.ifs.len(), 5);
1369        assert!(result.r#else.is_some());
1370    }
1371
1372    #[test]
1373    fn test_if_then_preserves_clause_order() {
1374        let extensions = SimpleExtensions::default();
1375        let input = "if_then(1 -> 10, 2 -> 20, 3 -> 30, _ -> 0)";
1376        let pair = parse_exact(Rule::if_then, input);
1377        let result = IfThen::parse_pair(&extensions, pair).unwrap();
1378
1379        assert_eq!(result.ifs.len(), 3);
1380
1381        // Verify the clauses are in order by checking the literal values
1382        for (i, clause) in result.ifs.iter().enumerate() {
1383            if let Some(Expression {
1384                rex_type: Some(RexType::Literal(lit)),
1385            }) = &clause.r#if
1386                && let Some(LiteralType::I64(val)) = &lit.literal_type
1387            {
1388                assert_eq!(*val, (i as i64) + 1);
1389            }
1390        }
1391    }
1392
1393    #[test]
1394    fn test_parse_if_then() {
1395        let extensions = SimpleExtensions::default();
1396
1397        let c1 = IfClause {
1398            r#if: Some(make_literal_bool(true)),
1399            then: Some(make_literal_bool(true)),
1400        };
1401
1402        let c2 = IfClause {
1403            r#if: Some(make_literal_bool(false)),
1404            then: Some(make_literal_bool(false)),
1405        };
1406
1407        let if_clause = IfThen {
1408            ifs: vec![c1, c2],
1409            r#else: Some(Box::new(make_literal_bool(false))),
1410        };
1411        assert_parses_with(
1412            &extensions,
1413            "if_then(true -> true , false -> false, _ -> false)",
1414            if_clause,
1415        );
1416    }
1417
1418    // ---- Tests for function_signature grammar rule ----
1419
1420    fn parse_function_signature(input: &str) -> CompoundName {
1421        let pair = parse_exact(Rule::function_signature, input);
1422        CompoundName::parse_pair(pair)
1423    }
1424
1425    #[test]
1426    fn test_compound_name_plain() {
1427        assert_eq!(parse_function_signature("add").full(), "add");
1428    }
1429
1430    #[test]
1431    fn test_compound_name_full_zero_arg_type_signature() {
1432        // A Full name whose type signature encodes zero argument types (nothing after the colon).
1433        let n = parse_function_signature("add:");
1434        assert_eq!(n.full(), "add:");
1435        assert_eq!(n.base(), "add");
1436        assert!(n.matches("add:"));
1437        assert!(!n.matches("add:i64_i64"));
1438        assert!(n.matches("add"));
1439    }
1440
1441    #[test]
1442    fn test_compound_name_with_signature() {
1443        assert_eq!(
1444            parse_function_signature("equal:any_any").full(),
1445            "equal:any_any"
1446        );
1447        assert_eq!(
1448            parse_function_signature("regexp_match_substring:str_str_i64").full(),
1449            "regexp_match_substring:str_str_i64"
1450        );
1451        assert_eq!(
1452            parse_function_signature("add:i64_i64").full(),
1453            "add:i64_i64"
1454        );
1455    }
1456
1457    #[test]
1458    fn test_compound_name_trailing_colon_grammar() {
1459        // "count:" (trailing colon, zero-arg type signature) parses as a compound name with
1460        // an empty signature suffix: base "count", has_signature true, full "count:".
1461        let name = parse_function_signature("count:");
1462        assert_eq!(name.base(), "count");
1463        assert_eq!(name.full(), "count:");
1464        assert!(
1465            name.has_signature(),
1466            "trailing colon must set has_signature"
1467        );
1468    }
1469
1470    #[test]
1471    fn test_compound_name_stops_at_opening_paren() {
1472        // In a function call, the function_signature must stop before the '('.
1473        let pairs = ExpressionParser::parse(Rule::function_signature, "equal:any_any").unwrap();
1474        assert_eq!(pairs.as_str(), "equal:any_any");
1475    }
1476
1477    // ---- Tests for ScalarFunction parsing with compound names ----
1478
1479    fn make_extensions_for_fn_tests() -> SimpleExtensions {
1480        let mut exts = SimpleExtensions::default();
1481        exts.add_extension_urn("urn".to_string(), 1).unwrap();
1482        exts.add_extension(
1483            crate::extensions::simple::ExtensionKind::Function,
1484            1,
1485            1,
1486            "equal:any_any".to_string(),
1487        )
1488        .unwrap();
1489        exts.add_extension(
1490            crate::extensions::simple::ExtensionKind::Function,
1491            1,
1492            2,
1493            "equal:str_str".to_string(),
1494        )
1495        .unwrap();
1496        exts.add_extension(
1497            crate::extensions::simple::ExtensionKind::Function,
1498            1,
1499            3,
1500            "add:i64_i64".to_string(),
1501        )
1502        .unwrap();
1503        exts
1504    }
1505
1506    #[test]
1507    fn test_scalar_function_full_compound_name() {
1508        // Full compound name without anchor
1509        let exts = make_extensions_for_fn_tests();
1510        let pair = parse_exact(Rule::function_call, "equal:any_any($0, $1):boolean");
1511        let f = ScalarFunction::parse_pair(&exts, pair).unwrap();
1512        assert_eq!(f.function_reference, 1);
1513        assert_eq!(f.arguments.len(), 2);
1514        assert!(
1515            f.output_type.is_some(),
1516            "output_type must be set after parsing"
1517        );
1518    }
1519
1520    #[test]
1521    fn test_scalar_function_second_overload() {
1522        let exts = make_extensions_for_fn_tests();
1523        let pair = parse_exact(Rule::function_call, "equal:str_str($0, $1):boolean");
1524        let f = ScalarFunction::parse_pair(&exts, pair).unwrap();
1525
1526        assert_eq!(f.arguments.len(), 2);
1527        assert_eq!(f.function_reference, 2);
1528    }
1529
1530    #[test]
1531    fn test_scalar_function_base_name_unique_overload() {
1532        // "add" has only one overload; base-name lookup should succeed
1533        let exts = make_extensions_for_fn_tests();
1534        let pair = parse_exact(Rule::function_call, "add($0, $1):i64");
1535        let f = ScalarFunction::parse_pair(&exts, pair).unwrap();
1536
1537        assert_eq!(f.arguments.len(), 2);
1538        assert_eq!(f.function_reference, 3);
1539        assert!(
1540            f.output_type.is_some(),
1541            "output_type must be set after parsing"
1542        );
1543    }
1544
1545    #[test]
1546    fn test_scalar_function_base_name_ambiguous_fails() {
1547        // "equal" has two overloads; base-name lookup should fail
1548        let exts = make_extensions_for_fn_tests();
1549        let pair = parse_exact(Rule::function_call, "equal($0, $1):boolean");
1550        let result = ScalarFunction::parse_pair(&exts, pair);
1551        assert!(result.is_err(), "ambiguous base name should fail");
1552    }
1553
1554    #[test]
1555    fn test_scalar_function_compound_name_with_anchor() {
1556        let exts = make_extensions_for_fn_tests();
1557        let pair = parse_exact(Rule::function_call, "equal:any_any#1($0, $1):boolean");
1558        let f = ScalarFunction::parse_pair(&exts, pair).unwrap();
1559        assert_eq!(f.function_reference, 1);
1560        assert_eq!(f.arguments.len(), 2);
1561    }
1562
1563    #[test]
1564    fn test_scalar_function_base_name_with_anchor() {
1565        // Base name + explicit anchor should resolve (anchor 1 stores equal:any_any)
1566        let exts = make_extensions_for_fn_tests();
1567        let pair = parse_exact(Rule::function_call, "equal#1($0, $1):boolean");
1568        let f = ScalarFunction::parse_pair(&exts, pair).unwrap();
1569        assert_eq!(f.function_reference, 1);
1570        assert_eq!(f.arguments.len(), 2);
1571    }
1572
1573    #[test]
1574    fn test_scalar_function_wrong_name_for_anchor_fails() {
1575        let exts = make_extensions_for_fn_tests();
1576        let pair = parse_exact(Rule::function_call, "like#1($0):boolean");
1577        let result = ScalarFunction::parse_pair(&exts, pair);
1578        assert!(result.is_err(), "mismatched name/anchor should fail");
1579    }
1580
1581    #[test]
1582    fn test_scalar_function_user_defined_type_in_signature() {
1583        // u!-prefixed type segments in function signatures parse and resolve.
1584        let mut exts = SimpleExtensions::default();
1585        exts.add_extension_urn("urn".to_string(), 1).unwrap();
1586        exts.add_extension(
1587            crate::extensions::simple::ExtensionKind::Function,
1588            1,
1589            10,
1590            "json_extract_path:u!json_str".to_string(),
1591        )
1592        .unwrap();
1593
1594        let pair = parse_exact(
1595            Rule::function_call,
1596            "json_extract_path:u!json_str($0, $1):string",
1597        );
1598        let f = ScalarFunction::parse_pair(&exts, pair).unwrap();
1599        assert_eq!(f.function_reference, 10);
1600        assert_eq!(f.arguments.len(), 2);
1601    }
1602
1603    #[test]
1604    fn test_scalar_function_missing_type_fails_to_parse() {
1605        // The grammar requires a type annotation; "add($0, $1)" without ":i64" must fail.
1606        let result = ExpressionParser::parse(Rule::function_call, "add($0, $1)");
1607        assert!(
1608            result.is_err(),
1609            "function call without type annotation should fail to parse"
1610        );
1611    }
1612
1613    #[test]
1614    fn test_parse_cast_expression_basic() {
1615        let extensions = SimpleExtensions::default();
1616        let pair = parse_exact(Rule::cast_expression, "(78:i32)::i16");
1617        let result = Cast::parse_pair(&extensions, pair).unwrap();
1618
1619        // Input should be 78:i32
1620        let input = result.input.as_ref().unwrap();
1621        match &input.rex_type {
1622            Some(RexType::Literal(lit)) => match &lit.literal_type {
1623                Some(LiteralType::I32(v)) => assert_eq!(*v, 78),
1624                other => panic!("Expected I32 literal, got: {:?}", other),
1625            },
1626            other => panic!("Expected literal, got: {:?}", other),
1627        }
1628
1629        // Target type should be i16
1630        let target = result.r#type.as_ref().unwrap();
1631        match &target.kind {
1632            Some(substrait::proto::r#type::Kind::I16(_)) => {}
1633            other => panic!("Expected i16 type, got: {:?}", other),
1634        }
1635
1636        assert_eq!(result.failure_behavior, 0);
1637    }
1638
1639    #[test]
1640    fn test_parse_cast_expression_via_expression_rule() {
1641        let extensions = SimpleExtensions::default();
1642        let pair = parse_exact(Rule::expression, "(78:i32)::i16");
1643        let result = Expression::parse_pair(&extensions, pair).unwrap();
1644
1645        match result.rex_type {
1646            Some(RexType::Cast(_)) => {}
1647            other => panic!("Expected Cast rex type, got: {:?}", other),
1648        }
1649    }
1650
1651    #[test]
1652    fn test_parse_cast_expression_nested() {
1653        let extensions = SimpleExtensions::default();
1654        let pair = parse_exact(Rule::cast_expression, "((78:i32)::i16)::i32");
1655        let result = Cast::parse_pair(&extensions, pair).unwrap();
1656
1657        // Input should itself be a Cast
1658        let input = result.input.as_ref().unwrap();
1659        match &input.rex_type {
1660            Some(RexType::Cast(inner)) => {
1661                let inner_input = inner.input.as_ref().unwrap();
1662                match &inner_input.rex_type {
1663                    Some(RexType::Literal(lit)) => match &lit.literal_type {
1664                        Some(LiteralType::I32(v)) => assert_eq!(*v, 78),
1665                        other => panic!("Expected I32 literal, got: {:?}", other),
1666                    },
1667                    other => panic!("Expected literal, got: {:?}", other),
1668                }
1669            }
1670            other => panic!("Expected inner Cast, got: {:?}", other),
1671        }
1672
1673        match &result.r#type.as_ref().unwrap().kind {
1674            Some(substrait::proto::r#type::Kind::I32(_)) => {}
1675            other => panic!("Expected i32 outer type, got: {:?}", other),
1676        }
1677    }
1678
1679    #[test]
1680    fn test_parse_cast_expression_with_boolean() {
1681        let extensions = SimpleExtensions::default();
1682        let pair = parse_exact(Rule::cast_expression, "(true)::i32");
1683        let result = Cast::parse_pair(&extensions, pair).unwrap();
1684
1685        let input = result.input.as_ref().unwrap();
1686        match &input.rex_type {
1687            Some(RexType::Literal(lit)) => match &lit.literal_type {
1688                Some(LiteralType::Boolean(v)) => assert!(*v),
1689                other => panic!("Expected Boolean literal, got: {:?}", other),
1690            },
1691            other => panic!("Expected literal, got: {:?}", other),
1692        }
1693    }
1694
1695    #[test]
1696    fn test_parse_cast_expression_with_whitespace() {
1697        let extensions = SimpleExtensions::default();
1698        // Grammar allows optional whitespace around the expression and ::
1699        let pair = parse_exact(Rule::cast_expression, "( 78:i32 ) :: i16");
1700        let result = Cast::parse_pair(&extensions, pair).unwrap();
1701        assert!(result.input.is_some());
1702        assert!(result.r#type.is_some());
1703    }
1704
1705    #[test]
1706    fn test_parse_cast_unspecified_failure_behavior() {
1707        let extensions = SimpleExtensions::default();
1708        let pair = parse_exact(Rule::cast_expression, "(78:i32)::i16");
1709        let result = Cast::parse_pair(&extensions, pair).unwrap();
1710        assert_eq!(
1711            result.failure_behavior,
1712            cast::FailureBehavior::Unspecified as i32
1713        );
1714    }
1715
1716    #[test]
1717    fn test_parse_cast_return_null_failure_behavior() {
1718        let extensions = SimpleExtensions::default();
1719        let pair = parse_exact(Rule::cast_expression, "(78:i32)::?i16");
1720        let result = Cast::parse_pair(&extensions, pair).unwrap();
1721        assert_eq!(
1722            result.failure_behavior,
1723            cast::FailureBehavior::ReturnNull as i32
1724        );
1725    }
1726
1727    #[test]
1728    fn test_parse_cast_throw_exception_failure_behavior() {
1729        let extensions = SimpleExtensions::default();
1730        let pair = parse_exact(Rule::cast_expression, "(78:i32)::!i16");
1731        let result = Cast::parse_pair(&extensions, pair).unwrap();
1732        assert_eq!(
1733            result.failure_behavior,
1734            cast::FailureBehavior::ThrowException as i32
1735        );
1736    }
1737
1738    #[test]
1739    fn test_parse_cast_to_user_defined_type_with_u_prefix() {
1740        // Cast target type is a u!-prefixed UDT; exercises the user_defined_type rule in the cast path.
1741        let mut extensions = SimpleExtensions::default();
1742        extensions.add_extension_urn("urn".to_string(), 1).unwrap();
1743        extensions
1744            .add_extension(
1745                crate::extensions::simple::ExtensionKind::Type,
1746                1,
1747                5,
1748                "u!json".to_string(),
1749            )
1750            .unwrap();
1751
1752        let pair = parse_exact(Rule::cast_expression, "($0)::u!json");
1753        let result = Cast::parse_pair(&extensions, pair).unwrap();
1754        match result.r#type.as_ref().unwrap().kind.as_ref().unwrap() {
1755            substrait::proto::r#type::Kind::UserDefined(u) => {
1756                assert_eq!(u.type_reference, 5);
1757            }
1758            other => panic!("expected UserDefined, got {other:?}"),
1759        }
1760    }
1761
1762    #[test]
1763    fn test_function_call_u_prefix_base_name_rejected() {
1764        // u! is not valid in a function call base name. The grammar's function_signature
1765        // rule uses `identifier` as the base, which cannot match "u!" + identifier.
1766        assert!(
1767            ExpressionParser::parse(Rule::function_call, "u!json_get($0)").is_err(),
1768            "u! prefix in function call base name must be rejected by the grammar"
1769        );
1770    }
1771}