Harvest per-column knowledge. `knowledge_stack` is a pre-allocated vector but is expected not to contain any elements.
(
&self,
expr: &mut MirRelationExpr,
knowledge: &mut BTreeMap<mz_expr::Id, Vec<DatumKnowledge>>,
knowledge_stack: &mut Vec<DatumKnowledge>,
)
| 74 | /// |
| 75 | /// `knowledge_stack` is a pre-allocated vector but is expected not to contain any elements. |
| 76 | fn harvest( |
| 77 | &self, |
| 78 | expr: &mut MirRelationExpr, |
| 79 | knowledge: &mut BTreeMap<mz_expr::Id, Vec<DatumKnowledge>>, |
| 80 | knowledge_stack: &mut Vec<DatumKnowledge>, |
| 81 | ) -> Result<Vec<DatumKnowledge>, TransformError> { |
| 82 | self.checked_recur(|_| { |
| 83 | let result = match expr { |
| 84 | MirRelationExpr::ArrangeBy { input, .. } => { |
| 85 | self.harvest(input, knowledge, knowledge_stack) |
| 86 | } |
| 87 | MirRelationExpr::Get { id, typ, .. } => { |
| 88 | Ok(knowledge.get(id).cloned().unwrap_or_else(|| { |
| 89 | typ.column_types.iter().map(DatumKnowledge::from).collect() |
| 90 | })) |
| 91 | } |
| 92 | MirRelationExpr::Constant { rows, typ } => { |
| 93 | // TODO: handle multi-row cases with some constant columns. |
| 94 | if let Ok([(row, _diff)]) = rows.as_deref() { |
| 95 | let knowledge = std::iter::zip(row.iter(), typ.column_types.iter()) |
| 96 | .map(DatumKnowledge::from) |
| 97 | .collect(); |
| 98 | Ok(knowledge) |
| 99 | } else { |
| 100 | Ok(typ.column_types.iter().map(DatumKnowledge::from).collect()) |
| 101 | } |
| 102 | } |
| 103 | MirRelationExpr::Let { id, value, body } => { |
| 104 | let value_knowledge = self.harvest(value, knowledge, knowledge_stack)?; |
| 105 | let prior_knowledge = |
| 106 | knowledge.insert(mz_expr::Id::Local(id.clone()), value_knowledge); |
| 107 | let body_knowledge = self.harvest(body, knowledge, knowledge_stack)?; |
| 108 | knowledge.remove(&mz_expr::Id::Local(id.clone())); |
| 109 | if let Some(prior_knowledge) = prior_knowledge { |
| 110 | knowledge.insert(mz_expr::Id::Local(id.clone()), prior_knowledge); |
| 111 | } |
| 112 | Ok(body_knowledge) |
| 113 | } |
| 114 | MirRelationExpr::LetRec { |
| 115 | ids, |
| 116 | values, |
| 117 | limits, |
| 118 | body, |
| 119 | } => { |
| 120 | // Set knowledge[i][j] = DatumKnowledge::bottom() for each |
| 121 | // column j and CTE i. This corresponds to the normal |
| 122 | // evaluation semantics where each recursive CTE is |
| 123 | // initialized to the empty collection. |
| 124 | for (id, value) in zip_eq(ids.iter(), values.iter()) { |
| 125 | let id = mz_expr::Id::Local(id.clone()); |
| 126 | let knowledge_new = vec![DatumKnowledge::bottom(); value.arity()]; |
| 127 | let knowledge_old = knowledge.insert(id, knowledge_new); |
| 128 | assert_none!(knowledge_old); |
| 129 | } |
| 130 | |
| 131 | // Sum up the arity of all ids in the enclosing LetRec node. |
| 132 | let let_rec_arity = ids.iter().fold(0, |acc, id| { |
| 133 | let id = mz_expr::Id::Local(id.clone()); |
no test coverage detected