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