mz_adapter/catalog/builtin_table_updates/
notice.rs1use std::sync::Arc;
11
12use mz_catalog::builtin::BuiltinTable;
13use mz_catalog::builtin::notice::MZ_OPTIMIZER_NOTICES;
14use mz_ore::now::EpochMillis;
15use mz_repr::explain::ExprHumanizer;
16use mz_repr::{Datum, Diff, GlobalId, Row};
17use mz_transform::dataflow::DataflowMetainfo;
18use mz_transform::notice::{
19 Action, ActionKind, OptimizerNotice, OptimizerNoticeApi, OptimizerNoticeKind,
20 RawOptimizerNotice,
21};
22
23use crate::catalog::{BuiltinTableUpdate, Catalog, CatalogState};
24
25impl Catalog {
26 pub fn render_notices(
32 &self,
33 df_meta: DataflowMetainfo<RawOptimizerNotice>,
34 notice_ids: Vec<GlobalId>,
35 item_id: Option<GlobalId>,
36 ) -> DataflowMetainfo<Arc<OptimizerNotice>> {
37 let conn_catalog = self.for_system_session();
40 CatalogState::render_notices_core(
41 &conn_catalog,
42 (self.config().now)(),
43 &df_meta,
44 notice_ids,
45 item_id,
46 )
47 }
48}
49
50impl CatalogState {
51 pub fn render_notices_core(
61 humanizer: &dyn ExprHumanizer,
62 now: EpochMillis,
63 df_meta: &DataflowMetainfo<RawOptimizerNotice>,
64 notice_ids: Vec<GlobalId>,
65 item_id: Option<GlobalId>,
66 ) -> DataflowMetainfo<Arc<OptimizerNotice>> {
67 assert_eq!(notice_ids.len(), df_meta.optimizer_notices.len());
69
70 fn some_if_neq<T: Eq>(x: T, y: &T) -> Option<T> {
72 if &x != y { Some(x) } else { None }
73 }
74
75 let optimizer_notices = std::iter::zip(&df_meta.optimizer_notices, notice_ids)
76 .map(|(notice, id)| {
77 let message = notice.message(humanizer, false).to_string();
79 let hint = notice.hint(humanizer, false).to_string();
80 let action = match notice.action_kind(humanizer) {
81 ActionKind::SqlStatements => {
82 Action::SqlStatements(notice.action(humanizer, false).to_string())
83 }
84 ActionKind::PlainText => {
85 Action::PlainText(notice.action(humanizer, false).to_string())
86 }
87 ActionKind::None => {
88 Action::None }
90 };
91 let message_redacted = notice.message(humanizer, true).to_string();
93 let hint_redacted = notice.hint(humanizer, true).to_string();
94 let action_redacted = match notice.action_kind(humanizer) {
95 ActionKind::SqlStatements => {
96 Action::SqlStatements(notice.action(humanizer, true).to_string())
97 }
98 ActionKind::PlainText => {
99 Action::PlainText(notice.action(humanizer, true).to_string())
100 }
101 ActionKind::None => {
102 Action::None }
104 };
105 OptimizerNotice {
107 id,
108 kind: OptimizerNoticeKind::from(notice),
109 item_id,
110 dependencies: notice.dependencies(),
111 message_redacted: some_if_neq(message_redacted, &message),
112 hint_redacted: some_if_neq(hint_redacted, &hint),
113 action_redacted: some_if_neq(action_redacted, &action),
114 message,
115 hint,
116 action,
117 created_at: now,
118 }
119 })
120 .map(From::from) .collect();
122
123 DataflowMetainfo {
124 optimizer_notices,
125 index_usage_types: df_meta.index_usage_types.clone(),
126 }
127 }
128}
129
130impl CatalogState {
131 pub(crate) fn pack_optimizer_notices<'a>(
134 &self,
135 updates: &mut Vec<BuiltinTableUpdate>,
136 notices: impl Iterator<Item = &'a Arc<OptimizerNotice>>,
137 diff: Diff,
138 ) {
139 let mut resolved = Vec::new();
140 self.pack_optimizer_notice_updates(&mut resolved, notices, diff);
141 updates.extend(self.resolve_builtin_table_updates(resolved));
142 }
143
144 pub(crate) fn pack_optimizer_notice_updates<'a>(
147 &self,
148 updates: &mut Vec<BuiltinTableUpdate<&'static BuiltinTable>>,
149 notices: impl Iterator<Item = &'a Arc<OptimizerNotice>>,
150 diff: Diff,
151 ) {
152 let mut row = Row::default();
153
154 for notice in notices {
155 let mut packer = row.packer();
156
157 let id = notice.id.to_string();
160 let item_id = notice.item_id.as_ref().map(ToString::to_string);
161 let deps = notice
162 .dependencies
163 .iter()
164 .map(ToString::to_string)
165 .collect::<Vec<_>>();
166 let created_at = mz_ore::now::to_datetime(notice.created_at)
167 .try_into()
168 .expect("must fit");
169
170 packer.push(Datum::String(id.as_str()));
172 packer.push(Datum::String(notice.kind.as_str()));
174 packer.push(Datum::String(¬ice.message));
176 packer.push(Datum::String(¬ice.hint));
178 packer.push(match ¬ice.action {
180 Action::None => Datum::Null,
181 Action::PlainText(text) => Datum::String(text),
182 Action::SqlStatements(text) => Datum::String(text),
183 });
184 packer.push(match notice.message_redacted.as_deref() {
186 Some(message_redacted) => Datum::String(message_redacted),
187 None => Datum::Null,
188 });
189 packer.push(match notice.hint_redacted.as_deref() {
191 Some(hint_redacted) => Datum::String(hint_redacted),
192 None => Datum::Null,
193 });
194 packer.push(match notice.action_redacted.as_ref() {
196 Some(action_redacted) => match action_redacted {
197 Action::None => Datum::Null,
198 Action::PlainText(text) => Datum::String(text),
199 Action::SqlStatements(text) => Datum::String(text),
200 },
201 None => Datum::Null,
202 });
203 packer.push(match ¬ice.action {
205 Action::None => Datum::Null,
206 action => Datum::String(action.kind().as_str()),
207 });
208 packer.push(match item_id.as_ref() {
210 Some(item_id) => Datum::String(item_id),
211 None => Datum::Null,
212 });
213 packer.push_list(deps.iter().map(|d| Datum::String(d)));
215 packer.push(Datum::TimestampTz(created_at));
217
218 updates.push(BuiltinTableUpdate::row(
219 &*MZ_OPTIMIZER_NOTICES,
220 row.clone(),
221 diff,
222 ));
223 }
224 }
225}