fn apply(
        &mut self,
        box_id: BoxId,
        get_outer: expr::MirRelationExpr,
        outer_column_map: &ColumnMap,
        id_gen: &mut IdGen,
    ) -> expr::MirRelationExpr {
        use expr::MirRelationExpr as SR;
        let the_box = self.model.get_box(box_id);

        let input = match &the_box.box_type {
            BoxType::Get(Get { id }) => {
                let typ = RelationType::new(
                    the_box
                        .columns
                        .iter()
                        .map(|c| {
                            if let BoxScalarExpr::BaseColumn(BaseColumn { column_type, .. }) =
                                &c.expr
                            {
                                column_type.clone()
                            } else {
                                panic!("expected all columns in Get BoxType to BaseColumn");
                            }
                        })
                        .collect::<Vec<_>>(),
                )
                .with_keys(the_box.unique_keys.clone());
                get_outer.product(SR::Get {
                    id: expr::Id::Global(*id),
                    typ,
                })
            }
            BoxType::Values(values) => {
                let identity = SR::constant(vec![vec![]], RelationType::new(vec![]));
                // TODO(asenac) lower actual values
                assert!(values.rows.len() == 1 && the_box.columns.len() == 0);
                get_outer.product(identity)
            }
            BoxType::Select(select) => {
                assert!(select.order_key.is_none(), "ORDER BY is not supported yet");
                assert!(
                    select.limit.is_none() && select.offset.is_none(),
                    "LIMIT/OFFSET is not supported yet"
                );
                // A Select box combines three operations, join, filter and project,
                // in that order.

                // 1) Lower the join component of the Select box.
                // TODO(asenac) We could join first all non-correlated quantifiers
                // and then apply the correlated ones one by one in order of dependency
                // on top the join built so far, adding the predicates as soon as their
                // dependencies are satisfied.
                let correlation_info = the_box.correlation_info(&self.model);
                if !correlation_info.is_empty() {
                    panic!("correlated joins are not supported yet");
                }

                let outer_arity = get_outer.arity();
                let (mut input, column_map) =
                    self.lower_join(get_outer, outer_column_map, &the_box.quantifiers, id_gen);
                let input_arity = input.arity();

                // 2) Lower the filter component.
                if !select.predicates.is_empty() {
                    input = input.filter(
                        select
                            .predicates
                            .iter()
                            .map(|p| Self::lower_expression(p, &column_map)),
                    );
                }

                // 3) Lower the project component.
                if !the_box.columns.is_empty() {
                    input = input.map(
                        the_box
                            .columns
                            .iter()
                            .map(|c| Self::lower_expression(&c.expr, &column_map))
                            .collect_vec(),
                    );
                }

                // Project the outer columns plus the ones in the projection of
                // this select box
                input.project(
                    (0..outer_arity)
                        .chain(input_arity..input_arity + the_box.columns.len())
                        .collect_vec(),
                )
            }
            BoxType::Grouping(grouping) => {
                // Note: a grouping box must only contain a single quantifier but we can still
                // re-use `lower_join` for single quantifier joins
                let (mut input, column_map) =
                    self.lower_join(get_outer, outer_column_map, &the_box.quantifiers, id_gen);

                // Build the reduction
                let group_key = grouping
                    .key
                    .iter()
                    .map(|k| Self::lower_expression(k, &column_map))
                    .collect_vec();
                let aggregates = the_box
                    .columns
                    .iter()
                    .filter_map(|c| {
                        if let BoxScalarExpr::Aggregate {
                            func,
                            expr,
                            distinct,
                        } = &c.expr
                        {
                            Some(expr::AggregateExpr {
                                func: func.clone(),
                                expr: Self::lower_expression(expr, &column_map),
                                distinct: *distinct,
                            })
                        } else {
                            None
                        }
                    })
                    .collect_vec();
                input = SR::Reduce {
                    input: Box::new(input),
                    group_key,
                    aggregates,
                    monotonic: false,
                    expected_group_size: None,
                };

                // Put the columns in the same order as projected by the Grouping box by
                // adding an additional projection.
                //
                // The aggregate expression are usually projected after the grouping key.
                // However, as a result of query rewrite, aggregate expression may be
                // replaced with grouping key items. For example, the following query:
                //
                //   select a, max(b), max(a) from t group by a;
                //
                // could be rewritten as:
                //
                //   select a, max(b), a from t group by a;
                //
                // resulting in a Grouping box projecting [a, max(b), a]. Even though
                // another query rewrite should remove duplicated columns in the projection
                // of the Grouping box, we should be able to lower any semantically valid
                // query graph.
                let mut aggregate_count = 0;
                let projection = the_box.columns.iter().map(|c| {
                    if let BoxScalarExpr::Aggregate { .. } = &c.expr {
                        let aggregate_pos = grouping.key.len() + aggregate_count;
                        aggregate_count += 1;
                        aggregate_pos
                    } else {
                        grouping
                            .key
                            .iter()
                            .position(|k| c.expr == **k)
                            .expect("expression in the projection of a Grouping box not included in the grouping key")
                    }
                }).collect_vec();
                input.project(projection)
            }
            _ => panic!(),
        };

        if the_box.distinct == DistinctOperation::Enforce {
            input.distinct()
        } else {
            input
        }
    }
