pub fn optimize(
    expr: &mut MirScalarExpr,
    input_type: &RelationType,
    column_knowledge: &[DatumKnowledge],
    knowledge_stack: &mut Vec<DatumKnowledge>,
) -> DatumKnowledge {
    // Storage for `DatumKnowledge` being propagated up through the
    // `MirScalarExpr`. When a node is visited, pop off as many `DatumKnowledge`
    // as the number of children the node has, and then push the
    // `DatumKnowledge` corresponding to the node back onto the stack.
    // Post-order traversal means that if a node has `n` children, the top `n`
    // `DatumKnowledge` in the stack are the `DatumKnowledge` corresponding to
    // the children.

    expr.visit_mut_pre_post(
        &mut |e| {
            // We should not eagerly memoize `if` branches that might not be taken.
            // TODO: Memoize expressions in the intersection of `then` and `els`.
            if let MirScalarExpr::If { then, els, .. } = e {
                Some(vec![then, els])
            } else {
                None
            }
        },
        &mut |e| {
            let result = match e {
                MirScalarExpr::Column(index) => {
                    let index = *index;
                    if let Some((datum, typ)) = &column_knowledge[index].value {
                        *e = MirScalarExpr::Literal(datum.clone(), typ.clone());
                    }
                    column_knowledge[index].clone()
                }
                MirScalarExpr::Literal(_, _) | MirScalarExpr::CallNullary(_) => {
                    DatumKnowledge::from(&*e)
                }
                MirScalarExpr::CallUnary { func, expr: _ } => {
                    let knowledge = knowledge_stack.pop().unwrap();
                    if knowledge.value.is_some() {
                        e.reduce(input_type);
                    } else if func == &UnaryFunc::IsNull(func::IsNull) && !knowledge.nullable {
                        *e = MirScalarExpr::literal_ok(Datum::False, ScalarType::Bool);
                    };
                    DatumKnowledge::from(&*e)
                }
                MirScalarExpr::CallBinary {
                    func: _,
                    expr1: _,
                    expr2: _,
                } => {
                    let knowledge2 = knowledge_stack.pop().unwrap();
                    let knowledge1 = knowledge_stack.pop().unwrap();
                    if knowledge1.value.is_some() && knowledge2.value.is_some() {
                        e.reduce(input_type);
                    }
                    DatumKnowledge::from(&*e)
                }
                MirScalarExpr::CallVariadic { func: _, exprs } => {
                    if (0..exprs.len()).all(|_| knowledge_stack.pop().unwrap().value.is_some()) {
                        e.reduce(input_type);
                    }
                    DatumKnowledge::from(&*e)
                }
                MirScalarExpr::If {
                    cond: _,
                    then: _,
                    els: _,
                } => {
                    // `cond` has been left un-optimized, as we should not remove the conditional
                    // nature of the evaluation based on column knowledge: the resulting
                    // expression could then move down past a filter or join that provided
                    // the guarantees, and would become wrong.
                    //
                    // Instead, each of the branches have been optimized, and we
                    // can union the states of their columns.
                    let know2 = knowledge_stack.pop().unwrap();
                    let mut know1 = knowledge_stack.pop().unwrap();
                    know1.union(&know2);
                    know1
                }
            };
            knowledge_stack.push(result);
        },
    );
    knowledge_stack.pop().unwrap()
}
/// Attempts to optimize
///
/// `knowledge_stack` is a pre-allocated vector but is expected not to contain any elements.
Attempts to optimize
`knowledge_stack` is a pre-allocated vector but is expected not to contain any elements.
Attempts to optimize ` knowledge_stack ` is a pre - allocated vector but is expected not to contain any elements .
pub fn optimize(
    expr: &mut MirScalarExpr,
    input_type: &RelationType,
    column_knowledge: &[DatumKnowledge],
    knowledge_stack: &mut Vec<DatumKnowledge>,
) -> DatumKnowledge {
    // Storage for `DatumKnowledge` being propagated up through the
    // `MirScalarExpr`. When a node is visited, pop off as many `DatumKnowledge`
    // as the number of children the node has, and then push the
    // `DatumKnowledge` corresponding to the node back onto the stack.
    // Post-order traversal means that if a node has `n` children, the top `n`
    // `DatumKnowledge` in the stack are the `DatumKnowledge` corresponding to
    // the children.
    expr.visit_mut_pre_post(
        &mut |e| {
            // We should not eagerly memoize `if` branches that might not be taken.
            // TODO: Memoize expressions in the intersection of `then` and `els`.
            if let MirScalarExpr::If { then, els, .. } = e {
                Some(vec![then, els])
            } else {
                None
            }
        },
        &mut |e| {
            let result = match e {
                MirScalarExpr::Column(index) => {
                    let index = *index;
                    if let Some((datum, typ)) = &column_knowledge[index].value {
                        *e = MirScalarExpr::Literal(datum.clone(), typ.clone());
                    }
                    column_knowledge[index].clone()
                }
                MirScalarExpr::Literal(_, _) | MirScalarExpr::CallNullary(_) => {
                    DatumKnowledge::from(&*e)
                }
                MirScalarExpr::CallUnary { func, expr: _ } => {
                    let knowledge = knowledge_stack.pop().unwrap();
                    if knowledge.value.is_some() {
                        e.reduce(input_type);
                    } else if func == &UnaryFunc::IsNull(func::IsNull) && !knowledge.nullable {
                        *e = MirScalarExpr::literal_ok(Datum::False, ScalarType::Bool);
                    };
                    DatumKnowledge::from(&*e)
                }
                MirScalarExpr::CallBinary {
                    func: _,
                    expr1: _,
                    expr2: _,
                } => {
                    let knowledge2 = knowledge_stack.pop().unwrap();
                    let knowledge1 = knowledge_stack.pop().unwrap();
                    if knowledge1.value.is_some() && knowledge2.value.is_some() {
                        e.reduce(input_type);
                    }
                    DatumKnowledge::from(&*e)
                }
                MirScalarExpr::CallVariadic { func: _, exprs } => {
                    if (0..exprs.len()).all(|_| knowledge_stack.pop().unwrap().value.is_some()) {
                        e.reduce(input_type);
                    }
                    DatumKnowledge::from(&*e)
                }
                MirScalarExpr::If {
                    cond: _,
                    then: _,
                    els: _,
                } => {
                    // `cond` has been left un-optimized, as we should not remove the conditional
                    // nature of the evaluation based on column knowledge: the resulting
                    // expression could then move down past a filter or join that provided
                    // the guarantees, and would become wrong.
                    //
                    // Instead, each of the branches have been optimized, and we
                    // can union the states of their columns.
                    let know2 = knowledge_stack.pop().unwrap();
                    let mut know1 = knowledge_stack.pop().unwrap();
                    know1.union(&know2);
                    know1
                }
            };
            knowledge_stack.push(result);
        },
    );
    knowledge_stack.pop().unwrap()
}
pub fn optimize ( expr : & mut MirScalarExpr , input_type : & RelationType , column_knowledge : & [ DatumKnowledge ] , knowledge_stack : & mut Vec < DatumKnowledge > , ) -> DatumKnowledge { // Storage for `DatumKnowledge` being propagated up through the // `MirScalarExpr`. When a node is visited, pop off as many `DatumKnowledge` // as the number of children the node has, and then push the // `DatumKnowledge` corresponding to the node back onto the stack. // Post-order traversal means that if a node has `n` children, the top `n` // `DatumKnowledge` in the stack are the `DatumKnowledge` corresponding to // the children. expr . visit_mut_pre_post ( & mut | e | { // We should not eagerly memoize `if` branches that might not be taken. // TODO: Memoize expressions in the intersection of `then` and `els`. if let MirScalarExpr :: If { then , els , .. } = e { Some ( vec ! [ then els ] ) } else { None } } , & mut | e | { let result = match e { MirScalarExpr :: Column ( index ) => { let index = * index ; if let Some ( ( datum , typ ) ) = & column_knowledge [ index ] . value { * e = MirScalarExpr :: Literal ( datum . clone ( ) , typ . clone ( ) ) ; } column_knowledge [ index ] . clone ( ) } MirScalarExpr :: Literal ( _ , _ ) | MirScalarExpr :: CallNullary ( _ ) => { DatumKnowledge :: from ( & * e ) } MirScalarExpr :: CallUnary { func , expr : _ } => { let knowledge = knowledge_stack . pop ( ) . unwrap ( ) ; if knowledge . value . is_some ( ) { e . reduce ( input_type ) ; } else if func == & UnaryFunc :: IsNull ( func :: IsNull ) && ! knowledge . nullable { * e = MirScalarExpr :: literal_ok ( Datum :: False , ScalarType :: Bool ) ; } ; DatumKnowledge :: from ( & * e ) } MirScalarExpr :: CallBinary { func : _ , expr1 : _ , expr2 : _ , } => { let knowledge2 = knowledge_stack . pop ( ) . unwrap ( ) ; let knowledge1 = knowledge_stack . pop ( ) . unwrap ( ) ; if knowledge1 . value . is_some ( ) && knowledge2 . value . is_some ( ) { e . reduce ( input_type ) ; } DatumKnowledge :: from ( & * e ) } MirScalarExpr :: CallVariadic { func : _ , exprs } => { if ( 0 .. exprs . len ( ) ) . all ( | _ | knowledge_stack . pop ( ) . unwrap ( ) . value . is_some ( ) ) { e . reduce ( input_type ) ; } DatumKnowledge :: from ( & * e ) } MirScalarExpr :: If { cond : _ , then : _ , els : _ , } => { // `cond` has been left un-optimized, as we should not remove the conditional // nature of the evaluation based on column knowledge: the resulting // expression could then move down past a filter or join that provided // the guarantees, and would become wrong. // // Instead, each of the branches have been optimized, and we // can union the states of their columns. let know2 = knowledge_stack . pop ( ) . unwrap ( ) ; let mut know1 = knowledge_stack . pop ( ) . unwrap ( ) ; know1 . union ( & know2 ) ; know1 } } ; knowledge_stack . push ( result ) ; } , ) ; knowledge_stack . pop ( ) . unwrap ( ) }
Attempts to optimize
`knowledge_stack` is a pre-allocated vector but is expected not to contain any elements.
Attempts to optimize ` knowledge_stack ` is a pre - allocated vector but is expected not to contain any elements .
expr
&mut MirScalarExpr
input_type
&RelationType
column_knowledge
&[DatumKnowledge]
knowledge_stack
&mut Vec<DatumKnowledge>
expr
&mut MirScalarExpr
input_type
&RelationType
column_knowledge
&[DatumKnowledge]
knowledge_stack
&mut Vec<DatumKnowledge>