pub(crate) fn has_expr(current_expr: &Expr, matching_expr: &Expr) -> bool {
    match current_expr {
        Expr::Duplicated(e) => {
            if matches!(current_expr, Expr::Duplicated(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::Unique(e) => {
            if matches!(current_expr, Expr::Unique(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::Reverse(e) => {
            if matches!(current_expr, Expr::Reverse(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::Alias(e, _) => {
            if matches!(current_expr, Expr::Alias(_, _)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::Column(_) => {
            if matches!(current_expr, Expr::Column(_)) {
                true
            } else {
                panic!("should not happen")
            }
        }
        Expr::Literal(_) => {
            if matches!(current_expr, Expr::Literal(_)) {
                true
            } else {
                panic!("should not happen")
            }
        }
        Expr::BinaryExpr { left, right, .. } => {
            if matches!(current_expr, Expr::BinaryExpr{..}) {
                true
            } else {
                has_expr(left, matching_expr) | has_expr(right, matching_expr)
            }
        }
        Expr::Not(e) => {
            if matches!(current_expr, Expr::Not(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::IsNotNull(e) => {
            if matches!(current_expr, Expr::IsNotNull(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::IsNull(e) => {
            if matches!(current_expr, Expr::IsNull(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::Cast { expr, .. } => {
            if matches!(current_expr, Expr::Cast{..}) {
                true
            } else {
                has_expr(expr, matching_expr)
            }
        }
        Expr::Sort { expr, .. } => {
            if matches!(current_expr, Expr::Sort{..}) {
                true
            } else {
                has_expr(expr, matching_expr)
            }
        }
        Expr::AggMin(e) => {
            if matches!(current_expr, Expr::AggMin(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::AggMax(e) => {
            if matches!(current_expr, Expr::AggMax(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::AggMedian(e) => {
            if matches!(current_expr, Expr::AggMedian(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::AggNUnique(e) => {
            if matches!(current_expr, Expr::AggNUnique(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::AggFirst(e) => {
            if matches!(current_expr, Expr::AggFirst(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::AggLast(e) => {
            if matches!(current_expr, Expr::AggLast(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::AggMean(e) => {
            if matches!(current_expr, Expr::AggMean(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::AggList(e) => {
            if matches!(current_expr, Expr::AggList(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::AggCount(e) => {
            if matches!(current_expr, Expr::AggCount(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::AggQuantile { expr, .. } => {
            if matches!(**expr, Expr::AggQuantile{..}) {
                true
            } else {
                has_expr(expr, matching_expr)
            }
        }
        Expr::AggSum(e) => {
            if matches!(current_expr, Expr::AggSum(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::AggGroups(e) => {
            if matches!(current_expr, Expr::AggGroups(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::Ternary {
            predicate,
            truthy,
            falsy,
        } => {
            if matches!(current_expr, Expr::Ternary{..}) {
                true
            } else {
                has_expr(predicate, matching_expr)
                    | has_expr(truthy, matching_expr)
                    | has_expr(falsy, matching_expr)
            }
        }
        Expr::Apply { input, .. } => {
            if matches!(current_expr, Expr::Apply{..}) {
                true
            } else {
                has_expr(input, matching_expr)
            }
        }
        Expr::Shift { input, .. } => {
            if matches!(current_expr, Expr::Shift{..}) {
                true
            } else {
                has_expr(input, matching_expr)
            }
        }
        Expr::Wildcard => {
            if matches!(current_expr, Expr::Wildcard) {
                true
            } else {
                panic!("should not happen")
            }
        }
    }
}
/// Can check if an expression tree has a matching_expr. This
/// requires a dummy expression to be created that will be used to patter match against.
///
/// Another option was to create a recursive macro but would increase code bloat.
Can check if an expression tree has a matching_expr. This
requires a dummy expression to be created that will be used to patter match against.

Another option was to create a recursive macro but would increase code bloat.
Can check if an expression tree has a matching_expr . This requires a dummy expression to be created that will be used to patter match against . Another option was to create a recursive macro but would increase code bloat .
pub(crate) fn has_expr(current_expr: &Expr, matching_expr: &Expr) -> bool {
    match current_expr {
        Expr::Duplicated(e) => {
            if matches!(current_expr, Expr::Duplicated(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::Unique(e) => {
            if matches!(current_expr, Expr::Unique(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::Reverse(e) => {
            if matches!(current_expr, Expr::Reverse(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::Alias(e, _) => {
            if matches!(current_expr, Expr::Alias(_, _)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::Column(_) => {
            if matches!(current_expr, Expr::Column(_)) {
                true
            } else {
                panic!("should not happen")
            }
        }
        Expr::Literal(_) => {
            if matches!(current_expr, Expr::Literal(_)) {
                true
            } else {
                panic!("should not happen")
            }
        }
        Expr::BinaryExpr { left, right, .. } => {
            if matches!(current_expr, Expr::BinaryExpr{..}) {
                true
            } else {
                has_expr(left, matching_expr) | has_expr(right, matching_expr)
            }
        }
        Expr::Not(e) => {
            if matches!(current_expr, Expr::Not(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::IsNotNull(e) => {
            if matches!(current_expr, Expr::IsNotNull(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::IsNull(e) => {
            if matches!(current_expr, Expr::IsNull(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::Cast { expr, .. } => {
            if matches!(current_expr, Expr::Cast{..}) {
                true
            } else {
                has_expr(expr, matching_expr)
            }
        }
        Expr::Sort { expr, .. } => {
            if matches!(current_expr, Expr::Sort{..}) {
                true
            } else {
                has_expr(expr, matching_expr)
            }
        }
        Expr::AggMin(e) => {
            if matches!(current_expr, Expr::AggMin(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::AggMax(e) => {
            if matches!(current_expr, Expr::AggMax(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::AggMedian(e) => {
            if matches!(current_expr, Expr::AggMedian(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::AggNUnique(e) => {
            if matches!(current_expr, Expr::AggNUnique(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::AggFirst(e) => {
            if matches!(current_expr, Expr::AggFirst(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::AggLast(e) => {
            if matches!(current_expr, Expr::AggLast(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::AggMean(e) => {
            if matches!(current_expr, Expr::AggMean(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::AggList(e) => {
            if matches!(current_expr, Expr::AggList(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::AggCount(e) => {
            if matches!(current_expr, Expr::AggCount(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::AggQuantile { expr, .. } => {
            if matches!(**expr, Expr::AggQuantile{..}) {
                true
            } else {
                has_expr(expr, matching_expr)
            }
        }
        Expr::AggSum(e) => {
            if matches!(current_expr, Expr::AggSum(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::AggGroups(e) => {
            if matches!(current_expr, Expr::AggGroups(_)) {
                true
            } else {
                has_expr(e, matching_expr)
            }
        }
        Expr::Ternary {
            predicate,
            truthy,
            falsy,
        } => {
            if matches!(current_expr, Expr::Ternary{..}) {
                true
            } else {
                has_expr(predicate, matching_expr)
                    | has_expr(truthy, matching_expr)
                    | has_expr(falsy, matching_expr)
            }
        }
        Expr::Apply { input, .. } => {
            if matches!(current_expr, Expr::Apply{..}) {
                true
            } else {
                has_expr(input, matching_expr)
            }
        }
        Expr::Shift { input, .. } => {
            if matches!(current_expr, Expr::Shift{..}) {
                true
            } else {
                has_expr(input, matching_expr)
            }
        }
        Expr::Wildcard => {
            if matches!(current_expr, Expr::Wildcard) {
                true
            } else {
                panic!("should not happen")
            }
        }
    }
}
pub ( crate ) fn has_expr ( current_expr : & Expr , matching_expr : & Expr ) -> bool { match current_expr { Expr :: Duplicated ( e ) => { if matches ! ( current_expr Expr Duplicated ( ) ) { true } else { has_expr ( e , matching_expr ) } } Expr :: Unique ( e ) => { if matches ! ( current_expr Expr Unique ( ) ) { true } else { has_expr ( e , matching_expr ) } } Expr :: Reverse ( e ) => { if matches ! ( current_expr Expr Reverse ( ) ) { true } else { has_expr ( e , matching_expr ) } } Expr :: Alias ( e , _ ) => { if matches ! ( current_expr Expr Alias ( ) ) { true } else { has_expr ( e , matching_expr ) } } Expr :: Column ( _ ) => { if matches ! ( current_expr Expr Column ( ) ) { true } else { panic ! ( " " ) } } Expr :: Literal ( _ ) => { if matches ! ( current_expr Expr Literal ( ) ) { true } else { panic ! ( " " ) } } Expr :: BinaryExpr { left , right , .. } => { if matches ! ( current_expr Expr BinaryExpr { } ) { true } else { has_expr ( left , matching_expr ) | has_expr ( right , matching_expr ) } } Expr :: Not ( e ) => { if matches ! ( current_expr Expr Not ( ) ) { true } else { has_expr ( e , matching_expr ) } } Expr :: IsNotNull ( e ) => { if matches ! ( current_expr Expr IsNotNull ( ) ) { true } else { has_expr ( e , matching_expr ) } } Expr :: IsNull ( e ) => { if matches ! ( current_expr Expr IsNull ( ) ) { true } else { has_expr ( e , matching_expr ) } } Expr :: Cast { expr , .. } => { if matches ! ( current_expr Expr Cast { } ) { true } else { has_expr ( expr , matching_expr ) } } Expr :: Sort { expr , .. } => { if matches ! ( current_expr Expr Sort { } ) { true } else { has_expr ( expr , matching_expr ) } } Expr :: AggMin ( e ) => { if matches ! ( current_expr Expr AggMin ( ) ) { true } else { has_expr ( e , matching_expr ) } } Expr :: AggMax ( e ) => { if matches ! ( current_expr Expr AggMax ( ) ) { true } else { has_expr ( e , matching_expr ) } } Expr :: AggMedian ( e ) => { if matches ! ( current_expr Expr AggMedian ( ) ) { true } else { has_expr ( e , matching_expr ) } } Expr :: AggNUnique ( e ) => { if matches ! ( current_expr Expr AggNUnique ( ) ) { true } else { has_expr ( e , matching_expr ) } } Expr :: AggFirst ( e ) => { if matches ! ( current_expr Expr AggFirst ( ) ) { true } else { has_expr ( e , matching_expr ) } } Expr :: AggLast ( e ) => { if matches ! ( current_expr Expr AggLast ( ) ) { true } else { has_expr ( e , matching_expr ) } } Expr :: AggMean ( e ) => { if matches ! ( current_expr Expr AggMean ( ) ) { true } else { has_expr ( e , matching_expr ) } } Expr :: AggList ( e ) => { if matches ! ( current_expr Expr AggList ( ) ) { true } else { has_expr ( e , matching_expr ) } } Expr :: AggCount ( e ) => { if matches ! ( current_expr Expr AggCount ( ) ) { true } else { has_expr ( e , matching_expr ) } } Expr :: AggQuantile { expr , .. } => { if matches ! ( expr Expr AggQuantile { } ) { true } else { has_expr ( expr , matching_expr ) } } Expr :: AggSum ( e ) => { if matches ! ( current_expr Expr AggSum ( ) ) { true } else { has_expr ( e , matching_expr ) } } Expr :: AggGroups ( e ) => { if matches ! ( current_expr Expr AggGroups ( ) ) { true } else { has_expr ( e , matching_expr ) } } Expr :: Ternary { predicate , truthy , falsy , } => { if matches ! ( current_expr Expr Ternary { } ) { true } else { has_expr ( predicate , matching_expr ) | has_expr ( truthy , matching_expr ) | has_expr ( falsy , matching_expr ) } } Expr :: Apply { input , .. } => { if matches ! ( current_expr Expr Apply { } ) { true } else { has_expr ( input , matching_expr ) } } Expr :: Shift { input , .. } => { if matches ! ( current_expr Expr Shift { } ) { true } else { has_expr ( input , matching_expr ) } } Expr :: Wildcard => { if matches ! ( current_expr Expr Wildcard ) { true } else { panic ! ( " " ) } } } }
Can check if an expression tree has a matching_expr.
Can check if an expression tree has a matching_expr .
current_expr
&Expr
matching_expr
&Expr
current_expr
&Expr
matching_expr
&Expr