/// Applies the given box identified by its ID to the given outer relation.
Applies the given box identified by its ID to the given outer relation.
Applies the given box identified by its ID to the given outer relation .
fn apply(
        &mut self,
        box_id: BoxId,
        get_outer: expr::MirRelationExpr,
        outer_column_map: &ColumnMap,
        id_gen: &mut IdGen,
    ) -> expr::MirRelationExpr {
        use expr::MirRelationExpr as SR;
        let the_box = self.model.get_box(box_id);
        let input = match &the_box.box_type {
            BoxType::Get(Get { id }) => {
                let typ = RelationType::new(
                    the_box
                        .columns
                        .iter()
                        .map(|c| {
                            if let BoxScalarExpr::BaseColumn(BaseColumn { column_type, .. }) =
                                &c.expr
                            {
                                column_type.clone()
                            } else {
                                panic!("expected all columns in Get BoxType to BaseColumn");
                            }
                        })
                        .collect::<Vec<_>>(),
                )
                .with_keys(the_box.unique_keys.clone());
                get_outer.product(SR::Get {
                    id: expr::Id::Global(*id),
                    typ,
                })
            }
            BoxType::Values(values) => {
                let identity = SR::constant(vec![vec![]], RelationType::new(vec![]));
                // TODO(asenac) lower actual values
                assert!(values.rows.len() == 1 && the_box.columns.len() == 0);
                get_outer.product(identity)
            }
            BoxType::Select(select) => {
                assert!(select.order_key.is_none(), "ORDER BY is not supported yet");
                assert!(
                    select.limit.is_none() && select.offset.is_none(),
                    "LIMIT/OFFSET is not supported yet"
                );
                // A Select box combines three operations, join, filter and project,
                // in that order.
                // 1) Lower the join component of the Select box.
                // TODO(asenac) We could join first all non-correlated quantifiers
                // and then apply the correlated ones one by one in order of dependency
                // on top the join built so far, adding the predicates as soon as their
                // dependencies are satisfied.
                let correlation_info = the_box.correlation_info(&self.model);
                if !correlation_info.is_empty() {
                    panic!("correlated joins are not supported yet");
                }
                let outer_arity = get_outer.arity();
                let (mut input, column_map) =
                    self.lower_join(get_outer, outer_column_map, &the_box.quantifiers, id_gen);
                let input_arity = input.arity();
                // 2) Lower the filter component.
                if !select.predicates.is_empty() {
                    input = input.filter(
                        select
                            .predicates
                            .iter()
                            .map(|p| Self::lower_expression(p, &column_map)),
                    );
                }
                // 3) Lower the project component.
                if !the_box.columns.is_empty() {
                    input = input.map(
                        the_box
                            .columns
                            .iter()
                            .map(|c| Self::lower_expression(&c.expr, &column_map))
                            .collect_vec(),
                    );
                }
                // Project the outer columns plus the ones in the projection of
                // this select box
                input.project(
                    (0..outer_arity)
                        .chain(input_arity..input_arity + the_box.columns.len())
                        .collect_vec(),
                )
            }
            BoxType::Grouping(grouping) => {
                // Note: a grouping box must only contain a single quantifier but we can still
                // re-use `lower_join` for single quantifier joins
                let (mut input, column_map) =
                    self.lower_join(get_outer, outer_column_map, &the_box.quantifiers, id_gen);
                // Build the reduction
                let group_key = grouping
                    .key
                    .iter()
                    .map(|k| Self::lower_expression(k, &column_map))
                    .collect_vec();
                let aggregates = the_box
                    .columns
                    .iter()
                    .filter_map(|c| {
                        if let BoxScalarExpr::Aggregate {
                            func,
                            expr,
                            distinct,
                        } = &c.expr
                        {
                            Some(expr::AggregateExpr {
                                func: func.clone(),
                                expr: Self::lower_expression(expr, &column_map),
                                distinct: *distinct,
                            })
                        } else {
                            None
                        }
                    })
                    .collect_vec();
                input = SR::Reduce {
                    input: Box::new(input),
                    group_key,
                    aggregates,
                    monotonic: false,
                    expected_group_size: None,
                };
                // Put the columns in the same order as projected by the Grouping box by
                // adding an additional projection.
                //
                // The aggregate expression are usually projected after the grouping key.
                // However, as a result of query rewrite, aggregate expression may be
                // replaced with grouping key items. For example, the following query:
                //
                //   select a, max(b), max(a) from t group by a;
                //
                // could be rewritten as:
                //
                //   select a, max(b), a from t group by a;
                //
                // resulting in a Grouping box projecting [a, max(b), a]. Even though
                // another query rewrite should remove duplicated columns in the projection
                // of the Grouping box, we should be able to lower any semantically valid
                // query graph.
                let mut aggregate_count = 0;
                let projection = the_box.columns.iter().map(|c| {
                    if let BoxScalarExpr::Aggregate { .. } = &c.expr {
                        let aggregate_pos = grouping.key.len() + aggregate_count;
                        aggregate_count += 1;
                        aggregate_pos
                    } else {
                        grouping
                            .key
                            .iter()
                            .position(|k| c.expr == **k)
                            .expect("expression in the projection of a Grouping box not included in the grouping key")
                    }
                }).collect_vec();
                input.project(projection)
            }
            _ => panic!(),
        };
        if the_box.distinct == DistinctOperation::Enforce {
            input.distinct()
        } else {
            input
        }
    }
