Path: blob/main/crates/polars-plan/src/plans/optimizer/simplify_expr/arity.rs
7889 views
use super::*;1use crate::dsl::Operator;23pub(super) fn simplify_binary(4left: Node,5op: Operator,6right: Node,7ctx: OptimizeExprContext,8expr_arena: &mut Arena<AExpr>,9) -> Option<AExpr> {10let in_filter = ctx.in_filter;1112use Operator as O;13match op {14O::And => {15let left_ae = expr_arena.get(left);16let right_ae = expr_arena.get(right);1718// true AND x => x19if matches!(20left_ae,21AExpr::Literal(lv) if lv.bool() == Some(true)22) && in_filter23{24// Only in filter as we might change the name from "literal"25// to whatever lhs columns is.26return Some(right_ae.clone());27}2829// x AND true => x30if matches!(31right_ae,32AExpr::Literal(lv) if lv.bool() == Some(true)33) {34return Some(left_ae.clone());35}3637// x AND false -> false38// FIXME: we need an optimizer redesign to allow x & false to be optimized39// in general as we can forget the length of a series otherwise.40// In filter we allow it as the length is not important there.41if (is_scalar_ae(left, expr_arena) | in_filter)42&& matches!(43right_ae,44AExpr::Literal(lv) if lv.bool() == Some(false)45)46{47return Some(AExpr::Literal(Scalar::from(false).into()));48}49},50O::Or => {51let left_ae = expr_arena.get(left);52let right_ae = expr_arena.get(right);5354// false OR x => x55if matches!(56left_ae,57AExpr::Literal(lv) if lv.bool() == Some(false)58) && in_filter59{60// Only in filter as we might change the name from "literal"61// to whatever lhs columns is.62return Some(right_ae.clone());63}6465// x OR false => x66if matches!(67right_ae,68AExpr::Literal(lv) if lv.bool() == Some(false)69) {70return Some(left_ae.clone());71}72// true OR x => true73// FIXME: we need an optimizer redesign to allow true | x to be optimized74// in general as we can forget the length of a series otherwise.75// In filter we allow it as the length is not important there.76if (is_scalar_ae(left, expr_arena) | in_filter)77&& matches!(78right_ae,79AExpr::Literal(lv) if lv.bool() == Some(true)80)81{82return Some(AExpr::Literal(Scalar::from(true).into()));83}8485// x OR true => true86// FIXME: we need an optimizer redesign to allow true | x to be optimized87// in general as we can forget the length of a series otherwise.88// In filter we allow it as the length is not important there.89if matches!(90left_ae,91AExpr::Literal(lv) if lv.bool() == Some(true)92) && (is_scalar_ae(right, expr_arena) | in_filter)93{94return Some(AExpr::Literal(Scalar::from(true).into()));95}96},9798_ => {},99}100None101}102103pub(super) fn simplify_ternary(104predicate: Node,105truthy: Node,106falsy: Node,107expr_arena: &mut Arena<AExpr>,108) -> Option<AExpr> {109let predicate = expr_arena.get(predicate);110111if let AExpr::Literal(lv) = predicate {112match lv.bool() {113None => {},114Some(true) => {115// Only replace if both are scalar or both are not scalar and are the same length,116// the latter is tested by checking if they are elementwise.117let t_is_scalar = is_scalar_ae(truthy, expr_arena);118let f_is_scalar = is_scalar_ae(falsy, expr_arena);119120if t_is_scalar == f_is_scalar121&& is_elementwise_rec(truthy, expr_arena)122&& is_elementwise_rec(falsy, expr_arena)123{124return Some(expr_arena.get(truthy).clone());125}126},127Some(false) => {128let t_is_scalar = is_scalar_ae(truthy, expr_arena);129let f_is_scalar = is_scalar_ae(falsy, expr_arena);130131if t_is_scalar == f_is_scalar132&& is_elementwise_rec(truthy, expr_arena)133&& is_elementwise_rec(falsy, expr_arena)134{135return Some(expr_arena.get(falsy).clone());136}137},138}139}140141None142}143144145