mz_transform/cse/relation_cse.rs
1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10//! Identifies common relation subexpressions and places them behind `Let` bindings.
11//!
12//! All structurally equivalent expressions, defined recursively as having structurally
13//! equivalent inputs, and identical parameters, will be placed behind `Let` bindings.
14//! The resulting expressions likely have an excess of `Let` expressions, and therefore
15//! we automatically run the `NormalizeLets` transformation to remove those that are not necessary.
16
17use mz_expr::MirRelationExpr;
18
19use crate::TransformCtx;
20use crate::normalize_lets::NormalizeLets;
21
22use super::anf::ANF;
23
24/// Identifies common relation subexpressions and places them behind `Let` bindings.
25#[derive(Debug)]
26pub struct RelationCSE {
27 anf: ANF,
28 normalize_lets: NormalizeLets,
29}
30
31impl RelationCSE {
32 /// Constructs a new [`RelationCSE`] instance.
33 ///
34 /// Also communicates its argument to let normalization.
35 pub fn new(inline_mfp: bool) -> RelationCSE {
36 RelationCSE {
37 anf: ANF::default(),
38 normalize_lets: NormalizeLets::new(inline_mfp),
39 }
40 }
41}
42
43impl crate::Transform for RelationCSE {
44 fn name(&self) -> &'static str {
45 "RelationCSE"
46 }
47
48 #[mz_ore::instrument(
49 target = "optimizer",
50 level = "debug",
51 fields(path.segment = "relation_cse")
52 )]
53 fn actually_perform_transform(
54 &self,
55 rel: &mut MirRelationExpr,
56 ctx: &mut TransformCtx,
57 ) -> Result<(), crate::TransformError> {
58 // Run ANF.
59 self.anf.transform_without_trace(rel)?;
60
61 // Run NormalizeLets.
62 self.normalize_lets.action(rel, ctx.features)?;
63
64 // Record the result and return.
65 mz_repr::explain::trace_plan(&*rel);
66 Ok(())
67 }
68}