mz_catalog/builtin/
notice.rs

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.
9
10use std::collections::BTreeMap;
11use std::sync::LazyLock;
12
13use mz_pgrepr::oid;
14use mz_repr::namespaces::MZ_INTERNAL_SCHEMA;
15use mz_repr::{RelationDesc, ScalarType};
16use mz_sql::catalog::NameReference;
17
18use crate::builtin::{Builtin, BuiltinIndex, BuiltinTable, BuiltinView, MONITOR_SELECT};
19
20use super::{MONITOR_REDACTED_SELECT, SUPPORT_SELECT};
21
22pub static MZ_OPTIMIZER_NOTICES: LazyLock<BuiltinTable> = LazyLock::new(|| {
23    use ScalarType::{List, String, TimestampTz};
24
25    BuiltinTable {
26        name: "mz_optimizer_notices",
27        schema: MZ_INTERNAL_SCHEMA,
28        oid: oid::TABLE_MZ_OPTIMIZER_NOTICES_OID,
29        desc: RelationDesc::builder()
30            .with_column("id", String.nullable(false))
31            .with_column("notice_type", String.nullable(false))
32            .with_column("message", String.nullable(false))
33            .with_column("hint", String.nullable(false))
34            .with_column("action", String.nullable(true))
35            .with_column("redacted_message", String.nullable(true))
36            .with_column("redacted_hint", String.nullable(true))
37            .with_column("redacted_action", String.nullable(true))
38            .with_column("action_type", String.nullable(true))
39            .with_column("object_id", String.nullable(true))
40            .with_column(
41                "dependency_ids",
42                List {
43                    element_type: Box::new(String),
44                    custom_id: None,
45                }
46                .nullable(false),
47            )
48            .with_column(
49                "created_at",
50                TimestampTz { precision: None }.nullable(false),
51            )
52            .with_key(vec![0])
53            .finish(),
54        column_comments: BTreeMap::new(),
55        is_retained_metrics_object: false,
56        access: vec![MONITOR_SELECT],
57    }
58});
59
60/// An [`MZ_NOTICES`] that is made safe to be viewed by Materialize staff
61/// because it binds the `redacted_~` from [`MZ_NOTICES`] as `~`.
62///
63/// This view is provisioned to accomodate the union of notice types (optimizer,
64/// sources and sinks, etc). Even though at the moment is only hosts optimizer
65/// notices, the idea is to evolve it over time as sketched in the design doc[^1].
66///
67/// [^1] <https://github.com/MaterializeInc/materialize/blob/main/doc/developer/design/20231113_optimizer_notice_catalog.md>
68pub static MZ_NOTICES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
69    name: "mz_notices",
70    schema: MZ_INTERNAL_SCHEMA,
71    oid: oid::VIEW_MZ_NOTICES_OID,
72    desc: RelationDesc::builder()
73        .with_column("id", ScalarType::String.nullable(false))
74        .with_column("notice_type", ScalarType::String.nullable(false))
75        .with_column("message", ScalarType::String.nullable(false))
76        .with_column("hint", ScalarType::String.nullable(false))
77        .with_column("action", ScalarType::String.nullable(true))
78        .with_column("redacted_message", ScalarType::String.nullable(true))
79        .with_column("redacted_hint", ScalarType::String.nullable(true))
80        .with_column("redacted_action", ScalarType::String.nullable(true))
81        .with_column("action_type", ScalarType::String.nullable(true))
82        .with_column("object_id", ScalarType::String.nullable(true))
83        .with_column(
84            "created_at",
85            ScalarType::TimestampTz { precision: None }.nullable(false),
86        )
87        .with_key(vec![0])
88        .finish(),
89    column_comments: BTreeMap::from_iter([
90        ("id", "Materialize's unique ID for this notice."),
91        ("notice_type", "The notice type."),
92        (
93            "message",
94            "A brief description of the issue highlighted by this notice.",
95        ),
96        (
97            "hint",
98            "A high-level hint that tells the user what can be improved.",
99        ),
100        ("action", "A concrete action that will resolve the notice."),
101        (
102            "redacted_message",
103            "A redacted version of the `message` column. `NULL` if no redaction is needed.",
104        ),
105        (
106            "redacted_hint",
107            "A redacted version of the `hint` column. `NULL` if no redaction is needed.",
108        ),
109        (
110            "redacted_action",
111            "A redacted version of the `action` column. `NULL` if no redaction is needed.",
112        ),
113        (
114            "action_type",
115            "The type of the `action` string (`sql_statements` for a valid SQL string or `plain_text` for plain text).",
116        ),
117        (
118            "object_id",
119            "The ID of the materialized view or index. Corresponds to `mz_objects.id`. For global notices, this column is `NULL`.",
120        ),
121        (
122            "created_at",
123            "The time at which the notice was created. Note that some notices are re-created on `environmentd` restart.",
124        ),
125    ]),
126    sql: "SELECT
127    n.id,
128    n.notice_type,
129    n.message,
130    n.hint,
131    n.action,
132    n.redacted_message,
133    n.redacted_hint,
134    n.redacted_action,
135    n.action_type,
136    n.object_id,
137    n.created_at
138FROM
139    mz_internal.mz_optimizer_notices n
140",
141    access: vec![MONITOR_SELECT],
142});
143
144/// A redacted version of [`MZ_NOTICES`] that is made safe to be viewed by
145/// Materialize staff because it binds the `redacted_~` from [`MZ_NOTICES`] as
146/// `~`.
147pub static MZ_NOTICES_REDACTED: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
148    name: "mz_notices_redacted",
149    schema: MZ_INTERNAL_SCHEMA,
150    oid: oid::VIEW_MZ_NOTICES_REDACTED_OID,
151    desc: RelationDesc::builder()
152        .with_column("id", ScalarType::String.nullable(false))
153        .with_column("notice_type", ScalarType::String.nullable(false))
154        .with_column("message", ScalarType::String.nullable(false))
155        .with_column("hint", ScalarType::String.nullable(false))
156        .with_column("action", ScalarType::String.nullable(true))
157        .with_column("action_type", ScalarType::String.nullable(true))
158        .with_column("object_id", ScalarType::String.nullable(true))
159        .with_column(
160            "created_at",
161            ScalarType::TimestampTz { precision: None }.nullable(false),
162        )
163        .with_key(vec![0])
164        .finish(),
165    column_comments: BTreeMap::from_iter([
166        ("id", "Materialize's unique ID for this notice."),
167        ("notice_type", "The notice type."),
168        (
169            "message",
170            "A redacted brief description of the issue highlighted by this notice.",
171        ),
172        (
173            "hint",
174            "A redacted high-level hint that tells the user what can be improved.",
175        ),
176        (
177            "action",
178            "A redacted concrete action that will resolve the notice.",
179        ),
180        (
181            "action_type",
182            "The type of the `action` string (`sql_statements` for a valid SQL string or `plain_text` for plain text).",
183        ),
184        (
185            "object_id",
186            "The ID of the materialized view or index. Corresponds to `mz_objects.id`. For global notices, this column is `NULL`.",
187        ),
188        (
189            "created_at",
190            "The time at which the notice was created. Note that some notices are re-created on `environmentd` restart.",
191        ),
192    ]),
193    sql: "SELECT
194    id,
195    notice_type,
196    coalesce(redacted_message, message) as message,
197    coalesce(redacted_hint, hint) as hint,
198    coalesce(redacted_action, action) as action,
199    action_type,
200    object_id,
201    created_at
202FROM
203    mz_internal.mz_notices
204",
205    access: vec![SUPPORT_SELECT, MONITOR_REDACTED_SELECT, MONITOR_SELECT],
206});
207
208pub const MZ_NOTICES_IND: BuiltinIndex = BuiltinIndex {
209    name: "mz_notices_ind",
210    schema: MZ_INTERNAL_SCHEMA,
211    oid: oid::INDEX_MZ_NOTICES_IND_OID,
212    sql: "IN CLUSTER mz_catalog_server ON mz_internal.mz_notices(id)",
213    is_retained_metrics_object: false,
214};
215
216/// An iterator over [`Builtin`] objects for optimization hints.
217///
218/// Used in the [`super::BUILTINS_STATIC`] initializer.
219pub(super) fn builtins() -> impl Iterator<Item = Builtin<NameReference>> {
220    [
221        Builtin::Table(&MZ_OPTIMIZER_NOTICES),
222        Builtin::View(&MZ_NOTICES),
223        Builtin::View(&MZ_NOTICES_REDACTED),
224        Builtin::Index(&MZ_NOTICES_IND),
225    ]
226    .into_iter()
227}