Normalize the way inputs of multi-input variants are rendered. After the transform is applied, non-trival inputs `$input` of variants with more than one input are wrapped in a `let $x = $input in $x` blocks. If these blocks are subsequently pulled up by `NormalizeLets`, the rendered version of the resulting tree will only have linear chains.
(expr: &mut MirRelationExpr)
| 221 | /// If these blocks are subsequently pulled up by `NormalizeLets`, |
| 222 | /// the rendered version of the resulting tree will only have linear chains. |
| 223 | pub fn enforce_linear_chains(expr: &mut MirRelationExpr) -> Result<(), ExplainError> { |
| 224 | use MirRelationExpr::{Constant, Get, Join, Union}; |
| 225 | |
| 226 | if expr.is_recursive() { |
| 227 | // `linear_chains` is not implemented for WMR, see |
| 228 | // https://github.com/MaterializeInc/database-issues/issues/5631 |
| 229 | return Err(LinearChainsPlusRecursive); |
| 230 | } |
| 231 | |
| 232 | // helper struct: a generator of fresh local ids |
| 233 | let mut id_gen = id_gen(expr).peekable(); |
| 234 | |
| 235 | let mut wrap_in_let = |input: &mut MirRelationExpr| { |
| 236 | match input { |
| 237 | Constant { .. } | Get { .. } => (), |
| 238 | input => { |
| 239 | // generate fresh local id |
| 240 | // let id = id_cnt |
| 241 | // .next() |
| 242 | // .map(|id| LocalId::new(1000_u64 + u64::cast_from(id_map.len()) + id)) |
| 243 | // .unwrap(); |
| 244 | let id = id_gen.next().unwrap(); |
| 245 | let value = input.take_safely(None); |
| 246 | // generate a `let $fresh_id = $body in $fresh_id` to replace this input |
| 247 | let mut binding = MirRelationExpr::Let { |
| 248 | id, |
| 249 | value: Box::new(value), |
| 250 | body: Box::new(Get { |
| 251 | id: Id::Local(id.clone()), |
| 252 | typ: input.typ(), |
| 253 | access_strategy: AccessStrategy::UnknownOrLocal, |
| 254 | }), |
| 255 | }; |
| 256 | // swap the current body with the replacement |
| 257 | std::mem::swap(input, &mut binding); |
| 258 | } |
| 259 | } |
| 260 | }; |
| 261 | |
| 262 | expr.try_visit_mut_post(&mut |expr: &mut MirRelationExpr| { |
| 263 | match expr { |
| 264 | Join { inputs, .. } => { |
| 265 | for input in inputs { |
| 266 | wrap_in_let(input); |
| 267 | } |
| 268 | } |
| 269 | Union { base, inputs } => { |
| 270 | wrap_in_let(base); |
| 271 | for input in inputs { |
| 272 | wrap_in_let(input); |
| 273 | } |
| 274 | } |
| 275 | _ => (), |
| 276 | } |
| 277 | Ok(()) |
| 278 | }) |
| 279 | } |
| 280 |