mz_adapter/explain/
mir.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//! `EXPLAIN` support for MIR structures.
11//!
12//! The specialized [`Explain`] implementation for an [`MirRelationExpr`]
13//! wrapped in an [`Explainable`] newtype struct allows us to interpret more
14//! [`mz_repr::explain::ExplainConfig`] options. This is the case because
15//! Analysis derivation and Let normalization are defined in [`mz_transform`]
16//! and consequently are not available for the default [`Explain`]
17//! implementation for [`MirRelationExpr`] in [`mz_expr`].
18
19use mz_compute_types::dataflows::DataflowDescription;
20use mz_compute_types::explain::export_ids_for;
21use mz_expr::explain::{
22    ExplainContext, ExplainMultiPlan, ExplainSinglePlan, ExplainSource, enforce_linear_chains,
23};
24use mz_expr::{MirRelationExpr, OptimizedMirRelationExpr};
25use mz_repr::explain::{Explain, ExplainError, UnsupportedFormat};
26use mz_transform::analysis::annotate_plan;
27use mz_transform::normalize_lets::normalize_lets;
28
29use crate::explain::Explainable;
30
31impl<'a> Explain<'a> for Explainable<'a, MirRelationExpr> {
32    type Context = ExplainContext<'a>;
33
34    type Text = ExplainSinglePlan<'a, MirRelationExpr>;
35
36    type VerboseText = ExplainSinglePlan<'a, MirRelationExpr>;
37
38    type Json = ExplainSinglePlan<'a, MirRelationExpr>;
39
40    type Dot = UnsupportedFormat;
41
42    fn explain_text(&'a mut self, context: &'a Self::Context) -> Result<Self::Text, ExplainError> {
43        self.as_explain_single_plan(context)
44    }
45
46    fn explain_verbose_text(
47        &'a mut self,
48        context: &'a Self::Context,
49    ) -> Result<Self::VerboseText, ExplainError> {
50        self.as_explain_single_plan(context)
51    }
52
53    fn explain_json(&'a mut self, context: &'a Self::Context) -> Result<Self::Json, ExplainError> {
54        self.as_explain_single_plan(context)
55    }
56}
57
58impl<'a> Explainable<'a, MirRelationExpr> {
59    fn as_explain_single_plan(
60        &'a mut self,
61        context: &'a ExplainContext<'a>,
62    ) -> Result<ExplainSinglePlan<'a, MirRelationExpr>, ExplainError> {
63        // normalize the representation as linear chains
64        // (this implies !context.config.raw_plans by construction)
65        if context.config.linear_chains {
66            enforce_linear_chains(self.0)?;
67        };
68        // unless raw plans are explicitly requested
69        // normalize the representation of nested Let bindings
70        // and enforce sequential Let binding IDs
71        if !context.config.raw_plans {
72            normalize_lets(self.0, context.features)
73                .map_err(|e| ExplainError::UnknownError(e.to_string()))?;
74        }
75
76        Ok(ExplainSinglePlan {
77            context,
78            plan: annotate_plan(self.0, context)?,
79        })
80    }
81}
82
83impl<'a> Explain<'a> for Explainable<'a, DataflowDescription<OptimizedMirRelationExpr>> {
84    type Context = ExplainContext<'a>;
85
86    type Text = ExplainMultiPlan<'a, MirRelationExpr>;
87
88    type VerboseText = ExplainMultiPlan<'a, MirRelationExpr>;
89
90    type Json = ExplainMultiPlan<'a, MirRelationExpr>;
91
92    type Dot = UnsupportedFormat;
93
94    fn explain_text(&'a mut self, context: &'a Self::Context) -> Result<Self::Text, ExplainError> {
95        self.as_explain_multi_plan(context)
96    }
97
98    fn explain_verbose_text(
99        &'a mut self,
100        context: &'a Self::Context,
101    ) -> Result<Self::VerboseText, ExplainError> {
102        self.as_explain_multi_plan(context)
103    }
104
105    fn explain_json(&'a mut self, context: &'a Self::Context) -> Result<Self::Text, ExplainError> {
106        self.as_explain_multi_plan(context)
107    }
108}
109
110impl<'a> Explainable<'a, DataflowDescription<OptimizedMirRelationExpr>> {
111    fn as_explain_multi_plan(
112        &'a mut self,
113        context: &'a ExplainContext<'a>,
114    ) -> Result<ExplainMultiPlan<'a, MirRelationExpr>, ExplainError> {
115        let export_ids = export_ids_for(self.0);
116        let plans = self
117            .0
118            .objects_to_build
119            .iter_mut()
120            .rev()
121            .map(|build_desc| {
122                let plan = build_desc.plan.as_inner_mut();
123
124                // normalize the representation as linear chains
125                // (this implies !context.config.raw_plans by construction)
126                if context.config.linear_chains {
127                    enforce_linear_chains(plan)?;
128                };
129                // unless raw plans are explicitly requested
130                // normalize the representation of nested Let bindings
131                // and enforce sequential Let binding IDs
132                if !context.config.raw_plans {
133                    normalize_lets(plan, context.features)
134                        .map_err(|e| ExplainError::UnknownError(e.to_string()))?;
135                }
136
137                let public_id = export_ids
138                    .get(&build_desc.id)
139                    .unwrap_or(&build_desc.id)
140                    .clone();
141                let id = context
142                    .humanizer
143                    .humanize_id(public_id)
144                    .unwrap_or_else(|| public_id.to_string());
145
146                Ok((id, annotate_plan(plan, context)?))
147            })
148            .collect::<Result<Vec<_>, ExplainError>>()?;
149
150        let sources = self
151            .0
152            .source_imports
153            .iter_mut()
154            .map(|(id, (source_desc, _, _upper))| {
155                let op = source_desc.arguments.operators.as_ref();
156                ExplainSource::new(*id, op, context.config.filter_pushdown)
157            })
158            .collect::<Vec<_>>();
159
160        Ok(ExplainMultiPlan {
161            context,
162            sources,
163            plans,
164        })
165    }
166}