(
e: &mut MirScalarExpr,
column_types: &[ReprColumnType],
temp_storage: &RowArena,
)
| 25 | use crate::{Eval, EvalError, MirScalarExpr}; |
| 26 | |
| 27 | pub(super) fn reduce_call_binary( |
| 28 | e: &mut MirScalarExpr, |
| 29 | column_types: &[ReprColumnType], |
| 30 | temp_storage: &RowArena, |
| 31 | ) { |
| 32 | let MirScalarExpr::CallBinary { func, expr1, expr2 } = e else { |
| 33 | unreachable!() |
| 34 | }; |
| 35 | |
| 36 | // Fold/propagate literal-shaped operands first; precompiles below assume |
| 37 | // these have already fired. |
| 38 | if expr1.is_literal() && expr2.is_literal() { |
| 39 | *e = MirScalarExpr::literal(e.eval(&[], temp_storage), e.typ(column_types).scalar_type); |
| 40 | return; |
| 41 | } |
| 42 | if (expr1.is_literal_null() || expr2.is_literal_null()) && func.propagates_nulls() { |
| 43 | *e = MirScalarExpr::literal_null(e.typ(column_types).scalar_type); |
| 44 | return; |
| 45 | } |
| 46 | if let Some(err) = expr1.as_literal_err() { |
| 47 | *e = MirScalarExpr::literal(Err(err.clone()), e.typ(column_types).scalar_type); |
| 48 | return; |
| 49 | } |
| 50 | if let Some(err) = expr2.as_literal_err() { |
| 51 | *e = MirScalarExpr::literal(Err(err.clone()), e.typ(column_types).scalar_type); |
| 52 | return; |
| 53 | } |
| 54 | |
| 55 | // Calls where a literal operand makes the call the identity function on |
| 56 | // the other operand reduce to that operand. |
| 57 | if reduce_call_binary_identity(e) { |
| 58 | return; |
| 59 | } |
| 60 | let MirScalarExpr::CallBinary { func, expr1, expr2 } = e else { |
| 61 | unreachable!() |
| 62 | }; |
| 63 | |
| 64 | // Per-function dispatch. Each precompile fires only if its literal-shaped |
| 65 | // argument is present; otherwise the call falls through unchanged. |
| 66 | match func { |
| 67 | BinaryFunc::IsLikeMatchCaseInsensitive(_) if expr2.is_literal() => { |
| 68 | // We can at least precompile the regex. |
| 69 | precompile_is_like(e, column_types, true); |
| 70 | } |
| 71 | BinaryFunc::IsLikeMatchCaseSensitive(_) if expr2.is_literal() => { |
| 72 | // We can at least precompile the regex. |
| 73 | precompile_is_like(e, column_types, false); |
| 74 | } |
| 75 | BinaryFunc::IsRegexpMatchCaseSensitive(_) | BinaryFunc::IsRegexpMatchCaseInsensitive(_) => { |
| 76 | let case_insensitive = matches!(func, BinaryFunc::IsRegexpMatchCaseInsensitive(_)); |
| 77 | if let MirScalarExpr::Literal(Ok(row), _) = &**expr2 { |
| 78 | *e = match Regex::new(row.unpack_first().unwrap_str(), case_insensitive) { |
| 79 | Ok(regex) => expr1 |
| 80 | .take() |
| 81 | .call_unary(UnaryFunc::IsRegexpMatch(func::IsRegexpMatch(regex))), |
| 82 | Err(err) => { |
| 83 | MirScalarExpr::literal(Err(err.into()), e.typ(column_types).scalar_type) |
| 84 | } |
no test coverage detected