delta_funnel/report/sql_server/
write_all.rs1use std::fmt;
2
3use crate::{
4 DeltaSourceReport, MssqlOutputWriteStatus, MssqlWorkflowWriteReport, PhaseTimingReport,
5 support::sanitize_text_for_display,
6};
7
8#[derive(Debug, Clone, PartialEq, Eq)]
15pub struct WriteAllReport {
16 workflow: MssqlWorkflowWriteReport,
17 cache: WriteAllCacheReport,
18 sources: Vec<DeltaSourceReport>,
19 phase_timings: Vec<PhaseTimingReport>,
20}
21
22impl WriteAllReport {
23 pub(crate) fn new(
24 workflow: MssqlWorkflowWriteReport,
25 cache: WriteAllCacheReport,
26 sources: Vec<DeltaSourceReport>,
27 ) -> Self {
28 Self {
29 workflow,
30 cache,
31 sources,
32 phase_timings: Vec::new(),
33 }
34 }
35
36 pub(crate) fn with_phase_timings(mut self, phase_timings: Vec<PhaseTimingReport>) -> Self {
37 self.phase_timings = phase_timings;
38 self
39 }
40
41 #[must_use]
43 pub const fn workflow(&self) -> &MssqlWorkflowWriteReport {
44 &self.workflow
45 }
46
47 #[must_use]
49 pub const fn cache(&self) -> &WriteAllCacheReport {
50 &self.cache
51 }
52
53 #[must_use]
55 pub fn sources(&self) -> &[DeltaSourceReport] {
56 &self.sources
57 }
58
59 #[must_use]
61 pub fn phase_timings(&self) -> &[PhaseTimingReport] {
62 &self.phase_timings
63 }
64
65 #[must_use]
67 pub fn len(&self) -> usize {
68 self.workflow.len()
69 }
70
71 #[must_use]
73 pub fn is_empty(&self) -> bool {
74 self.workflow.is_empty()
75 }
76
77 #[must_use]
79 pub fn outputs(&self) -> &[MssqlOutputWriteStatus] {
80 self.workflow.outputs()
81 }
82
83 #[must_use]
85 pub fn all_succeeded(&self) -> bool {
86 self.workflow.all_succeeded()
87 }
88
89 #[must_use]
91 pub fn succeeded_count(&self) -> usize {
92 self.workflow.succeeded_count()
93 }
94
95 #[must_use]
97 pub fn failed_count(&self) -> usize {
98 self.workflow.failed_count()
99 }
100
101 #[must_use]
103 pub fn skipped_count(&self) -> usize {
104 self.workflow.skipped_count()
105 }
106}
107
108#[derive(Debug, Clone, PartialEq, Eq)]
115pub enum WriteAllCacheReport {
116 Disabled,
118 NoCache {
120 reason: WriteAllNoCacheReason,
122 skipped_candidates: Vec<WriteAllCacheCandidateSkip>,
124 },
125 CacheAliases {
127 aliases: Vec<WriteAllCacheAliasReport>,
129 skipped_candidates: Vec<WriteAllCacheCandidateSkip>,
131 },
132}
133
134impl WriteAllCacheReport {
135 pub(crate) fn disabled() -> Self {
136 Self::Disabled
137 }
138
139 pub(crate) fn no_cache(
140 reason: WriteAllNoCacheReason,
141 skipped_candidates: Vec<WriteAllCacheCandidateSkip>,
142 ) -> Self {
143 Self::NoCache {
144 reason,
145 skipped_candidates,
146 }
147 }
148
149 pub(crate) fn cache_aliases(
150 aliases: Vec<WriteAllCacheAliasReport>,
151 skipped_candidates: Vec<WriteAllCacheCandidateSkip>,
152 ) -> Self {
153 Self::CacheAliases {
154 aliases,
155 skipped_candidates,
156 }
157 }
158}
159
160#[derive(Debug, Clone, Copy, PartialEq, Eq)]
162pub enum WriteAllNoCacheReason {
163 FewerThanTwoOutputs,
165 NoSharedRegisteredDerivedAlias,
167 AmbiguousSharedDerivedAlias,
169}
170
171#[derive(Clone, PartialEq, Eq)]
177pub struct WriteAllCacheAliasReport {
178 table_id: u64,
179 alias: String,
180 output_indexes: Vec<usize>,
181 status: WriteAllCacheAliasStatus,
182}
183
184impl WriteAllCacheAliasReport {
185 pub(crate) fn new(
186 table_id: u64,
187 alias: impl Into<String>,
188 output_indexes: Vec<usize>,
189 status: WriteAllCacheAliasStatus,
190 ) -> Self {
191 Self {
192 table_id,
193 alias: alias.into(),
194 output_indexes,
195 status,
196 }
197 }
198
199 #[must_use]
201 pub const fn table_id(&self) -> u64 {
202 self.table_id
203 }
204
205 #[must_use]
207 pub fn alias(&self) -> &str {
208 &self.alias
209 }
210
211 #[must_use]
213 pub fn output_indexes(&self) -> &[usize] {
214 &self.output_indexes
215 }
216
217 #[must_use]
219 pub const fn status(&self) -> WriteAllCacheAliasStatus {
220 self.status
221 }
222}
223
224impl fmt::Debug for WriteAllCacheAliasReport {
225 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
226 formatter
227 .debug_struct("WriteAllCacheAliasReport")
228 .field("table_id", &self.table_id)
229 .field("alias", &sanitize_text_for_display(&self.alias))
230 .field("output_indexes", &self.output_indexes)
231 .field("status", &self.status)
232 .finish()
233 }
234}
235
236#[derive(Debug, Clone, Copy, PartialEq, Eq)]
238pub enum WriteAllCacheAliasStatus {
239 Selected,
246 MaterializedAndRestored,
251}
252
253#[derive(Clone, PartialEq, Eq)]
255pub struct WriteAllCacheCandidateSkip {
256 table_id: u64,
257 alias: String,
258 reason: WriteAllCacheCandidateSkipReason,
259}
260
261impl WriteAllCacheCandidateSkip {
262 pub(crate) fn new(
263 table_id: u64,
264 alias: impl Into<String>,
265 reason: WriteAllCacheCandidateSkipReason,
266 ) -> Self {
267 Self {
268 table_id,
269 alias: alias.into(),
270 reason,
271 }
272 }
273
274 #[must_use]
276 pub const fn table_id(&self) -> u64 {
277 self.table_id
278 }
279
280 #[must_use]
282 pub fn alias(&self) -> &str {
283 &self.alias
284 }
285
286 #[must_use]
288 pub const fn reason(&self) -> &WriteAllCacheCandidateSkipReason {
289 &self.reason
290 }
291}
292
293impl fmt::Debug for WriteAllCacheCandidateSkip {
294 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
295 formatter
296 .debug_struct("WriteAllCacheCandidateSkip")
297 .field("table_id", &self.table_id)
298 .field("alias", &sanitize_text_for_display(&self.alias))
299 .field("reason", &self.reason)
300 .finish()
301 }
302}
303
304#[derive(Debug, Clone, PartialEq, Eq)]
306pub enum WriteAllCacheCandidateSkipReason {
307 NotShared {
309 output_count: usize,
311 },
312 MissingSqlText,
314 IncompleteLineage,
316 CoveredByDeeperSharedAlias {
318 selected_table_id: u64,
320 },
321 AmbiguousDepth,
323}