fn apply ( & mut self , box_id : BoxId , get_outer : expr :: MirRelationExpr , outer_column_map : & ColumnMap , id_gen : & mut IdGen , ) -> expr :: MirRelationExpr { use expr :: MirRelationExpr as SR ; let the_box = self . model . get_box ( box_id ) ; let input = match & the_box . box_type { BoxType :: Get ( Get { id } ) => { let typ = RelationType :: new ( the_box . columns . iter ( ) . map ( | c | { if let BoxScalarExpr :: BaseColumn ( BaseColumn { column_type , .. } ) = & c . expr { column_type . clone ( ) } else { panic ! ( " " ) ; } } ) . collect :: < Vec < _ > > ( ) , ) . with_keys ( the_box . unique_keys . clone ( ) ) ; get_outer . product ( SR :: Get { id : expr :: Id :: Global ( * id ) , typ , } ) } BoxType :: Values ( values ) => { let identity = SR :: constant ( vec ! [ vec [ ] ] , RelationType :: new ( vec ! [ ] ) ) ; // TODO(asenac) lower actual values assert ! ( values rows len ( ) 1 the_box columns len ( ) 0 ) ; get_outer . product ( identity ) } BoxType :: Select ( select ) => { assert ! ( select order_key is_none ( ) " " ) ; assert ! ( select limit is_none ( ) select offset is_none ( ) " " ) ; // A Select box combines three operations, join, filter and project, // in that order. // 1) Lower the join component of the Select box. // TODO(asenac) We could join first all non-correlated quantifiers // and then apply the correlated ones one by one in order of dependency // on top the join built so far, adding the predicates as soon as their // dependencies are satisfied. let correlation_info = the_box . correlation_info ( & self . model ) ; if ! correlation_info . is_empty ( ) { panic ! ( " " ) ; } let outer_arity = get_outer . arity ( ) ; let ( mut input , column_map ) = self . lower_join ( get_outer , outer_column_map , & the_box . quantifiers , id_gen ) ; let input_arity = input . arity ( ) ; // 2) Lower the filter component. if ! select . predicates . is_empty ( ) { input = input . filter ( select . predicates . iter ( ) . map ( | p | Self :: lower_expression ( p , & column_map ) ) , ) ; } // 3) Lower the project component. if ! the_box . columns . is_empty ( ) { input = input . map ( the_box . columns . iter ( ) . map ( | c | Self :: lower_expression ( & c . expr , & column_map ) ) . collect_vec ( ) , ) ; } // Project the outer columns plus the ones in the projection of // this select box input . project ( ( 0 .. outer_arity ) . chain ( input_arity .. input_arity + the_box . columns . len ( ) ) . collect_vec ( ) , ) } BoxType :: Grouping ( grouping ) => { // Note: a grouping box must only contain a single quantifier but we can still // re-use `lower_join` for single quantifier joins let ( mut input , column_map ) = self . lower_join ( get_outer , outer_column_map , & the_box . quantifiers , id_gen ) ; // Build the reduction let group_key = grouping . key . iter ( ) . map ( | k | Self :: lower_expression ( k , & column_map ) ) . collect_vec ( ) ; let aggregates = the_box . columns . iter ( ) . filter_map ( | c | { if let BoxScalarExpr :: Aggregate { func , expr , distinct , } = & c . expr { Some ( expr :: AggregateExpr { func : func . clone ( ) , expr : Self :: lower_expression ( expr , & column_map ) , distinct : * distinct , } ) } else { None } } ) . collect_vec ( ) ; input = SR :: Reduce { input : Box :: new ( input ) , group_key , aggregates , monotonic : false , expected_group_size : None , } ; // Put the columns in the same order as projected by the Grouping box by // adding an additional projection. // // The aggregate expression are usually projected after the grouping key. // However, as a result of query rewrite, aggregate expression may be // replaced with grouping key items. For example, the following query: // //   select a, max(b), max(a) from t group by a; // // could be rewritten as: // //   select a, max(b), a from t group by a; // // resulting in a Grouping box projecting [a, max(b), a]. Even though // another query rewrite should remove duplicated columns in the projection // of the Grouping box, we should be able to lower any semantically valid // query graph. let mut aggregate_count = 0 ; let projection = the_box . columns . iter ( ) . map ( | c | { if let BoxScalarExpr :: Aggregate { .. } = & c . expr { let aggregate_pos = grouping . key . len ( ) + aggregate_count ; aggregate_count += 1 ; aggregate_pos } else { grouping . key . iter ( ) . position ( | k | c . expr == * * k ) . expect ( " " ) } } ) . collect_vec ( ) ; input . project ( projection ) } _ => panic ! ( ) , } ; if the_box . distinct == DistinctOperation :: Enforce { input . distinct ( ) } else { input } }
Applies the given box identified by its ID to the given outer relation.
Applies the given box identified by its ID to the given outer relation .
&mut self
box_id
BoxId
get_outer
expr::MirRelationExpr
outer_column_map
&ColumnMap
id_gen
&mut IdGen
&mut self
box_id
BoxId
get_outer
expr::MirRelationExpr
outer_column_map
&ColumnMap
id_gen
&mut IdGen