mz_compute_types/
explain.rs1pub(crate) mod text;
13
14use std::borrow::Cow;
15use std::collections::BTreeMap;
16
17use mz_expr::explain::{ExplainContext, ExplainMultiPlan, ExplainSource, enforce_linear_chains};
18use mz_expr::{MfpPlan, MirRelationExpr, OptimizedMirRelationExpr};
19
20use mz_repr::GlobalId;
21use mz_repr::explain::{AnnotatedPlan, Explain, ExplainError, UnsupportedFormat};
22
23use crate::dataflows::{DataflowDescription, LirDataflowDescription};
24use crate::plan::LirRelationExpr;
25use crate::plan::scalar::LirScalarExpr;
26
27impl<'a> Explain<'a> for LirDataflowDescription {
28 type Context = ExplainContext<'a>;
29
30 type Text = ExplainMultiPlan<'a, LirRelationExpr, MfpPlan<LirScalarExpr>>;
31
32 type Json = ExplainMultiPlan<'a, LirRelationExpr, MfpPlan<LirScalarExpr>>;
33
34 type Dot = UnsupportedFormat;
35
36 fn explain_text(&'a mut self, context: &'a Self::Context) -> Result<Self::Text, ExplainError> {
37 self.as_explain_multi_plan(context)
38 }
39
40 fn explain_json(&'a mut self, context: &'a Self::Context) -> Result<Self::Text, ExplainError> {
41 self.as_explain_multi_plan(context)
42 }
43}
44
45impl<'a> LirDataflowDescription {
46 fn as_explain_multi_plan(
47 &'a mut self,
48 context: &'a ExplainContext<'a>,
49 ) -> Result<ExplainMultiPlan<'a, LirRelationExpr, MfpPlan<LirScalarExpr>>, ExplainError> {
50 let export_ids = export_ids_for(self);
51 let plans = self
52 .objects_to_build
53 .iter_mut()
54 .rev()
55 .map(|build_desc| {
56 let public_id = export_ids
57 .get(&build_desc.id)
58 .unwrap_or(&build_desc.id)
59 .clone();
60 let id = context
61 .humanizer
62 .humanize_id(public_id)
63 .unwrap_or_else(|| public_id.to_string());
64 let plan = AnnotatedPlan {
65 plan: &build_desc.plan,
66 annotations: BTreeMap::default(),
67 };
68 (id, plan)
69 })
70 .collect::<Vec<_>>();
71
72 let sources = self
73 .source_imports
74 .iter_mut()
75 .map(|(id, import)| {
76 let op = import.desc.arguments.operators.as_ref().map(Cow::Borrowed);
77 ExplainSource::new(*id, op, context.config.filter_pushdown)
78 })
79 .collect::<Vec<_>>();
80
81 Ok(ExplainMultiPlan {
82 context,
83 sources,
84 plans,
85 })
86 }
87}
88
89impl<'a> Explain<'a> for DataflowDescription<OptimizedMirRelationExpr> {
90 type Context = ExplainContext<'a>;
91
92 type Text = ExplainMultiPlan<'a, MirRelationExpr>;
93
94 type Json = ExplainMultiPlan<'a, MirRelationExpr>;
95
96 type Dot = UnsupportedFormat;
97
98 fn explain_text(&'a mut self, context: &'a Self::Context) -> Result<Self::Text, ExplainError> {
99 self.as_explain_multi_plan(context)
100 }
101
102 fn explain_json(&'a mut self, context: &'a Self::Context) -> Result<Self::Text, ExplainError> {
103 self.as_explain_multi_plan(context)
104 }
105}
106
107impl<'a> DataflowDescription<OptimizedMirRelationExpr> {
108 fn as_explain_multi_plan(
109 &'a mut self,
110 context: &'a ExplainContext<'a>,
111 ) -> Result<ExplainMultiPlan<'a, MirRelationExpr>, ExplainError> {
112 let export_ids = export_ids_for(self);
113 let plans = self
114 .objects_to_build
115 .iter_mut()
116 .rev()
117 .map(|build_desc| {
118 if context.config.linear_chains {
121 enforce_linear_chains(build_desc.plan.as_inner_mut())?;
122 };
123
124 let id = export_ids
125 .get(&build_desc.id)
126 .unwrap_or(&build_desc.id)
127 .clone();
128 let id = context
129 .humanizer
130 .humanize_id(id)
131 .unwrap_or_else(|| id.to_string());
132 let plan = AnnotatedPlan {
133 plan: build_desc.plan.as_inner(),
134 annotations: BTreeMap::default(),
135 };
136 Ok((id, plan))
137 })
138 .collect::<Result<Vec<_>, ExplainError>>()?;
139
140 let sources = self
141 .source_imports
142 .iter_mut()
143 .map(|(id, import)| {
144 let op = import.desc.arguments.operators.as_ref().map(Cow::Borrowed);
145 ExplainSource::new(*id, op, context.config.filter_pushdown)
146 })
147 .collect::<Vec<_>>();
148
149 Ok(ExplainMultiPlan {
150 context,
151 sources,
152 plans,
153 })
154 }
155}
156
157pub fn export_ids_for<P, S, O>(dd: &DataflowDescription<P, S, O>) -> BTreeMap<GlobalId, GlobalId> {
159 let mut map = BTreeMap::<GlobalId, GlobalId>::default();
160
161 if dd.sink_exports.len() == 1 && dd.objects_to_build.len() == 1 && dd.index_exports.is_empty() {
173 for (public_id, export) in dd.sink_exports.iter() {
174 map.insert(export.from, *public_id);
175 }
176 }
177
178 map
197}