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.
910//! `EXPLAIN` support for various intermediate representations.
11//!
12//! Ideally, the `EXPLAIN` support for each IR should be in the crate where this
13//! IR is defined. However, we need to resort to an [`Explainable`] newtype
14//! struct in order to provide alternate [`mz_repr::explain::Explain`]
15//! implementations for some structs (see the [`mir`]) module for details.
1617use std::collections::BTreeMap;
18use std::sync::Arc;
1920use mz_compute_types::dataflows::DataflowDescription;
21use mz_expr::explain::ExplainContext;
22use mz_repr::GlobalId;
23use mz_repr::explain::{Explain, ExplainConfig, ExplainError, ExplainFormat, ExprHumanizer};
24use mz_repr::optimize::OptimizerFeatures;
25use mz_transform::dataflow::DataflowMetainfo;
26use mz_transform::notice::OptimizerNotice;
2728use crate::AdapterError;
2930pub(crate) mod fast_path;
31pub(crate) mod hir;
32pub(crate) mod insights;
33pub(crate) mod lir;
34pub(crate) mod mir;
35pub(crate) mod optimizer_trace;
3637/// Newtype struct for wrapping types that should
38/// implement the [`mz_repr::explain::Explain`] trait.
39pub(crate) struct Explainable<'a, T>(&'a mut T);
4041impl<'a, T> Explainable<'a, T> {
42pub(crate) fn new(t: &'a mut T) -> Explainable<'a, T> {
43 Explainable(t)
44 }
45}
4647/// Convenience method to derive an `ExplainContext` from the `index_imports` in
48/// the given `plan` and all other input parameters, wrap the `plan` in an
49/// `Explainable`, and finally compute and return the `explain(...)` result.
50pub(crate) fn explain_dataflow<T>(
51mut plan: DataflowDescription<T>,
52 format: ExplainFormat,
53 config: &ExplainConfig,
54 features: &OptimizerFeatures,
55 humanizer: &dyn ExprHumanizer,
56 cardinality_stats: BTreeMap<GlobalId, usize>,
57 target_cluster: Option<&str>,
58 dataflow_metainfo: &DataflowMetainfo<Arc<OptimizerNotice>>,
59) -> Result<String, AdapterError>
60where
61 for<'a> Explainable<'a, DataflowDescription<T>>: Explain<'a, Context = ExplainContext<'a>>,
62{
63// Collect the list of indexes used by the dataflow at this point.
64let used_indexes = dataflow_metainfo.used_indexes(&plan);
6566let optimizer_notices = OptimizerNotice::explain(
67&dataflow_metainfo.optimizer_notices,
68 humanizer,
69 config.redacted,
70 )
71 .map_err(ExplainError::FormatError)?;
7273let context = ExplainContext {
74 config,
75 features,
76 humanizer,
77 cardinality_stats,
78 used_indexes,
79 finishing: Default::default(),
80 duration: Default::default(),
81 target_cluster,
82 optimizer_notices,
83 };
8485Ok(Explainable::new(&mut plan).explain(&format, &context)?)
86}
8788/// Convenience method to explain a single plan.
89///
90/// In the long term, this method and [`explain_dataflow`] should be unified. In
91/// order to do that, however, we first need to generalize the role
92/// [`DataflowMetainfo`] as a carrier of metainformation for the optimization
93/// pass in general, and not for a specific structure representing an
94/// intermediate result.
95pub(crate) fn explain_plan<T>(
96mut plan: T,
97 format: ExplainFormat,
98 config: &ExplainConfig,
99 features: &OptimizerFeatures,
100 humanizer: &dyn ExprHumanizer,
101 cardinality_stats: BTreeMap<GlobalId, usize>,
102 target_cluster: Option<&str>,
103) -> Result<String, AdapterError>
104where
105 for<'a> Explainable<'a, T>: Explain<'a, Context = ExplainContext<'a>>,
106{
107let context = ExplainContext {
108 config,
109 features,
110 humanizer,
111 cardinality_stats,
112 used_indexes: Default::default(),
113 finishing: Default::default(),
114 duration: Default::default(),
115 target_cluster,
116 optimizer_notices: Default::default(),
117 };
118119Ok(Explainable::new(&mut plan).explain(&format, &context)?)
120}