MCPcopy Create free account
hub / github.com/MaterializeInc/materialize / extract_common

Method extract_common

src/expr/src/linear.rs:480–630  ·  view source on GitHub ↗

Extracts common expressions from multiple `Self` into a result `Self`. The argument `mfps` are mutated so that each are functionaly equivalent to their corresponding input, when composed atop the resulting `Self`. The `extract_exprs` argument is temporary, as we roll out the `extract_common_mfp_expressions` flag.

(mfps: &mut [&mut Self])

Source from the content-addressed store, hash-verified

478 ///
479 /// The `extract_exprs` argument is temporary, as we roll out the `extract_common_mfp_expressions` flag.
480 pub fn extract_common(mfps: &mut [&mut Self]) -> Self {
481 match mfps.len() {
482 0 => {
483 panic!("Cannot call method on empty arguments");
484 }
485 1 => {
486 let output_arity = mfps[0].projection.len();
487 std::mem::replace(mfps[0], MapFilterProject::new(output_arity))
488 }
489 _ => {
490 // More generally, we convert each mfp to ANF, at which point we can
491 // repeatedly extract atomic expressions that depend only on input
492 // columns, migrate them to an input mfp, and repeat until no such
493 // expressions exist. At this point, we can also migrate predicates
494 // and then determine and push down projections.
495
496 // Prepare a return `Self`.
497 let mut result_mfp = MapFilterProject::new(mfps[0].input_arity);
498
499 // We convert each mfp to ANF, using `memoize_expressions`.
500 for mfp in mfps.iter_mut() {
501 mfp.memoize_expressions();
502 }
503
504 // We repeatedly extract common expressions, until none remain.
505 let mut done = false;
506 while !done {
507 // We use references to determine common expressions, and must
508 // introduce a scope here to drop the borrows before mutation.
509 let common = {
510 // The input arity may increase as we iterate, so recapture.
511 let input_arity = result_mfp.projection.len();
512 let mut prev: BTreeSet<_> = mfps[0]
513 .expressions
514 .iter()
515 .filter(|e| e.support().last() < Some(&input_arity))
516 .collect();
517 let mut next = BTreeSet::default();
518 for mfp in mfps[1..].iter() {
519 for expr in mfp.expressions.iter() {
520 if prev.contains(expr) {
521 next.insert(expr);
522 }
523 }
524 std::mem::swap(&mut prev, &mut next);
525 next.clear();
526 }
527 prev.into_iter().cloned().collect::<Vec<_>>()
528 };
529 // Without new common expressions, we should terminate the loop.
530 done = common.is_empty();
531
532 // Migrate each expression in `common` to `result_mfp`.
533 for expr in common.into_iter() {
534 // Update each mfp by removing expr and updating column references.
535 for mfp in mfps.iter_mut() {
536 // With `expr` next in `result_mfp`, it is as if we are rotating it to
537 // be the first expression in `mfp`, and then removing it from `mfp` and

Callers

nothing calls this directly

Calls 15

memoize_expressionsMethod · 0.80
lastMethod · 0.80
unwrapMethod · 0.80
demandMethod · 0.80
enumerateMethod · 0.80
permute_fnMethod · 0.80
replaceFunction · 0.50
actionFunction · 0.50
lenMethod · 0.45
collectMethod · 0.45
filterMethod · 0.45
iterMethod · 0.45

Tested by

no test coverage detected