(&self, expr: &mut MirRelationExpr, derived: DerivedView, generalize: bool)
| 66 | |
| 67 | impl WillDistinct { |
| 68 | fn apply(&self, expr: &mut MirRelationExpr, derived: DerivedView, generalize: bool) { |
| 69 | // Maintain a todo list of triples of 1. expression, 2. child analysis results, and 3. a "will distinct" bit. |
| 70 | // The "will distinct" bit says that a subsequent operator will make the specific multiplicities of each record |
| 71 | // irrelevant, and the expression only needs to present the correct *multiset* of records, with any positive |
| 72 | // cardinality allowed. |
| 73 | let mut todo = vec![(expr, derived, false)]; |
| 74 | while let Some((expr, derived, distinct_by)) = todo.pop() { |
| 75 | // If we find a `Distinct` expression in the shadow of another `Distinct` that will apply to its key columns, |
| 76 | // we can remove this `Distinct` operator as the distinctness will be enforced by the other expression. |
| 77 | if let ( |
| 78 | MirRelationExpr::Reduce { |
| 79 | input, |
| 80 | group_key, |
| 81 | aggregates, |
| 82 | .. |
| 83 | }, |
| 84 | true, |
| 85 | ) = (&mut *expr, distinct_by) |
| 86 | { |
| 87 | if aggregates.is_empty() { |
| 88 | // We can remove the `Distinct`, but we must install a `Map` and a `Project` to implement that |
| 89 | // aspect of the operator. We do this by hand so that we can still descend down `input` and |
| 90 | // continue to remove shadowed `Distinct` operators. |
| 91 | let arity = input.arity(); |
| 92 | *expr = MirRelationExpr::Project { |
| 93 | outputs: (arity..arity + group_key.len()).collect::<Vec<_>>(), |
| 94 | input: Box::new(MirRelationExpr::Map { |
| 95 | scalars: group_key.clone(), |
| 96 | input: Box::new(input.take_dangerous()), |
| 97 | }), |
| 98 | }; |
| 99 | // We are certain to have a specific pattern of AST nodes, which we need to push through so that |
| 100 | // we can continue recursively. |
| 101 | if let MirRelationExpr::Project { input, .. } = expr { |
| 102 | // `input` is a `Map` node, but it has a single input like the `Distinct` it came from. |
| 103 | // Although it reads a bit weird, this lines up the child of the distinct with its derived |
| 104 | // analysis results. |
| 105 | todo.extend( |
| 106 | input |
| 107 | .children_mut() |
| 108 | .rev() |
| 109 | .zip_eq(derived.children_rev()) |
| 110 | .map(|(x, y)| (x, y, true)), |
| 111 | ); |
| 112 | } |
| 113 | } else { |
| 114 | todo.extend( |
| 115 | expr.children_mut() |
| 116 | .rev() |
| 117 | .zip_eq(derived.children_rev()) |
| 118 | .map(|(x, y)| (x, y, false)), |
| 119 | ); |
| 120 | } |
| 121 | } else { |
| 122 | match expr { |
| 123 | MirRelationExpr::Reduce { |
| 124 | input, aggregates, .. |
| 125 | } => { |
no test coverage detected