Skip to main content

substrait_explain/parser/
expressions.rs

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