Path: blob/main/crates/polars-plan/src/plans/aexpr/builder.rs
6940 views
use polars_core::chunked_array::cast::CastOptions;1use polars_core::prelude::{DataType, SortMultipleOptions, SortOptions};2use polars_core::scalar::Scalar;3use polars_utils::IdxSize;4use polars_utils::arena::{Arena, Node};5use polars_utils::pl_str::PlSmallStr;67use super::{AExpr, IRAggExpr, IRBooleanFunction, IRFunctionExpr, RowEncodingVariant};8use crate::dsl::Operator;9use crate::plans::{ExprIR, LiteralValue, OutputName};1011#[derive(Clone, Copy)]12pub struct AExprBuilder {13node: Node,14}1516impl AExprBuilder {17pub fn new_from_node(node: Node) -> Self {18Self { node }19}2021pub fn new_from_aexpr(expr: AExpr, arena: &mut Arena<AExpr>) -> Self {22Self::new_from_node(arena.add(expr))23}2425pub fn lit(lit: LiteralValue, arena: &mut Arena<AExpr>) -> Self {26Self::new_from_aexpr(AExpr::Literal(lit), arena)27}2829pub fn lit_scalar(scalar: Scalar, arena: &mut Arena<AExpr>) -> Self {30Self::lit(LiteralValue::Scalar(scalar), arena)31}3233pub fn col(name: impl Into<PlSmallStr>, arena: &mut Arena<AExpr>) -> Self {34Self::new_from_aexpr(AExpr::Column(name.into()), arena)35}3637pub fn dataframe_length(arena: &mut Arena<AExpr>) -> Self {38Self::new_from_aexpr(AExpr::Len, arena)39}4041pub fn function(42input: Vec<ExprIR>,43function: IRFunctionExpr,44arena: &mut Arena<AExpr>,45) -> Self {46let options = function.function_options();47Self::new_from_aexpr(48AExpr::Function {49input,50function,51options,52},53arena,54)55}5657pub fn row_encode_unary(58self,59variant: RowEncodingVariant,60dtype: DataType,61arena: &mut Arena<AExpr>,62) -> Self {63Self::function(64vec![ExprIR::from_node(self.node(), arena)],65IRFunctionExpr::RowEncode(vec![dtype], variant),66arena,67)68}6970pub fn cast(self, dtype: DataType, arena: &mut Arena<AExpr>) -> Self {71Self {72node: arena.add(AExpr::Cast {73expr: self.node,74dtype,75options: CastOptions::Strict,76}),77}78}7980pub fn binary_op(81self,82other: impl IntoAExprBuilder,83op: Operator,84arena: &mut Arena<AExpr>,85) -> Self {86Self {87node: arena.add(AExpr::BinaryExpr {88left: self.node,89op,90right: other.into_aexpr_builder().node,91}),92}93}9495pub fn agg(agg: IRAggExpr, arena: &mut Arena<AExpr>) -> Self {96Self::new_from_aexpr(AExpr::Agg(agg), arena)97}9899pub fn first(self, arena: &mut Arena<AExpr>) -> Self {100Self::agg(IRAggExpr::First(self.node()), arena)101}102103pub fn last(self, arena: &mut Arena<AExpr>) -> Self {104Self::agg(IRAggExpr::Last(self.node()), arena)105}106107pub fn min(self, arena: &mut Arena<AExpr>) -> Self {108Self::agg(109IRAggExpr::Min {110input: self.node(),111propagate_nans: false,112},113arena,114)115}116117pub fn max(self, arena: &mut Arena<AExpr>) -> Self {118Self::agg(119IRAggExpr::Max {120input: self.node(),121propagate_nans: false,122},123arena,124)125}126127pub fn nan_min(self, arena: &mut Arena<AExpr>) -> Self {128Self::agg(129IRAggExpr::Min {130input: self.node(),131propagate_nans: true,132},133arena,134)135}136137pub fn nan_max(self, arena: &mut Arena<AExpr>) -> Self {138Self::agg(139IRAggExpr::Max {140input: self.node(),141propagate_nans: true,142},143arena,144)145}146147pub fn sum(self, arena: &mut Arena<AExpr>) -> Self {148Self::agg(IRAggExpr::Sum(self.node()), arena)149}150151pub fn len(self, arena: &mut Arena<AExpr>) -> Self {152Self::agg(153IRAggExpr::Count {154input: self.node(),155include_nulls: true,156},157arena,158)159}160161pub fn count(self, arena: &mut Arena<AExpr>) -> Self {162Self::agg(163IRAggExpr::Count {164input: self.node(),165include_nulls: false,166},167arena,168)169}170171pub fn count_opt_nulls(self, include_nulls: bool, arena: &mut Arena<AExpr>) -> Self {172Self::agg(173IRAggExpr::Count {174input: self.node(),175include_nulls,176},177arena,178)179}180181pub fn explode_skip_empty(self, arena: &mut Arena<AExpr>) -> Self {182Self::new_from_aexpr(183AExpr::Explode {184expr: self.node(),185skip_empty: true,186},187arena,188)189}190191pub fn explode_null_empty(self, arena: &mut Arena<AExpr>) -> Self {192Self::new_from_aexpr(193AExpr::Explode {194expr: self.node(),195skip_empty: false,196},197arena,198)199}200201pub fn sort(self, options: SortOptions, arena: &mut Arena<AExpr>) -> Self {202Self::new_from_aexpr(203AExpr::Sort {204expr: self.node(),205options,206},207arena,208)209}210211pub fn sort_by(212self,213by: Vec<Node>,214options: SortMultipleOptions,215arena: &mut Arena<AExpr>,216) -> Self {217Self::new_from_aexpr(218AExpr::SortBy {219expr: self.node(),220by,221sort_options: options,222},223arena,224)225}226227pub fn filter(self, by: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {228Self::new_from_aexpr(229AExpr::Filter {230input: self.node(),231by: by.into_aexpr_builder().node(),232},233arena,234)235}236237pub fn when_then_otherwise(238when: impl IntoAExprBuilder,239then: impl IntoAExprBuilder,240otherwise: impl IntoAExprBuilder,241arena: &mut Arena<AExpr>,242) -> Self {243when.into_aexpr_builder().ternary(then, otherwise, arena)244}245246pub fn ternary(247self,248truthy: impl IntoAExprBuilder,249falsy: impl IntoAExprBuilder,250arena: &mut Arena<AExpr>,251) -> Self {252Self::new_from_aexpr(253AExpr::Ternary {254predicate: self.into_aexpr_builder().node(),255truthy: truthy.into_aexpr_builder().node(),256falsy: falsy.into_aexpr_builder().node(),257},258arena,259)260}261262pub fn shift(self, periods: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {263Self::function(264vec![265self.expr_ir_unnamed(),266periods.into_aexpr_builder().expr_ir_unnamed(),267],268IRFunctionExpr::Shift,269arena,270)271}272273pub fn slice(274self,275offset: impl IntoAExprBuilder,276length: impl IntoAExprBuilder,277arena: &mut Arena<AExpr>,278) -> Self {279Self::new_from_aexpr(280AExpr::Slice {281input: self.into_aexpr_builder().node(),282offset: offset.into_aexpr_builder().node(),283length: length.into_aexpr_builder().node(),284},285arena,286)287}288289#[cfg(feature = "is_in")]290pub fn is_in(291self,292other: impl IntoAExprBuilder,293nulls_equal: bool,294arena: &mut Arena<AExpr>,295) -> Self {296Self::function(297vec![298self.expr_ir_unnamed(),299other.into_aexpr_builder().expr_ir_unnamed(),300],301IRFunctionExpr::Boolean(IRBooleanFunction::IsIn { nulls_equal }),302arena,303)304}305306pub fn to_physical(self, arena: &mut Arena<AExpr>) -> Self {307Self::function(308vec![self.expr_ir_unnamed()],309IRFunctionExpr::ToPhysical,310arena,311)312}313314#[cfg(feature = "abs")]315pub fn abs(self, arena: &mut Arena<AExpr>) -> Self {316Self::function(vec![self.expr_ir_unnamed()], IRFunctionExpr::Abs, arena)317}318319pub fn negate(self, arena: &mut Arena<AExpr>) -> Self {320Self::function(vec![self.expr_ir_unnamed()], IRFunctionExpr::Negate, arena)321}322323pub fn not(self, arena: &mut Arena<AExpr>) -> Self {324Self::function(325vec![self.expr_ir_unnamed()],326IRFunctionExpr::Boolean(IRBooleanFunction::Not),327arena,328)329}330331pub fn null_count(self, arena: &mut Arena<AExpr>) -> Self {332Self::function(333vec![self.expr_ir_unnamed()],334IRFunctionExpr::NullCount,335arena,336)337}338339pub fn is_null(self, arena: &mut Arena<AExpr>) -> Self {340Self::function(341vec![self.expr_ir_unnamed()],342IRFunctionExpr::Boolean(IRBooleanFunction::IsNull),343arena,344)345}346347pub fn is_not_null(self, arena: &mut Arena<AExpr>) -> Self {348Self::function(349vec![self.expr_ir_unnamed()],350IRFunctionExpr::Boolean(IRBooleanFunction::IsNotNull),351arena,352)353}354355pub fn is_nan(self, arena: &mut Arena<AExpr>) -> Self {356Self::function(357vec![self.expr_ir_unnamed()],358IRFunctionExpr::Boolean(IRBooleanFunction::IsNan),359arena,360)361}362363pub fn is_not_nan(self, arena: &mut Arena<AExpr>) -> Self {364Self::function(365vec![self.expr_ir_unnamed()],366IRFunctionExpr::Boolean(IRBooleanFunction::IsNotNan),367arena,368)369}370371pub fn has_no_nulls(self, arena: &mut Arena<AExpr>) -> Self {372let nc = self.null_count(arena);373let idx_zero = Self::lit_scalar(Scalar::from(0 as IdxSize), arena);374nc.eq(idx_zero, arena)375}376377pub fn has_nulls(self, arena: &mut Arena<AExpr>) -> Self {378let nc = self.null_count(arena);379let idx_zero = Self::lit_scalar(Scalar::from(0 as IdxSize), arena);380nc.gt(idx_zero, arena)381}382383pub fn drop_nulls(self, arena: &mut Arena<AExpr>) -> Self {384Self::function(385vec![self.expr_ir_retain_name(arena)],386IRFunctionExpr::DropNulls,387arena,388)389}390391pub fn drop_nans(self, arena: &mut Arena<AExpr>) -> Self {392Self::function(393vec![self.expr_ir_retain_name(arena)],394IRFunctionExpr::DropNans,395arena,396)397}398399pub fn eq(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {400self.binary_op(other, Operator::Eq, arena)401}402403pub fn eq_validity(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {404self.binary_op(other, Operator::EqValidity, arena)405}406407pub fn not_eq(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {408self.binary_op(other, Operator::NotEq, arena)409}410411pub fn not_eq_validity(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {412self.binary_op(other, Operator::NotEqValidity, arena)413}414415pub fn lt(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {416self.binary_op(other, Operator::Lt, arena)417}418419pub fn lt_eq(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {420self.binary_op(other, Operator::LtEq, arena)421}422423pub fn gt(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {424self.binary_op(other, Operator::Gt, arena)425}426427pub fn gt_eq(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {428self.binary_op(other, Operator::GtEq, arena)429}430431pub fn plus(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {432self.binary_op(other, Operator::Plus, arena)433}434435pub fn minus(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {436self.binary_op(other, Operator::Minus, arena)437}438439pub fn multiply(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {440self.binary_op(other, Operator::Multiply, arena)441}442443pub fn divide(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {444self.binary_op(other, Operator::Divide, arena)445}446447pub fn true_divide(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {448self.binary_op(other, Operator::TrueDivide, arena)449}450451pub fn floor_divide(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {452self.binary_op(other, Operator::FloorDivide, arena)453}454455pub fn modulus(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {456self.binary_op(other, Operator::Modulus, arena)457}458459pub fn and(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {460self.binary_op(other, Operator::And, arena)461}462463pub fn or(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {464self.binary_op(other, Operator::Or, arena)465}466467pub fn xor(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {468self.binary_op(other, Operator::Xor, arena)469}470471pub fn logical_and(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {472self.binary_op(other, Operator::LogicalAnd, arena)473}474475pub fn logical_or(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {476self.binary_op(other, Operator::LogicalOr, arena)477}478479pub fn expr_ir(self, name: impl Into<PlSmallStr>) -> ExprIR {480ExprIR::new(self.node(), OutputName::Alias(name.into()))481}482483pub fn expr_ir_retain_name(self, arena: &Arena<AExpr>) -> ExprIR {484ExprIR::from_node(self.node(), arena)485}486487pub fn expr_ir_unnamed(self) -> ExprIR {488self.expr_ir(PlSmallStr::EMPTY)489}490491pub fn node(self) -> Node {492self.node493}494}495496pub trait IntoAExprBuilder {497fn into_aexpr_builder(self) -> AExprBuilder;498}499500impl IntoAExprBuilder for Node {501fn into_aexpr_builder(self) -> AExprBuilder {502AExprBuilder { node: self }503}504}505506impl IntoAExprBuilder for AExprBuilder {507fn into_aexpr_builder(self) -> AExprBuilder {508self509}510}511512513