Returns the special-case handling for a particular function, if it exists.
(func: &UnaryFunc)
| 556 | impl SpecialUnary { |
| 557 | /// Returns the special-case handling for a particular function, if it exists. |
| 558 | fn for_func(func: &UnaryFunc) -> Option<SpecialUnary> { |
| 559 | /// Eager in the same sense as `func.rs` uses the term; this assumes that |
| 560 | /// nulls and errors propagate up, and we only need to define the behaviour |
| 561 | /// on values. |
| 562 | fn eagerly<'b>( |
| 563 | spec: ResultSpec<'b>, |
| 564 | value_fn: impl FnOnce(Values<'b>) -> ResultSpec<'b>, |
| 565 | ) -> ResultSpec<'b> { |
| 566 | let result = match spec.values { |
| 567 | Values::Empty => ResultSpec::nothing(), |
| 568 | other => value_fn(other), |
| 569 | }; |
| 570 | ResultSpec { |
| 571 | fallible: spec.fallible || result.fallible, |
| 572 | nullable: spec.nullable || result.nullable, |
| 573 | values: result.values, |
| 574 | } |
| 575 | } |
| 576 | match func { |
| 577 | UnaryFunc::TryParseMonotonicIso8601Timestamp(_) => Some(SpecialUnary { |
| 578 | map_fn: |specs, range| { |
| 579 | let expr = MirScalarExpr::CallUnary { |
| 580 | func: UnaryFunc::TryParseMonotonicIso8601Timestamp( |
| 581 | crate::func::TryParseMonotonicIso8601Timestamp, |
| 582 | ), |
| 583 | expr: Box::new(MirScalarExpr::column(0)), |
| 584 | }; |
| 585 | let eval = |d| specs.eval_result(expr.eval(&[d], specs.arena)); |
| 586 | |
| 587 | eagerly(range, |values| { |
| 588 | match values { |
| 589 | Values::Within(a, b) if a == b => eval(a), |
| 590 | Values::Within(a, b) => { |
| 591 | let spec = eval(a).union(eval(b)); |
| 592 | let values_spec = if spec.nullable { |
| 593 | // At least one of the endpoints of the range wasn't a valid |
| 594 | // timestamp. We can't compute a precise range in this case. |
| 595 | // If we used the general is_monotone handling, that code would |
| 596 | // incorrectly assume the whole range mapped to null if each |
| 597 | // endpoint did. |
| 598 | ResultSpec::value_all() |
| 599 | } else { |
| 600 | spec |
| 601 | }; |
| 602 | // A range of strings will always contain strings that don't parse |
| 603 | // as timestamps - so unlike the general case, we'll assume null |
| 604 | // is present in every range of output values. |
| 605 | values_spec.union(ResultSpec::null()) |
| 606 | } |
| 607 | // Otherwise, assume the worst: this function may return either a valid |
| 608 | // value or null. |
| 609 | _ => ResultSpec::any_infallible(), |
| 610 | } |
| 611 | }) |
| 612 | }, |
| 613 | pushdownable: true, |
| 614 | }), |
| 615 | _ => None, |
nothing calls this directly
no test coverage detected