Skip to main content

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