Skip to main content

mz_catalog/builtin/
mz_internal.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
10//! Built-in catalog items for the `mz_internal` schema.
11
12use std::collections::BTreeMap;
13use std::sync::LazyLock;
14
15use mz_pgrepr::oid;
16use mz_repr::adt::mz_acl_item::MzAclItem;
17use mz_repr::namespaces::MZ_INTERNAL_SCHEMA;
18use mz_repr::{RelationDesc, SemanticType, SqlScalarType};
19use mz_sql::catalog::{ObjectType, SystemObjectType};
20use mz_sql::rbac;
21use mz_sql::session::user::{MZ_ANALYTICS_ROLE_ID, MZ_SYSTEM_ROLE_ID};
22use mz_storage_client::controller::IntrospectionType;
23use mz_storage_client::healthcheck::{
24    MZ_AWS_PRIVATELINK_CONNECTION_STATUS_HISTORY_DESC, MZ_PREPARED_STATEMENT_HISTORY_DESC,
25    MZ_SESSION_HISTORY_DESC, MZ_SINK_STATUS_HISTORY_DESC, MZ_SOURCE_STATUS_HISTORY_DESC,
26    MZ_SQL_TEXT_DESC, MZ_STATEMENT_EXECUTION_HISTORY_DESC, REPLICA_METRICS_HISTORY_DESC,
27    REPLICA_STATUS_HISTORY_DESC, WALLCLOCK_GLOBAL_LAG_HISTOGRAM_RAW_DESC,
28    WALLCLOCK_LAG_HISTORY_DESC,
29};
30use mz_storage_client::statistics::{MZ_SINK_STATISTICS_RAW_DESC, MZ_SOURCE_STATISTICS_RAW_DESC};
31
32use crate::memory::objects::DataSourceDesc;
33
34use super::{
35    ANALYTICS_SELECT, BuiltinConnection, BuiltinIndex, BuiltinMaterializedView, BuiltinSource,
36    BuiltinTable, BuiltinView, Cardinality, LinkProperties, MONITOR_REDACTED_SELECT,
37    MONITOR_SELECT, Ontology, OntologyLink, PUBLIC_SELECT, SUPPORT_SELECT,
38};
39
40pub static MZ_CATALOG_RAW: LazyLock<BuiltinSource> = LazyLock::new(|| BuiltinSource {
41    name: "mz_catalog_raw",
42    schema: MZ_INTERNAL_SCHEMA,
43    oid: oid::SOURCE_MZ_CATALOG_RAW_OID,
44    data_source: DataSourceDesc::Catalog,
45    desc: crate::durable::persist_desc(),
46    column_comments: BTreeMap::new(),
47    is_retained_metrics_object: false,
48    // The raw catalog contains unredacted SQL statements, so we limit access to the system user.
49    access: vec![],
50    ontology: None,
51});
52pub static MZ_POSTGRES_SOURCES: LazyLock<BuiltinTable> = LazyLock::new(|| BuiltinTable {
53    name: "mz_postgres_sources",
54    schema: MZ_INTERNAL_SCHEMA,
55    oid: oid::TABLE_MZ_POSTGRES_SOURCES_OID,
56    desc: RelationDesc::builder()
57        .with_column("id", SqlScalarType::String.nullable(false))
58        .with_column("replication_slot", SqlScalarType::String.nullable(false))
59        .with_column("timeline_id", SqlScalarType::UInt64.nullable(true))
60        .finish(),
61    column_comments: BTreeMap::from_iter([
62        (
63            "id",
64            "The ID of the source. Corresponds to `mz_catalog.mz_sources.id`.",
65        ),
66        (
67            "replication_slot",
68            "The name of the replication slot in the PostgreSQL database that Materialize will create and stream data from.",
69        ),
70        (
71            "timeline_id",
72            "The PostgreSQL timeline ID determined on source creation.",
73        ),
74    ]),
75    is_retained_metrics_object: false,
76    access: vec![PUBLIC_SELECT],
77    ontology: Some(Ontology {
78        entity_name: "postgres_source",
79        description: "Postgres source-level details",
80        links: &const {
81            [OntologyLink {
82                name: "details_of",
83                target: "source",
84                properties: LinkProperties::fk("id", "id", Cardinality::OneToOne),
85            }]
86        },
87        column_semantic_types: &[("id", SemanticType::CatalogItemId)],
88    }),
89});
90pub static MZ_POSTGRES_SOURCE_TABLES: LazyLock<BuiltinTable> = LazyLock::new(|| BuiltinTable {
91    name: "mz_postgres_source_tables",
92    schema: MZ_INTERNAL_SCHEMA,
93    oid: oid::TABLE_MZ_POSTGRES_SOURCE_TABLES_OID,
94    desc: RelationDesc::builder()
95        .with_column("id", SqlScalarType::String.nullable(false))
96        .with_column("schema_name", SqlScalarType::String.nullable(false))
97        .with_column("table_name", SqlScalarType::String.nullable(false))
98        .finish(),
99    column_comments: BTreeMap::from_iter([
100        (
101            "id",
102            "The ID of the subsource or table. Corresponds to `mz_catalog.mz_sources.id` or `mz_catalog.mz_tables.id`.",
103        ),
104        (
105            "schema_name",
106            "The schema of the upstream table being ingested.",
107        ),
108        (
109            "table_name",
110            "The name of the upstream table being ingested.",
111        ),
112    ]),
113    is_retained_metrics_object: true,
114    access: vec![PUBLIC_SELECT],
115    ontology: Some(Ontology {
116        entity_name: "postgres_source_table",
117        description: "Postgres source table-level details",
118        links: &const {
119            [OntologyLink {
120                name: "describes_source_table",
121                target: "table",
122                properties: LinkProperties::fk("id", "id", Cardinality::OneToOne),
123            }]
124        },
125        column_semantic_types: &[("id", SemanticType::CatalogItemId)],
126    }),
127});
128pub static MZ_MYSQL_SOURCE_TABLES: LazyLock<BuiltinTable> = LazyLock::new(|| BuiltinTable {
129    name: "mz_mysql_source_tables",
130    schema: MZ_INTERNAL_SCHEMA,
131    oid: oid::TABLE_MZ_MYSQL_SOURCE_TABLES_OID,
132    desc: RelationDesc::builder()
133        .with_column("id", SqlScalarType::String.nullable(false))
134        .with_column("schema_name", SqlScalarType::String.nullable(false))
135        .with_column("table_name", SqlScalarType::String.nullable(false))
136        .finish(),
137    column_comments: BTreeMap::from_iter([
138        (
139            "id",
140            "The ID of the subsource or table. Corresponds to `mz_catalog.mz_sources.id` or `mz_catalog.mz_tables.id`.",
141        ),
142        (
143            "schema_name",
144            "The schema (or, database) of the upstream table being ingested.",
145        ),
146        (
147            "table_name",
148            "The name of the upstream table being ingested.",
149        ),
150    ]),
151    is_retained_metrics_object: true,
152    access: vec![PUBLIC_SELECT],
153    ontology: Some(Ontology {
154        entity_name: "mysql_source_table",
155        description: "MySQL source table-level details",
156        links: &const {
157            [OntologyLink {
158                name: "describes_source_table",
159                target: "table",
160                properties: LinkProperties::fk("id", "id", Cardinality::OneToOne),
161            }]
162        },
163        column_semantic_types: &[("id", SemanticType::CatalogItemId)],
164    }),
165});
166pub static MZ_SQL_SERVER_SOURCE_TABLES: LazyLock<BuiltinTable> = LazyLock::new(|| BuiltinTable {
167    name: "mz_sql_server_source_tables",
168    schema: MZ_INTERNAL_SCHEMA,
169    oid: oid::TABLE_MZ_SQL_SERVER_SOURCE_TABLES_OID,
170    desc: RelationDesc::builder()
171        .with_column("id", SqlScalarType::String.nullable(false))
172        .with_column("schema_name", SqlScalarType::String.nullable(false))
173        .with_column("table_name", SqlScalarType::String.nullable(false))
174        .finish(),
175    column_comments: BTreeMap::from_iter([
176        (
177            "id",
178            "The ID of the subsource or table. Corresponds to `mz_catalog.mz_sources.id` or `mz_catalog.mz_tables.id`.",
179        ),
180        (
181            "schema_name",
182            "The schema of the upstream table being ingested.",
183        ),
184        (
185            "table_name",
186            "The name of the upstream table being ingested.",
187        ),
188    ]),
189    is_retained_metrics_object: true,
190    access: vec![PUBLIC_SELECT],
191    ontology: Some(Ontology {
192        entity_name: "sql_server_source_table",
193        description: "SQL Server source table-level details",
194        links: &const {
195            [OntologyLink {
196                name: "describes_source_table",
197                target: "table",
198                properties: LinkProperties::fk("id", "id", Cardinality::OneToOne),
199            }]
200        },
201        column_semantic_types: &[("id", SemanticType::CatalogItemId)],
202    }),
203});
204pub static MZ_KAFKA_SOURCE_TABLES: LazyLock<BuiltinTable> = LazyLock::new(|| BuiltinTable {
205    name: "mz_kafka_source_tables",
206    schema: MZ_INTERNAL_SCHEMA,
207    oid: oid::TABLE_MZ_KAFKA_SOURCE_TABLES_OID,
208    desc: RelationDesc::builder()
209        .with_column("id", SqlScalarType::String.nullable(false))
210        .with_column("topic", SqlScalarType::String.nullable(false))
211        .with_column("envelope_type", SqlScalarType::String.nullable(true))
212        .with_column("key_format", SqlScalarType::String.nullable(true))
213        .with_column("value_format", SqlScalarType::String.nullable(true))
214        .finish(),
215    column_comments: BTreeMap::from_iter([
216        (
217            "id",
218            "The ID of the table. Corresponds to `mz_catalog.mz_tables.id`.",
219        ),
220        ("topic", "The topic being ingested."),
221        (
222            "envelope_type",
223            "The envelope type: `none`, `upsert`, or `debezium`. `NULL` for other source types.",
224        ),
225        (
226            "key_format",
227            "The format of the Kafka message key: `avro`, `csv`, `regex`, `bytes`, `json`, `text`, or `NULL`.",
228        ),
229        (
230            "value_format",
231            "The format of the Kafka message value: `avro`, `csv`, `regex`, `bytes`, `json`, `text`. `NULL` for other source types.",
232        ),
233    ]),
234    is_retained_metrics_object: true,
235    access: vec![PUBLIC_SELECT],
236    ontology: Some(Ontology {
237        entity_name: "kafka_source_table",
238        description: "Kafka source table-level details",
239        links: &const {
240            [OntologyLink {
241                name: "describes_source_table",
242                target: "table",
243                properties: LinkProperties::fk("id", "id", Cardinality::OneToOne),
244            }]
245        },
246        column_semantic_types: &[("id", SemanticType::CatalogItemId)],
247    }),
248});
249pub static MZ_OBJECT_DEPENDENCIES: LazyLock<BuiltinTable> = LazyLock::new(|| BuiltinTable {
250    name: "mz_object_dependencies",
251    schema: MZ_INTERNAL_SCHEMA,
252    oid: oid::TABLE_MZ_OBJECT_DEPENDENCIES_OID,
253    desc: RelationDesc::builder()
254        .with_column("object_id", SqlScalarType::String.nullable(false))
255        .with_column(
256            "referenced_object_id",
257            SqlScalarType::String.nullable(false),
258        )
259        .finish(),
260    column_comments: BTreeMap::from_iter([
261        (
262            "object_id",
263            "The ID of the dependent object. Corresponds to `mz_objects.id`.",
264        ),
265        (
266            "referenced_object_id",
267            "The ID of the referenced object. Corresponds to `mz_objects.id`.",
268        ),
269    ]),
270    is_retained_metrics_object: true,
271    access: vec![PUBLIC_SELECT],
272    ontology: Some(Ontology {
273        entity_name: "object_dependency",
274        description: "A dependency edge: one object depends on another",
275        links: &const {
276            [
277                OntologyLink {
278                    name: "depends_on",
279                    target: "object",
280                    properties: LinkProperties::DependsOn {
281                        source_column: "object_id",
282                        target_column: "id",
283                        source_id_type: Some(mz_repr::SemanticType::CatalogItemId),
284                        requires_mapping: None,
285                    },
286                },
287                OntologyLink {
288                    name: "dependency_is",
289                    target: "object",
290                    properties: LinkProperties::DependsOn {
291                        source_column: "referenced_object_id",
292                        target_column: "id",
293                        source_id_type: Some(mz_repr::SemanticType::CatalogItemId),
294                        requires_mapping: None,
295                    },
296                },
297            ]
298        },
299        column_semantic_types: &const {
300            [
301                ("object_id", SemanticType::CatalogItemId),
302                ("referenced_object_id", SemanticType::CatalogItemId),
303            ]
304        },
305    }),
306});
307pub static MZ_COMPUTE_DEPENDENCIES: LazyLock<BuiltinSource> = LazyLock::new(|| BuiltinSource {
308    name: "mz_compute_dependencies",
309    schema: MZ_INTERNAL_SCHEMA,
310    oid: oid::SOURCE_MZ_COMPUTE_DEPENDENCIES_OID,
311    data_source: IntrospectionType::ComputeDependencies.into(),
312    desc: RelationDesc::builder()
313        .with_column("object_id", SqlScalarType::String.nullable(false))
314        .with_column("dependency_id", SqlScalarType::String.nullable(false))
315        .finish(),
316    column_comments: BTreeMap::from_iter([
317        (
318            "object_id",
319            "The ID of a compute object. Corresponds to `mz_catalog.mz_indexes.id`, `mz_catalog.mz_materialized_views.id`, or `mz_internal.mz_subscriptions.id`.",
320        ),
321        (
322            "dependency_id",
323            "The ID of a compute dependency. Corresponds to `mz_catalog.mz_indexes.id`, `mz_catalog.mz_materialized_views.id`, `mz_catalog.mz_sources.id`, or `mz_catalog.mz_tables.id`.",
324        ),
325    ]),
326    is_retained_metrics_object: false,
327    access: vec![PUBLIC_SELECT],
328    ontology: Some(Ontology {
329        entity_name: "compute_dependency",
330        description: "Dependency edge from a compute object (index, materialized view, or subscription) to one of the sources of its data",
331        links: &const {
332            [
333                OntologyLink {
334                    name: "depends_on",
335                    target: "object",
336                    properties: LinkProperties::DependsOn {
337                        source_column: "object_id",
338                        target_column: "id",
339                        source_id_type: Some(mz_repr::SemanticType::GlobalId),
340                        requires_mapping: Some("mz_internal.mz_object_global_ids"),
341                    },
342                },
343                OntologyLink {
344                    name: "dependency_is",
345                    target: "object",
346                    properties: LinkProperties::DependsOn {
347                        source_column: "dependency_id",
348                        target_column: "id",
349                        source_id_type: Some(mz_repr::SemanticType::GlobalId),
350                        requires_mapping: Some("mz_internal.mz_object_global_ids"),
351                    },
352                },
353            ]
354        },
355        column_semantic_types: &const {
356            [
357                ("object_id", SemanticType::GlobalId),
358                ("dependency_id", SemanticType::GlobalId),
359            ]
360        },
361    }),
362});
363
364pub static MZ_MATERIALIZED_VIEW_REFRESH_STRATEGIES: LazyLock<BuiltinTable> = LazyLock::new(|| {
365    BuiltinTable {
366        name: "mz_materialized_view_refresh_strategies",
367        schema: MZ_INTERNAL_SCHEMA,
368        oid: oid::TABLE_MZ_MATERIALIZED_VIEW_REFRESH_STRATEGIES_OID,
369        desc: RelationDesc::builder()
370            .with_column(
371                "materialized_view_id",
372                SqlScalarType::String.nullable(false),
373            )
374            .with_column("type", SqlScalarType::String.nullable(false))
375            .with_column("interval", SqlScalarType::Interval.nullable(true))
376            .with_column(
377                "aligned_to",
378                SqlScalarType::TimestampTz { precision: None }.nullable(true),
379            )
380            .with_column(
381                "at",
382                SqlScalarType::TimestampTz { precision: None }.nullable(true),
383            )
384            .finish(),
385        column_comments: BTreeMap::from_iter([
386            (
387                "materialized_view_id",
388                "The ID of the materialized view. Corresponds to `mz_catalog.mz_materialized_views.id`",
389            ),
390            (
391                "type",
392                "`at`, `every`, or `on-commit`. Default: `on-commit`",
393            ),
394            (
395                "interval",
396                "The refresh interval of a `REFRESH EVERY` option, or `NULL` if the `type` is not `every`.",
397            ),
398            (
399                "aligned_to",
400                "The `ALIGNED TO` option of a `REFRESH EVERY` option, or `NULL` if the `type` is not `every`.",
401            ),
402            (
403                "at",
404                "The time of a `REFRESH AT`, or `NULL` if the `type` is not `at`.",
405            ),
406        ]),
407        is_retained_metrics_object: false,
408        access: vec![PUBLIC_SELECT],
409        ontology: None,
410    }
411});
412
413pub static MZ_NETWORK_POLICIES: LazyLock<BuiltinMaterializedView> = LazyLock::new(|| {
414    BuiltinMaterializedView {
415        name: "mz_network_policies",
416        schema: MZ_INTERNAL_SCHEMA,
417        oid: oid::MV_MZ_NETWORK_POLICIES_OID,
418        desc: RelationDesc::builder()
419            .with_column("id", SqlScalarType::String.nullable(false))
420            .with_column("name", SqlScalarType::String.nullable(false))
421            .with_column("owner_id", SqlScalarType::String.nullable(false))
422            .with_column(
423                "privileges",
424                SqlScalarType::Array(Box::new(SqlScalarType::MzAclItem)).nullable(false),
425            )
426            .with_column("oid", SqlScalarType::Oid.nullable(false))
427            .with_key(vec![0])
428            .with_key(vec![4])
429            .finish(),
430        column_comments: BTreeMap::from_iter([
431            ("id", "The ID of the network policy."),
432            ("name", "The name of the network policy."),
433            (
434                "owner_id",
435                "The role ID of the owner of the network policy. Corresponds to `mz_catalog.mz_roles.id`.",
436            ),
437            (
438                "privileges",
439                "The privileges belonging to the network policy.",
440            ),
441            ("oid", "A PostgreSQL-compatible OID for the network policy."),
442        ]),
443        sql: "
444IN CLUSTER mz_catalog_server
445WITH (
446    ASSERT NOT NULL id,
447    ASSERT NOT NULL name,
448    ASSERT NOT NULL owner_id,
449    ASSERT NOT NULL privileges,
450    ASSERT NOT NULL oid
451) AS
452SELECT
453    mz_internal.parse_catalog_id(data->'key'->'id') AS id,
454    data->'value'->>'name' AS name,
455    mz_internal.parse_catalog_id(data->'value'->'owner_id') AS owner_id,
456    mz_internal.parse_catalog_privileges(data->'value'->'privileges') AS privileges,
457    (data->'value'->>'oid')::oid AS oid
458FROM mz_internal.mz_catalog_raw
459WHERE data->>'kind' = 'NetworkPolicy'",
460        is_retained_metrics_object: false,
461        access: vec![PUBLIC_SELECT],
462        ontology: Some(Ontology {
463            entity_name: "network_policy",
464            description: "Network access policies",
465            links: &const {
466                [OntologyLink {
467                    name: "owned_by",
468                    target: "role",
469                    properties: LinkProperties::fk("owner_id", "id", Cardinality::ManyToOne),
470                }]
471            },
472            column_semantic_types: &const {
473                [
474                    ("id", SemanticType::NetworkPolicyId),
475                    ("owner_id", SemanticType::RoleId),
476                    ("oid", SemanticType::OID),
477                ]
478            },
479        }),
480    }
481});
482
483pub static MZ_NETWORK_POLICY_RULES: LazyLock<BuiltinMaterializedView> = LazyLock::new(|| {
484    BuiltinMaterializedView {
485        name: "mz_network_policy_rules",
486        schema: MZ_INTERNAL_SCHEMA,
487        oid: oid::MV_MZ_NETWORK_POLICY_RULES_OID,
488        desc: RelationDesc::builder()
489            .with_column("name", SqlScalarType::String.nullable(false))
490            .with_column("policy_id", SqlScalarType::String.nullable(false))
491            .with_column("action", SqlScalarType::String.nullable(false))
492            .with_column("address", SqlScalarType::String.nullable(false))
493            .with_column("direction", SqlScalarType::String.nullable(false))
494            .finish(),
495        column_comments: BTreeMap::from_iter([
496            (
497                "name",
498                "The name of the network policy rule. Can be combined with `policy_id` to form a unique identifier.",
499            ),
500            (
501                "policy_id",
502                "The ID the network policy the rule is part of. Corresponds to `mz_internal.mz_network_policies.id`.",
503            ),
504            (
505                "action",
506                "The action of the rule. `allow` is the only supported action.",
507            ),
508            ("address", "The address the rule will take action on."),
509            (
510                "direction",
511                "The direction of traffic the rule applies to. `ingress` is the only supported direction.",
512            ),
513        ]),
514        sql: "
515IN CLUSTER mz_catalog_server
516WITH (
517    ASSERT NOT NULL name,
518    ASSERT NOT NULL policy_id,
519    ASSERT NOT NULL action,
520    ASSERT NOT NULL address,
521    ASSERT NOT NULL direction
522) AS
523SELECT
524    rule->>'name' AS name,
525    mz_internal.parse_catalog_id(data->'key'->'id') AS policy_id,
526    lower(rule->>'action') AS action,
527    rule->>'address' AS address,
528    lower(rule->>'direction') AS direction
529FROM
530    mz_internal.mz_catalog_raw,
531    jsonb_array_elements(data->'value'->'rules') AS rule
532WHERE data->>'kind' = 'NetworkPolicy'",
533        is_retained_metrics_object: false,
534        access: vec![PUBLIC_SELECT],
535        ontology: Some(Ontology {
536            entity_name: "network_policy_rule",
537            description: "Individual rules within a network policy",
538            links: &const {
539                [OntologyLink {
540                    name: "belongs_to_policy",
541                    target: "network_policy",
542                    properties: LinkProperties::fk("policy_id", "id", Cardinality::ManyToOne),
543                }]
544            },
545            column_semantic_types: &[],
546        }),
547    }
548});
549
550/// PostgreSQL-specific metadata about types that doesn't make sense to expose
551/// in the `mz_types` table as part of our public, stable API.
552pub static MZ_TYPE_PG_METADATA: LazyLock<BuiltinTable> = LazyLock::new(|| BuiltinTable {
553    name: "mz_type_pg_metadata",
554    schema: MZ_INTERNAL_SCHEMA,
555    oid: oid::TABLE_MZ_TYPE_PG_METADATA_OID,
556    desc: RelationDesc::builder()
557        .with_column("id", SqlScalarType::String.nullable(false))
558        .with_column("typinput", SqlScalarType::Oid.nullable(false))
559        .with_column("typreceive", SqlScalarType::Oid.nullable(false))
560        .finish(),
561    column_comments: BTreeMap::new(),
562    is_retained_metrics_object: false,
563    access: vec![PUBLIC_SELECT],
564    ontology: None,
565});
566pub static MZ_AGGREGATES: LazyLock<BuiltinTable> = LazyLock::new(|| BuiltinTable {
567    name: "mz_aggregates",
568    schema: MZ_INTERNAL_SCHEMA,
569    oid: oid::TABLE_MZ_AGGREGATES_OID,
570    desc: RelationDesc::builder()
571        .with_column("oid", SqlScalarType::Oid.nullable(false))
572        .with_column("agg_kind", SqlScalarType::String.nullable(false))
573        .with_column("agg_num_direct_args", SqlScalarType::Int16.nullable(false))
574        .finish(),
575    column_comments: BTreeMap::new(),
576    is_retained_metrics_object: false,
577    access: vec![PUBLIC_SELECT],
578    ontology: Some(Ontology {
579        entity_name: "aggregate",
580        description: "Aggregate function metadata",
581        links: &const { [] },
582        column_semantic_types: &[("oid", SemanticType::OID)],
583    }),
584});
585
586pub static MZ_CLUSTER_WORKLOAD_CLASSES: LazyLock<BuiltinMaterializedView> =
587    LazyLock::new(|| BuiltinMaterializedView {
588        name: "mz_cluster_workload_classes",
589        schema: MZ_INTERNAL_SCHEMA,
590        oid: oid::MV_MZ_CLUSTER_WORKLOAD_CLASSES_OID,
591        desc: RelationDesc::builder()
592            .with_column("id", SqlScalarType::String.nullable(false))
593            .with_column("workload_class", SqlScalarType::String.nullable(true))
594            .with_key(vec![0])
595            .finish(),
596        column_comments: BTreeMap::new(),
597        sql: "
598IN CLUSTER mz_catalog_server
599WITH (
600    ASSERT NOT NULL id
601) AS
602SELECT
603    mz_internal.parse_catalog_id(data->'key'->'id') AS id,
604    CASE WHEN data->'value'->'config'->'workload_class' != 'null'
605         THEN data->'value'->'config'->>'workload_class'
606    END AS workload_class
607FROM mz_internal.mz_catalog_raw
608WHERE data->>'kind' = 'Cluster'",
609        is_retained_metrics_object: false,
610        access: vec![PUBLIC_SELECT],
611        ontology: None,
612    });
613
614pub const MZ_CLUSTER_WORKLOAD_CLASSES_IND: BuiltinIndex = BuiltinIndex {
615    name: "mz_cluster_workload_classes_ind",
616    schema: MZ_INTERNAL_SCHEMA,
617    oid: oid::INDEX_MZ_CLUSTER_WORKLOAD_CLASSES_IND_OID,
618    sql: "IN CLUSTER mz_catalog_server
619ON mz_internal.mz_cluster_workload_classes (id)",
620    is_retained_metrics_object: false,
621};
622
623pub static MZ_CLUSTER_SCHEDULES: LazyLock<BuiltinTable> = LazyLock::new(|| BuiltinTable {
624    name: "mz_cluster_schedules",
625    schema: MZ_INTERNAL_SCHEMA,
626    oid: oid::TABLE_MZ_CLUSTER_SCHEDULES_OID,
627    desc: RelationDesc::builder()
628        .with_column("cluster_id", SqlScalarType::String.nullable(false))
629        .with_column("type", SqlScalarType::String.nullable(false))
630        .with_column(
631            "refresh_hydration_time_estimate",
632            SqlScalarType::Interval.nullable(true),
633        )
634        .finish(),
635    column_comments: BTreeMap::from_iter([
636        (
637            "cluster_id",
638            "The ID of the cluster. Corresponds to `mz_clusters.id`.",
639        ),
640        ("type", "`on-refresh`, or `manual`. Default: `manual`"),
641        (
642            "refresh_hydration_time_estimate",
643            "The interval given in the `HYDRATION TIME ESTIMATE` option.",
644        ),
645    ]),
646    is_retained_metrics_object: false,
647    access: vec![PUBLIC_SELECT],
648    ontology: Some(Ontology {
649        entity_name: "cluster_schedule",
650        description: "Cluster scheduling configuration",
651        links: &const {
652            [OntologyLink {
653                name: "belongs_to_cluster",
654                target: "cluster",
655                properties: LinkProperties::fk("cluster_id", "id", Cardinality::ManyToOne),
656            }]
657        },
658        column_semantic_types: &[("cluster_id", SemanticType::ClusterId)],
659    }),
660});
661
662pub static MZ_INTERNAL_CLUSTER_REPLICAS: LazyLock<BuiltinMaterializedView> =
663    LazyLock::new(|| BuiltinMaterializedView {
664        name: "mz_internal_cluster_replicas",
665        schema: MZ_INTERNAL_SCHEMA,
666        oid: oid::MV_MZ_INTERNAL_CLUSTER_REPLICAS_OID,
667        desc: RelationDesc::builder()
668            .with_column("id", SqlScalarType::String.nullable(false))
669            .with_key(vec![0])
670            .finish(),
671        column_comments: BTreeMap::from_iter([(
672            "id",
673            "The ID of a cluster replica. Corresponds to `mz_cluster_replicas.id`.",
674        )]),
675        sql: "
676IN CLUSTER mz_catalog_server
677WITH (
678    ASSERT NOT NULL id
679) AS
680SELECT mz_internal.parse_catalog_id(data->'key'->'id') AS id
681FROM mz_internal.mz_catalog_raw
682WHERE
683    data->>'kind' = 'ClusterReplica' AND
684    (data->'value'->'config'->'location'->'Managed'->>'internal')::bool = true",
685        is_retained_metrics_object: false,
686        access: vec![PUBLIC_SELECT],
687        ontology: None,
688    });
689
690pub static MZ_PENDING_CLUSTER_REPLICAS: LazyLock<BuiltinMaterializedView> =
691    LazyLock::new(|| BuiltinMaterializedView {
692        name: "mz_pending_cluster_replicas",
693        schema: MZ_INTERNAL_SCHEMA,
694        oid: oid::MV_MZ_PENDING_CLUSTER_REPLICAS_OID,
695        desc: RelationDesc::builder()
696            .with_column("id", SqlScalarType::String.nullable(false))
697            .with_key(vec![0])
698            .finish(),
699        column_comments: BTreeMap::from_iter([(
700            "id",
701            "The ID of a cluster replica. Corresponds to `mz_cluster_replicas.id`.",
702        )]),
703        sql: "
704IN CLUSTER mz_catalog_server
705WITH (
706    ASSERT NOT NULL id
707) AS
708SELECT mz_internal.parse_catalog_id(data->'key'->'id') AS id
709FROM mz_internal.mz_catalog_raw
710WHERE
711    data->>'kind' = 'ClusterReplica' AND
712    (data->'value'->'config'->'location'->'Managed'->>'pending')::bool = true",
713        is_retained_metrics_object: false,
714        access: vec![PUBLIC_SELECT],
715        ontology: None,
716    });
717
718pub static MZ_CLUSTER_REPLICA_STATUS_HISTORY: LazyLock<BuiltinSource> = LazyLock::new(|| {
719    BuiltinSource {
720        name: "mz_cluster_replica_status_history",
721        schema: MZ_INTERNAL_SCHEMA,
722        oid: oid::SOURCE_MZ_CLUSTER_REPLICA_STATUS_HISTORY_OID,
723        data_source: IntrospectionType::ReplicaStatusHistory.into(),
724        desc: REPLICA_STATUS_HISTORY_DESC.clone(),
725        column_comments: BTreeMap::from_iter([
726            ("replica_id", "The ID of a cluster replica."),
727            ("process_id", "The ID of a process within the replica."),
728            (
729                "status",
730                "The status of the cluster replica: `online` or `offline`.",
731            ),
732            (
733                "reason",
734                "If the cluster replica is in an `offline` state, the reason (if available). For example, `oom-killed`.",
735            ),
736            (
737                "occurred_at",
738                "Wall-clock timestamp at which the event occurred.",
739            ),
740        ]),
741        is_retained_metrics_object: false,
742        access: vec![PUBLIC_SELECT],
743        ontology: Some(Ontology {
744            entity_name: "replica_status_event",
745            description: "Historical replica status events (ready, not-ready, etc.)",
746            links: &const {
747                [OntologyLink {
748                    name: "status_event_of_replica",
749                    target: "replica",
750                    properties: LinkProperties::fk_typed(
751                        "replica_id",
752                        "id",
753                        Cardinality::ManyToOne,
754                        mz_repr::SemanticType::CatalogItemId,
755                    ),
756                }]
757            },
758            column_semantic_types: &[("replica_id", SemanticType::ReplicaId)],
759        }),
760    }
761});
762
763pub static MZ_CLUSTER_REPLICA_STATUSES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
764    name: "mz_cluster_replica_statuses",
765    schema: MZ_INTERNAL_SCHEMA,
766    oid: oid::VIEW_MZ_CLUSTER_REPLICA_STATUSES_OID,
767    desc: RelationDesc::builder()
768        .with_column("replica_id", SqlScalarType::String.nullable(false))
769        .with_column("process_id", SqlScalarType::UInt64.nullable(false))
770        .with_column("status", SqlScalarType::String.nullable(false))
771        .with_column("reason", SqlScalarType::String.nullable(true))
772        .with_column(
773            "updated_at",
774            SqlScalarType::TimestampTz { precision: None }.nullable(false),
775        )
776        .with_key(vec![0, 1])
777        .finish(),
778    column_comments: BTreeMap::from_iter([
779        (
780            "replica_id",
781            "Materialize's unique ID for the cluster replica.",
782        ),
783        (
784            "process_id",
785            "The ID of the process within the cluster replica.",
786        ),
787        (
788            "status",
789            "The status of the cluster replica: `online` or `offline`.",
790        ),
791        (
792            "reason",
793            "If the cluster replica is in a `offline` state, the reason (if available). For example, `oom-killed`.",
794        ),
795        (
796            "updated_at",
797            "The time at which the status was last updated.",
798        ),
799    ]),
800    sql: "
801SELECT
802    DISTINCT ON (replica_id, process_id)
803    replica_id,
804    process_id,
805    status,
806    reason,
807    occurred_at as updated_at
808FROM mz_internal.mz_cluster_replica_status_history
809JOIN mz_cluster_replicas r ON r.id = replica_id
810ORDER BY replica_id, process_id, occurred_at DESC",
811    access: vec![PUBLIC_SELECT],
812    ontology: Some(Ontology {
813        entity_name: "replica_status",
814        description: "Current status of each replica",
815        links: &const {
816            [OntologyLink {
817                name: "status_of_replica",
818                target: "replica",
819                properties: LinkProperties::fk_typed(
820                    "replica_id",
821                    "id",
822                    Cardinality::ManyToOne,
823                    mz_repr::SemanticType::ReplicaId,
824                ),
825            }]
826        },
827        column_semantic_types: &const {
828            [
829                ("replica_id", SemanticType::ReplicaId),
830                ("updated_at", SemanticType::WallclockTimestamp),
831            ]
832        },
833    }),
834});
835
836pub static MZ_SOURCE_STATUS_HISTORY: LazyLock<BuiltinSource> = LazyLock::new(|| BuiltinSource {
837    name: "mz_source_status_history",
838    schema: MZ_INTERNAL_SCHEMA,
839    oid: oid::SOURCE_MZ_SOURCE_STATUS_HISTORY_OID,
840    data_source: IntrospectionType::SourceStatusHistory.into(),
841    desc: MZ_SOURCE_STATUS_HISTORY_DESC.clone(),
842    column_comments: BTreeMap::from_iter([
843        (
844            "occurred_at",
845            "Wall-clock timestamp of the source status change.",
846        ),
847        (
848            "source_id",
849            "The ID of the source. Corresponds to `mz_catalog.mz_sources.id`.",
850        ),
851        (
852            "status",
853            "The status of the source: one of `created`, `starting`, `running`, `paused`, `stalled`, `failed`, or `dropped`.",
854        ),
855        (
856            "error",
857            "If the source is in an error state, the error message.",
858        ),
859        (
860            "details",
861            "Additional metadata provided by the source. In case of error, may contain a `hint` field with helpful suggestions.",
862        ),
863        (
864            "replica_id",
865            "The ID of the replica that an instance of a source is running on.",
866        ),
867    ]),
868    is_retained_metrics_object: false,
869    access: vec![PUBLIC_SELECT],
870    ontology: Some(Ontology {
871        entity_name: "source_status_event",
872        description: "Historical source status events",
873        links: &const {
874            [
875                OntologyLink {
876                    name: "status_event_of_source",
877                    target: "source",
878                    properties: LinkProperties::fk_mapped(
879                        "source_id",
880                        "id",
881                        Cardinality::ManyToOne,
882                        mz_repr::SemanticType::GlobalId,
883                        "mz_internal.mz_object_global_ids",
884                    ),
885                },
886                OntologyLink {
887                    name: "on_replica",
888                    target: "replica",
889                    properties: LinkProperties::fk_nullable(
890                        "replica_id",
891                        "id",
892                        Cardinality::ManyToOne,
893                    ),
894                },
895            ]
896        },
897        column_semantic_types: &const {
898            [
899                ("occurred_at", SemanticType::WallclockTimestamp),
900                ("source_id", SemanticType::GlobalId),
901                ("replica_id", SemanticType::ReplicaId),
902            ]
903        },
904    }),
905});
906
907pub static MZ_AWS_PRIVATELINK_CONNECTION_STATUS_HISTORY: LazyLock<BuiltinSource> = LazyLock::new(
908    || BuiltinSource {
909        name: "mz_aws_privatelink_connection_status_history",
910        schema: MZ_INTERNAL_SCHEMA,
911        oid: oid::SOURCE_MZ_AWS_PRIVATELINK_CONNECTION_STATUS_HISTORY_OID,
912        data_source: DataSourceDesc::Introspection(
913            IntrospectionType::PrivatelinkConnectionStatusHistory,
914        ),
915        desc: MZ_AWS_PRIVATELINK_CONNECTION_STATUS_HISTORY_DESC.clone(),
916        column_comments: BTreeMap::from_iter([
917            ("occurred_at", "Wall-clock timestamp of the status change."),
918            (
919                "connection_id",
920                "The unique identifier of the AWS PrivateLink connection. Corresponds to `mz_catalog.mz_connections.id`.",
921            ),
922            (
923                "status",
924                "The status of the connection: one of `pending-service-discovery`, `creating-endpoint`, `recreating-endpoint`, `updating-endpoint`, `available`, `deleted`, `deleting`, `expired`, `failed`, `pending`, `pending-acceptance`, `rejected`, or `unknown`.",
925            ),
926        ]),
927        is_retained_metrics_object: false,
928        access: vec![PUBLIC_SELECT],
929        ontology: None,
930    },
931);
932
933pub static MZ_AWS_PRIVATELINK_CONNECTION_STATUSES: LazyLock<BuiltinView> = LazyLock::new(|| {
934    BuiltinView {
935        name: "mz_aws_privatelink_connection_statuses",
936        schema: MZ_INTERNAL_SCHEMA,
937        oid: oid::VIEW_MZ_AWS_PRIVATELINK_CONNECTION_STATUSES_OID,
938        desc: RelationDesc::builder()
939            .with_column("id", SqlScalarType::String.nullable(false))
940            .with_column("name", SqlScalarType::String.nullable(false))
941            .with_column(
942                "last_status_change_at",
943                SqlScalarType::TimestampTz { precision: None }.nullable(true),
944            )
945            .with_column("status", SqlScalarType::String.nullable(true))
946            .with_key(vec![0])
947            .finish(),
948        column_comments: BTreeMap::from_iter([
949            (
950                "id",
951                "The ID of the connection. Corresponds to `mz_catalog.mz_connections.id`.",
952            ),
953            ("name", "The name of the connection."),
954            (
955                "last_status_change_at",
956                "Wall-clock timestamp of the connection status change.",
957            ),
958            (
959                "status",
960                "The status of the connection: one of `pending-service-discovery`, `creating-endpoint`, `recreating-endpoint`, `updating-endpoint`, `available`, `deleted`, `deleting`, `expired`, `failed`, `pending`, `pending-acceptance`, `rejected`, or `unknown`.",
961            ),
962        ]),
963        sql: "
964    WITH statuses_w_last_status AS (
965        SELECT
966            connection_id,
967            occurred_at,
968            status,
969            lag(status) OVER (PARTITION BY connection_id ORDER BY occurred_at) AS last_status
970        FROM mz_internal.mz_aws_privatelink_connection_status_history
971    ),
972    latest_events AS (
973        -- Only take the most recent transition for each ID
974        SELECT DISTINCT ON(connection_id) connection_id, occurred_at, status
975        FROM statuses_w_last_status
976        -- Only keep first status transitions
977        WHERE status <> last_status OR last_status IS NULL
978        ORDER BY connection_id, occurred_at DESC
979    )
980    SELECT
981        conns.id,
982        name,
983        occurred_at as last_status_change_at,
984        status
985    FROM latest_events
986    JOIN mz_catalog.mz_connections AS conns
987    ON conns.id = latest_events.connection_id",
988        access: vec![PUBLIC_SELECT],
989        ontology: Some(Ontology {
990            entity_name: "privatelink_status",
991            description: "PrivateLink connection health status",
992            links: &const {
993                [OntologyLink {
994                    name: "status_of",
995                    target: "connection",
996                    properties: LinkProperties::fk("id", "id", Cardinality::OneToOne),
997                }]
998            },
999            column_semantic_types: &[("id", SemanticType::CatalogItemId)],
1000        }),
1001    }
1002});
1003
1004pub static MZ_STATEMENT_EXECUTION_HISTORY: LazyLock<BuiltinSource> =
1005    LazyLock::new(|| BuiltinSource {
1006        name: "mz_statement_execution_history",
1007        schema: MZ_INTERNAL_SCHEMA,
1008        oid: oid::SOURCE_MZ_STATEMENT_EXECUTION_HISTORY_OID,
1009        data_source: IntrospectionType::StatementExecutionHistory.into(),
1010        desc: MZ_STATEMENT_EXECUTION_HISTORY_DESC.clone(),
1011        column_comments: BTreeMap::new(),
1012        is_retained_metrics_object: false,
1013        access: vec![MONITOR_SELECT],
1014        ontology: None,
1015    });
1016
1017pub static MZ_STATEMENT_EXECUTION_HISTORY_REDACTED: LazyLock<BuiltinView> = LazyLock::new(|| {
1018    BuiltinView {
1019    name: "mz_statement_execution_history_redacted",
1020    schema: MZ_INTERNAL_SCHEMA,
1021    oid: oid::VIEW_MZ_STATEMENT_EXECUTION_HISTORY_REDACTED_OID,
1022    // everything but `params` and `error_message`
1023    desc: RelationDesc::builder()
1024        .with_column("id", SqlScalarType::Uuid.nullable(false))
1025        .with_column("prepared_statement_id", SqlScalarType::Uuid.nullable(false))
1026        .with_column("sample_rate", SqlScalarType::Float64.nullable(false))
1027        .with_column("cluster_id", SqlScalarType::String.nullable(true))
1028        .with_column("application_name", SqlScalarType::String.nullable(false))
1029        .with_column("cluster_name", SqlScalarType::String.nullable(true))
1030        .with_column("database_name", SqlScalarType::String.nullable(false))
1031        .with_column("search_path", SqlScalarType::List { element_type: Box::new(SqlScalarType::String), custom_id: None }.nullable(false))
1032        .with_column("transaction_isolation", SqlScalarType::String.nullable(false))
1033        .with_column("execution_timestamp", SqlScalarType::UInt64.nullable(true))
1034        .with_column("transaction_id", SqlScalarType::UInt64.nullable(false))
1035        .with_column("transient_index_id", SqlScalarType::String.nullable(true))
1036        .with_column("mz_version", SqlScalarType::String.nullable(false))
1037        .with_column("began_at", SqlScalarType::TimestampTz { precision: None }.nullable(false))
1038        .with_column("finished_at", SqlScalarType::TimestampTz { precision: None }.nullable(true))
1039        .with_column("finished_status", SqlScalarType::String.nullable(true))
1040        .with_column("result_size", SqlScalarType::Int64.nullable(true))
1041        .with_column("rows_returned", SqlScalarType::Int64.nullable(true))
1042        .with_column("execution_strategy", SqlScalarType::String.nullable(true))
1043        .finish(),
1044    column_comments: BTreeMap::new(),
1045    sql: "
1046SELECT id, prepared_statement_id, sample_rate, cluster_id, application_name,
1047cluster_name, database_name, search_path, transaction_isolation, execution_timestamp, transaction_id,
1048transient_index_id, mz_version, began_at, finished_at, finished_status,
1049result_size, rows_returned, execution_strategy
1050FROM mz_internal.mz_statement_execution_history",
1051    access: vec![SUPPORT_SELECT, ANALYTICS_SELECT, MONITOR_REDACTED_SELECT, MONITOR_SELECT],
1052    ontology: None,
1053}
1054});
1055
1056pub static MZ_PREPARED_STATEMENT_HISTORY: LazyLock<BuiltinSource> =
1057    LazyLock::new(|| BuiltinSource {
1058        name: "mz_prepared_statement_history",
1059        schema: MZ_INTERNAL_SCHEMA,
1060        oid: oid::SOURCE_MZ_PREPARED_STATEMENT_HISTORY_OID,
1061        data_source: IntrospectionType::PreparedStatementHistory.into(),
1062        desc: MZ_PREPARED_STATEMENT_HISTORY_DESC.clone(),
1063        column_comments: BTreeMap::new(),
1064        is_retained_metrics_object: false,
1065        access: vec![
1066            SUPPORT_SELECT,
1067            ANALYTICS_SELECT,
1068            MONITOR_REDACTED_SELECT,
1069            MONITOR_SELECT,
1070        ],
1071        ontology: None,
1072    });
1073
1074pub static MZ_SQL_TEXT: LazyLock<BuiltinSource> = LazyLock::new(|| BuiltinSource {
1075    name: "mz_sql_text",
1076    schema: MZ_INTERNAL_SCHEMA,
1077    oid: oid::SOURCE_MZ_SQL_TEXT_OID,
1078    desc: MZ_SQL_TEXT_DESC.clone(),
1079    data_source: IntrospectionType::SqlText.into(),
1080    column_comments: BTreeMap::new(),
1081    is_retained_metrics_object: false,
1082    access: vec![MONITOR_SELECT],
1083    ontology: Some(Ontology {
1084        entity_name: "sql_text",
1085        description: "Raw SQL text of executed statements",
1086        links: &const { [] },
1087        column_semantic_types: &[],
1088    }),
1089});
1090
1091pub static MZ_SQL_TEXT_REDACTED: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
1092    name: "mz_sql_text_redacted",
1093    schema: MZ_INTERNAL_SCHEMA,
1094    oid: oid::VIEW_MZ_SQL_TEXT_REDACTED_OID,
1095    desc: RelationDesc::builder()
1096        .with_column("sql_hash", SqlScalarType::Bytes.nullable(false))
1097        .with_column("redacted_sql", SqlScalarType::String.nullable(false))
1098        .finish(),
1099    column_comments: BTreeMap::new(),
1100    sql: "SELECT sql_hash, redacted_sql FROM mz_internal.mz_sql_text",
1101    access: vec![
1102        MONITOR_SELECT,
1103        MONITOR_REDACTED_SELECT,
1104        SUPPORT_SELECT,
1105        ANALYTICS_SELECT,
1106    ],
1107    ontology: None,
1108});
1109
1110pub static MZ_RECENT_SQL_TEXT: LazyLock<BuiltinView> = LazyLock::new(|| {
1111    BuiltinView {
1112        name: "mz_recent_sql_text",
1113        schema: MZ_INTERNAL_SCHEMA,
1114        oid: oid::VIEW_MZ_RECENT_SQL_TEXT_OID,
1115        // This should always be 1 day more than the interval in
1116        // `MZ_RECENT_THINNED_ACTIVITY_LOG` , because `prepared_day`
1117        // is rounded down to the nearest day.  Thus something that actually happened three days ago
1118        // could have a `prepared day` anywhere from 3 to 4 days back.
1119        desc: RelationDesc::builder()
1120            .with_column("sql_hash", SqlScalarType::Bytes.nullable(false))
1121            .with_column("sql", SqlScalarType::String.nullable(false))
1122            .with_column("redacted_sql", SqlScalarType::String.nullable(false))
1123            .with_key(vec![0, 1, 2])
1124            .finish(),
1125        column_comments: BTreeMap::new(),
1126        sql: "SELECT DISTINCT sql_hash, sql, redacted_sql FROM mz_internal.mz_sql_text WHERE prepared_day + INTERVAL '4 days' >= mz_now()",
1127        access: vec![MONITOR_SELECT],
1128        ontology: Some(Ontology {
1129            entity_name: "recent_sql_text",
1130            description: "Recent SQL text (indexed, last ~3-4 days)",
1131            links: &const { [] },
1132            column_semantic_types: &[("sql", SemanticType::SqlDefinition)],
1133        }),
1134    }
1135});
1136
1137pub static MZ_RECENT_SQL_TEXT_REDACTED: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
1138    name: "mz_recent_sql_text_redacted",
1139    schema: MZ_INTERNAL_SCHEMA,
1140    oid: oid::VIEW_MZ_RECENT_SQL_TEXT_REDACTED_OID,
1141    desc: RelationDesc::builder()
1142        .with_column("sql_hash", SqlScalarType::Bytes.nullable(false))
1143        .with_column("redacted_sql", SqlScalarType::String.nullable(false))
1144        .finish(),
1145    column_comments: BTreeMap::new(),
1146    sql: "SELECT sql_hash, redacted_sql FROM mz_internal.mz_recent_sql_text",
1147    access: vec![
1148        MONITOR_SELECT,
1149        MONITOR_REDACTED_SELECT,
1150        SUPPORT_SELECT,
1151        ANALYTICS_SELECT,
1152    ],
1153    ontology: None,
1154});
1155
1156pub static MZ_RECENT_SQL_TEXT_IND: LazyLock<BuiltinIndex> = LazyLock::new(|| BuiltinIndex {
1157    name: "mz_recent_sql_text_ind",
1158    schema: MZ_INTERNAL_SCHEMA,
1159    oid: oid::INDEX_MZ_RECENT_SQL_TEXT_IND_OID,
1160    sql: "IN CLUSTER mz_catalog_server ON mz_internal.mz_recent_sql_text (sql_hash)",
1161    is_retained_metrics_object: false,
1162});
1163
1164pub static MZ_SESSION_HISTORY: LazyLock<BuiltinSource> = LazyLock::new(|| BuiltinSource {
1165    name: "mz_session_history",
1166    schema: MZ_INTERNAL_SCHEMA,
1167    oid: oid::SOURCE_MZ_SESSION_HISTORY_OID,
1168    data_source: IntrospectionType::SessionHistory.into(),
1169    desc: MZ_SESSION_HISTORY_DESC.clone(),
1170    column_comments: BTreeMap::from_iter([
1171        (
1172            "session_id",
1173            "The globally unique ID of the session. Corresponds to `mz_sessions.id`.",
1174        ),
1175        (
1176            "connected_at",
1177            "The time at which the session was established.",
1178        ),
1179        (
1180            "initial_application_name",
1181            "The `application_name` session metadata field.",
1182        ),
1183        (
1184            "authenticated_user",
1185            "The name of the user for which the session was established.",
1186        ),
1187    ]),
1188    is_retained_metrics_object: false,
1189    access: vec![PUBLIC_SELECT],
1190    ontology: Some(Ontology {
1191        entity_name: "session",
1192        description: "Historical session connection events",
1193        links: &const {
1194            [OntologyLink {
1195                name: "active_as",
1196                target: "active_session",
1197                properties: LinkProperties::fk_nullable("session_id", "id", Cardinality::ManyToOne),
1198            }]
1199        },
1200        column_semantic_types: &[("connected_at", SemanticType::WallclockTimestamp)],
1201    }),
1202});
1203
1204pub static MZ_ACTIVITY_LOG_THINNED: LazyLock<BuiltinView> = LazyLock::new(|| {
1205    BuiltinView {
1206        name: "mz_activity_log_thinned",
1207        schema: MZ_INTERNAL_SCHEMA,
1208        oid: oid::VIEW_MZ_ACTIVITY_LOG_THINNED_OID,
1209        desc: RelationDesc::builder()
1210            .with_column("execution_id", SqlScalarType::Uuid.nullable(false))
1211            .with_column("sample_rate", SqlScalarType::Float64.nullable(false))
1212            .with_column("cluster_id", SqlScalarType::String.nullable(true))
1213            .with_column("application_name", SqlScalarType::String.nullable(false))
1214            .with_column("cluster_name", SqlScalarType::String.nullable(true))
1215            .with_column("database_name", SqlScalarType::String.nullable(false))
1216            .with_column("search_path", SqlScalarType::List { element_type: Box::new(SqlScalarType::String), custom_id: None }.nullable(false))
1217            .with_column("transaction_isolation", SqlScalarType::String.nullable(false))
1218            .with_column("execution_timestamp", SqlScalarType::UInt64.nullable(true))
1219            .with_column("transient_index_id", SqlScalarType::String.nullable(true))
1220            .with_column("params", SqlScalarType::Array(Box::new(SqlScalarType::String)).nullable(false))
1221            .with_column("mz_version", SqlScalarType::String.nullable(false))
1222            .with_column("began_at", SqlScalarType::TimestampTz { precision: None }.nullable(false))
1223            .with_column("finished_at", SqlScalarType::TimestampTz { precision: None }.nullable(true))
1224            .with_column("finished_status", SqlScalarType::String.nullable(true))
1225            .with_column("error_message", SqlScalarType::String.nullable(true))
1226            .with_column("result_size", SqlScalarType::Int64.nullable(true))
1227            .with_column("rows_returned", SqlScalarType::Int64.nullable(true))
1228            .with_column("execution_strategy", SqlScalarType::String.nullable(true))
1229            .with_column("transaction_id", SqlScalarType::UInt64.nullable(false))
1230            .with_column("prepared_statement_id", SqlScalarType::Uuid.nullable(false))
1231            .with_column("sql_hash", SqlScalarType::Bytes.nullable(false))
1232            .with_column("prepared_statement_name", SqlScalarType::String.nullable(false))
1233            .with_column("session_id", SqlScalarType::Uuid.nullable(false))
1234            .with_column("prepared_at", SqlScalarType::TimestampTz { precision: None }.nullable(false))
1235            .with_column("statement_type", SqlScalarType::String.nullable(true))
1236            .with_column("throttled_count", SqlScalarType::UInt64.nullable(false))
1237            .with_column("connected_at", SqlScalarType::TimestampTz { precision: None }.nullable(false))
1238            .with_column("initial_application_name", SqlScalarType::String.nullable(false))
1239            .with_column("authenticated_user", SqlScalarType::String.nullable(false))
1240            .finish(),
1241        column_comments: BTreeMap::new(),
1242        sql: "
1243SELECT mseh.id AS execution_id, sample_rate, cluster_id, application_name, cluster_name, database_name, search_path,
1244transaction_isolation, execution_timestamp, transient_index_id, params, mz_version, began_at, finished_at, finished_status,
1245error_message, result_size, rows_returned, execution_strategy, transaction_id,
1246mpsh.id AS prepared_statement_id, sql_hash, mpsh.name AS prepared_statement_name,
1247mpsh.session_id, prepared_at, statement_type, throttled_count,
1248connected_at, initial_application_name, authenticated_user
1249FROM mz_internal.mz_statement_execution_history mseh,
1250     mz_internal.mz_prepared_statement_history mpsh,
1251     mz_internal.mz_session_history msh
1252WHERE mseh.prepared_statement_id = mpsh.id
1253AND mpsh.session_id = msh.session_id",
1254        access: vec![MONITOR_SELECT],
1255        ontology: None,
1256    }
1257});
1258
1259pub static MZ_RECENT_ACTIVITY_LOG_THINNED: LazyLock<BuiltinView> = LazyLock::new(|| {
1260    BuiltinView {
1261        name: "mz_recent_activity_log_thinned",
1262        schema: MZ_INTERNAL_SCHEMA,
1263        oid: oid::VIEW_MZ_RECENT_ACTIVITY_LOG_THINNED_OID,
1264        desc: RelationDesc::builder()
1265            .with_column("execution_id", SqlScalarType::Uuid.nullable(false))
1266            .with_column("sample_rate", SqlScalarType::Float64.nullable(false))
1267            .with_column("cluster_id", SqlScalarType::String.nullable(true))
1268            .with_column("application_name", SqlScalarType::String.nullable(false))
1269            .with_column("cluster_name", SqlScalarType::String.nullable(true))
1270            .with_column("database_name", SqlScalarType::String.nullable(false))
1271            .with_column("search_path", SqlScalarType::List { element_type: Box::new(SqlScalarType::String), custom_id: None }.nullable(false))
1272            .with_column("transaction_isolation", SqlScalarType::String.nullable(false))
1273            .with_column("execution_timestamp", SqlScalarType::UInt64.nullable(true))
1274            .with_column("transient_index_id", SqlScalarType::String.nullable(true))
1275            .with_column("params", SqlScalarType::Array(Box::new(SqlScalarType::String)).nullable(false))
1276            .with_column("mz_version", SqlScalarType::String.nullable(false))
1277            .with_column("began_at", SqlScalarType::TimestampTz { precision: None }.nullable(false))
1278            .with_column("finished_at", SqlScalarType::TimestampTz { precision: None }.nullable(true))
1279            .with_column("finished_status", SqlScalarType::String.nullable(true))
1280            .with_column("error_message", SqlScalarType::String.nullable(true))
1281            .with_column("result_size", SqlScalarType::Int64.nullable(true))
1282            .with_column("rows_returned", SqlScalarType::Int64.nullable(true))
1283            .with_column("execution_strategy", SqlScalarType::String.nullable(true))
1284            .with_column("transaction_id", SqlScalarType::UInt64.nullable(false))
1285            .with_column("prepared_statement_id", SqlScalarType::Uuid.nullable(false))
1286            .with_column("sql_hash", SqlScalarType::Bytes.nullable(false))
1287            .with_column("prepared_statement_name", SqlScalarType::String.nullable(false))
1288            .with_column("session_id", SqlScalarType::Uuid.nullable(false))
1289            .with_column("prepared_at", SqlScalarType::TimestampTz { precision: None }.nullable(false))
1290            .with_column("statement_type", SqlScalarType::String.nullable(true))
1291            .with_column("throttled_count", SqlScalarType::UInt64.nullable(false))
1292            .with_column("connected_at", SqlScalarType::TimestampTz { precision: None }.nullable(false))
1293            .with_column("initial_application_name", SqlScalarType::String.nullable(false))
1294            .with_column("authenticated_user", SqlScalarType::String.nullable(false))
1295            .finish(),
1296        column_comments: BTreeMap::new(),
1297        // We use a temporal window of 2 days rather than 1 day for `mz_session_history`'s `connected_at` since a statement execution at
1298        // the edge of the 1 day temporal window could've been executed in a session that was established an hour before the 1 day window.
1299        sql:
1300        "SELECT * FROM mz_internal.mz_activity_log_thinned WHERE prepared_at + INTERVAL '1 day' > mz_now()
1301AND began_at + INTERVAL '1 day' > mz_now() AND connected_at + INTERVAL '2 days' > mz_now()",
1302        access: vec![MONITOR_SELECT],
1303        ontology: None,
1304    }
1305});
1306
1307pub static MZ_RECENT_ACTIVITY_LOG: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
1308    name: "mz_recent_activity_log",
1309    schema: MZ_INTERNAL_SCHEMA,
1310    oid: oid::VIEW_MZ_RECENT_ACTIVITY_LOG_OID,
1311    desc: RelationDesc::builder()
1312        .with_column("execution_id", SqlScalarType::Uuid.nullable(false))
1313        .with_column("sample_rate", SqlScalarType::Float64.nullable(false))
1314        .with_column("cluster_id", SqlScalarType::String.nullable(true))
1315        .with_column("application_name", SqlScalarType::String.nullable(false))
1316        .with_column("cluster_name", SqlScalarType::String.nullable(true))
1317        .with_column("database_name", SqlScalarType::String.nullable(false))
1318        .with_column(
1319            "search_path",
1320            SqlScalarType::List {
1321                element_type: Box::new(SqlScalarType::String),
1322                custom_id: None,
1323            }
1324            .nullable(false),
1325        )
1326        .with_column(
1327            "transaction_isolation",
1328            SqlScalarType::String.nullable(false),
1329        )
1330        .with_column("execution_timestamp", SqlScalarType::UInt64.nullable(true))
1331        .with_column("transient_index_id", SqlScalarType::String.nullable(true))
1332        .with_column(
1333            "params",
1334            SqlScalarType::Array(Box::new(SqlScalarType::String)).nullable(false),
1335        )
1336        .with_column("mz_version", SqlScalarType::String.nullable(false))
1337        .with_column(
1338            "began_at",
1339            SqlScalarType::TimestampTz { precision: None }.nullable(false),
1340        )
1341        .with_column(
1342            "finished_at",
1343            SqlScalarType::TimestampTz { precision: None }.nullable(true),
1344        )
1345        .with_column("finished_status", SqlScalarType::String.nullable(true))
1346        .with_column("error_message", SqlScalarType::String.nullable(true))
1347        .with_column("result_size", SqlScalarType::Int64.nullable(true))
1348        .with_column("rows_returned", SqlScalarType::Int64.nullable(true))
1349        .with_column("execution_strategy", SqlScalarType::String.nullable(true))
1350        .with_column("transaction_id", SqlScalarType::UInt64.nullable(false))
1351        .with_column("prepared_statement_id", SqlScalarType::Uuid.nullable(false))
1352        .with_column("sql_hash", SqlScalarType::Bytes.nullable(false))
1353        .with_column(
1354            "prepared_statement_name",
1355            SqlScalarType::String.nullable(false),
1356        )
1357        .with_column("session_id", SqlScalarType::Uuid.nullable(false))
1358        .with_column(
1359            "prepared_at",
1360            SqlScalarType::TimestampTz { precision: None }.nullable(false),
1361        )
1362        .with_column("statement_type", SqlScalarType::String.nullable(true))
1363        .with_column("throttled_count", SqlScalarType::UInt64.nullable(false))
1364        .with_column(
1365            "connected_at",
1366            SqlScalarType::TimestampTz { precision: None }.nullable(false),
1367        )
1368        .with_column(
1369            "initial_application_name",
1370            SqlScalarType::String.nullable(false),
1371        )
1372        .with_column("authenticated_user", SqlScalarType::String.nullable(false))
1373        .with_column("sql", SqlScalarType::String.nullable(false))
1374        .finish(),
1375    column_comments: BTreeMap::from_iter([
1376        (
1377            "execution_id",
1378            "An ID that is unique for each executed statement.",
1379        ),
1380        (
1381            "sample_rate",
1382            "The actual rate at which the statement was sampled.",
1383        ),
1384        (
1385            "cluster_id",
1386            "The ID of the cluster the statement execution was directed to. Corresponds to mz_clusters.id.",
1387        ),
1388        (
1389            "application_name",
1390            "The value of the `application_name` configuration parameter at execution time.",
1391        ),
1392        (
1393            "cluster_name",
1394            "The name of the cluster with ID `cluster_id` at execution time.",
1395        ),
1396        (
1397            "database_name",
1398            "The value of the `database` configuration parameter at execution time.",
1399        ),
1400        (
1401            "search_path",
1402            "The value of the `search_path` configuration parameter at execution time.",
1403        ),
1404        (
1405            "transaction_isolation",
1406            "The value of the `transaction_isolation` configuration parameter at execution time.",
1407        ),
1408        (
1409            "execution_timestamp",
1410            "The logical timestamp at which execution was scheduled.",
1411        ),
1412        (
1413            "transient_index_id",
1414            "The internal index of the compute dataflow created for the query, if any.",
1415        ),
1416        (
1417            "params",
1418            "The parameters with which the statement was executed.",
1419        ),
1420        (
1421            "mz_version",
1422            "The version of Materialize that was running when the statement was executed.",
1423        ),
1424        (
1425            "began_at",
1426            "The wall-clock time at which the statement began executing.",
1427        ),
1428        (
1429            "finished_at",
1430            "The wall-clock time at which the statement finished executing.",
1431        ),
1432        (
1433            "finished_status",
1434            "The final status of the statement (e.g., `success`, `canceled`, `error`, or `aborted`). `aborted` means that Materialize exited before the statement finished executing.",
1435        ),
1436        (
1437            "error_message",
1438            "The error message, if the statement failed.",
1439        ),
1440        (
1441            "result_size",
1442            "The size in bytes of the result, for statements that return rows.",
1443        ),
1444        (
1445            "rows_returned",
1446            "The number of rows returned, for statements that return rows.",
1447        ),
1448        (
1449            "execution_strategy",
1450            "For `SELECT` queries, the strategy for executing the query. `constant` means computed in the control plane without the involvement of a cluster, `fast-path` means read by a cluster directly from an in-memory index, and `standard` means computed by a temporary dataflow.",
1451        ),
1452        (
1453            "transaction_id",
1454            "The ID of the transaction that the statement was part of. Note that transaction IDs are only unique per session.",
1455        ),
1456        (
1457            "prepared_statement_id",
1458            "An ID that is unique for each prepared statement. For example, if a statement is prepared once and then executed multiple times, all executions will have the same value for this column (but different values for `execution_id`).",
1459        ),
1460        (
1461            "sql_hash",
1462            "An opaque value uniquely identifying the text of the query.",
1463        ),
1464        (
1465            "prepared_statement_name",
1466            "The name given by the client library to the prepared statement.",
1467        ),
1468        (
1469            "session_id",
1470            "An ID that is unique for each session. Corresponds to mz_sessions.id.",
1471        ),
1472        (
1473            "prepared_at",
1474            "The time at which the statement was prepared.",
1475        ),
1476        (
1477            "statement_type",
1478            "The _type_ of the statement, e.g. `select` for a `SELECT` query, or `NULL` if the statement was empty.",
1479        ),
1480        (
1481            "throttled_count",
1482            "The number of statement executions that were dropped due to throttling before the current one was seen. If you have a very high volume of queries and need to log them without throttling, contact our team.",
1483        ),
1484        (
1485            "connected_at",
1486            "The time at which the session was established.",
1487        ),
1488        (
1489            "initial_application_name",
1490            "The initial value of `application_name` at the beginning of the session.",
1491        ),
1492        (
1493            "authenticated_user",
1494            "The name of the user for which the session was established.",
1495        ),
1496        ("sql", "The SQL text of the statement."),
1497    ]),
1498    sql: "SELECT mralt.*, mrst.sql
1499FROM mz_internal.mz_recent_activity_log_thinned mralt,
1500     mz_internal.mz_recent_sql_text mrst
1501WHERE mralt.sql_hash = mrst.sql_hash",
1502    access: vec![MONITOR_SELECT],
1503    ontology: Some(Ontology {
1504        entity_name: "activity_log",
1505        description: "Recent query activity with execution stats",
1506        links: &const {
1507            [
1508                OntologyLink {
1509                    name: "in_session",
1510                    target: "session",
1511                    properties: LinkProperties::fk("session_id", "id", Cardinality::ManyToOne),
1512                },
1513                OntologyLink {
1514                    name: "in_active_session",
1515                    target: "active_session",
1516                    properties: LinkProperties::fk_nullable(
1517                        "session_id",
1518                        "id",
1519                        Cardinality::ManyToOne,
1520                    ),
1521                },
1522                OntologyLink {
1523                    name: "ran_on_cluster",
1524                    target: "cluster",
1525                    properties: LinkProperties::fk_nullable(
1526                        "cluster_id",
1527                        "id",
1528                        Cardinality::ManyToOne,
1529                    ),
1530                },
1531                OntologyLink {
1532                    name: "used_transient_index",
1533                    target: "object",
1534                    properties: LinkProperties::ForeignKey {
1535                        source_column: "transient_index_id",
1536                        target_column: "id",
1537                        cardinality: Cardinality::ManyToOne,
1538                        source_id_type: Some(mz_repr::SemanticType::GlobalId),
1539                        requires_mapping: Some("mz_internal.mz_object_global_ids"),
1540                        nullable: true,
1541                        note: None,
1542                        extra_key_columns: None,
1543                    },
1544                },
1545            ]
1546        },
1547        column_semantic_types: &const {
1548            [
1549                ("cluster_id", SemanticType::ClusterId),
1550                ("execution_timestamp", SemanticType::MzTimestamp),
1551                ("transient_index_id", SemanticType::GlobalId),
1552                ("began_at", SemanticType::WallclockTimestamp),
1553                ("finished_at", SemanticType::WallclockTimestamp),
1554                ("prepared_at", SemanticType::WallclockTimestamp),
1555                ("connected_at", SemanticType::WallclockTimestamp),
1556                ("sql", SemanticType::SqlDefinition),
1557            ]
1558        },
1559    }),
1560});
1561
1562pub static MZ_RECENT_ACTIVITY_LOG_REDACTED: LazyLock<BuiltinView> = LazyLock::new(|| {
1563    BuiltinView {
1564    name: "mz_recent_activity_log_redacted",
1565    schema: MZ_INTERNAL_SCHEMA,
1566    oid: oid::VIEW_MZ_RECENT_ACTIVITY_LOG_REDACTED_OID,
1567    // Includes all the columns in mz_recent_activity_log_thinned except 'error_message'.
1568    desc: RelationDesc::builder()
1569        .with_column("execution_id", SqlScalarType::Uuid.nullable(false))
1570        .with_column("sample_rate", SqlScalarType::Float64.nullable(false))
1571        .with_column("cluster_id", SqlScalarType::String.nullable(true))
1572        .with_column("application_name", SqlScalarType::String.nullable(false))
1573        .with_column("cluster_name", SqlScalarType::String.nullable(true))
1574        .with_column("database_name", SqlScalarType::String.nullable(false))
1575        .with_column("search_path", SqlScalarType::List { element_type: Box::new(SqlScalarType::String), custom_id: None }.nullable(false))
1576        .with_column("transaction_isolation", SqlScalarType::String.nullable(false))
1577        .with_column("execution_timestamp", SqlScalarType::UInt64.nullable(true))
1578        .with_column("transient_index_id", SqlScalarType::String.nullable(true))
1579        .with_column("mz_version", SqlScalarType::String.nullable(false))
1580        .with_column("began_at", SqlScalarType::TimestampTz { precision: None }.nullable(false))
1581        .with_column("finished_at", SqlScalarType::TimestampTz { precision: None }.nullable(true))
1582        .with_column("finished_status", SqlScalarType::String.nullable(true))
1583        .with_column("result_size", SqlScalarType::Int64.nullable(true))
1584        .with_column("rows_returned", SqlScalarType::Int64.nullable(true))
1585        .with_column("execution_strategy", SqlScalarType::String.nullable(true))
1586        .with_column("transaction_id", SqlScalarType::UInt64.nullable(false))
1587        .with_column("prepared_statement_id", SqlScalarType::Uuid.nullable(false))
1588        .with_column("sql_hash", SqlScalarType::Bytes.nullable(false))
1589        .with_column("prepared_statement_name", SqlScalarType::String.nullable(false))
1590        .with_column("session_id", SqlScalarType::Uuid.nullable(false))
1591        .with_column("prepared_at", SqlScalarType::TimestampTz { precision: None }.nullable(false))
1592        .with_column("statement_type", SqlScalarType::String.nullable(true))
1593        .with_column("throttled_count", SqlScalarType::UInt64.nullable(false))
1594        .with_column("initial_application_name", SqlScalarType::String.nullable(false))
1595        .with_column("authenticated_user", SqlScalarType::String.nullable(false))
1596        .with_column("redacted_sql", SqlScalarType::String.nullable(false))
1597        .finish(),
1598    column_comments: BTreeMap::new(),
1599    sql: "SELECT mralt.execution_id, mralt.sample_rate, mralt.cluster_id, mralt.application_name,
1600    mralt.cluster_name, mralt.database_name, mralt.search_path, mralt.transaction_isolation, mralt.execution_timestamp,
1601    mralt.transient_index_id, mralt.mz_version, mralt.began_at, mralt.finished_at,
1602    mralt.finished_status, mralt.result_size, mralt.rows_returned, mralt.execution_strategy, mralt.transaction_id,
1603    mralt.prepared_statement_id, mralt.sql_hash, mralt.prepared_statement_name, mralt.session_id,
1604    mralt.prepared_at, mralt.statement_type, mralt.throttled_count,
1605    mralt.initial_application_name, mralt.authenticated_user,
1606    mrst.redacted_sql
1607FROM mz_internal.mz_recent_activity_log_thinned mralt,
1608     mz_internal.mz_recent_sql_text mrst
1609WHERE mralt.sql_hash = mrst.sql_hash",
1610    access: vec![MONITOR_SELECT, MONITOR_REDACTED_SELECT, SUPPORT_SELECT, ANALYTICS_SELECT],
1611    ontology: None,
1612}
1613});
1614
1615pub static MZ_STATEMENT_LIFECYCLE_HISTORY: LazyLock<BuiltinSource> = LazyLock::new(|| {
1616    BuiltinSource {
1617        name: "mz_statement_lifecycle_history",
1618        schema: MZ_INTERNAL_SCHEMA,
1619        oid: oid::SOURCE_MZ_STATEMENT_LIFECYCLE_HISTORY_OID,
1620        desc: RelationDesc::builder()
1621            .with_column("statement_id", SqlScalarType::Uuid.nullable(false))
1622            .with_column("event_type", SqlScalarType::String.nullable(false))
1623            .with_column(
1624                "occurred_at",
1625                SqlScalarType::TimestampTz { precision: None }.nullable(false),
1626            )
1627            .finish(),
1628        data_source: IntrospectionType::StatementLifecycleHistory.into(),
1629        column_comments: BTreeMap::from_iter([
1630            (
1631                "statement_id",
1632                "The ID of the execution event. Corresponds to `mz_recent_activity_log.execution_id`",
1633            ),
1634            (
1635                "event_type",
1636                "The type of lifecycle event, e.g. `'execution-began'`, `'storage-dependencies-finished'`, `'compute-dependencies-finished'`, or `'execution-finished'`",
1637            ),
1638            ("occurred_at", "The time at which the event took place."),
1639        ]),
1640        is_retained_metrics_object: false,
1641        // TODO[btv]: Maybe this should be public instead of
1642        // `MONITOR_REDACTED`, but since that would be a backwards-compatible
1643        // change, we probably don't need to worry about it now.
1644        access: vec![
1645            SUPPORT_SELECT,
1646            ANALYTICS_SELECT,
1647            MONITOR_REDACTED_SELECT,
1648            MONITOR_SELECT,
1649        ],
1650        ontology: Some(Ontology {
1651            entity_name: "statement_lifecycle_event",
1652            description: "Statement lifecycle events (parse, bind, execute)",
1653            links: &const {
1654                [OntologyLink {
1655                    name: "for_execution",
1656                    target: "activity_log",
1657                    properties: LinkProperties::fk(
1658                        "statement_id",
1659                        "execution_id",
1660                        Cardinality::ManyToOne,
1661                    ),
1662                }]
1663            },
1664            column_semantic_types: &[],
1665        }),
1666    }
1667});
1668
1669pub static MZ_SOURCE_STATUSES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
1670    name: "mz_source_statuses",
1671    schema: MZ_INTERNAL_SCHEMA,
1672    oid: oid::VIEW_MZ_SOURCE_STATUSES_OID,
1673    desc: RelationDesc::builder()
1674        .with_column("id", SqlScalarType::String.nullable(false))
1675        .with_column("name", SqlScalarType::String.nullable(false))
1676        .with_column("type", SqlScalarType::String.nullable(false))
1677        .with_column(
1678            "last_status_change_at",
1679            SqlScalarType::TimestampTz { precision: None }.nullable(true),
1680        )
1681        .with_column("status", SqlScalarType::String.nullable(false))
1682        .with_column("error", SqlScalarType::String.nullable(true))
1683        .with_column("details", SqlScalarType::Jsonb.nullable(true))
1684        .finish(),
1685    column_comments: BTreeMap::from_iter([
1686        (
1687            "id",
1688            "The ID of the source. Corresponds to `mz_catalog.mz_sources.id`.",
1689        ),
1690        ("name", "The name of the source."),
1691        ("type", "The type of the source."),
1692        (
1693            "last_status_change_at",
1694            "Wall-clock timestamp of the source status change.",
1695        ),
1696        (
1697            "status",
1698            "The status of the source: one of `created`, `starting`, `running`, `paused`, `stalled`, `failed`, or `dropped`.",
1699        ),
1700        (
1701            "error",
1702            "If the source is in an error state, the error message.",
1703        ),
1704        (
1705            "details",
1706            "Additional metadata provided by the source. In case of error, may contain a `hint` field with helpful suggestions.",
1707        ),
1708    ]),
1709    sql: "
1710    WITH
1711    -- The status history contains per-replica events and source-global events.
1712    -- For the latter, replica_id is NULL. We turn these into '<source>', so that
1713    -- we can treat them uniformly below.
1714    uniform_status_history AS
1715    (
1716        SELECT
1717            s.source_id,
1718            COALESCE(s.replica_id, '<source>') as replica_id,
1719            s.occurred_at,
1720            s.status,
1721            s.error,
1722            s.details
1723        FROM mz_internal.mz_source_status_history s
1724    ),
1725    -- For getting the latest events, we first determine the latest per-replica
1726    -- events here and then apply precedence rules below.
1727    latest_per_replica_events AS
1728    (
1729        SELECT DISTINCT ON (source_id, replica_id)
1730            occurred_at, source_id, replica_id, status, error, details
1731        FROM uniform_status_history
1732        ORDER BY source_id, replica_id, occurred_at DESC
1733    ),
1734    -- We have a precedence list that determines the overall status in case
1735    -- there is differing per-replica (including source-global) statuses. If
1736    -- there is no 'dropped' status, and any replica reports 'running', the
1737    -- overall status is 'running' even if there might be some replica that has
1738    -- errors or is paused.
1739    latest_events AS
1740    (
1741       SELECT DISTINCT ON (source_id)
1742            source_id,
1743            occurred_at,
1744            status,
1745            error,
1746            details
1747        FROM latest_per_replica_events
1748        ORDER BY source_id, CASE status
1749                    WHEN 'dropped' THEN 1
1750                    WHEN 'running' THEN 2
1751                    WHEN 'stalled' THEN 3
1752                    WHEN 'starting' THEN 4
1753                    WHEN 'paused' THEN 5
1754                    WHEN 'ceased' THEN 6
1755                    ELSE 7  -- For any other status values
1756                END
1757    ),
1758    -- Determine which sources are subsources and which are parent sources
1759    subsources AS
1760    (
1761        SELECT subsources.id AS self, sources.id AS parent
1762        FROM
1763            mz_catalog.mz_sources AS subsources
1764                JOIN
1765                    mz_internal.mz_object_dependencies AS deps
1766                    ON subsources.id = deps.object_id
1767                JOIN mz_catalog.mz_sources AS sources ON sources.id = deps.referenced_object_id
1768    ),
1769    -- Determine which sources are source tables
1770    tables AS
1771    (
1772        SELECT tables.id AS self, tables.source_id AS parent, tables.name
1773        FROM mz_catalog.mz_tables AS tables
1774        WHERE tables.source_id IS NOT NULL
1775    ),
1776    -- Determine which collection's ID to use for the status
1777    id_of_status_to_use AS
1778    (
1779        SELECT
1780            self_events.source_id,
1781            -- If self not errored, but parent is, use parent; else self
1782            CASE
1783                WHEN
1784                    self_events.status <> 'ceased' AND
1785                    parent_events.status = 'stalled'
1786                THEN parent_events.source_id
1787                ELSE self_events.source_id
1788            END AS id_to_use
1789        FROM
1790            latest_events AS self_events
1791                LEFT JOIN subsources ON self_events.source_id = subsources.self
1792                LEFT JOIN tables ON self_events.source_id = tables.self
1793                LEFT JOIN
1794                    latest_events AS parent_events
1795                    ON parent_events.source_id = COALESCE(subsources.parent, tables.parent)
1796    ),
1797    -- Swap out events for the ID of the event we plan to use instead
1798    latest_events_to_use AS
1799    (
1800        SELECT occurred_at, s.source_id, status, error, details
1801        FROM
1802            id_of_status_to_use AS s
1803                JOIN latest_events AS e ON e.source_id = s.id_to_use
1804    ),
1805    combined AS (
1806        SELECT
1807            mz_sources.id,
1808            mz_sources.name,
1809            mz_sources.type,
1810            occurred_at,
1811            status,
1812            error,
1813            details
1814        FROM
1815            mz_catalog.mz_sources
1816            LEFT JOIN latest_events_to_use AS e ON mz_sources.id = e.source_id
1817        UNION ALL
1818        SELECT
1819            tables.self AS id,
1820            tables.name,
1821            'table' AS type,
1822            occurred_at,
1823            status,
1824            error,
1825            details
1826        FROM
1827            tables
1828            LEFT JOIN latest_events_to_use AS e ON tables.self = e.source_id
1829    )
1830SELECT
1831    id,
1832    name,
1833    type,
1834    occurred_at AS last_status_change_at,
1835    -- TODO(parkmycar): Report status of webhook source once database-issues#5986 is closed.
1836    CASE
1837        WHEN
1838            type = 'webhook' OR
1839            type = 'progress'
1840        THEN 'running'
1841        ELSE COALESCE(status, 'created')
1842    END AS status,
1843    error,
1844    details
1845FROM combined
1846WHERE id NOT LIKE 's%';",
1847    access: vec![PUBLIC_SELECT],
1848    ontology: Some(Ontology {
1849        entity_name: "source_status",
1850        description: "Current source status (running, stalled, etc.)",
1851        links: &const {
1852            [OntologyLink {
1853                name: "status_of_source",
1854                target: "source",
1855                properties: LinkProperties::fk("id", "id", Cardinality::OneToOne),
1856            }]
1857        },
1858        column_semantic_types: &const {
1859            [
1860                ("id", SemanticType::CatalogItemId),
1861                ("type", SemanticType::SourceType),
1862                ("last_status_change_at", SemanticType::WallclockTimestamp),
1863            ]
1864        },
1865    }),
1866});
1867
1868pub static MZ_SINK_STATUS_HISTORY: LazyLock<BuiltinSource> = LazyLock::new(|| BuiltinSource {
1869    name: "mz_sink_status_history",
1870    schema: MZ_INTERNAL_SCHEMA,
1871    oid: oid::SOURCE_MZ_SINK_STATUS_HISTORY_OID,
1872    data_source: IntrospectionType::SinkStatusHistory.into(),
1873    desc: MZ_SINK_STATUS_HISTORY_DESC.clone(),
1874    column_comments: BTreeMap::from_iter([
1875        (
1876            "occurred_at",
1877            "Wall-clock timestamp of the sink status change.",
1878        ),
1879        (
1880            "sink_id",
1881            "The ID of the sink. Corresponds to `mz_catalog.mz_sinks.id`.",
1882        ),
1883        (
1884            "status",
1885            "The status of the sink: one of `created`, `starting`, `running`, `stalled`, `failed`, or `dropped`.",
1886        ),
1887        (
1888            "error",
1889            "If the sink is in an error state, the error message.",
1890        ),
1891        (
1892            "details",
1893            "Additional metadata provided by the sink. In case of error, may contain a `hint` field with helpful suggestions.",
1894        ),
1895        (
1896            "replica_id",
1897            "The ID of the replica that an instance of a sink is running on.",
1898        ),
1899    ]),
1900    is_retained_metrics_object: false,
1901    access: vec![PUBLIC_SELECT],
1902    ontology: Some(Ontology {
1903        entity_name: "sink_status_event",
1904        description: "Historical sink status events",
1905        links: &const {
1906            [
1907                OntologyLink {
1908                    name: "status_event_of_sink",
1909                    target: "sink",
1910                    properties: LinkProperties::fk_mapped(
1911                        "sink_id",
1912                        "id",
1913                        Cardinality::ManyToOne,
1914                        mz_repr::SemanticType::GlobalId,
1915                        "mz_internal.mz_object_global_ids",
1916                    ),
1917                },
1918                OntologyLink {
1919                    name: "on_replica",
1920                    target: "replica",
1921                    properties: LinkProperties::fk_nullable(
1922                        "replica_id",
1923                        "id",
1924                        Cardinality::ManyToOne,
1925                    ),
1926                },
1927            ]
1928        },
1929        column_semantic_types: &const {
1930            [
1931                ("occurred_at", SemanticType::WallclockTimestamp),
1932                ("sink_id", SemanticType::GlobalId),
1933                ("replica_id", SemanticType::ReplicaId),
1934            ]
1935        },
1936    }),
1937});
1938
1939pub static MZ_SINK_STATUSES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
1940    name: "mz_sink_statuses",
1941    schema: MZ_INTERNAL_SCHEMA,
1942    oid: oid::VIEW_MZ_SINK_STATUSES_OID,
1943    desc: RelationDesc::builder()
1944        .with_column("id", SqlScalarType::String.nullable(false))
1945        .with_column("name", SqlScalarType::String.nullable(false))
1946        .with_column("type", SqlScalarType::String.nullable(false))
1947        .with_column(
1948            "last_status_change_at",
1949            SqlScalarType::TimestampTz { precision: None }.nullable(true),
1950        )
1951        .with_column("status", SqlScalarType::String.nullable(false))
1952        .with_column("error", SqlScalarType::String.nullable(true))
1953        .with_column("details", SqlScalarType::Jsonb.nullable(true))
1954        .finish(),
1955    column_comments: BTreeMap::from_iter([
1956        (
1957            "id",
1958            "The ID of the sink. Corresponds to `mz_catalog.mz_sinks.id`.",
1959        ),
1960        ("name", "The name of the sink."),
1961        ("type", "The type of the sink."),
1962        (
1963            "last_status_change_at",
1964            "Wall-clock timestamp of the sink status change.",
1965        ),
1966        (
1967            "status",
1968            "The status of the sink: one of `created`, `starting`, `running`, `stalled`, `failed`, or `dropped`.",
1969        ),
1970        (
1971            "error",
1972            "If the sink is in an error state, the error message.",
1973        ),
1974        (
1975            "details",
1976            "Additional metadata provided by the sink. In case of error, may contain a `hint` field with helpful suggestions.",
1977        ),
1978    ]),
1979    sql: "
1980WITH
1981-- The status history contains per-replica events and sink-global events.
1982-- For the latter, replica_id is NULL. We turn these into '<sink>', so that
1983-- we can treat them uniformly below.
1984uniform_status_history AS
1985(
1986    SELECT
1987        s.sink_id,
1988        COALESCE(s.replica_id, '<sink>') as replica_id,
1989        s.occurred_at,
1990        s.status,
1991        s.error,
1992        s.details
1993    FROM mz_internal.mz_sink_status_history s
1994),
1995-- For getting the latest events, we first determine the latest per-replica
1996-- events here and then apply precedence rules below.
1997latest_per_replica_events AS
1998(
1999    SELECT DISTINCT ON (sink_id, replica_id)
2000        occurred_at, sink_id, replica_id, status, error, details
2001    FROM uniform_status_history
2002    ORDER BY sink_id, replica_id, occurred_at DESC
2003),
2004-- We have a precedence list that determines the overall status in case
2005-- there is differing per-replica (including sink-global) statuses. If
2006-- there is no 'dropped' status, and any replica reports 'running', the
2007-- overall status is 'running' even if there might be some replica that has
2008-- errors or is paused.
2009latest_events AS
2010(
2011    SELECT DISTINCT ON (sink_id)
2012        sink_id,
2013        occurred_at,
2014        status,
2015        error,
2016        details
2017    FROM latest_per_replica_events
2018    ORDER BY sink_id, CASE status
2019                WHEN 'dropped' THEN 1
2020                WHEN 'running' THEN 2
2021                WHEN 'stalled' THEN 3
2022                WHEN 'starting' THEN 4
2023                WHEN 'paused' THEN 5
2024                WHEN 'ceased' THEN 6
2025                ELSE 7  -- For any other status values
2026            END
2027)
2028SELECT
2029    mz_sinks.id,
2030    name,
2031    mz_sinks.type,
2032    occurred_at as last_status_change_at,
2033    coalesce(status, 'created') as status,
2034    error,
2035    details
2036FROM mz_catalog.mz_sinks
2037LEFT JOIN latest_events ON mz_sinks.id = latest_events.sink_id
2038WHERE
2039    -- This is a convenient way to filter out system sinks, like the status_history table itself.
2040    mz_sinks.id NOT LIKE 's%'",
2041    access: vec![PUBLIC_SELECT],
2042    ontology: Some(Ontology {
2043        entity_name: "sink_status",
2044        description: "Current sink status",
2045        links: &const {
2046            [OntologyLink {
2047                name: "status_of_sink",
2048                target: "sink",
2049                properties: LinkProperties::fk_typed(
2050                    "id",
2051                    "id",
2052                    Cardinality::OneToOne,
2053                    mz_repr::SemanticType::CatalogItemId,
2054                ),
2055            }]
2056        },
2057        column_semantic_types: &const {
2058            [
2059                ("id", SemanticType::CatalogItemId),
2060                ("last_status_change_at", SemanticType::WallclockTimestamp),
2061            ]
2062        },
2063    }),
2064});
2065
2066pub static MZ_STORAGE_USAGE_BY_SHARD: LazyLock<BuiltinTable> = LazyLock::new(|| BuiltinTable {
2067    name: "mz_storage_usage_by_shard",
2068    schema: MZ_INTERNAL_SCHEMA,
2069    oid: oid::TABLE_MZ_STORAGE_USAGE_BY_SHARD_OID,
2070    desc: RelationDesc::builder()
2071        .with_column("id", SqlScalarType::UInt64.nullable(false))
2072        .with_column("shard_id", SqlScalarType::String.nullable(true))
2073        .with_column("size_bytes", SqlScalarType::UInt64.nullable(false))
2074        .with_column(
2075            "collection_timestamp",
2076            SqlScalarType::TimestampTz { precision: None }.nullable(false),
2077        )
2078        .finish(),
2079    column_comments: BTreeMap::new(),
2080    is_retained_metrics_object: false,
2081    access: vec![PUBLIC_SELECT],
2082    ontology: Some(Ontology {
2083        entity_name: "storage_usage_by_shard",
2084        description: "Storage usage broken down by shard",
2085        links: &const { [] },
2086        column_semantic_types: &const {
2087            [
2088                ("shard_id", SemanticType::ShardId),
2089                ("size_bytes", SemanticType::ByteCount),
2090                ("collection_timestamp", SemanticType::WallclockTimestamp),
2091            ]
2092        },
2093    }),
2094});
2095
2096pub static MZ_AWS_CONNECTIONS: LazyLock<BuiltinTable> = LazyLock::new(|| BuiltinTable {
2097    name: "mz_aws_connections",
2098    schema: MZ_INTERNAL_SCHEMA,
2099    oid: oid::TABLE_MZ_AWS_CONNECTIONS_OID,
2100    desc: RelationDesc::builder()
2101        .with_column("id", SqlScalarType::String.nullable(false))
2102        .with_column("endpoint", SqlScalarType::String.nullable(true))
2103        .with_column("region", SqlScalarType::String.nullable(true))
2104        .with_column("access_key_id", SqlScalarType::String.nullable(true))
2105        .with_column(
2106            "access_key_id_secret_id",
2107            SqlScalarType::String.nullable(true),
2108        )
2109        .with_column(
2110            "secret_access_key_secret_id",
2111            SqlScalarType::String.nullable(true),
2112        )
2113        .with_column("session_token", SqlScalarType::String.nullable(true))
2114        .with_column(
2115            "session_token_secret_id",
2116            SqlScalarType::String.nullable(true),
2117        )
2118        .with_column("assume_role_arn", SqlScalarType::String.nullable(true))
2119        .with_column(
2120            "assume_role_session_name",
2121            SqlScalarType::String.nullable(true),
2122        )
2123        .with_column("principal", SqlScalarType::String.nullable(true))
2124        .with_column("external_id", SqlScalarType::String.nullable(true))
2125        .with_column("example_trust_policy", SqlScalarType::Jsonb.nullable(true))
2126        .finish(),
2127    column_comments: BTreeMap::from_iter([
2128        ("id", "The ID of the connection."),
2129        ("endpoint", "The value of the `ENDPOINT` option, if set."),
2130        ("region", "The value of the `REGION` option, if set."),
2131        (
2132            "access_key_id",
2133            "The value of the `ACCESS KEY ID` option, if provided in line.",
2134        ),
2135        (
2136            "access_key_id_secret_id",
2137            "The ID of the secret referenced by the `ACCESS KEY ID` option, if provided via a secret.",
2138        ),
2139        (
2140            "secret_access_key_secret_id",
2141            "The ID of the secret referenced by the `SECRET ACCESS KEY` option, if set.",
2142        ),
2143        (
2144            "session_token",
2145            "The value of the `SESSION TOKEN` option, if provided in line.",
2146        ),
2147        (
2148            "session_token_secret_id",
2149            "The ID of the secret referenced by the `SESSION TOKEN` option, if provided via a secret.",
2150        ),
2151        (
2152            "assume_role_arn",
2153            "The value of the `ASSUME ROLE ARN` option, if set.",
2154        ),
2155        (
2156            "assume_role_session_name",
2157            "The value of the `ASSUME ROLE SESSION NAME` option, if set.",
2158        ),
2159        (
2160            "principal",
2161            "The ARN of the AWS principal Materialize will use when assuming the provided role, if the connection is configured to use role assumption.",
2162        ),
2163        (
2164            "external_id",
2165            "The external ID Materialize will use when assuming the provided role, if the connection is configured to use role assumption.",
2166        ),
2167        (
2168            "example_trust_policy",
2169            "An example of an IAM role trust policy that allows this connection's principal and external ID to assume the role.",
2170        ),
2171    ]),
2172    is_retained_metrics_object: false,
2173    access: vec![PUBLIC_SELECT],
2174    ontology: Some(Ontology {
2175        entity_name: "aws_connection",
2176        description: "AWS connection configuration details",
2177        links: &const {
2178            [OntologyLink {
2179                name: "details_of",
2180                target: "connection",
2181                properties: LinkProperties::fk("id", "id", Cardinality::OneToOne),
2182            }]
2183        },
2184        column_semantic_types: &[],
2185    }),
2186});
2187
2188pub static MZ_CLUSTER_REPLICA_METRICS_HISTORY: LazyLock<BuiltinSource> =
2189    LazyLock::new(|| BuiltinSource {
2190        name: "mz_cluster_replica_metrics_history",
2191        schema: MZ_INTERNAL_SCHEMA,
2192        oid: oid::SOURCE_MZ_CLUSTER_REPLICA_METRICS_HISTORY_OID,
2193        data_source: IntrospectionType::ReplicaMetricsHistory.into(),
2194        desc: REPLICA_METRICS_HISTORY_DESC.clone(),
2195        column_comments: BTreeMap::from_iter([
2196            ("replica_id", "The ID of a cluster replica."),
2197            ("process_id", "The ID of a process within the replica."),
2198            (
2199                "cpu_nano_cores",
2200                "Approximate CPU usage, in billionths of a vCPU core.",
2201            ),
2202            ("memory_bytes", "Approximate memory usage, in bytes."),
2203            ("disk_bytes", "Approximate disk usage, in bytes."),
2204            (
2205                "occurred_at",
2206                "Wall-clock timestamp at which the event occurred.",
2207            ),
2208            (
2209                "heap_bytes",
2210                "Approximate heap (RAM + swap) usage, in bytes.",
2211            ),
2212            ("heap_limit", "Available heap (RAM + swap) space, in bytes."),
2213        ]),
2214        is_retained_metrics_object: false,
2215        access: vec![PUBLIC_SELECT],
2216        ontology: None,
2217    });
2218
2219pub static MZ_CLUSTER_REPLICA_METRICS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
2220    name: "mz_cluster_replica_metrics",
2221    schema: MZ_INTERNAL_SCHEMA,
2222    oid: oid::VIEW_MZ_CLUSTER_REPLICA_METRICS_OID,
2223    desc: RelationDesc::builder()
2224        .with_column("replica_id", SqlScalarType::String.nullable(false))
2225        .with_column("process_id", SqlScalarType::UInt64.nullable(false))
2226        .with_column("cpu_nano_cores", SqlScalarType::UInt64.nullable(true))
2227        .with_column("memory_bytes", SqlScalarType::UInt64.nullable(true))
2228        .with_column("disk_bytes", SqlScalarType::UInt64.nullable(true))
2229        .with_column("heap_bytes", SqlScalarType::UInt64.nullable(true))
2230        .with_column("heap_limit", SqlScalarType::UInt64.nullable(true))
2231        .with_key(vec![0, 1])
2232        .finish(),
2233    column_comments: BTreeMap::from_iter([
2234        ("replica_id", "The ID of a cluster replica."),
2235        ("process_id", "The ID of a process within the replica."),
2236        (
2237            "cpu_nano_cores",
2238            "Approximate CPU usage, in billionths of a vCPU core.",
2239        ),
2240        ("memory_bytes", "Approximate RAM usage, in bytes."),
2241        ("disk_bytes", "Approximate disk usage, in bytes."),
2242        (
2243            "heap_bytes",
2244            "Approximate heap (RAM + swap) usage, in bytes.",
2245        ),
2246        ("heap_limit", "Available heap (RAM + swap) space, in bytes."),
2247    ]),
2248    sql: "
2249SELECT
2250    DISTINCT ON (replica_id, process_id)
2251    replica_id,
2252    process_id,
2253    cpu_nano_cores,
2254    memory_bytes,
2255    disk_bytes,
2256    heap_bytes,
2257    heap_limit
2258FROM mz_internal.mz_cluster_replica_metrics_history
2259JOIN mz_cluster_replicas r ON r.id = replica_id
2260ORDER BY replica_id, process_id, occurred_at DESC",
2261    access: vec![PUBLIC_SELECT],
2262    ontology: Some(Ontology {
2263        entity_name: "replica_metrics",
2264        description: "CPU and memory metrics per replica",
2265        links: &const {
2266            [OntologyLink {
2267                name: "metrics_of_replica",
2268                target: "replica",
2269                properties: LinkProperties::fk_typed(
2270                    "replica_id",
2271                    "id",
2272                    Cardinality::OneToOne,
2273                    mz_repr::SemanticType::CatalogItemId,
2274                ),
2275            }]
2276        },
2277        column_semantic_types: &const {
2278            [
2279                ("replica_id", SemanticType::ReplicaId),
2280                ("memory_bytes", SemanticType::ByteCount),
2281                ("disk_bytes", SemanticType::ByteCount),
2282                ("heap_bytes", SemanticType::ByteCount),
2283                ("heap_limit", SemanticType::ByteCount),
2284            ]
2285        },
2286    }),
2287});
2288
2289pub static MZ_FRONTIERS: LazyLock<BuiltinSource> = LazyLock::new(|| BuiltinSource {
2290    name: "mz_frontiers",
2291    schema: MZ_INTERNAL_SCHEMA,
2292    oid: oid::SOURCE_MZ_FRONTIERS_OID,
2293    data_source: IntrospectionType::Frontiers.into(),
2294    desc: RelationDesc::builder()
2295        .with_column("object_id", SqlScalarType::String.nullable(false))
2296        .with_column("read_frontier", SqlScalarType::MzTimestamp.nullable(true))
2297        .with_column("write_frontier", SqlScalarType::MzTimestamp.nullable(true))
2298        .finish(),
2299    column_comments: BTreeMap::from_iter([
2300        (
2301            "object_id",
2302            "The ID of the source, sink, table, index, materialized view, or subscription.",
2303        ),
2304        (
2305            "read_frontier",
2306            "The earliest timestamp at which the output is still readable.",
2307        ),
2308        (
2309            "write_frontier",
2310            "The next timestamp at which the output may change.",
2311        ),
2312    ]),
2313    is_retained_metrics_object: false,
2314    access: vec![PUBLIC_SELECT],
2315    ontology: Some(Ontology {
2316        entity_name: "frontier",
2317        description: "Current read/write frontiers for sources, sinks, tables, materialized views, indexes, and subscriptions",
2318        links: &const {
2319            [OntologyLink {
2320                name: "frontier_of",
2321                target: "object",
2322                properties: LinkProperties::fk_mapped(
2323                    "object_id",
2324                    "id",
2325                    Cardinality::ManyToOne,
2326                    mz_repr::SemanticType::GlobalId,
2327                    "mz_internal.mz_object_global_ids",
2328                ),
2329            }]
2330        },
2331        column_semantic_types: &const {
2332            [
2333                ("object_id", SemanticType::GlobalId),
2334                ("read_frontier", SemanticType::MzTimestamp),
2335                ("write_frontier", SemanticType::MzTimestamp),
2336            ]
2337        },
2338    }),
2339});
2340
2341/// DEPRECATED and scheduled for removal! Use `mz_frontiers` instead.
2342pub static MZ_GLOBAL_FRONTIERS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
2343    name: "mz_global_frontiers",
2344    schema: MZ_INTERNAL_SCHEMA,
2345    oid: oid::VIEW_MZ_GLOBAL_FRONTIERS_OID,
2346    desc: RelationDesc::builder()
2347        .with_column("object_id", SqlScalarType::String.nullable(false))
2348        .with_column("time", SqlScalarType::MzTimestamp.nullable(false))
2349        .finish(),
2350    column_comments: BTreeMap::new(),
2351    sql: "
2352SELECT object_id, write_frontier AS time
2353FROM mz_internal.mz_frontiers
2354WHERE write_frontier IS NOT NULL",
2355    access: vec![PUBLIC_SELECT],
2356    ontology: None,
2357});
2358
2359pub static MZ_WALLCLOCK_LAG_HISTORY: LazyLock<BuiltinSource> = LazyLock::new(|| BuiltinSource {
2360    name: "mz_wallclock_lag_history",
2361    schema: MZ_INTERNAL_SCHEMA,
2362    oid: oid::SOURCE_MZ_WALLCLOCK_LAG_HISTORY_OID,
2363    desc: WALLCLOCK_LAG_HISTORY_DESC.clone(),
2364    data_source: IntrospectionType::WallclockLagHistory.into(),
2365    column_comments: BTreeMap::from_iter([
2366        (
2367            "object_id",
2368            "The ID of the table, source, materialized view, index, or sink. Corresponds to `mz_objects.id`.",
2369        ),
2370        (
2371            "replica_id",
2372            "The ID of a replica computing the object, or `NULL` for persistent objects. Corresponds to `mz_cluster_replicas.id`.",
2373        ),
2374        (
2375            "lag",
2376            "The amount of time the object's write frontier lags behind wallclock time.",
2377        ),
2378        (
2379            "occurred_at",
2380            "Wall-clock timestamp at which the event occurred.",
2381        ),
2382    ]),
2383    is_retained_metrics_object: false,
2384    access: vec![PUBLIC_SELECT],
2385    ontology: Some(Ontology {
2386        entity_name: "wallclock_lag_event",
2387        description: "Historical wallclock lag per object",
2388        links: &const {
2389            [
2390                OntologyLink {
2391                    name: "measures_lag_of",
2392                    target: "object",
2393                    properties: LinkProperties::measures_mapped(
2394                        "object_id",
2395                        "id",
2396                        "wallclock_lag",
2397                        mz_repr::SemanticType::GlobalId,
2398                        "mz_internal.mz_object_global_ids",
2399                    ),
2400                },
2401                OntologyLink {
2402                    name: "on_replica",
2403                    target: "replica",
2404                    properties: LinkProperties::fk_nullable(
2405                        "replica_id",
2406                        "id",
2407                        Cardinality::ManyToOne,
2408                    ),
2409                },
2410            ]
2411        },
2412        column_semantic_types: &const {
2413            [
2414                ("object_id", SemanticType::GlobalId),
2415                ("replica_id", SemanticType::ReplicaId),
2416                ("occurred_at", SemanticType::WallclockTimestamp),
2417            ]
2418        },
2419    }),
2420});
2421
2422pub static MZ_WALLCLOCK_GLOBAL_LAG_HISTORY: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
2423    name: "mz_wallclock_global_lag_history",
2424    schema: MZ_INTERNAL_SCHEMA,
2425    oid: oid::VIEW_MZ_WALLCLOCK_GLOBAL_LAG_HISTORY_OID,
2426    desc: RelationDesc::builder()
2427        .with_column("object_id", SqlScalarType::String.nullable(false))
2428        .with_column("lag", SqlScalarType::Interval.nullable(true))
2429        .with_column(
2430            "occurred_at",
2431            SqlScalarType::TimestampTz { precision: None }.nullable(false),
2432        )
2433        .with_key(vec![0, 2])
2434        .finish(),
2435    column_comments: BTreeMap::from_iter([
2436        (
2437            "object_id",
2438            "The ID of the table, source, materialized view, index, or sink. Corresponds to `mz_objects.id`.",
2439        ),
2440        (
2441            "lag",
2442            "The minimum wallclock lag observed for the object during the minute.",
2443        ),
2444        (
2445            "occurred_at",
2446            "The minute-aligned timestamp of the observation.",
2447        ),
2448    ]),
2449    sql: "
2450WITH times_binned AS (
2451    SELECT
2452        object_id,
2453        lag,
2454        date_trunc('minute', occurred_at) AS occurred_at
2455    FROM mz_internal.mz_wallclock_lag_history
2456)
2457SELECT
2458    object_id,
2459    min(lag) AS lag,
2460    occurred_at
2461FROM times_binned
2462GROUP BY object_id, occurred_at
2463OPTIONS (AGGREGATE INPUT GROUP SIZE = 1)",
2464    access: vec![PUBLIC_SELECT],
2465    ontology: Some(Ontology {
2466        entity_name: "wallclock_global_lag_event",
2467        description: "Historical global wallclock lag",
2468        links: &const {
2469            [OntologyLink {
2470                name: "lag_of",
2471                target: "object_global_id",
2472                properties: LinkProperties::fk("object_id", "global_id", Cardinality::ManyToOne),
2473            }]
2474        },
2475        column_semantic_types: &const {
2476            [
2477                ("object_id", SemanticType::GlobalId),
2478                ("occurred_at", SemanticType::WallclockTimestamp),
2479            ]
2480        },
2481    }),
2482});
2483
2484pub static MZ_WALLCLOCK_GLOBAL_LAG_RECENT_HISTORY: LazyLock<BuiltinView> = LazyLock::new(|| {
2485    BuiltinView {
2486        name: "mz_wallclock_global_lag_recent_history",
2487        schema: MZ_INTERNAL_SCHEMA,
2488        oid: oid::VIEW_MZ_WALLCLOCK_GLOBAL_LAG_RECENT_HISTORY_OID,
2489        desc: RelationDesc::builder()
2490            .with_column("object_id", SqlScalarType::String.nullable(false))
2491            .with_column("lag", SqlScalarType::Interval.nullable(true))
2492            .with_column(
2493                "occurred_at",
2494                SqlScalarType::TimestampTz { precision: None }.nullable(false),
2495            )
2496            .with_key(vec![0, 2])
2497            .finish(),
2498        column_comments: BTreeMap::from_iter([
2499            (
2500                "object_id",
2501                "The ID of the table, source, materialized view, index, or sink. Corresponds to `mz_objects.id`.",
2502            ),
2503            (
2504                "lag",
2505                "The minimum wallclock lag observed for the object during the minute.",
2506            ),
2507            (
2508                "occurred_at",
2509                "The minute-aligned timestamp of the observation.",
2510            ),
2511        ]),
2512        sql: "
2513SELECT object_id, lag, occurred_at
2514FROM mz_internal.mz_wallclock_global_lag_history
2515WHERE occurred_at + '1 day' > mz_now()",
2516        access: vec![PUBLIC_SELECT],
2517        ontology: None,
2518    }
2519});
2520
2521pub static MZ_WALLCLOCK_GLOBAL_LAG: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
2522    name: "mz_wallclock_global_lag",
2523    schema: MZ_INTERNAL_SCHEMA,
2524    oid: oid::VIEW_MZ_WALLCLOCK_GLOBAL_LAG_OID,
2525    desc: RelationDesc::builder()
2526        .with_column("object_id", SqlScalarType::String.nullable(false))
2527        .with_column("lag", SqlScalarType::Interval.nullable(true))
2528        .with_key(vec![0])
2529        .finish(),
2530    column_comments: BTreeMap::from_iter([
2531        (
2532            "object_id",
2533            "The ID of the table, source, materialized view, index, or sink. Corresponds to `mz_objects.id`.",
2534        ),
2535        (
2536            "lag",
2537            "The amount of time the object's write frontier lags behind wallclock time.",
2538        ),
2539    ]),
2540    sql: "
2541SELECT DISTINCT ON (object_id) object_id, lag
2542FROM mz_internal.mz_wallclock_global_lag_recent_history
2543WHERE occurred_at + '5 minutes' > mz_now()
2544ORDER BY object_id, occurred_at DESC",
2545    access: vec![PUBLIC_SELECT],
2546    ontology: Some(Ontology {
2547        entity_name: "wallclock_global_lag",
2548        description: "Current wallclock lag aggregated across replicas",
2549        links: &const {
2550            [OntologyLink {
2551                name: "measures_global_lag_of",
2552                target: "object",
2553                properties: LinkProperties::measures_mapped(
2554                    "object_id",
2555                    "id",
2556                    "wallclock_lag_global",
2557                    mz_repr::SemanticType::GlobalId,
2558                    "mz_internal.mz_object_global_ids",
2559                ),
2560            }]
2561        },
2562        column_semantic_types: &[("object_id", SemanticType::GlobalId)],
2563    }),
2564});
2565
2566pub static MZ_WALLCLOCK_GLOBAL_LAG_HISTOGRAM_RAW: LazyLock<BuiltinSource> =
2567    LazyLock::new(|| BuiltinSource {
2568        name: "mz_wallclock_global_lag_histogram_raw",
2569        schema: MZ_INTERNAL_SCHEMA,
2570        oid: oid::SOURCE_MZ_WALLCLOCK_GLOBAL_LAG_HISTOGRAM_RAW_OID,
2571        desc: WALLCLOCK_GLOBAL_LAG_HISTOGRAM_RAW_DESC.clone(),
2572        column_comments: BTreeMap::new(),
2573        data_source: IntrospectionType::WallclockLagHistogram.into(),
2574        is_retained_metrics_object: false,
2575        access: vec![PUBLIC_SELECT],
2576        ontology: None,
2577    });
2578
2579pub static MZ_WALLCLOCK_GLOBAL_LAG_HISTOGRAM: LazyLock<BuiltinView> =
2580    LazyLock::new(|| BuiltinView {
2581        name: "mz_wallclock_global_lag_histogram",
2582        schema: MZ_INTERNAL_SCHEMA,
2583        oid: oid::VIEW_MZ_WALLCLOCK_GLOBAL_LAG_HISTOGRAM_OID,
2584        desc: RelationDesc::builder()
2585            .with_column(
2586                "period_start",
2587                SqlScalarType::TimestampTz { precision: None }.nullable(false),
2588            )
2589            .with_column(
2590                "period_end",
2591                SqlScalarType::TimestampTz { precision: None }.nullable(false),
2592            )
2593            .with_column("object_id", SqlScalarType::String.nullable(false))
2594            .with_column("lag_seconds", SqlScalarType::UInt64.nullable(true))
2595            .with_column("labels", SqlScalarType::Jsonb.nullable(false))
2596            .with_column("count", SqlScalarType::Int64.nullable(false))
2597            .with_key(vec![0, 1, 2, 3, 4])
2598            .finish(),
2599        column_comments: BTreeMap::new(),
2600        sql: "
2601SELECT *, count(*) AS count
2602FROM mz_internal.mz_wallclock_global_lag_histogram_raw
2603GROUP BY period_start, period_end, object_id, lag_seconds, labels",
2604        access: vec![PUBLIC_SELECT],
2605        ontology: None,
2606    });
2607
2608pub static MZ_MATERIALIZED_VIEW_REFRESHES: LazyLock<BuiltinSource> = LazyLock::new(|| {
2609    BuiltinSource {
2610        name: "mz_materialized_view_refreshes",
2611        schema: MZ_INTERNAL_SCHEMA,
2612        oid: oid::SOURCE_MZ_MATERIALIZED_VIEW_REFRESHES_OID,
2613        data_source: DataSourceDesc::Introspection(
2614            IntrospectionType::ComputeMaterializedViewRefreshes,
2615        ),
2616        desc: RelationDesc::builder()
2617            .with_column(
2618                "materialized_view_id",
2619                SqlScalarType::String.nullable(false),
2620            )
2621            .with_column(
2622                "last_completed_refresh",
2623                SqlScalarType::MzTimestamp.nullable(true),
2624            )
2625            .with_column("next_refresh", SqlScalarType::MzTimestamp.nullable(true))
2626            .finish(),
2627        column_comments: BTreeMap::from_iter([
2628            (
2629                "materialized_view_id",
2630                "The ID of the materialized view. Corresponds to `mz_catalog.mz_materialized_views.id`",
2631            ),
2632            (
2633                "last_completed_refresh",
2634                "The time of the last successfully completed refresh. `NULL` if the materialized view hasn't completed any refreshes yet.",
2635            ),
2636            (
2637                "next_refresh",
2638                "The time of the next scheduled refresh. `NULL` if the materialized view has no future scheduled refreshes.",
2639            ),
2640        ]),
2641        is_retained_metrics_object: false,
2642        access: vec![PUBLIC_SELECT],
2643        ontology: None,
2644    }
2645});
2646
2647pub static MZ_SUBSCRIPTIONS: LazyLock<BuiltinTable> = LazyLock::new(|| BuiltinTable {
2648    name: "mz_subscriptions",
2649    schema: MZ_INTERNAL_SCHEMA,
2650    oid: oid::TABLE_MZ_SUBSCRIPTIONS_OID,
2651    desc: RelationDesc::builder()
2652        .with_column("id", SqlScalarType::String.nullable(false))
2653        .with_column("session_id", SqlScalarType::Uuid.nullable(false))
2654        .with_column("cluster_id", SqlScalarType::String.nullable(false))
2655        .with_column(
2656            "created_at",
2657            SqlScalarType::TimestampTz { precision: None }.nullable(false),
2658        )
2659        .with_column(
2660            "referenced_object_ids",
2661            SqlScalarType::List {
2662                element_type: Box::new(SqlScalarType::String),
2663                custom_id: None,
2664            }
2665            .nullable(false),
2666        )
2667        .finish(),
2668    column_comments: BTreeMap::from_iter([
2669        ("id", "The ID of the subscription."),
2670        (
2671            "session_id",
2672            "The ID of the session that runs the subscription. Corresponds to `mz_sessions.id`.",
2673        ),
2674        (
2675            "cluster_id",
2676            "The ID of the cluster on which the subscription is running. Corresponds to `mz_clusters.id`.",
2677        ),
2678        (
2679            "created_at",
2680            "The time at which the subscription was created.",
2681        ),
2682        (
2683            "referenced_object_ids",
2684            "The IDs of objects referenced by the subscription. Corresponds to `mz_objects.id`",
2685        ),
2686    ]),
2687    is_retained_metrics_object: false,
2688    access: vec![PUBLIC_SELECT],
2689    ontology: Some(Ontology {
2690        entity_name: "subscription",
2691        description: "Active SUBSCRIBE operations",
2692        links: &const {
2693            [
2694                OntologyLink {
2695                    name: "uses_session",
2696                    target: "session",
2697                    properties: LinkProperties::fk("session_id", "id", Cardinality::ManyToOne),
2698                },
2699                OntologyLink {
2700                    name: "in_active_session",
2701                    target: "active_session",
2702                    properties: LinkProperties::fk_nullable(
2703                        "session_id",
2704                        "id",
2705                        Cardinality::ManyToOne,
2706                    ),
2707                },
2708                OntologyLink {
2709                    name: "belongs_to_cluster",
2710                    target: "cluster",
2711                    properties: LinkProperties::fk("cluster_id", "id", Cardinality::ManyToOne),
2712                },
2713            ]
2714        },
2715        column_semantic_types: &const {
2716            [
2717                ("id", SemanticType::CatalogItemId),
2718                ("cluster_id", SemanticType::ClusterId),
2719            ]
2720        },
2721    }),
2722});
2723
2724pub static MZ_SESSIONS: LazyLock<BuiltinTable> = LazyLock::new(|| BuiltinTable {
2725    name: "mz_sessions",
2726    schema: MZ_INTERNAL_SCHEMA,
2727    oid: oid::TABLE_MZ_SESSIONS_OID,
2728    desc: RelationDesc::builder()
2729        .with_column("id", SqlScalarType::Uuid.nullable(false))
2730        .with_column("connection_id", SqlScalarType::UInt32.nullable(false))
2731        .with_column("role_id", SqlScalarType::String.nullable(false))
2732        .with_column("client_ip", SqlScalarType::String.nullable(true))
2733        .with_column(
2734            "connected_at",
2735            SqlScalarType::TimestampTz { precision: None }.nullable(false),
2736        )
2737        .finish(),
2738    column_comments: BTreeMap::from_iter([
2739        ("id", "The globally unique ID of the session."),
2740        (
2741            "connection_id",
2742            "The connection ID of the session. Unique only for active sessions and can be recycled. Corresponds to `pg_backend_pid()`.",
2743        ),
2744        (
2745            "role_id",
2746            "The role ID of the role that the session is logged in as. Corresponds to `mz_catalog.mz_roles`.",
2747        ),
2748        (
2749            "client_ip",
2750            "The IP address of the client that initiated the session.",
2751        ),
2752        (
2753            "connected_at",
2754            "The time at which the session connected to the system.",
2755        ),
2756    ]),
2757    is_retained_metrics_object: false,
2758    access: vec![PUBLIC_SELECT],
2759    ontology: Some(Ontology {
2760        entity_name: "active_session",
2761        description: "Currently active sessions",
2762        links: &const {
2763            [OntologyLink {
2764                name: "logged_in_as",
2765                target: "role",
2766                properties: LinkProperties::fk("role_id", "id", Cardinality::ManyToOne),
2767            }]
2768        },
2769        column_semantic_types: &[("role_id", SemanticType::RoleId)],
2770    }),
2771});
2772
2773pub static MZ_COMMENTS: LazyLock<BuiltinTable> = LazyLock::new(|| BuiltinTable {
2774    name: "mz_comments",
2775    schema: MZ_INTERNAL_SCHEMA,
2776    oid: oid::TABLE_MZ_COMMENTS_OID,
2777    desc: RelationDesc::builder()
2778        .with_column("id", SqlScalarType::String.nullable(false))
2779        .with_column("object_type", SqlScalarType::String.nullable(false))
2780        .with_column("object_sub_id", SqlScalarType::Int32.nullable(true))
2781        .with_column("comment", SqlScalarType::String.nullable(false))
2782        .finish(),
2783    column_comments: BTreeMap::from_iter([
2784        (
2785            "id",
2786            "The ID of the object. Corresponds to `mz_objects.id`.",
2787        ),
2788        (
2789            "object_type",
2790            "The type of object the comment is associated with.",
2791        ),
2792        (
2793            "object_sub_id",
2794            "For a comment on a column of a relation, the column number. `NULL` for other object types.",
2795        ),
2796        ("comment", "The comment itself."),
2797    ]),
2798    is_retained_metrics_object: false,
2799    access: vec![PUBLIC_SELECT],
2800    ontology: Some(Ontology {
2801        entity_name: "comment",
2802        description: "A COMMENT ON annotation for a catalog object or column",
2803        links: &const {
2804            [OntologyLink {
2805                name: "comment_on",
2806                target: "object",
2807                properties: LinkProperties::fk_typed(
2808                    "id",
2809                    "id",
2810                    Cardinality::ManyToOne,
2811                    mz_repr::SemanticType::CatalogItemId,
2812                ),
2813            }]
2814        },
2815        column_semantic_types: &const {
2816            [
2817                ("id", SemanticType::CatalogItemId),
2818                ("object_type", SemanticType::ObjectType),
2819            ]
2820        },
2821    }),
2822});
2823
2824pub static MZ_SOURCE_REFERENCES: LazyLock<BuiltinTable> = LazyLock::new(|| BuiltinTable {
2825    name: "mz_source_references",
2826    schema: MZ_INTERNAL_SCHEMA,
2827    oid: oid::TABLE_MZ_SOURCE_REFERENCES_OID,
2828    desc: RelationDesc::builder()
2829        .with_column("source_id", SqlScalarType::String.nullable(false))
2830        .with_column("namespace", SqlScalarType::String.nullable(true))
2831        .with_column("name", SqlScalarType::String.nullable(false))
2832        .with_column(
2833            "updated_at",
2834            SqlScalarType::TimestampTz { precision: None }.nullable(false),
2835        )
2836        .with_column(
2837            "columns",
2838            SqlScalarType::Array(Box::new(SqlScalarType::String)).nullable(true),
2839        )
2840        .finish(),
2841    column_comments: BTreeMap::new(),
2842    is_retained_metrics_object: false,
2843    access: vec![PUBLIC_SELECT],
2844    ontology: Some(Ontology {
2845        entity_name: "source_reference",
2846        description: "External references tracked by sources",
2847        links: &const {
2848            [OntologyLink {
2849                name: "references_source",
2850                target: "source",
2851                properties: LinkProperties::fk("source_id", "id", Cardinality::ManyToOne),
2852            }]
2853        },
2854        column_semantic_types: &[("source_id", SemanticType::CatalogItemId)],
2855    }),
2856});
2857
2858pub static MZ_WEBHOOKS_SOURCES: LazyLock<BuiltinTable> = LazyLock::new(|| BuiltinTable {
2859    name: "mz_webhook_sources",
2860    schema: MZ_INTERNAL_SCHEMA,
2861    oid: oid::TABLE_MZ_WEBHOOK_SOURCES_OID,
2862    desc: RelationDesc::builder()
2863        .with_column("id", SqlScalarType::String.nullable(false))
2864        .with_column("name", SqlScalarType::String.nullable(false))
2865        .with_column("url", SqlScalarType::String.nullable(false))
2866        .finish(),
2867    column_comments: BTreeMap::from_iter([
2868        (
2869            "id",
2870            "The ID of the webhook source. Corresponds to `mz_sources.id`.",
2871        ),
2872        ("name", "The name of the webhook source."),
2873        (
2874            "url",
2875            "The URL which can be used to send events to the source.",
2876        ),
2877    ]),
2878    is_retained_metrics_object: false,
2879    access: vec![PUBLIC_SELECT],
2880    ontology: Some(Ontology {
2881        entity_name: "webhook_source",
2882        description: "Webhook source configuration",
2883        links: &const {
2884            [OntologyLink {
2885                name: "details_of",
2886                target: "source",
2887                properties: LinkProperties::fk("id", "id", Cardinality::OneToOne),
2888            }]
2889        },
2890        column_semantic_types: &[("id", SemanticType::CatalogItemId)],
2891    }),
2892});
2893
2894pub static MZ_HISTORY_RETENTION_STRATEGIES: LazyLock<BuiltinTable> = LazyLock::new(|| {
2895    BuiltinTable {
2896        name: "mz_history_retention_strategies",
2897        schema: MZ_INTERNAL_SCHEMA,
2898        oid: oid::TABLE_MZ_HISTORY_RETENTION_STRATEGIES_OID,
2899        desc: RelationDesc::builder()
2900            .with_column("id", SqlScalarType::String.nullable(false))
2901            .with_column("strategy", SqlScalarType::String.nullable(false))
2902            .with_column("value", SqlScalarType::Jsonb.nullable(false))
2903            .finish(),
2904        column_comments: BTreeMap::from_iter([
2905            ("id", "The ID of the object."),
2906            (
2907                "strategy",
2908                "The strategy. `FOR` is the only strategy, and means the object's compaction window is the duration of the `value` field.",
2909            ),
2910            (
2911                "value",
2912                "The value of the strategy. For `FOR`, is a number of milliseconds.",
2913            ),
2914        ]),
2915        is_retained_metrics_object: false,
2916        access: vec![PUBLIC_SELECT],
2917        ontology: Some(Ontology {
2918            entity_name: "history_retention",
2919            description: "History retention strategy for an object",
2920            links: &const { [] },
2921            column_semantic_types: &[("id", SemanticType::CatalogItemId)],
2922        }),
2923    }
2924});
2925
2926pub static MZ_LICENSE_KEYS: LazyLock<BuiltinTable> = LazyLock::new(|| BuiltinTable {
2927    name: "mz_license_keys",
2928    schema: MZ_INTERNAL_SCHEMA,
2929    oid: oid::TABLE_MZ_LICENSE_KEYS_OID,
2930    desc: RelationDesc::builder()
2931        .with_column("id", SqlScalarType::String.nullable(false))
2932        .with_column("organization", SqlScalarType::String.nullable(false))
2933        .with_column("environment_id", SqlScalarType::String.nullable(false))
2934        .with_column(
2935            "expiration",
2936            SqlScalarType::TimestampTz { precision: None }.nullable(false),
2937        )
2938        .with_column(
2939            "not_before",
2940            SqlScalarType::TimestampTz { precision: None }.nullable(false),
2941        )
2942        .finish(),
2943    column_comments: BTreeMap::from_iter([
2944        ("id", "The identifier of the license key."),
2945        (
2946            "organization",
2947            "The name of the organization that this license key was issued to.",
2948        ),
2949        (
2950            "environment_id",
2951            "The environment ID that this license key was issued for.",
2952        ),
2953        (
2954            "expiration",
2955            "The date and time when this license key expires.",
2956        ),
2957        (
2958            "not_before",
2959            "The start of the validity period for this license key.",
2960        ),
2961    ]),
2962    is_retained_metrics_object: false,
2963    access: vec![PUBLIC_SELECT],
2964    ontology: Some(Ontology {
2965        entity_name: "license_key",
2966        description: "License key metadata",
2967        links: &const { [] },
2968        column_semantic_types: &[("id", SemanticType::CatalogItemId)],
2969    }),
2970});
2971
2972pub static MZ_REPLACEMENTS: LazyLock<BuiltinTable> = LazyLock::new(|| BuiltinTable {
2973    name: "mz_replacements",
2974    schema: MZ_INTERNAL_SCHEMA,
2975    oid: oid::TABLE_MZ_REPLACEMENTS_OID,
2976    desc: RelationDesc::builder()
2977        .with_column("id", SqlScalarType::String.nullable(false))
2978        .with_column("target_id", SqlScalarType::String.nullable(false))
2979        .finish(),
2980    column_comments: BTreeMap::from_iter([
2981        (
2982            "id",
2983            "The ID of the replacement object. Corresponds to `mz_objects.id`.",
2984        ),
2985        (
2986            "target_id",
2987            "The ID of the replacement target. Corresponds to `mz_objects.id`.",
2988        ),
2989    ]),
2990    is_retained_metrics_object: false,
2991    access: vec![PUBLIC_SELECT],
2992    ontology: Some(Ontology {
2993        entity_name: "replacement",
2994        description: "A record of an object replacement (ALTER ... SWAP)",
2995        links: &const {
2996            [
2997                OntologyLink {
2998                    name: "replacement_object",
2999                    target: "object",
3000                    properties: LinkProperties::fk("id", "id", Cardinality::ManyToOne),
3001                },
3002                OntologyLink {
3003                    name: "replacement_target",
3004                    target: "object",
3005                    properties: LinkProperties::fk("target_id", "id", Cardinality::ManyToOne),
3006                },
3007            ]
3008        },
3009        column_semantic_types: &[("id", SemanticType::CatalogItemId)],
3010    }),
3011});
3012
3013// These will be replaced with per-replica tables once source/sink multiplexing on
3014// a single cluster is supported.
3015pub static MZ_SOURCE_STATISTICS_RAW: LazyLock<BuiltinSource> = LazyLock::new(|| BuiltinSource {
3016    name: "mz_source_statistics_raw",
3017    schema: MZ_INTERNAL_SCHEMA,
3018    oid: oid::SOURCE_MZ_SOURCE_STATISTICS_RAW_OID,
3019    data_source: IntrospectionType::StorageSourceStatistics.into(),
3020    desc: MZ_SOURCE_STATISTICS_RAW_DESC.clone(),
3021    column_comments: BTreeMap::new(),
3022    is_retained_metrics_object: true,
3023    access: vec![PUBLIC_SELECT],
3024    ontology: None,
3025});
3026pub static MZ_SINK_STATISTICS_RAW: LazyLock<BuiltinSource> = LazyLock::new(|| BuiltinSource {
3027    name: "mz_sink_statistics_raw",
3028    schema: MZ_INTERNAL_SCHEMA,
3029    oid: oid::SOURCE_MZ_SINK_STATISTICS_RAW_OID,
3030    data_source: IntrospectionType::StorageSinkStatistics.into(),
3031    desc: MZ_SINK_STATISTICS_RAW_DESC.clone(),
3032    column_comments: BTreeMap::new(),
3033    is_retained_metrics_object: true,
3034    access: vec![PUBLIC_SELECT],
3035    ontology: None,
3036});
3037
3038pub static MZ_STORAGE_SHARDS: LazyLock<BuiltinSource> = LazyLock::new(|| BuiltinSource {
3039    name: "mz_storage_shards",
3040    schema: MZ_INTERNAL_SCHEMA,
3041    oid: oid::SOURCE_MZ_STORAGE_SHARDS_OID,
3042    data_source: IntrospectionType::ShardMapping.into(),
3043    desc: RelationDesc::builder()
3044        .with_column("object_id", SqlScalarType::String.nullable(false))
3045        .with_column("shard_id", SqlScalarType::String.nullable(false))
3046        .finish(),
3047    column_comments: BTreeMap::new(),
3048    is_retained_metrics_object: false,
3049    access: vec![PUBLIC_SELECT],
3050    ontology: Some(Ontology {
3051        entity_name: "storage_shard",
3052        description: "Persist shards used by storage objects",
3053        links: &const {
3054            [OntologyLink {
3055                name: "shard_of",
3056                target: "object",
3057                properties: LinkProperties::fk_mapped(
3058                    "object_id",
3059                    "id",
3060                    Cardinality::ManyToOne,
3061                    mz_repr::SemanticType::GlobalId,
3062                    "mz_internal.mz_object_global_ids",
3063                ),
3064            }]
3065        },
3066        column_semantic_types: &const {
3067            [
3068                ("object_id", SemanticType::GlobalId),
3069                ("shard_id", SemanticType::ShardId),
3070            ]
3071        },
3072    }),
3073});
3074
3075pub static MZ_OBJECTS_ID_NAMESPACE_TYPES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
3076    name: "mz_objects_id_namespace_types",
3077    schema: MZ_INTERNAL_SCHEMA,
3078    oid: oid::VIEW_MZ_OBJECTS_ID_NAMESPACE_TYPES_OID,
3079    desc: RelationDesc::builder()
3080        .with_column("object_type", SqlScalarType::String.nullable(false))
3081        .with_key(vec![0])
3082        .finish(),
3083    column_comments: BTreeMap::new(),
3084    sql: r#"SELECT *
3085    FROM (
3086        VALUES
3087            ('table'),
3088            ('view'),
3089            ('materialized-view'),
3090            ('source'),
3091            ('sink'),
3092            ('index'),
3093            ('connection'),
3094            ('type'),
3095            ('function'),
3096            ('secret')
3097    )
3098    AS _ (object_type)"#,
3099    access: vec![PUBLIC_SELECT],
3100    ontology: None,
3101});
3102
3103pub static MZ_OBJECT_OID_ALIAS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
3104    name: "mz_object_oid_alias",
3105    schema: MZ_INTERNAL_SCHEMA,
3106    oid: oid::VIEW_MZ_OBJECT_OID_ALIAS_OID,
3107    desc: RelationDesc::builder()
3108        .with_column("object_type", SqlScalarType::String.nullable(false))
3109        .with_column("oid_alias", SqlScalarType::String.nullable(false))
3110        .with_key(vec![0])
3111        .finish(),
3112    column_comments: BTreeMap::new(),
3113    sql: "SELECT object_type, oid_alias
3114    FROM (
3115        VALUES
3116            (
3117                'table'::pg_catalog.text,
3118                'regclass'::pg_catalog.text
3119            ),
3120            ('source', 'regclass'),
3121            ('view', 'regclass'),
3122            ('materialized-view', 'regclass'),
3123            ('index', 'regclass'),
3124            ('type', 'regtype'),
3125            ('function', 'regproc')
3126    )
3127    AS _ (object_type, oid_alias);",
3128    access: vec![PUBLIC_SELECT],
3129    ontology: None,
3130});
3131
3132pub static MZ_OBJECT_FULLY_QUALIFIED_NAMES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
3133    name: "mz_object_fully_qualified_names",
3134    schema: MZ_INTERNAL_SCHEMA,
3135    oid: oid::VIEW_MZ_OBJECT_FULLY_QUALIFIED_NAMES_OID,
3136    desc: RelationDesc::builder()
3137        .with_column("id", SqlScalarType::String.nullable(false))
3138        .with_column("name", SqlScalarType::String.nullable(false))
3139        .with_column("object_type", SqlScalarType::String.nullable(false))
3140        .with_column("schema_id", SqlScalarType::String.nullable(false))
3141        .with_column("schema_name", SqlScalarType::String.nullable(false))
3142        .with_column("database_id", SqlScalarType::String.nullable(true))
3143        .with_column("database_name", SqlScalarType::String.nullable(true))
3144        .with_column("cluster_id", SqlScalarType::String.nullable(true))
3145        .finish(),
3146    column_comments: BTreeMap::from_iter([
3147        ("id", "Materialize's unique ID for the object."),
3148        ("name", "The name of the object."),
3149        (
3150            "object_type",
3151            "The type of the object: one of `table`, `source`, `view`, `materialized-view`, `sink`, `index`, `connection`, `secret`, `type`, or `function`.",
3152        ),
3153        (
3154            "schema_id",
3155            "The ID of the schema to which the object belongs. Corresponds to `mz_schemas.id`.",
3156        ),
3157        (
3158            "schema_name",
3159            "The name of the schema to which the object belongs. Corresponds to `mz_schemas.name`.",
3160        ),
3161        (
3162            "database_id",
3163            "The ID of the database to which the object belongs. Corresponds to `mz_databases.id`.",
3164        ),
3165        (
3166            "database_name",
3167            "The name of the database to which the object belongs. Corresponds to `mz_databases.name`.",
3168        ),
3169        (
3170            "cluster_id",
3171            "The ID of the cluster maintaining the source, materialized view, index, or sink. Corresponds to `mz_clusters.id`. `NULL` for other object types.",
3172        ),
3173    ]),
3174    sql: "
3175    SELECT o.id,
3176        o.name,
3177        o.type as object_type,
3178        sc.id as schema_id,
3179        sc.name as schema_name,
3180        db.id as database_id,
3181        db.name as database_name,
3182        o.cluster_id
3183    FROM mz_catalog.mz_objects o
3184    INNER JOIN mz_catalog.mz_schemas sc ON sc.id = o.schema_id
3185    -- LEFT JOIN accounts for objects in the ambient database.
3186    LEFT JOIN mz_catalog.mz_databases db ON db.id = sc.database_id",
3187    access: vec![PUBLIC_SELECT],
3188    ontology: Some(Ontology {
3189        entity_name: "object_fqn",
3190        description: "Fully qualified name (database.schema.name) for objects",
3191        links: &const {
3192            [
3193                OntologyLink {
3194                    name: "details_of",
3195                    target: "object",
3196                    properties: LinkProperties::fk("id", "id", Cardinality::OneToOne),
3197                },
3198                OntologyLink {
3199                    name: "in_schema",
3200                    target: "schema",
3201                    properties: LinkProperties::fk("schema_id", "id", Cardinality::ManyToOne),
3202                },
3203                OntologyLink {
3204                    name: "in_database",
3205                    target: "database",
3206                    properties: LinkProperties::fk("database_id", "id", Cardinality::ManyToOne),
3207                },
3208                OntologyLink {
3209                    name: "belongs_to_cluster",
3210                    target: "cluster",
3211                    properties: LinkProperties::fk("cluster_id", "id", Cardinality::ManyToOne),
3212                },
3213            ]
3214        },
3215        column_semantic_types: &const {
3216            [
3217                ("id", SemanticType::CatalogItemId),
3218                ("object_type", SemanticType::ObjectType),
3219                ("schema_id", SemanticType::SchemaId),
3220                ("database_id", SemanticType::DatabaseId),
3221                ("cluster_id", SemanticType::ClusterId),
3222            ]
3223        },
3224    }),
3225});
3226
3227pub static MZ_OBJECT_GLOBAL_IDS: LazyLock<BuiltinTable> = LazyLock::new(|| BuiltinTable {
3228    name: "mz_object_global_ids",
3229    schema: MZ_INTERNAL_SCHEMA,
3230    oid: oid::VIEW_MZ_OBJECT_GLOBAL_IDS_OID,
3231    desc: RelationDesc::builder()
3232        .with_column("id", SqlScalarType::String.nullable(false))
3233        .with_column("global_id", SqlScalarType::String.nullable(false))
3234        .finish(),
3235    column_comments: BTreeMap::from_iter([
3236        (
3237            "id",
3238            "The ID of the object. Corresponds to `mz_objects.id`.",
3239        ),
3240        ("global_id", "The global ID of the object."),
3241    ]),
3242    is_retained_metrics_object: false,
3243    access: vec![PUBLIC_SELECT],
3244    ontology: Some(Ontology {
3245        entity_name: "object_global_id",
3246        description: "Mapping between CatalogItemId (SQL layer) and GlobalId (runtime layer)",
3247        links: &const {
3248            [OntologyLink {
3249                name: "id_references",
3250                target: "object",
3251                properties: LinkProperties::fk("id", "id", Cardinality::ManyToOne),
3252            }]
3253        },
3254        column_semantic_types: &[("id", SemanticType::CatalogItemId)],
3255    }),
3256});
3257
3258// TODO (SangJunBak): Remove once mz_object_history is released and used in the Console https://github.com/MaterializeInc/console/issues/3342
3259pub static MZ_OBJECT_LIFETIMES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
3260    name: "mz_object_lifetimes",
3261    schema: MZ_INTERNAL_SCHEMA,
3262    oid: oid::VIEW_MZ_OBJECT_LIFETIMES_OID,
3263    desc: RelationDesc::builder()
3264        .with_column("id", SqlScalarType::String.nullable(true))
3265        .with_column("previous_id", SqlScalarType::String.nullable(true))
3266        .with_column("object_type", SqlScalarType::String.nullable(false))
3267        .with_column("event_type", SqlScalarType::String.nullable(false))
3268        .with_column(
3269            "occurred_at",
3270            SqlScalarType::TimestampTz { precision: None }.nullable(false),
3271        )
3272        .finish(),
3273    column_comments: BTreeMap::from_iter([
3274        ("id", "Materialize's unique ID for the object."),
3275        ("previous_id", "The object's previous ID, if one exists."),
3276        (
3277            "object_type",
3278            "The type of the object: one of `table`, `source`, `view`, `materialized-view`, `sink`, `index`, `connection`, `secret`, `type`, or `function`.",
3279        ),
3280        (
3281            "event_type",
3282            "The lifetime event, either `create` or `drop`.",
3283        ),
3284        (
3285            "occurred_at",
3286            "Wall-clock timestamp of when the event occurred.",
3287        ),
3288    ]),
3289    sql: "
3290    SELECT
3291        CASE
3292            WHEN a.object_type = 'cluster-replica' THEN a.details ->> 'replica_id'
3293            ELSE a.details ->> 'id'
3294        END id,
3295        a.details ->> 'previous_id' as previous_id,
3296        a.object_type,
3297        a.event_type,
3298        a.occurred_at
3299    FROM mz_catalog.mz_audit_events a
3300    WHERE a.event_type = 'create' OR a.event_type = 'drop'",
3301    access: vec![PUBLIC_SELECT],
3302    ontology: Some(Ontology {
3303        entity_name: "object_lifetime_event",
3304        description: "Create or drop lifecycle event for a catalog object",
3305        links: &const {
3306            [OntologyLink {
3307                name: "lifetime_event_of",
3308                target: "object",
3309                properties: LinkProperties::fk_typed(
3310                    "id",
3311                    "id",
3312                    Cardinality::ManyToOne,
3313                    mz_repr::SemanticType::CatalogItemId,
3314                ),
3315            }]
3316        },
3317        column_semantic_types: &const {
3318            [
3319                ("id", SemanticType::CatalogItemId),
3320                ("object_type", SemanticType::ObjectType),
3321            ]
3322        },
3323    }),
3324});
3325
3326pub static MZ_OBJECT_HISTORY: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
3327    name: "mz_object_history",
3328    schema: MZ_INTERNAL_SCHEMA,
3329    oid: oid::VIEW_MZ_OBJECT_HISTORY_OID,
3330    desc: RelationDesc::builder()
3331        .with_column("id", SqlScalarType::String.nullable(true))
3332        .with_column("cluster_id", SqlScalarType::String.nullable(true))
3333        .with_column("object_type", SqlScalarType::String.nullable(false))
3334        .with_column(
3335            "created_at",
3336            SqlScalarType::TimestampTz { precision: None }.nullable(true),
3337        )
3338        .with_column(
3339            "dropped_at",
3340            SqlScalarType::TimestampTz { precision: None }.nullable(true),
3341        )
3342        .finish(),
3343    column_comments: BTreeMap::from_iter([
3344        ("id", "Materialize's unique ID for the object."),
3345        (
3346            "cluster_id",
3347            "The object's cluster ID. `NULL` if the object has no associated cluster.",
3348        ),
3349        (
3350            "object_type",
3351            "The type of the object: one of `table`, `source`, `view`, `materialized-view`, `sink`, `index`, `connection`, `secret`, `type`, or `function`.",
3352        ),
3353        (
3354            "created_at",
3355            "Wall-clock timestamp of when the object was created. `NULL` for built in system objects.",
3356        ),
3357        (
3358            "dropped_at",
3359            "Wall-clock timestamp of when the object was dropped. `NULL` for built in system objects or if the object hasn't been dropped.",
3360        ),
3361    ]),
3362    sql: r#"
3363    WITH
3364        creates AS
3365        (
3366            SELECT
3367                details ->> 'id' AS id,
3368                -- We need to backfill cluster_id since older object create events don't include the cluster ID in the audit log
3369                COALESCE(details ->> 'cluster_id', objects.cluster_id) AS cluster_id,
3370                object_type,
3371                occurred_at
3372            FROM
3373                mz_catalog.mz_audit_events AS events
3374                    LEFT JOIN mz_catalog.mz_objects AS objects ON details ->> 'id' = objects.id
3375            WHERE event_type = 'create' AND object_type IN ( SELECT object_type FROM mz_internal.mz_objects_id_namespace_types )
3376        ),
3377        drops AS
3378        (
3379            SELECT details ->> 'id' AS id, occurred_at
3380            FROM mz_catalog.mz_audit_events
3381            WHERE event_type = 'drop' AND object_type IN ( SELECT object_type FROM mz_internal.mz_objects_id_namespace_types )
3382        ),
3383        user_object_history AS
3384        (
3385            SELECT
3386                creates.id,
3387                creates.cluster_id,
3388                creates.object_type,
3389                creates.occurred_at AS created_at,
3390                drops.occurred_at AS dropped_at
3391            FROM creates LEFT JOIN drops ON creates.id = drops.id
3392            WHERE creates.id LIKE 'u%'
3393        ),
3394        -- We need to union built in objects since they aren't in the audit log
3395        built_in_objects AS
3396        (
3397            -- Functions that accept different arguments have different oids but the same id. We deduplicate in this case.
3398            SELECT DISTINCT ON (objects.id)
3399                objects.id,
3400                objects.cluster_id,
3401                objects.type AS object_type,
3402                NULL::timestamptz AS created_at,
3403                NULL::timestamptz AS dropped_at
3404            FROM mz_catalog.mz_objects AS objects
3405            WHERE objects.id LIKE 's%'
3406        )
3407    SELECT * FROM user_object_history UNION ALL (SELECT * FROM built_in_objects)"#,
3408    access: vec![PUBLIC_SELECT],
3409    ontology: Some(Ontology {
3410        entity_name: "object_history",
3411        description: "Historical record of object creation and drops",
3412        links: &const {
3413            [OntologyLink {
3414                name: "history_of",
3415                target: "object",
3416                properties: LinkProperties::fk("id", "id", Cardinality::ManyToOne),
3417            }]
3418        },
3419        column_semantic_types: &[("id", SemanticType::CatalogItemId)],
3420    }),
3421});
3422
3423pub static MZ_OBJECT_TRANSITIVE_DEPENDENCIES: LazyLock<BuiltinView> = LazyLock::new(|| {
3424    BuiltinView {
3425        name: "mz_object_transitive_dependencies",
3426        schema: MZ_INTERNAL_SCHEMA,
3427        oid: oid::VIEW_MZ_OBJECT_TRANSITIVE_DEPENDENCIES_OID,
3428        desc: RelationDesc::builder()
3429            .with_column("object_id", SqlScalarType::String.nullable(false))
3430            .with_column(
3431                "referenced_object_id",
3432                SqlScalarType::String.nullable(false),
3433            )
3434            .with_key(vec![0, 1])
3435            .finish(),
3436        column_comments: BTreeMap::from_iter([
3437            (
3438                "object_id",
3439                "The ID of the dependent object. Corresponds to `mz_objects.id`.",
3440            ),
3441            (
3442                "referenced_object_id",
3443                "The ID of the (possibly transitively) referenced object. Corresponds to `mz_objects.id`.",
3444            ),
3445        ]),
3446        sql: "
3447WITH MUTUALLY RECURSIVE
3448  reach(object_id text, referenced_object_id text) AS (
3449    SELECT object_id, referenced_object_id FROM mz_internal.mz_object_dependencies
3450    UNION
3451    SELECT x, z FROM reach r1(x, y) JOIN reach r2(y, z) USING(y)
3452  )
3453SELECT object_id, referenced_object_id FROM reach;",
3454        access: vec![PUBLIC_SELECT],
3455        ontology: Some(Ontology {
3456            entity_name: "transitive_dependency",
3457            description: "Transitive closure of object dependencies — all direct and indirect dependencies",
3458            links: &const {
3459                [
3460                    OntologyLink {
3461                        name: "depends_on",
3462                        target: "object",
3463                        properties: LinkProperties::DependsOn {
3464                            source_column: "object_id",
3465                            target_column: "id",
3466                            source_id_type: Some(mz_repr::SemanticType::CatalogItemId),
3467                            requires_mapping: None,
3468                        },
3469                    },
3470                    OntologyLink {
3471                        name: "dependency_is",
3472                        target: "object",
3473                        properties: LinkProperties::DependsOn {
3474                            source_column: "referenced_object_id",
3475                            target_column: "id",
3476                            source_id_type: Some(mz_repr::SemanticType::CatalogItemId),
3477                            requires_mapping: None,
3478                        },
3479                    },
3480                ]
3481            },
3482            column_semantic_types: &const {
3483                [
3484                    ("object_id", SemanticType::CatalogItemId),
3485                    ("referenced_object_id", SemanticType::CatalogItemId),
3486                ]
3487            },
3488        }),
3489    }
3490});
3491
3492/// Peeled version of `PG_NAMESPACE`:
3493/// - This doesn't check `mz_schemas.database_id IS NULL OR d.name = pg_catalog.current_database()`,
3494///   in order to make this view indexable.
3495/// - This has the database name as an extra column, so that downstream views can check it against
3496///  `current_database()`.
3497pub static PG_NAMESPACE_ALL_DATABASES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
3498    name: "pg_namespace_all_databases",
3499    schema: MZ_INTERNAL_SCHEMA,
3500    oid: oid::VIEW_PG_NAMESPACE_ALL_DATABASES_OID,
3501    desc: RelationDesc::builder()
3502        .with_column("oid", SqlScalarType::Oid.nullable(false))
3503        .with_column("nspname", SqlScalarType::String.nullable(false))
3504        .with_column("nspowner", SqlScalarType::Oid.nullable(false))
3505        .with_column(
3506            "nspacl",
3507            SqlScalarType::Array(Box::new(SqlScalarType::String)).nullable(true),
3508        )
3509        .with_column("database_name", SqlScalarType::String.nullable(true))
3510        .finish(),
3511    column_comments: BTreeMap::new(),
3512    sql: "
3513SELECT
3514    s.oid AS oid,
3515    s.name AS nspname,
3516    role_owner.oid AS nspowner,
3517    NULL::pg_catalog.text[] AS nspacl,
3518    d.name as database_name
3519FROM mz_catalog.mz_schemas s
3520LEFT JOIN mz_catalog.mz_databases d ON d.id = s.database_id
3521JOIN mz_catalog.mz_roles role_owner ON role_owner.id = s.owner_id",
3522    access: vec![PUBLIC_SELECT],
3523    ontology: None,
3524});
3525
3526pub const PG_NAMESPACE_ALL_DATABASES_IND: BuiltinIndex = BuiltinIndex {
3527    name: "pg_namespace_all_databases_ind",
3528    schema: MZ_INTERNAL_SCHEMA,
3529    oid: oid::INDEX_PG_NAMESPACE_ALL_DATABASES_IND_OID,
3530    sql: "IN CLUSTER mz_catalog_server
3531ON mz_internal.pg_namespace_all_databases (nspname)",
3532    is_retained_metrics_object: false,
3533};
3534
3535/// Peeled version of `PG_CLASS`:
3536/// - This doesn't check `mz_schemas.database_id IS NULL OR d.name = pg_catalog.current_database()`,
3537///   in order to make this view indexable.
3538/// - This has the database name as an extra column, so that downstream views can check it against
3539///  `current_database()`.
3540pub static PG_CLASS_ALL_DATABASES: LazyLock<BuiltinView> = LazyLock::new(|| {
3541    BuiltinView {
3542        name: "pg_class_all_databases",
3543        schema: MZ_INTERNAL_SCHEMA,
3544        oid: oid::VIEW_PG_CLASS_ALL_DATABASES_OID,
3545        desc: RelationDesc::builder()
3546            .with_column("oid", SqlScalarType::Oid.nullable(false))
3547            .with_column("relname", SqlScalarType::String.nullable(false))
3548            .with_column("relnamespace", SqlScalarType::Oid.nullable(false))
3549            .with_column("reloftype", SqlScalarType::Oid.nullable(false))
3550            .with_column("relowner", SqlScalarType::Oid.nullable(false))
3551            .with_column("relam", SqlScalarType::Oid.nullable(false))
3552            .with_column("reltablespace", SqlScalarType::Oid.nullable(false))
3553            .with_column("reltuples", SqlScalarType::Float32.nullable(false))
3554            .with_column("reltoastrelid", SqlScalarType::Oid.nullable(false))
3555            .with_column("relhasindex", SqlScalarType::Bool.nullable(false))
3556            .with_column("relpersistence", SqlScalarType::PgLegacyChar.nullable(false))
3557            .with_column("relkind", SqlScalarType::String.nullable(true))
3558            .with_column("relnatts", SqlScalarType::Int16.nullable(false))
3559            .with_column("relchecks", SqlScalarType::Int16.nullable(false))
3560            .with_column("relhasrules", SqlScalarType::Bool.nullable(false))
3561            .with_column("relhastriggers", SqlScalarType::Bool.nullable(false))
3562            .with_column("relhassubclass", SqlScalarType::Bool.nullable(false))
3563            .with_column("relrowsecurity", SqlScalarType::Bool.nullable(false))
3564            .with_column("relforcerowsecurity", SqlScalarType::Bool.nullable(false))
3565            .with_column("relreplident", SqlScalarType::PgLegacyChar.nullable(false))
3566            .with_column("relispartition", SqlScalarType::Bool.nullable(false))
3567            .with_column("relhasoids", SqlScalarType::Bool.nullable(false))
3568            .with_column("reloptions", SqlScalarType::Array(Box::new(SqlScalarType::String)).nullable(true))
3569            .with_column("database_name", SqlScalarType::String.nullable(true))
3570            .finish(),
3571        column_comments: BTreeMap::new(),
3572        sql: "
3573SELECT
3574    class_objects.oid,
3575    class_objects.name AS relname,
3576    mz_schemas.oid AS relnamespace,
3577    -- MZ doesn't support typed tables so reloftype is filled with 0
3578    0::pg_catalog.oid AS reloftype,
3579    role_owner.oid AS relowner,
3580    0::pg_catalog.oid AS relam,
3581    -- MZ doesn't have tablespaces so reltablespace is filled in with 0 implying the default tablespace
3582    0::pg_catalog.oid AS reltablespace,
3583    -- MZ doesn't support (estimated) row counts currently.
3584    -- Postgres defines a value of -1 as unknown.
3585    -1::float4 as reltuples,
3586    -- MZ doesn't use TOAST tables so reltoastrelid is filled with 0
3587    0::pg_catalog.oid AS reltoastrelid,
3588    EXISTS (SELECT id, oid, name, on_id, cluster_id FROM mz_catalog.mz_indexes where mz_indexes.on_id = class_objects.id) AS relhasindex,
3589    -- MZ doesn't have unlogged tables and because of (https://github.com/MaterializeInc/database-issues/issues/2689)
3590    -- temporary objects don't show up here, so relpersistence is filled with 'p' for permanent.
3591    -- TODO(jkosh44): update this column when issue is resolved.
3592    'p'::pg_catalog.\"char\" AS relpersistence,
3593    CASE
3594        WHEN class_objects.type = 'table' THEN 'r'
3595        WHEN class_objects.type = 'source' THEN 'r'
3596        WHEN class_objects.type = 'index' THEN 'i'
3597        WHEN class_objects.type = 'view' THEN 'v'
3598        WHEN class_objects.type = 'materialized-view' THEN 'm'
3599    END relkind,
3600    CASE
3601        WHEN class_objects.type = 'index' THEN COALESCE(
3602            (
3603                SELECT count(*)::pg_catalog.int2
3604                FROM mz_catalog.mz_index_columns
3605                WHERE mz_index_columns.index_id = class_objects.id
3606            ),
3607            0::pg_catalog.int2
3608        )
3609        ELSE COALESCE(
3610            (
3611                SELECT count(*)::pg_catalog.int2
3612                FROM mz_catalog.mz_columns
3613                WHERE mz_columns.id = class_objects.id
3614            ),
3615            0::pg_catalog.int2
3616        )
3617    END AS relnatts,
3618    -- MZ doesn't support CHECK constraints so relchecks is filled with 0
3619    0::pg_catalog.int2 AS relchecks,
3620    -- MZ doesn't support creating rules so relhasrules is filled with false
3621    false AS relhasrules,
3622    -- MZ doesn't support creating triggers so relhastriggers is filled with false
3623    false AS relhastriggers,
3624    -- MZ doesn't support table inheritance or partitions so relhassubclass is filled with false
3625    false AS relhassubclass,
3626    -- MZ doesn't have row level security so relrowsecurity and relforcerowsecurity is filled with false
3627    false AS relrowsecurity,
3628    false AS relforcerowsecurity,
3629    -- MZ doesn't support replication so relreplident is filled with 'd' for default
3630    'd'::pg_catalog.\"char\" AS relreplident,
3631    -- MZ doesn't support table partitioning so relispartition is filled with false
3632    false AS relispartition,
3633    -- PG removed relhasoids in v12 so it's filled with false
3634    false AS relhasoids,
3635    -- MZ doesn't support options for relations
3636    NULL::pg_catalog.text[] as reloptions,
3637    d.name as database_name
3638FROM (
3639    -- pg_class catalogs relations and indexes
3640    SELECT id, oid, schema_id, name, type, owner_id FROM mz_catalog.mz_relations
3641    UNION ALL
3642        SELECT mz_indexes.id, mz_indexes.oid, mz_relations.schema_id, mz_indexes.name, 'index' AS type, mz_indexes.owner_id
3643        FROM mz_catalog.mz_indexes
3644        JOIN mz_catalog.mz_relations ON mz_indexes.on_id = mz_relations.id
3645) AS class_objects
3646JOIN mz_catalog.mz_schemas ON mz_schemas.id = class_objects.schema_id
3647LEFT JOIN mz_catalog.mz_databases d ON d.id = mz_schemas.database_id
3648JOIN mz_catalog.mz_roles role_owner ON role_owner.id = class_objects.owner_id",
3649        access: vec![PUBLIC_SELECT],
3650        ontology: None,
3651    }
3652});
3653
3654pub const PG_CLASS_ALL_DATABASES_IND: BuiltinIndex = BuiltinIndex {
3655    name: "pg_class_all_databases_ind",
3656    schema: MZ_INTERNAL_SCHEMA,
3657    oid: oid::INDEX_PG_CLASS_ALL_DATABASES_IND_OID,
3658    sql: "IN CLUSTER mz_catalog_server
3659ON mz_internal.pg_class_all_databases (relname)",
3660    is_retained_metrics_object: false,
3661};
3662
3663/// Peeled version of `PG_DESCRIPTION`:
3664/// - This doesn't check `mz_schemas.database_id IS NULL OR d.name = pg_catalog.current_database()`,
3665///   in order to make this view indexable.
3666/// - This has 2 extra columns for the database names, so that downstream views can check them
3667///   against `current_database()`.
3668pub static PG_DESCRIPTION_ALL_DATABASES: LazyLock<BuiltinView> = LazyLock::new(|| {
3669    BuiltinView {
3670        name: "pg_description_all_databases",
3671        schema: MZ_INTERNAL_SCHEMA,
3672        oid: oid::VIEW_PG_DESCRIPTION_ALL_DATABASES_OID,
3673        desc: RelationDesc::builder()
3674            .with_column("objoid", SqlScalarType::Oid.nullable(false))
3675            .with_column("classoid", SqlScalarType::Oid.nullable(true))
3676            .with_column("objsubid", SqlScalarType::Int32.nullable(false))
3677            .with_column("description", SqlScalarType::String.nullable(false))
3678            .with_column("oid_database_name", SqlScalarType::String.nullable(true))
3679            .with_column("class_database_name", SqlScalarType::String.nullable(true))
3680            .finish(),
3681        column_comments: BTreeMap::new(),
3682        sql: "
3683(
3684    -- Gather all of the class oid's for objects that can have comments.
3685    WITH pg_classoids AS (
3686        SELECT oid, database_name as oid_database_name,
3687          (SELECT oid FROM mz_internal.pg_class_all_databases WHERE relname = 'pg_class') AS classoid,
3688          (SELECT database_name FROM mz_internal.pg_class_all_databases WHERE relname = 'pg_class') AS class_database_name
3689        FROM mz_internal.pg_class_all_databases
3690        UNION ALL
3691        SELECT oid, database_name as oid_database_name,
3692          (SELECT oid FROM mz_internal.pg_class_all_databases WHERE relname = 'pg_type') AS classoid,
3693          (SELECT database_name FROM mz_internal.pg_class_all_databases WHERE relname = 'pg_type') AS class_database_name
3694        FROM mz_internal.pg_type_all_databases
3695        UNION ALL
3696        SELECT oid, database_name as oid_database_name,
3697          (SELECT oid FROM mz_internal.pg_class_all_databases WHERE relname = 'pg_namespace') AS classoid,
3698          (SELECT database_name FROM mz_internal.pg_class_all_databases WHERE relname = 'pg_namespace') AS class_database_name
3699        FROM mz_internal.pg_namespace_all_databases
3700    ),
3701
3702    -- Gather all of the MZ ids for objects that can have comments.
3703    mz_objects AS (
3704        SELECT id, oid, type FROM mz_catalog.mz_objects
3705        UNION ALL
3706        SELECT id, oid, 'schema' AS type FROM mz_catalog.mz_schemas
3707    )
3708    SELECT
3709        pg_classoids.oid AS objoid,
3710        pg_classoids.classoid as classoid,
3711        COALESCE(cmt.object_sub_id, 0) AS objsubid,
3712        cmt.comment AS description,
3713        -- Columns added because of the peeling. (Note that there are 2 of these here.)
3714        oid_database_name,
3715        class_database_name
3716    FROM
3717        pg_classoids
3718    JOIN
3719        mz_objects ON pg_classoids.oid = mz_objects.oid
3720    JOIN
3721        mz_internal.mz_comments AS cmt ON mz_objects.id = cmt.id AND lower(mz_objects.type) = lower(cmt.object_type)
3722)",
3723        access: vec![PUBLIC_SELECT],
3724        ontology: None,
3725    }
3726});
3727
3728pub const PG_DESCRIPTION_ALL_DATABASES_IND: BuiltinIndex = BuiltinIndex {
3729    name: "pg_description_all_databases_ind",
3730    schema: MZ_INTERNAL_SCHEMA,
3731    oid: oid::INDEX_PG_DESCRIPTION_ALL_DATABASES_IND_OID,
3732    sql: "IN CLUSTER mz_catalog_server
3733ON mz_internal.pg_description_all_databases (objoid, classoid, objsubid, description, oid_database_name, class_database_name)",
3734    is_retained_metrics_object: false,
3735};
3736
3737/// Peeled version of `PG_TYPE`:
3738/// - This doesn't check `mz_schemas.database_id IS NULL OR d.name = pg_catalog.current_database()`,
3739///   in order to make this view indexable.
3740/// - This has the database name as an extra column, so that downstream views can check it against
3741///  `current_database()`.
3742pub static PG_TYPE_ALL_DATABASES: LazyLock<BuiltinView> = LazyLock::new(|| {
3743    BuiltinView {
3744        name: "pg_type_all_databases",
3745        schema: MZ_INTERNAL_SCHEMA,
3746        oid: oid::VIEW_PG_TYPE_ALL_DATABASES_OID,
3747        desc: RelationDesc::builder()
3748            .with_column("oid", SqlScalarType::Oid.nullable(false))
3749            .with_column("typname", SqlScalarType::String.nullable(false))
3750            .with_column("typnamespace", SqlScalarType::Oid.nullable(false))
3751            .with_column("typowner", SqlScalarType::Oid.nullable(false))
3752            .with_column("typlen", SqlScalarType::Int16.nullable(true))
3753            .with_column("typtype", SqlScalarType::PgLegacyChar.nullable(false))
3754            .with_column("typcategory", SqlScalarType::PgLegacyChar.nullable(true))
3755            .with_column("typdelim", SqlScalarType::PgLegacyChar.nullable(false))
3756            .with_column("typrelid", SqlScalarType::Oid.nullable(false))
3757            .with_column("typelem", SqlScalarType::Oid.nullable(false))
3758            .with_column("typarray", SqlScalarType::Oid.nullable(false))
3759            .with_column("typinput", SqlScalarType::RegProc.nullable(true))
3760            .with_column("typreceive", SqlScalarType::Oid.nullable(false))
3761            .with_column("typnotnull", SqlScalarType::Bool.nullable(false))
3762            .with_column("typbasetype", SqlScalarType::Oid.nullable(false))
3763            .with_column("typtypmod", SqlScalarType::Int32.nullable(false))
3764            .with_column("typcollation", SqlScalarType::Oid.nullable(false))
3765            .with_column("typdefault", SqlScalarType::String.nullable(true))
3766            .with_column("database_name", SqlScalarType::String.nullable(true))
3767            .finish(),
3768        column_comments: BTreeMap::new(),
3769        sql: "
3770SELECT
3771    mz_types.oid,
3772    mz_types.name AS typname,
3773    mz_schemas.oid AS typnamespace,
3774    role_owner.oid AS typowner,
3775    NULL::pg_catalog.int2 AS typlen,
3776    -- 'a' is used internally to denote an array type, but in postgres they show up
3777    -- as 'b'.
3778    (CASE mztype WHEN 'a' THEN 'b' ELSE mztype END)::pg_catalog.char AS typtype,
3779    (CASE category
3780        WHEN 'array' THEN 'A'
3781        WHEN 'bit-string' THEN 'V'
3782        WHEN 'boolean' THEN 'B'
3783        WHEN 'composite' THEN 'C'
3784        WHEN 'date-time' THEN 'D'
3785        WHEN 'enum' THEN 'E'
3786        WHEN 'geometric' THEN 'G'
3787        WHEN 'list' THEN 'U' -- List types are user-defined from PostgreSQL's perspective.
3788        WHEN 'network-address' THEN 'I'
3789        WHEN 'numeric' THEN 'N'
3790        WHEN 'pseudo' THEN 'P'
3791        WHEN 'string' THEN 'S'
3792        WHEN 'timespan' THEN 'T'
3793        WHEN 'user-defined' THEN 'U'
3794        WHEN 'unknown' THEN 'X'
3795    END)::pg_catalog.char AS typcategory,
3796    -- In pg only the 'box' type is not ','.
3797    ','::pg_catalog.char AS typdelim,
3798    0::pg_catalog.oid AS typrelid,
3799    coalesce(
3800        (
3801            SELECT t.oid
3802            FROM mz_catalog.mz_array_types a
3803            JOIN mz_catalog.mz_types t ON a.element_id = t.id
3804            WHERE a.id = mz_types.id
3805        ),
3806        (
3807            SELECT t.oid
3808            FROM mz_catalog.mz_list_types l
3809            JOIN mz_catalog.mz_types t ON l.element_id = t.id
3810            WHERE l.id = mz_types.id
3811        ),
3812        0
3813    ) AS typelem,
3814    coalesce(
3815        (
3816            SELECT
3817                t.oid
3818            FROM
3819                mz_catalog.mz_array_types AS a
3820                JOIN mz_catalog.mz_types AS t ON a.id = t.id
3821            WHERE
3822                a.element_id = mz_types.id
3823        ),
3824        0
3825    )
3826        AS typarray,
3827    mz_internal.mz_type_pg_metadata.typinput::pg_catalog.regproc AS typinput,
3828    COALESCE(mz_internal.mz_type_pg_metadata.typreceive, 0) AS typreceive,
3829    false::pg_catalog.bool AS typnotnull,
3830    0::pg_catalog.oid AS typbasetype,
3831    -1::pg_catalog.int4 AS typtypmod,
3832    -- MZ doesn't support COLLATE so typcollation is filled with 0
3833    0::pg_catalog.oid AS typcollation,
3834    NULL::pg_catalog.text AS typdefault,
3835    d.name as database_name
3836FROM
3837    mz_catalog.mz_types
3838    LEFT JOIN mz_internal.mz_type_pg_metadata ON mz_catalog.mz_types.id = mz_internal.mz_type_pg_metadata.id
3839    JOIN mz_catalog.mz_schemas ON mz_schemas.id = mz_types.schema_id
3840    JOIN (
3841            -- 'a' is not a supported typtype, but we use it to denote an array. It is
3842            -- converted to the correct value above.
3843            SELECT id, 'a' AS mztype FROM mz_catalog.mz_array_types
3844            UNION ALL SELECT id, 'b' FROM mz_catalog.mz_base_types
3845            UNION ALL SELECT id, 'l' FROM mz_catalog.mz_list_types
3846            UNION ALL SELECT id, 'm' FROM mz_catalog.mz_map_types
3847            UNION ALL SELECT id, 'p' FROM mz_catalog.mz_pseudo_types
3848        )
3849            AS t ON mz_types.id = t.id
3850    LEFT JOIN mz_catalog.mz_databases d ON d.id = mz_schemas.database_id
3851    JOIN mz_catalog.mz_roles role_owner ON role_owner.id = mz_types.owner_id",
3852        access: vec![PUBLIC_SELECT],
3853        ontology: None,
3854    }
3855});
3856
3857pub const PG_TYPE_ALL_DATABASES_IND: BuiltinIndex = BuiltinIndex {
3858    name: "pg_type_all_databases_ind",
3859    schema: MZ_INTERNAL_SCHEMA,
3860    oid: oid::INDEX_PG_TYPE_ALL_DATABASES_IND_OID,
3861    sql: "IN CLUSTER mz_catalog_server
3862ON mz_internal.pg_type_all_databases (oid)",
3863    is_retained_metrics_object: false,
3864};
3865
3866/// Peeled version of `PG_ATTRIBUTE`:
3867/// - This doesn't check `mz_schemas.database_id IS NULL OR d.name = pg_catalog.current_database()`,
3868///   in order to make this view indexable.
3869/// - This has 2 extra columns for the database names, so that downstream views can check them
3870///   against `current_database()`.
3871pub static PG_ATTRIBUTE_ALL_DATABASES: LazyLock<BuiltinView> = LazyLock::new(|| {
3872    BuiltinView {
3873        name: "pg_attribute_all_databases",
3874        schema: MZ_INTERNAL_SCHEMA,
3875        oid: oid::VIEW_PG_ATTRIBUTE_ALL_DATABASES_OID,
3876        desc: RelationDesc::builder()
3877            .with_column("attrelid", SqlScalarType::Oid.nullable(false))
3878            .with_column("attname", SqlScalarType::String.nullable(false))
3879            .with_column("atttypid", SqlScalarType::Oid.nullable(false))
3880            .with_column("attlen", SqlScalarType::Int16.nullable(true))
3881            .with_column("attnum", SqlScalarType::Int16.nullable(false))
3882            .with_column("atttypmod", SqlScalarType::Int32.nullable(false))
3883            .with_column("attndims", SqlScalarType::Int16.nullable(false))
3884            .with_column("attnotnull", SqlScalarType::Bool.nullable(false))
3885            .with_column("atthasdef", SqlScalarType::Bool.nullable(false))
3886            .with_column("attidentity", SqlScalarType::PgLegacyChar.nullable(false))
3887            .with_column("attgenerated", SqlScalarType::PgLegacyChar.nullable(false))
3888            .with_column("attisdropped", SqlScalarType::Bool.nullable(false))
3889            .with_column("attcollation", SqlScalarType::Oid.nullable(false))
3890            .with_column("database_name", SqlScalarType::String.nullable(true))
3891            .with_column("pg_type_database_name", SqlScalarType::String.nullable(true))
3892            .finish(),
3893        column_comments: BTreeMap::new(),
3894        sql: "
3895SELECT
3896    class_objects.oid as attrelid,
3897    mz_columns.name as attname,
3898    mz_columns.type_oid AS atttypid,
3899    pg_type_all_databases.typlen AS attlen,
3900    position::int8::int2 as attnum,
3901    mz_columns.type_mod as atttypmod,
3902    -- dummy value, just to make go-jet's workaround work for now. Discussion:
3903    -- https://github.com/MaterializeInc/materialize/pull/34649#issuecomment-3714291409
3904    0::int2 as attndims,
3905    NOT nullable as attnotnull,
3906    mz_columns.default IS NOT NULL as atthasdef,
3907    ''::pg_catalog.\"char\" as attidentity,
3908    -- MZ doesn't support generated columns so attgenerated is filled with ''
3909    ''::pg_catalog.\"char\" as attgenerated,
3910    FALSE as attisdropped,
3911    -- MZ doesn't support COLLATE so attcollation is filled with 0
3912    0::pg_catalog.oid as attcollation,
3913    -- Columns added because of the peeling. (Note that there are 2 of these here.)
3914    d.name as database_name,
3915    pg_type_all_databases.database_name as pg_type_database_name
3916FROM (
3917    -- pg_attribute catalogs columns on relations and indexes
3918    SELECT id, oid, schema_id, name, type FROM mz_catalog.mz_relations
3919    UNION ALL
3920        SELECT mz_indexes.id, mz_indexes.oid, mz_relations.schema_id, mz_indexes.name, 'index' AS type
3921        FROM mz_catalog.mz_indexes
3922        JOIN mz_catalog.mz_relations ON mz_indexes.on_id = mz_relations.id
3923) AS class_objects
3924JOIN mz_catalog.mz_columns ON class_objects.id = mz_columns.id
3925JOIN mz_internal.pg_type_all_databases ON pg_type_all_databases.oid = mz_columns.type_oid
3926JOIN mz_catalog.mz_schemas ON mz_schemas.id = class_objects.schema_id
3927LEFT JOIN mz_catalog.mz_databases d ON d.id = mz_schemas.database_id",
3928        // Since this depends on pg_type, its id must be higher due to initialization
3929        // ordering.
3930        access: vec![PUBLIC_SELECT],
3931        ontology: None,
3932    }
3933});
3934
3935pub const PG_ATTRIBUTE_ALL_DATABASES_IND: BuiltinIndex = BuiltinIndex {
3936    name: "pg_attribute_all_databases_ind",
3937    schema: MZ_INTERNAL_SCHEMA,
3938    oid: oid::INDEX_PG_ATTRIBUTE_ALL_DATABASES_IND_OID,
3939    sql: "IN CLUSTER mz_catalog_server
3940ON mz_internal.pg_attribute_all_databases (
3941    attrelid, attname, atttypid, attlen, attnum, atttypmod, attnotnull, atthasdef, attidentity,
3942    attgenerated, attisdropped, attcollation, database_name, pg_type_database_name
3943)",
3944    is_retained_metrics_object: false,
3945};
3946
3947/// Peeled version of `PG_ATTRDEF`:
3948/// - This doesn't check `mz_schemas.database_id IS NULL OR d.name = pg_catalog.current_database()`,
3949///   in order to make this view indexable.
3950pub static PG_ATTRDEF_ALL_DATABASES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
3951    name: "pg_attrdef_all_databases",
3952    schema: MZ_INTERNAL_SCHEMA,
3953    oid: oid::VIEW_PG_ATTRDEF_ALL_DATABASES_OID,
3954    desc: RelationDesc::builder()
3955        .with_column("oid", SqlScalarType::Oid.nullable(true))
3956        .with_column("adrelid", SqlScalarType::Oid.nullable(false))
3957        .with_column("adnum", SqlScalarType::Int64.nullable(false))
3958        .with_column("adbin", SqlScalarType::String.nullable(false))
3959        .with_column("adsrc", SqlScalarType::String.nullable(false))
3960        .finish(),
3961    column_comments: BTreeMap::new(),
3962    sql: "
3963SELECT
3964    NULL::pg_catalog.oid AS oid,
3965    mz_objects.oid AS adrelid,
3966    mz_columns.position::int8 AS adnum,
3967    mz_columns.default AS adbin,
3968    mz_columns.default AS adsrc
3969FROM mz_catalog.mz_columns
3970    JOIN mz_catalog.mz_objects ON mz_columns.id = mz_objects.id
3971WHERE default IS NOT NULL",
3972    access: vec![PUBLIC_SELECT],
3973    ontology: None,
3974});
3975
3976pub const PG_ATTRDEF_ALL_DATABASES_IND: BuiltinIndex = BuiltinIndex {
3977    name: "pg_attrdef_all_databases_ind",
3978    schema: MZ_INTERNAL_SCHEMA,
3979    oid: oid::INDEX_PG_ATTRDEF_ALL_DATABASES_IND_OID,
3980    sql: "IN CLUSTER mz_catalog_server
3981ON mz_internal.pg_attrdef_all_databases (oid, adrelid, adnum, adbin, adsrc)",
3982    is_retained_metrics_object: false,
3983};
3984
3985pub static MZ_COMPUTE_ERROR_COUNTS_RAW_UNIFIED: LazyLock<BuiltinSource> =
3986    LazyLock::new(|| BuiltinSource {
3987        // TODO(database-issues#8173): Rename this source to `mz_compute_error_counts_raw`. Currently this causes a
3988        // naming conflict because the resolver stumbles over the source with the same name in
3989        // `mz_introspection` due to the automatic schema translation.
3990        name: "mz_compute_error_counts_raw_unified",
3991        schema: MZ_INTERNAL_SCHEMA,
3992        oid: oid::SOURCE_MZ_COMPUTE_ERROR_COUNTS_RAW_UNIFIED_OID,
3993        desc: RelationDesc::builder()
3994            .with_column("replica_id", SqlScalarType::String.nullable(false))
3995            .with_column("object_id", SqlScalarType::String.nullable(false))
3996            .with_column(
3997                "count",
3998                SqlScalarType::Numeric { max_scale: None }.nullable(false),
3999            )
4000            .finish(),
4001        data_source: IntrospectionType::ComputeErrorCounts.into(),
4002        column_comments: BTreeMap::new(),
4003        is_retained_metrics_object: false,
4004        access: vec![PUBLIC_SELECT],
4005        ontology: None,
4006    });
4007
4008pub static MZ_COMPUTE_HYDRATION_TIMES: LazyLock<BuiltinSource> = LazyLock::new(|| BuiltinSource {
4009    name: "mz_compute_hydration_times",
4010    schema: MZ_INTERNAL_SCHEMA,
4011    oid: oid::SOURCE_MZ_COMPUTE_HYDRATION_TIMES_OID,
4012    desc: RelationDesc::builder()
4013        .with_column("replica_id", SqlScalarType::String.nullable(false))
4014        .with_column("object_id", SqlScalarType::String.nullable(false))
4015        .with_column("time_ns", SqlScalarType::UInt64.nullable(true))
4016        .finish(),
4017    data_source: IntrospectionType::ComputeHydrationTimes.into(),
4018    column_comments: BTreeMap::new(),
4019    is_retained_metrics_object: true,
4020    access: vec![PUBLIC_SELECT],
4021    ontology: Some(Ontology {
4022        entity_name: "compute_hydration_time",
4023        description: "Time to hydrate compute objects",
4024        links: &const { [] },
4025        column_semantic_types: &const {
4026            [
4027                ("replica_id", SemanticType::ReplicaId),
4028                ("object_id", SemanticType::CatalogItemId),
4029            ]
4030        },
4031    }),
4032});
4033
4034pub static MZ_COMPUTE_HYDRATION_TIMES_IND: LazyLock<BuiltinIndex> =
4035    LazyLock::new(|| BuiltinIndex {
4036        name: "mz_compute_hydration_times_ind",
4037        schema: MZ_INTERNAL_SCHEMA,
4038        oid: oid::INDEX_MZ_COMPUTE_HYDRATION_TIMES_IND_OID,
4039        sql: "IN CLUSTER mz_catalog_server
4040    ON mz_internal.mz_compute_hydration_times (replica_id)",
4041        is_retained_metrics_object: true,
4042    });
4043
4044pub static MZ_OBJECT_ARRANGEMENT_SIZES_UNIFIED: LazyLock<BuiltinSource> = LazyLock::new(|| {
4045    BuiltinSource {
4046        name: "mz_object_arrangement_sizes",
4047        schema: MZ_INTERNAL_SCHEMA,
4048        oid: oid::SOURCE_MZ_OBJECT_ARRANGEMENT_SIZES_OID,
4049        desc: RelationDesc::builder()
4050            .with_column("replica_id", SqlScalarType::String.nullable(false))
4051            .with_column("object_id", SqlScalarType::String.nullable(false))
4052            .with_column("size", SqlScalarType::Int64.nullable(true))
4053            .finish(),
4054        data_source: IntrospectionType::ComputeObjectArrangementSizes.into(),
4055        column_comments: BTreeMap::from_iter([
4056            (
4057                "replica_id",
4058                "The ID of the cluster replica. Corresponds to `mz_cluster_replicas.id`.",
4059            ),
4060            (
4061                "object_id",
4062                "The ID of the compute object (index or materialized view). Corresponds to `mz_objects.id`.",
4063            ),
4064            (
4065                "size",
4066                "The total arrangement heap and batcher size in bytes for this object on this replica. \
4067                 Objects smaller than 10 MiB are reported at their exact size; objects 10 MiB or larger \
4068                 are rounded to the nearest 10 MiB boundary to reduce per-byte churn in the differential \
4069                 collection.",
4070            ),
4071        ]),
4072        is_retained_metrics_object: true,
4073        access: vec![PUBLIC_SELECT],
4074        ontology: None,
4075    }
4076});
4077
4078pub static MZ_OBJECT_ARRANGEMENT_SIZES_IND: LazyLock<BuiltinIndex> =
4079    LazyLock::new(|| BuiltinIndex {
4080        name: "mz_object_arrangement_sizes_ind",
4081        schema: MZ_INTERNAL_SCHEMA,
4082        oid: oid::INDEX_MZ_OBJECT_ARRANGEMENT_SIZES_IND_OID,
4083        sql: "IN CLUSTER mz_catalog_server
4084    ON mz_internal.mz_object_arrangement_sizes (replica_id)",
4085        is_retained_metrics_object: true,
4086    });
4087
4088pub static MZ_OBJECT_ARRANGEMENT_SIZE_HISTORY: LazyLock<BuiltinTable> = LazyLock::new(|| {
4089    BuiltinTable {
4090        name: "mz_object_arrangement_size_history",
4091        schema: MZ_INTERNAL_SCHEMA,
4092        oid: oid::TABLE_MZ_OBJECT_ARRANGEMENT_SIZE_HISTORY_OID,
4093        desc: RelationDesc::builder()
4094            .with_column("replica_id", SqlScalarType::String.nullable(false))
4095            .with_column("object_id", SqlScalarType::String.nullable(false))
4096            .with_column("size", SqlScalarType::Int64.nullable(false))
4097            .with_column(
4098                "collection_timestamp",
4099                SqlScalarType::TimestampTz { precision: None }.nullable(false),
4100            )
4101            .with_column("hydration_complete", SqlScalarType::Bool.nullable(false))
4102            .finish(),
4103        column_comments: BTreeMap::from_iter([
4104            (
4105                "replica_id",
4106                "The ID of the cluster replica. Corresponds to `mz_cluster_replicas.id`.",
4107            ),
4108            (
4109                "object_id",
4110                "The ID of the compute object (index or materialized view). Corresponds to `mz_objects.id`.",
4111            ),
4112            (
4113                "size",
4114                "The total arrangement heap and batcher size in bytes for this object on this replica \
4115                 at `collection_timestamp`. Objects below 10 MiB are dropped from the snapshot; \
4116                 objects at or above the floor are rounded to the nearest 10 MiB to reduce \
4117                 per-byte churn in the underlying differential collection. May reflect a mid-build \
4118                 size if `hydration_complete` is `false`.",
4119            ),
4120            (
4121                "collection_timestamp",
4122                "The timestamp when this snapshot was collected.",
4123            ),
4124            (
4125                "hydration_complete",
4126                "Whether the arrangement had finished its initial hydration on this replica when \
4127                 the snapshot was collected. Filter for `true` to consider only stable, post-build \
4128                 sizes.",
4129            ),
4130        ]),
4131        is_retained_metrics_object: true,
4132        access: vec![PUBLIC_SELECT],
4133        ontology: None,
4134    }
4135});
4136
4137pub static MZ_OBJECT_ARRANGEMENT_SIZE_HISTORY_OBJECT_IND: LazyLock<BuiltinIndex> =
4138    LazyLock::new(|| BuiltinIndex {
4139        name: "mz_object_arrangement_size_history_object_ind",
4140        schema: MZ_INTERNAL_SCHEMA,
4141        oid: oid::INDEX_MZ_OBJECT_ARRANGEMENT_SIZE_HISTORY_OBJECT_IND_OID,
4142        sql: "IN CLUSTER mz_catalog_server
4143    ON mz_internal.mz_object_arrangement_size_history (object_id)",
4144        is_retained_metrics_object: true,
4145    });
4146
4147pub static MZ_OBJECT_ARRANGEMENT_SIZE_HISTORY_TS_IND: LazyLock<BuiltinIndex> =
4148    LazyLock::new(|| BuiltinIndex {
4149        name: "mz_object_arrangement_size_history_ts_ind",
4150        schema: MZ_INTERNAL_SCHEMA,
4151        oid: oid::INDEX_MZ_OBJECT_ARRANGEMENT_SIZE_HISTORY_TS_IND_OID,
4152        sql: "IN CLUSTER mz_catalog_server
4153    ON mz_internal.mz_object_arrangement_size_history (collection_timestamp)",
4154        is_retained_metrics_object: true,
4155    });
4156
4157pub static MZ_COMPUTE_HYDRATION_STATUSES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
4158    name: "mz_compute_hydration_statuses",
4159    schema: MZ_INTERNAL_SCHEMA,
4160    oid: oid::SOURCE_MZ_COMPUTE_HYDRATION_STATUSES_OID,
4161    desc: RelationDesc::builder()
4162        .with_column("object_id", SqlScalarType::String.nullable(false))
4163        .with_column("replica_id", SqlScalarType::String.nullable(false))
4164        .with_column("hydrated", SqlScalarType::Bool.nullable(false))
4165        .with_column("hydration_time", SqlScalarType::Interval.nullable(true))
4166        .finish(),
4167    column_comments: BTreeMap::from_iter([
4168        (
4169            "object_id",
4170            "The ID of a compute object. Corresponds to `mz_catalog.mz_indexes.id` or `mz_catalog.mz_materialized_views.id`",
4171        ),
4172        ("replica_id", "The ID of a cluster replica."),
4173        (
4174            "hydrated",
4175            "Whether the compute object is hydrated on the replica.",
4176        ),
4177        (
4178            "hydration_time",
4179            "The amount of time it took for the replica to hydrate the compute object.",
4180        ),
4181    ]),
4182    sql: "
4183WITH
4184    dataflows AS (
4185        SELECT
4186            object_id,
4187            replica_id,
4188            time_ns IS NOT NULL AS hydrated,
4189            ((time_ns / 1000) || 'microseconds')::interval AS hydration_time
4190        FROM mz_internal.mz_compute_hydration_times
4191    ),
4192    -- MVs that have advanced to the empty frontier don't have a dataflow installed anymore and
4193    -- therefore don't show up in `mz_compute_hydration_times`. We still want to show them here to
4194    -- avoid surprises for people joining `mz_materialized_views` against this relation (like the
4195    -- blue-green readiness query does), so we include them as 'hydrated'.
4196    complete_mvs AS (
4197        SELECT
4198            mv.id,
4199            f.replica_id,
4200            true AS hydrated,
4201            NULL::interval AS hydration_time
4202        FROM mz_materialized_views mv
4203        JOIN mz_catalog.mz_cluster_replica_frontiers f ON f.object_id = mv.id
4204        WHERE f.write_frontier IS NULL
4205    )
4206SELECT * FROM dataflows
4207UNION ALL
4208SELECT * FROM complete_mvs",
4209    access: vec![PUBLIC_SELECT],
4210    ontology: Some(Ontology {
4211        entity_name: "compute_hydration_status_view",
4212        description: "Computed hydration status per compute object",
4213        links: &const { [] },
4214        column_semantic_types: &const {
4215            [
4216                ("object_id", SemanticType::GlobalId),
4217                ("replica_id", SemanticType::ReplicaId),
4218            ]
4219        },
4220    }),
4221});
4222
4223pub static MZ_COMPUTE_OPERATOR_HYDRATION_STATUSES: LazyLock<BuiltinSource> = LazyLock::new(|| {
4224    BuiltinSource {
4225        name: "mz_compute_operator_hydration_statuses",
4226        schema: MZ_INTERNAL_SCHEMA,
4227        oid: oid::SOURCE_MZ_COMPUTE_OPERATOR_HYDRATION_STATUSES_OID,
4228        desc: RelationDesc::builder()
4229            .with_column("replica_id", SqlScalarType::String.nullable(false))
4230            .with_column("object_id", SqlScalarType::String.nullable(false))
4231            .with_column(
4232                "physical_plan_node_id",
4233                SqlScalarType::UInt64.nullable(false),
4234            )
4235            .with_column("hydrated", SqlScalarType::Bool.nullable(false))
4236            .with_key(vec![0, 1, 2])
4237            .finish(),
4238        data_source: IntrospectionType::ComputeOperatorHydrationStatus.into(),
4239        column_comments: BTreeMap::from_iter([
4240            ("replica_id", "The ID of a cluster replica."),
4241            (
4242                "object_id",
4243                "The ID of a compute object. Corresponds to `mz_catalog.mz_indexes.id` or `mz_catalog.mz_materialized_views.id`.",
4244            ),
4245            (
4246                "physical_plan_node_id",
4247                "The ID of a node in the physical plan of the compute object. Corresponds to a `node_id` displayed in the output of `EXPLAIN PHYSICAL PLAN WITH (node identifiers)`.",
4248            ),
4249            ("hydrated", "Whether the node is hydrated on the replica."),
4250        ]),
4251        is_retained_metrics_object: false,
4252        access: vec![PUBLIC_SELECT],
4253        ontology: Some(Ontology {
4254            entity_name: "compute_hydration_status",
4255            description: "Hydration status per compute operator",
4256            links: &const { [] },
4257            column_semantic_types: &const {
4258                [
4259                    ("replica_id", SemanticType::ReplicaId),
4260                    ("object_id", SemanticType::CatalogItemId),
4261                ]
4262            },
4263        }),
4264    }
4265});
4266
4267pub static MZ_CLUSTER_REPLICA_UTILIZATION: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
4268    name: "mz_cluster_replica_utilization",
4269    schema: MZ_INTERNAL_SCHEMA,
4270    oid: oid::VIEW_MZ_CLUSTER_REPLICA_UTILIZATION_OID,
4271    desc: RelationDesc::builder()
4272        .with_column("replica_id", SqlScalarType::String.nullable(false))
4273        .with_column("process_id", SqlScalarType::UInt64.nullable(false))
4274        .with_column("cpu_percent", SqlScalarType::Float64.nullable(true))
4275        .with_column("memory_percent", SqlScalarType::Float64.nullable(true))
4276        .with_column("disk_percent", SqlScalarType::Float64.nullable(true))
4277        .with_column("heap_percent", SqlScalarType::Float64.nullable(true))
4278        .finish(),
4279    column_comments: BTreeMap::from_iter([
4280        ("replica_id", "The ID of a cluster replica."),
4281        ("process_id", "The ID of a process within the replica."),
4282        (
4283            "cpu_percent",
4284            "Approximate CPU usage, in percent of the total allocation.",
4285        ),
4286        (
4287            "memory_percent",
4288            "Approximate RAM usage, in percent of the total allocation.",
4289        ),
4290        (
4291            "disk_percent",
4292            "Approximate disk usage, in percent of the total allocation.",
4293        ),
4294        (
4295            "heap_percent",
4296            "Approximate heap (RAM + swap) usage, in percent of the total allocation.",
4297        ),
4298    ]),
4299    sql: "
4300SELECT
4301    r.id AS replica_id,
4302    m.process_id,
4303    m.cpu_nano_cores::float8 / NULLIF(s.cpu_nano_cores, 0) * 100 AS cpu_percent,
4304    m.memory_bytes::float8 / NULLIF(s.memory_bytes, 0) * 100 AS memory_percent,
4305    m.disk_bytes::float8 / NULLIF(s.disk_bytes, 0) * 100 AS disk_percent,
4306    m.heap_bytes::float8 / NULLIF(m.heap_limit, 0) * 100 AS heap_percent
4307FROM
4308    mz_catalog.mz_cluster_replicas AS r
4309        JOIN mz_catalog.mz_cluster_replica_sizes AS s ON r.size = s.size
4310        JOIN mz_internal.mz_cluster_replica_metrics AS m ON m.replica_id = r.id",
4311    access: vec![PUBLIC_SELECT],
4312    ontology: Some(Ontology {
4313        entity_name: "replica_utilization",
4314        description: "Computed utilization metrics per replica",
4315        links: &const {
4316            [OntologyLink {
4317                name: "utilization_of_replica",
4318                target: "replica",
4319                properties: LinkProperties::fk_typed(
4320                    "replica_id",
4321                    "id",
4322                    Cardinality::OneToOne,
4323                    mz_repr::SemanticType::CatalogItemId,
4324                ),
4325            }]
4326        },
4327        column_semantic_types: &[("replica_id", SemanticType::ReplicaId)],
4328    }),
4329});
4330
4331pub static MZ_CLUSTER_REPLICA_UTILIZATION_HISTORY: LazyLock<BuiltinView> =
4332    LazyLock::new(|| BuiltinView {
4333        name: "mz_cluster_replica_utilization_history",
4334        schema: MZ_INTERNAL_SCHEMA,
4335        oid: oid::VIEW_MZ_CLUSTER_REPLICA_UTILIZATION_HISTORY_OID,
4336        desc: RelationDesc::builder()
4337            .with_column("replica_id", SqlScalarType::String.nullable(false))
4338            .with_column("process_id", SqlScalarType::UInt64.nullable(false))
4339            .with_column("cpu_percent", SqlScalarType::Float64.nullable(true))
4340            .with_column("memory_percent", SqlScalarType::Float64.nullable(true))
4341            .with_column("disk_percent", SqlScalarType::Float64.nullable(true))
4342            .with_column("heap_percent", SqlScalarType::Float64.nullable(true))
4343            .with_column(
4344                "occurred_at",
4345                SqlScalarType::TimestampTz { precision: None }.nullable(false),
4346            )
4347            .finish(),
4348        column_comments: BTreeMap::from_iter([
4349            ("replica_id", "The ID of a cluster replica."),
4350            ("process_id", "The ID of a process within the replica."),
4351            (
4352                "cpu_percent",
4353                "Approximate CPU usage, in percent of the total allocation.",
4354            ),
4355            (
4356                "memory_percent",
4357                "Approximate RAM usage, in percent of the total allocation.",
4358            ),
4359            (
4360                "disk_percent",
4361                "Approximate disk usage, in percent of the total allocation.",
4362            ),
4363            (
4364                "heap_percent",
4365                "Approximate heap (RAM + swap) usage, in percent of the total allocation.",
4366            ),
4367            (
4368                "occurred_at",
4369                "Wall-clock timestamp at which the event occurred.",
4370            ),
4371        ]),
4372        sql: "
4373SELECT
4374    r.id AS replica_id,
4375    m.process_id,
4376    m.cpu_nano_cores::float8 / NULLIF(s.cpu_nano_cores, 0) * 100 AS cpu_percent,
4377    m.memory_bytes::float8 / NULLIF(s.memory_bytes, 0) * 100 AS memory_percent,
4378    m.disk_bytes::float8 / NULLIF(s.disk_bytes, 0) * 100 AS disk_percent,
4379    m.heap_bytes::float8 / NULLIF(m.heap_limit, 0) * 100 AS heap_percent,
4380    m.occurred_at
4381FROM
4382    mz_catalog.mz_cluster_replicas AS r
4383        JOIN mz_catalog.mz_cluster_replica_sizes AS s ON r.size = s.size
4384        JOIN mz_internal.mz_cluster_replica_metrics_history AS m ON m.replica_id = r.id",
4385        access: vec![PUBLIC_SELECT],
4386        ontology: None,
4387    });
4388
4389pub static MZ_INDEX_ADVICE: LazyLock<BuiltinView> = LazyLock::new(|| {
4390    BuiltinView {
4391        name: "mz_index_advice",
4392        schema: MZ_INTERNAL_SCHEMA,
4393        oid: oid::VIEW_MZ_INDEX_ADVICE_OID,
4394        desc: RelationDesc::builder()
4395            .with_column("object_id", SqlScalarType::String.nullable(true))
4396            .with_column("hint", SqlScalarType::String.nullable(false))
4397            .with_column("details", SqlScalarType::String.nullable(false))
4398            .with_column("referenced_object_ids", SqlScalarType::List { element_type: Box::new(SqlScalarType::String), custom_id: None }.nullable(true))
4399            .finish(),
4400        column_comments: BTreeMap::from_iter([
4401            ("object_id", "The ID of the object. Corresponds to mz_objects.id."),
4402            ("hint", "A suggestion to either change the object (e.g. create an index, turn a materialized view into an indexed view) or keep the object unchanged."),
4403            ("details", "Additional details on why the `hint` was proposed based on the dependencies of the object."),
4404            ("referenced_object_ids", "The IDs of objects referenced by `details`. Corresponds to mz_objects.id."),
4405        ]),
4406        sql: "
4407-- To avoid confusion with sources and sinks in the materialize sense,
4408-- the following uses the terms leafs (instead of sinks) and roots (instead of sources)
4409-- when referring to the object dependency graph.
4410--
4411-- The basic idea is to walk up the dependency graph to propagate the transitive dependencies
4412-- of maintained objected upwards. The leaves of the dependency graph are maintained objects
4413-- that are not depended on by other maintained objects and have a justification why they must
4414-- be maintained (e.g. a materialized view that is depended on by a sink).
4415-- Starting from these leaves, the dependencies are propagated upwards towards the roots according
4416-- to the object dependencies. Whenever there is a node that is being depended on by multiple
4417-- downstream objects, that node is marked to be converted into a maintained object and this
4418-- node is then propagated further up. Once completed, the list of objects that are marked as
4419-- maintained is checked against all objects to generate appropriate recommendations.
4420--
4421-- Note that the recommendations only incorporate dependencies between objects.
4422-- This can lead to bad recommendations, e.g. filters can no longer be pushed into (or close to)
4423-- a sink if an index is added in between the sink and the filter. For very selective filters,
4424-- this can lead to redundant work: the index is computing stuff only to discarded by the selective
4425-- filter later on. But these kind of aspects cannot be understood by merely looking at the
4426-- dependencies.
4427WITH MUTUALLY RECURSIVE
4428    -- for all objects, understand if they have an index on them and on which cluster they are running
4429    -- this avoids having different cases for views with an index and materialized views later on
4430    objects(id text, type text, cluster_id text, indexes text list) AS (
4431        -- views and materialized views without an index
4432        SELECT
4433            o.id,
4434            o.type,
4435            o.cluster_id,
4436            '{}'::text list AS indexes
4437        FROM mz_catalog.mz_objects o
4438        WHERE o.id LIKE 'u%' AND o.type IN ('materialized-view', 'view') AND NOT EXISTS (
4439            SELECT FROM mz_internal.mz_object_dependencies d
4440            JOIN mz_catalog.mz_objects AS i
4441                ON (i.id = d.object_id AND i.type = 'index')
4442            WHERE (o.id = d.referenced_object_id)
4443        )
4444
4445        UNION ALL
4446
4447        -- views and materialized views with an index
4448        SELECT
4449            o.id,
4450            o.type,
4451            -- o.cluster_id is always NULL for views, so use the cluster of the index instead
4452            COALESCE(o.cluster_id, i.cluster_id) AS cluster_id,
4453            list_agg(i.id) AS indexes
4454        FROM mz_catalog.mz_objects o
4455        JOIN mz_internal.mz_object_dependencies AS d
4456            ON (o.id = d.referenced_object_id)
4457        JOIN mz_catalog.mz_objects AS i
4458            ON (i.id = d.object_id AND i.type = 'index')
4459        WHERE o.id LIKE 'u%' AND o.type IN ('materialized-view', 'view', 'source')
4460        GROUP BY o.id, o.type, o.cluster_id, i.cluster_id
4461    ),
4462
4463    -- maintained objects that are at the leafs of the dependency graph with respect to a specific cluster
4464    maintained_leafs(id text, justification text) AS (
4465        -- materialized views that are connected to a sink
4466        SELECT
4467            m.id,
4468            s.id AS justification
4469        FROM objects AS m
4470        JOIN mz_internal.mz_object_dependencies AS d
4471            ON (m.id = d.referenced_object_id)
4472        JOIN mz_catalog.mz_objects AS s
4473            ON (s.id = d.object_id AND s.type = 'sink')
4474        WHERE m.type = 'materialized-view'
4475
4476        UNION ALL
4477
4478        -- (materialized) views with an index that are not transitively depend on by maintained objects on the same cluster
4479        SELECT
4480            v.id,
4481            unnest(v.indexes) AS justification
4482        FROM objects AS v
4483        WHERE v.type IN ('view', 'materialized-view', 'source') AND NOT EXISTS (
4484            SELECT FROM mz_internal.mz_object_transitive_dependencies AS d
4485            INNER JOIN mz_catalog.mz_objects AS child
4486                ON (d.object_id = child.id)
4487            WHERE d.referenced_object_id = v.id AND child.type IN ('materialized-view', 'index') AND v.cluster_id = child.cluster_id AND NOT v.indexes @> LIST[child.id]
4488        )
4489    ),
4490
4491    -- this is just a helper cte to union multiple lists as part of an aggregation, which is not directly possible in SQL
4492    agg_maintained_children(id text, maintained_children text list) AS (
4493        SELECT
4494            parent_id AS id,
4495            list_agg(maintained_child) AS maintained_leafs
4496        FROM (
4497            SELECT DISTINCT
4498                d.referenced_object_id AS parent_id,
4499                -- it's not possible to union lists in an aggregation, so we have to unnest the list first
4500                unnest(child.maintained_children) AS maintained_child
4501            FROM propagate_dependencies AS child
4502            INNER JOIN mz_internal.mz_object_dependencies AS d
4503                ON (child.id = d.object_id)
4504        )
4505        GROUP BY parent_id
4506    ),
4507
4508    -- propagate dependencies of maintained objects from the leafs to the roots of the dependency graph and
4509    -- record a justification when an object should be maintained, e.g. when it is depended on by more than one maintained object
4510    -- when an object should be maintained, maintained_children will just contain that object so that further upstream objects refer to it in their maintained_children
4511    propagate_dependencies(id text, maintained_children text list, justification text list) AS (
4512        -- base case: start with the leafs
4513        SELECT DISTINCT
4514            id,
4515            LIST[id] AS maintained_children,
4516            list_agg(justification) AS justification
4517        FROM maintained_leafs
4518        GROUP BY id
4519
4520        UNION
4521
4522        -- recursive case: if there is a child with the same dependencies as the parent,
4523        -- the parent is only reused by a single child
4524        SELECT
4525            parent.id,
4526            child.maintained_children,
4527            NULL::text list AS justification
4528        FROM agg_maintained_children AS parent
4529        INNER JOIN mz_internal.mz_object_dependencies AS d
4530            ON (parent.id = d.referenced_object_id)
4531        INNER JOIN propagate_dependencies AS child
4532            ON (d.object_id = child.id)
4533        WHERE parent.maintained_children = child.maintained_children
4534
4535        UNION
4536
4537        -- recursive case: if there is NO child with the same dependencies as the parent,
4538        -- different children are reusing the parent so maintaining the object is justified by itself
4539        SELECT DISTINCT
4540            parent.id,
4541            LIST[parent.id] AS maintained_children,
4542            parent.maintained_children AS justification
4543        FROM agg_maintained_children AS parent
4544        WHERE NOT EXISTS (
4545            SELECT FROM mz_internal.mz_object_dependencies AS d
4546            INNER JOIN propagate_dependencies AS child
4547                ON (d.object_id = child.id AND d.referenced_object_id = parent.id)
4548            WHERE parent.maintained_children = child.maintained_children
4549        )
4550    ),
4551
4552    objects_with_justification(id text, type text, cluster_id text, maintained_children text list, justification text list, indexes text list) AS (
4553        SELECT
4554            p.id,
4555            o.type,
4556            o.cluster_id,
4557            p.maintained_children,
4558            p.justification,
4559            o.indexes
4560        FROM propagate_dependencies p
4561        JOIN objects AS o
4562            ON (p.id = o.id)
4563    ),
4564
4565    hints(id text, hint text, details text, justification text list) AS (
4566        -- materialized views that are not required
4567        SELECT
4568            id,
4569            'convert to a view' AS hint,
4570            'no dependencies from sinks nor from objects on different clusters' AS details,
4571            justification
4572        FROM objects_with_justification
4573        WHERE type = 'materialized-view' AND justification IS NULL
4574
4575        UNION ALL
4576
4577        -- materialized views that are required because a sink or a maintained object from a different cluster depends on them
4578        SELECT
4579            id,
4580            'keep' AS hint,
4581            'dependencies from sinks or objects on different clusters: ' AS details,
4582            justification
4583        FROM objects_with_justification AS m
4584        WHERE type = 'materialized-view' AND justification IS NOT NULL AND EXISTS (
4585            SELECT FROM unnest(justification) AS dependency
4586            JOIN mz_catalog.mz_objects s ON (s.type = 'sink' AND s.id = dependency)
4587
4588            UNION ALL
4589
4590            SELECT FROM unnest(justification) AS dependency
4591            JOIN mz_catalog.mz_objects AS d ON (d.id = dependency)
4592            WHERE d.cluster_id != m.cluster_id
4593        )
4594
4595        UNION ALL
4596
4597        -- materialized views that can be converted to a view with or without an index because NO sink or a maintained object from a different cluster depends on them
4598        SELECT
4599            id,
4600            'convert to a view with an index' AS hint,
4601            'no dependencies from sinks nor from objects on different clusters, but maintained dependencies on the same cluster: ' AS details,
4602            justification
4603        FROM objects_with_justification AS m
4604        WHERE type = 'materialized-view' AND justification IS NOT NULL AND NOT EXISTS (
4605            SELECT FROM unnest(justification) AS dependency
4606            JOIN mz_catalog.mz_objects s ON (s.type = 'sink' AND s.id = dependency)
4607
4608            UNION ALL
4609
4610            SELECT FROM unnest(justification) AS dependency
4611            JOIN mz_catalog.mz_objects AS d ON (d.id = dependency)
4612            WHERE d.cluster_id != m.cluster_id
4613        )
4614
4615        UNION ALL
4616
4617        -- views that have indexes on different clusters should be a materialized view
4618        SELECT
4619            o.id,
4620            'convert to materialized view' AS hint,
4621            'dependencies on multiple clusters: ' AS details,
4622            o.justification
4623        FROM objects_with_justification o,
4624            LATERAL unnest(o.justification) j
4625        LEFT JOIN mz_catalog.mz_objects AS m
4626            ON (m.id = j AND m.type IN ('index', 'materialized-view'))
4627        WHERE o.type = 'view' AND o.justification IS NOT NULL
4628        GROUP BY o.id, o.justification
4629        HAVING count(DISTINCT m.cluster_id) >= 2
4630
4631        UNION ALL
4632
4633        -- views without an index that should be maintained
4634        SELECT
4635            id,
4636            'add index' AS hint,
4637            'multiple downstream dependencies: ' AS details,
4638            justification
4639        FROM objects_with_justification
4640        WHERE type = 'view' AND justification IS NOT NULL AND indexes = '{}'::text list
4641
4642        UNION ALL
4643
4644        -- index inside the dependency graph (not a leaf)
4645        SELECT
4646            unnest(indexes) AS id,
4647            'drop unless queried directly' AS hint,
4648            'fewer than two downstream dependencies: ' AS details,
4649            maintained_children AS justification
4650        FROM objects_with_justification
4651        WHERE type = 'view' AND NOT indexes = '{}'::text list AND justification IS NULL
4652
4653        UNION ALL
4654
4655        -- index on a leaf of the dependency graph
4656        SELECT
4657            unnest(indexes) AS id,
4658            'drop unless queried directly' AS hint,
4659            'associated object does not have any dependencies (maintained or not maintained)' AS details,
4660            NULL::text list AS justification
4661        FROM objects_with_justification
4662        -- indexes can only be part of justification for leaf nodes
4663        WHERE type IN ('view', 'materialized-view') AND NOT indexes = '{}'::text list AND justification @> indexes
4664
4665        UNION ALL
4666
4667        -- index on a source
4668        SELECT
4669            unnest(indexes) AS id,
4670            'drop unless queried directly' AS hint,
4671            'sources do not transform data and can expose data directly' AS details,
4672            NULL::text list AS justification
4673        FROM objects_with_justification
4674        -- indexes can only be part of justification for leaf nodes
4675        WHERE type = 'source' AND NOT indexes = '{}'::text list
4676
4677        UNION ALL
4678
4679        -- indexes on views inside the dependency graph
4680        SELECT
4681            unnest(indexes) AS id,
4682            'keep' AS hint,
4683            'multiple downstream dependencies: ' AS details,
4684            justification
4685        FROM objects_with_justification
4686        -- indexes can only be part of justification for leaf nodes
4687        WHERE type = 'view' AND justification IS NOT NULL AND NOT indexes = '{}'::text list AND NOT justification @> indexes
4688    ),
4689
4690    hints_resolved_ids(id text, hint text, details text, justification text list) AS (
4691        SELECT
4692            h.id,
4693            h.hint,
4694            h.details || list_agg(o.name)::text AS details,
4695            h.justification
4696        FROM hints AS h,
4697            LATERAL unnest(h.justification) j
4698        JOIN mz_catalog.mz_objects AS o
4699            ON (o.id = j)
4700        GROUP BY h.id, h.hint, h.details, h.justification
4701
4702        UNION ALL
4703
4704        SELECT
4705            id,
4706            hint,
4707            details,
4708            justification
4709        FROM hints
4710        WHERE justification IS NULL
4711    )
4712
4713SELECT
4714    h.id AS object_id,
4715    h.hint AS hint,
4716    h.details,
4717    h.justification AS referenced_object_ids
4718FROM hints_resolved_ids AS h",
4719        access: vec![PUBLIC_SELECT],
4720        ontology: None,
4721    }
4722});
4723
4724/// Peeled version of `PG_AUTHID`: Excludes the columns rolcreaterole and rolcreatedb, to make this
4725/// view indexable.
4726pub static PG_AUTHID_CORE: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
4727    name: "pg_authid_core",
4728    schema: MZ_INTERNAL_SCHEMA,
4729    oid: oid::VIEW_PG_AUTHID_CORE_OID,
4730    desc: RelationDesc::builder()
4731        .with_column("oid", SqlScalarType::Oid.nullable(false))
4732        .with_column("rolname", SqlScalarType::String.nullable(false))
4733        .with_column("rolsuper", SqlScalarType::Bool.nullable(true))
4734        .with_column("rolinherit", SqlScalarType::Bool.nullable(false))
4735        .with_column("rolcanlogin", SqlScalarType::Bool.nullable(false))
4736        .with_column("rolreplication", SqlScalarType::Bool.nullable(false))
4737        .with_column("rolbypassrls", SqlScalarType::Bool.nullable(false))
4738        .with_column("rolconnlimit", SqlScalarType::Int32.nullable(false))
4739        .with_column("rolpassword", SqlScalarType::String.nullable(true))
4740        .with_column(
4741            "rolvaliduntil",
4742            SqlScalarType::TimestampTz { precision: None }.nullable(true),
4743        )
4744        .finish(),
4745    column_comments: BTreeMap::new(),
4746    sql: r#"
4747SELECT
4748    r.oid AS oid,
4749    r.name AS rolname,
4750    rolsuper,
4751    inherit AS rolinherit,
4752    COALESCE(r.rolcanlogin, false) AS rolcanlogin,
4753    -- MZ doesn't support replication in the same way Postgres does
4754    false AS rolreplication,
4755    -- MZ doesn't how row level security
4756    false AS rolbypassrls,
4757    -- MZ doesn't have a connection limit
4758    -1 AS rolconnlimit,
4759    a.password_hash AS rolpassword,
4760    NULL::pg_catalog.timestamptz AS rolvaliduntil
4761FROM mz_catalog.mz_roles r
4762LEFT JOIN mz_catalog.mz_role_auth a ON r.oid = a.role_oid"#,
4763    access: vec![rbac::owner_privilege(ObjectType::Table, MZ_SYSTEM_ROLE_ID)],
4764    ontology: None,
4765});
4766
4767pub const PG_AUTHID_CORE_IND: BuiltinIndex = BuiltinIndex {
4768    name: "pg_authid_core_ind",
4769    schema: MZ_INTERNAL_SCHEMA,
4770    oid: oid::INDEX_PG_AUTHID_CORE_IND_OID,
4771    sql: "IN CLUSTER mz_catalog_server
4772ON mz_internal.pg_authid_core (rolname)",
4773    is_retained_metrics_object: false,
4774};
4775
4776pub static MZ_SHOW_ALL_OBJECTS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
4777    name: "mz_show_all_objects",
4778    schema: MZ_INTERNAL_SCHEMA,
4779    oid: oid::VIEW_MZ_SHOW_ALL_OBJECTS_OID,
4780    desc: RelationDesc::builder()
4781        .with_column("schema_id", SqlScalarType::String.nullable(false))
4782        .with_column("name", SqlScalarType::String.nullable(false))
4783        .with_column("type", SqlScalarType::String.nullable(false))
4784        .with_column("comment", SqlScalarType::String.nullable(false))
4785        .finish(),
4786    column_comments: BTreeMap::new(),
4787    sql: "WITH comments AS (
4788        SELECT id, object_type, comment
4789        FROM mz_internal.mz_comments
4790        WHERE object_sub_id IS NULL
4791    )
4792    SELECT schema_id, name, type, COALESCE(comment, '') AS comment
4793    FROM mz_catalog.mz_objects AS objs
4794    LEFT JOIN comments ON objs.id = comments.id
4795    WHERE (comments.object_type = objs.type OR comments.object_type IS NULL)",
4796    access: vec![PUBLIC_SELECT],
4797    ontology: None,
4798});
4799
4800pub static MZ_SHOW_CLUSTERS: LazyLock<BuiltinView> = LazyLock::new(|| {
4801    BuiltinView {
4802    name: "mz_show_clusters",
4803    schema: MZ_INTERNAL_SCHEMA,
4804    oid: oid::VIEW_MZ_SHOW_CLUSTERS_OID,
4805    desc: RelationDesc::builder()
4806        .with_column("name", SqlScalarType::String.nullable(false))
4807        .with_column("replicas", SqlScalarType::String.nullable(true))
4808        .with_column("comment", SqlScalarType::String.nullable(false))
4809        .finish(),
4810    column_comments: BTreeMap::new(),
4811    sql: "
4812    WITH clusters AS (
4813        SELECT
4814            mc.id,
4815            mc.name,
4816            pg_catalog.string_agg(mcr.name || ' (' || mcr.size || ')', ', ' ORDER BY mcr.name) AS replicas
4817        FROM mz_catalog.mz_clusters mc
4818        LEFT JOIN mz_catalog.mz_cluster_replicas mcr
4819        ON mc.id = mcr.cluster_id
4820        GROUP BY mc.id, mc.name
4821    ),
4822    comments AS (
4823        SELECT id, comment
4824        FROM mz_internal.mz_comments
4825        WHERE object_type = 'cluster' AND object_sub_id IS NULL
4826    )
4827    SELECT name, replicas, COALESCE(comment, '') as comment
4828    FROM clusters
4829    LEFT JOIN comments ON clusters.id = comments.id",
4830    access: vec![PUBLIC_SELECT],
4831    ontology: None,
4832}
4833});
4834
4835pub static MZ_SHOW_SECRETS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
4836    name: "mz_show_secrets",
4837    schema: MZ_INTERNAL_SCHEMA,
4838    oid: oid::VIEW_MZ_SHOW_SECRETS_OID,
4839    desc: RelationDesc::builder()
4840        .with_column("schema_id", SqlScalarType::String.nullable(false))
4841        .with_column("name", SqlScalarType::String.nullable(false))
4842        .with_column("comment", SqlScalarType::String.nullable(false))
4843        .finish(),
4844    column_comments: BTreeMap::new(),
4845    sql: "WITH comments AS (
4846        SELECT id, comment
4847        FROM mz_internal.mz_comments
4848        WHERE object_type = 'secret' AND object_sub_id IS NULL
4849    )
4850    SELECT schema_id, name, COALESCE(comment, '') as comment
4851    FROM mz_catalog.mz_secrets secrets
4852    LEFT JOIN comments ON secrets.id = comments.id",
4853    access: vec![PUBLIC_SELECT],
4854    ontology: None,
4855});
4856
4857pub static MZ_SHOW_COLUMNS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
4858    name: "mz_show_columns",
4859    schema: MZ_INTERNAL_SCHEMA,
4860    oid: oid::VIEW_MZ_SHOW_COLUMNS_OID,
4861    desc: RelationDesc::builder()
4862        .with_column("id", SqlScalarType::String.nullable(false))
4863        .with_column("name", SqlScalarType::String.nullable(false))
4864        .with_column("nullable", SqlScalarType::Bool.nullable(false))
4865        .with_column("type", SqlScalarType::String.nullable(false))
4866        .with_column("position", SqlScalarType::UInt64.nullable(false))
4867        .with_column("comment", SqlScalarType::String.nullable(false))
4868        .finish(),
4869    column_comments: BTreeMap::new(),
4870    sql: "
4871    SELECT columns.id, name, nullable, type, position, COALESCE(comment, '') as comment
4872    FROM mz_catalog.mz_columns columns
4873    LEFT JOIN mz_internal.mz_comments comments
4874    ON columns.id = comments.id AND columns.position = comments.object_sub_id",
4875    access: vec![PUBLIC_SELECT],
4876    ontology: None,
4877});
4878
4879pub static MZ_SHOW_DATABASES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
4880    name: "mz_show_databases",
4881    schema: MZ_INTERNAL_SCHEMA,
4882    oid: oid::VIEW_MZ_SHOW_DATABASES_OID,
4883    desc: RelationDesc::builder()
4884        .with_column("name", SqlScalarType::String.nullable(false))
4885        .with_column("comment", SqlScalarType::String.nullable(false))
4886        .finish(),
4887    column_comments: BTreeMap::new(),
4888    sql: "WITH comments AS (
4889        SELECT id, comment
4890        FROM mz_internal.mz_comments
4891        WHERE object_type = 'database' AND object_sub_id IS NULL
4892    )
4893    SELECT name, COALESCE(comment, '') as comment
4894    FROM mz_catalog.mz_databases databases
4895    LEFT JOIN comments ON databases.id = comments.id",
4896    access: vec![PUBLIC_SELECT],
4897    ontology: None,
4898});
4899
4900pub static MZ_SHOW_SCHEMAS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
4901    name: "mz_show_schemas",
4902    schema: MZ_INTERNAL_SCHEMA,
4903    oid: oid::VIEW_MZ_SHOW_SCHEMAS_OID,
4904    desc: RelationDesc::builder()
4905        .with_column("database_id", SqlScalarType::String.nullable(true))
4906        .with_column("name", SqlScalarType::String.nullable(false))
4907        .with_column("comment", SqlScalarType::String.nullable(false))
4908        .finish(),
4909    column_comments: BTreeMap::new(),
4910    sql: "WITH comments AS (
4911        SELECT id, comment
4912        FROM mz_internal.mz_comments
4913        WHERE object_type = 'schema' AND object_sub_id IS NULL
4914    )
4915    SELECT database_id, name, COALESCE(comment, '') as comment
4916    FROM mz_catalog.mz_schemas schemas
4917    LEFT JOIN comments ON schemas.id = comments.id",
4918    access: vec![PUBLIC_SELECT],
4919    ontology: None,
4920});
4921
4922pub static MZ_SHOW_ROLES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
4923    name: "mz_show_roles",
4924    schema: MZ_INTERNAL_SCHEMA,
4925    oid: oid::VIEW_MZ_SHOW_ROLES_OID,
4926    desc: RelationDesc::builder()
4927        .with_column("name", SqlScalarType::String.nullable(false))
4928        .with_column("comment", SqlScalarType::String.nullable(false))
4929        .finish(),
4930    column_comments: BTreeMap::new(),
4931    sql: "WITH comments AS (
4932        SELECT id, comment
4933        FROM mz_internal.mz_comments
4934        WHERE object_type = 'role' AND object_sub_id IS NULL
4935    )
4936    SELECT name, COALESCE(comment, '') as comment
4937    FROM mz_catalog.mz_roles roles
4938    LEFT JOIN comments ON roles.id = comments.id
4939    WHERE roles.id NOT LIKE 's%'
4940      AND roles.id NOT LIKE 'g%'",
4941    access: vec![PUBLIC_SELECT],
4942    ontology: None,
4943});
4944
4945pub static MZ_SHOW_TABLES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
4946    name: "mz_show_tables",
4947    schema: MZ_INTERNAL_SCHEMA,
4948    oid: oid::VIEW_MZ_SHOW_TABLES_OID,
4949    desc: RelationDesc::builder()
4950        .with_column("schema_id", SqlScalarType::String.nullable(false))
4951        .with_column("name", SqlScalarType::String.nullable(false))
4952        .with_column("comment", SqlScalarType::String.nullable(false))
4953        .with_column("source_id", SqlScalarType::String.nullable(true))
4954        .finish(),
4955    column_comments: BTreeMap::new(),
4956    sql: "WITH comments AS (
4957        SELECT id, comment
4958        FROM mz_internal.mz_comments
4959        WHERE object_type = 'table' AND object_sub_id IS NULL
4960    )
4961    SELECT schema_id, name, COALESCE(comment, '') as comment, source_id
4962    FROM mz_catalog.mz_tables tables
4963    LEFT JOIN comments ON tables.id = comments.id",
4964    access: vec![PUBLIC_SELECT],
4965    ontology: None,
4966});
4967
4968pub static MZ_SHOW_VIEWS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
4969    name: "mz_show_views",
4970    schema: MZ_INTERNAL_SCHEMA,
4971    oid: oid::VIEW_MZ_SHOW_VIEWS_OID,
4972    desc: RelationDesc::builder()
4973        .with_column("schema_id", SqlScalarType::String.nullable(false))
4974        .with_column("name", SqlScalarType::String.nullable(false))
4975        .with_column("comment", SqlScalarType::String.nullable(false))
4976        .finish(),
4977    column_comments: BTreeMap::new(),
4978    sql: "WITH comments AS (
4979        SELECT id, comment
4980        FROM mz_internal.mz_comments
4981        WHERE object_type = 'view' AND object_sub_id IS NULL
4982    )
4983    SELECT schema_id, name, COALESCE(comment, '') as comment
4984    FROM mz_catalog.mz_views views
4985    LEFT JOIN comments ON views.id = comments.id",
4986    access: vec![PUBLIC_SELECT],
4987    ontology: None,
4988});
4989
4990pub static MZ_SHOW_TYPES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
4991    name: "mz_show_types",
4992    schema: MZ_INTERNAL_SCHEMA,
4993    oid: oid::VIEW_MZ_SHOW_TYPES_OID,
4994    desc: RelationDesc::builder()
4995        .with_column("schema_id", SqlScalarType::String.nullable(false))
4996        .with_column("name", SqlScalarType::String.nullable(false))
4997        .with_column("comment", SqlScalarType::String.nullable(false))
4998        .finish(),
4999    column_comments: BTreeMap::new(),
5000    sql: "WITH comments AS (
5001        SELECT id, comment
5002        FROM mz_internal.mz_comments
5003        WHERE object_type = 'type' AND object_sub_id IS NULL
5004    )
5005    SELECT schema_id, name, COALESCE(comment, '') as comment
5006    FROM mz_catalog.mz_types types
5007    LEFT JOIN comments ON types.id = comments.id",
5008    access: vec![PUBLIC_SELECT],
5009    ontology: None,
5010});
5011
5012pub static MZ_SHOW_CONNECTIONS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
5013    name: "mz_show_connections",
5014    schema: MZ_INTERNAL_SCHEMA,
5015    oid: oid::VIEW_MZ_SHOW_CONNECTIONS_OID,
5016    desc: RelationDesc::builder()
5017        .with_column("schema_id", SqlScalarType::String.nullable(false))
5018        .with_column("name", SqlScalarType::String.nullable(false))
5019        .with_column("type", SqlScalarType::String.nullable(false))
5020        .with_column("comment", SqlScalarType::String.nullable(false))
5021        .finish(),
5022    column_comments: BTreeMap::new(),
5023    sql: "WITH comments AS (
5024        SELECT id, comment
5025        FROM mz_internal.mz_comments
5026        WHERE object_type = 'connection' AND object_sub_id IS NULL
5027    )
5028    SELECT schema_id, name, type, COALESCE(comment, '') as comment
5029    FROM mz_catalog.mz_connections connections
5030    LEFT JOIN comments ON connections.id = comments.id",
5031    access: vec![PUBLIC_SELECT],
5032    ontology: None,
5033});
5034
5035pub static MZ_SHOW_SOURCES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
5036    name: "mz_show_sources",
5037    schema: MZ_INTERNAL_SCHEMA,
5038    oid: oid::VIEW_MZ_SHOW_SOURCES_OID,
5039    desc: RelationDesc::builder()
5040        .with_column("id", SqlScalarType::String.nullable(false))
5041        .with_column("name", SqlScalarType::String.nullable(false))
5042        .with_column("type", SqlScalarType::String.nullable(false))
5043        .with_column("cluster", SqlScalarType::String.nullable(true))
5044        .with_column("schema_id", SqlScalarType::String.nullable(false))
5045        .with_column("cluster_id", SqlScalarType::String.nullable(true))
5046        .with_column("comment", SqlScalarType::String.nullable(false))
5047        .finish(),
5048    column_comments: BTreeMap::new(),
5049    sql: "
5050WITH comments AS (
5051    SELECT id, comment
5052    FROM mz_internal.mz_comments
5053    WHERE object_type = 'source' AND object_sub_id IS NULL
5054)
5055SELECT
5056    sources.id,
5057    sources.name,
5058    sources.type,
5059    clusters.name AS cluster,
5060    schema_id,
5061    cluster_id,
5062    COALESCE(comments.comment, '') as comment
5063FROM
5064    mz_catalog.mz_sources AS sources
5065        LEFT JOIN
5066            mz_catalog.mz_clusters AS clusters
5067            ON clusters.id = sources.cluster_id
5068        LEFT JOIN comments ON sources.id = comments.id",
5069    access: vec![PUBLIC_SELECT],
5070    ontology: None,
5071});
5072
5073pub static MZ_SHOW_SINKS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
5074    name: "mz_show_sinks",
5075    schema: MZ_INTERNAL_SCHEMA,
5076    oid: oid::VIEW_MZ_SHOW_SINKS_OID,
5077    desc: RelationDesc::builder()
5078        .with_column("id", SqlScalarType::String.nullable(false))
5079        .with_column("name", SqlScalarType::String.nullable(false))
5080        .with_column("type", SqlScalarType::String.nullable(false))
5081        .with_column("cluster", SqlScalarType::String.nullable(false))
5082        .with_column("schema_id", SqlScalarType::String.nullable(false))
5083        .with_column("cluster_id", SqlScalarType::String.nullable(false))
5084        .with_column("comment", SqlScalarType::String.nullable(false))
5085        .finish(),
5086    column_comments: BTreeMap::new(),
5087    sql: "
5088WITH comments AS (
5089    SELECT id, comment
5090    FROM mz_internal.mz_comments
5091    WHERE object_type = 'sink' AND object_sub_id IS NULL
5092)
5093SELECT
5094    sinks.id,
5095    sinks.name,
5096    sinks.type,
5097    clusters.name AS cluster,
5098    schema_id,
5099    cluster_id,
5100    COALESCE(comments.comment, '') as comment
5101FROM
5102    mz_catalog.mz_sinks AS sinks
5103    JOIN
5104        mz_catalog.mz_clusters AS clusters
5105        ON clusters.id = sinks.cluster_id
5106    LEFT JOIN comments ON sinks.id = comments.id",
5107    access: vec![PUBLIC_SELECT],
5108    ontology: None,
5109});
5110
5111pub static MZ_SHOW_MATERIALIZED_VIEWS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
5112    name: "mz_show_materialized_views",
5113    schema: MZ_INTERNAL_SCHEMA,
5114    oid: oid::VIEW_MZ_SHOW_MATERIALIZED_VIEWS_OID,
5115    desc: RelationDesc::builder()
5116        .with_column("id", SqlScalarType::String.nullable(false))
5117        .with_column("name", SqlScalarType::String.nullable(false))
5118        .with_column("cluster", SqlScalarType::String.nullable(false))
5119        .with_column("schema_id", SqlScalarType::String.nullable(false))
5120        .with_column("cluster_id", SqlScalarType::String.nullable(false))
5121        .with_column("comment", SqlScalarType::String.nullable(false))
5122        .finish(),
5123    column_comments: BTreeMap::new(),
5124    sql: "
5125WITH
5126    comments AS (
5127        SELECT id, comment
5128        FROM mz_internal.mz_comments
5129        WHERE object_type = 'materialized-view' AND object_sub_id IS NULL
5130    )
5131SELECT
5132    mviews.id as id,
5133    mviews.name,
5134    clusters.name AS cluster,
5135    schema_id,
5136    cluster_id,
5137    COALESCE(comments.comment, '') as comment
5138FROM
5139    mz_catalog.mz_materialized_views AS mviews
5140    JOIN mz_catalog.mz_clusters AS clusters ON clusters.id = mviews.cluster_id
5141    LEFT JOIN comments ON mviews.id = comments.id",
5142    access: vec![PUBLIC_SELECT],
5143    ontology: None,
5144});
5145
5146pub static MZ_SHOW_INDEXES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
5147    name: "mz_show_indexes",
5148    schema: MZ_INTERNAL_SCHEMA,
5149    oid: oid::VIEW_MZ_SHOW_INDEXES_OID,
5150    desc: RelationDesc::builder()
5151        .with_column("id", SqlScalarType::String.nullable(false))
5152        .with_column("name", SqlScalarType::String.nullable(false))
5153        .with_column("on", SqlScalarType::String.nullable(false))
5154        .with_column("cluster", SqlScalarType::String.nullable(false))
5155        .with_column(
5156            "key",
5157            SqlScalarType::Array(Box::new(SqlScalarType::String)).nullable(false),
5158        )
5159        .with_column("on_id", SqlScalarType::String.nullable(false))
5160        .with_column("schema_id", SqlScalarType::String.nullable(false))
5161        .with_column("cluster_id", SqlScalarType::String.nullable(false))
5162        .with_column("comment", SqlScalarType::String.nullable(false))
5163        .finish(),
5164    column_comments: BTreeMap::new(),
5165    sql: "
5166WITH comments AS (
5167    SELECT id, comment
5168    FROM mz_internal.mz_comments
5169    WHERE object_type = 'index' AND object_sub_id IS NULL
5170)
5171SELECT
5172    idxs.id AS id,
5173    idxs.name AS name,
5174    objs.name AS on,
5175    clusters.name AS cluster,
5176    COALESCE(keys.key, '{}'::_text) AS key,
5177    idxs.on_id AS on_id,
5178    objs.schema_id AS schema_id,
5179    clusters.id AS cluster_id,
5180    COALESCE(comments.comment, '') as comment
5181FROM
5182    mz_catalog.mz_indexes AS idxs
5183    JOIN mz_catalog.mz_objects AS objs ON idxs.on_id = objs.id
5184    JOIN mz_catalog.mz_clusters AS clusters ON clusters.id = idxs.cluster_id
5185    LEFT JOIN
5186        (SELECT
5187            idxs.id,
5188            ARRAY_AGG(
5189                CASE
5190                    WHEN idx_cols.on_expression IS NULL THEN obj_cols.name
5191                    ELSE idx_cols.on_expression
5192                END
5193                ORDER BY idx_cols.index_position ASC
5194            ) AS key
5195        FROM
5196            mz_catalog.mz_indexes AS idxs
5197            JOIN mz_catalog.mz_index_columns idx_cols ON idxs.id = idx_cols.index_id
5198            LEFT JOIN mz_catalog.mz_columns obj_cols ON
5199                idxs.on_id = obj_cols.id AND idx_cols.on_position = obj_cols.position
5200        GROUP BY idxs.id) AS keys
5201    ON idxs.id = keys.id
5202    LEFT JOIN comments ON idxs.id = comments.id",
5203    access: vec![PUBLIC_SELECT],
5204    ontology: None,
5205});
5206
5207pub static MZ_SHOW_CLUSTER_REPLICAS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
5208    name: "mz_show_cluster_replicas",
5209    schema: MZ_INTERNAL_SCHEMA,
5210    oid: oid::VIEW_MZ_SHOW_CLUSTER_REPLICAS_OID,
5211    desc: RelationDesc::builder()
5212        .with_column("cluster", SqlScalarType::String.nullable(false))
5213        .with_column("replica", SqlScalarType::String.nullable(false))
5214        .with_column("replica_id", SqlScalarType::String.nullable(false))
5215        .with_column("size", SqlScalarType::String.nullable(true))
5216        .with_column("ready", SqlScalarType::Bool.nullable(false))
5217        .with_column("comment", SqlScalarType::String.nullable(false))
5218        .finish(),
5219    column_comments: BTreeMap::new(),
5220    sql: r#"SELECT
5221    mz_catalog.mz_clusters.name AS cluster,
5222    mz_catalog.mz_cluster_replicas.name AS replica,
5223    mz_catalog.mz_cluster_replicas.id as replica_id,
5224    mz_catalog.mz_cluster_replicas.size AS size,
5225    coalesce(statuses.ready, FALSE) AS ready,
5226    coalesce(comments.comment, '') as comment
5227FROM
5228    mz_catalog.mz_cluster_replicas
5229        JOIN mz_catalog.mz_clusters
5230            ON mz_catalog.mz_cluster_replicas.cluster_id = mz_catalog.mz_clusters.id
5231        LEFT JOIN
5232            (
5233                SELECT
5234                    replica_id,
5235                    bool_and(hydrated) AS ready
5236                FROM mz_internal.mz_hydration_statuses
5237                WHERE replica_id is not null
5238                GROUP BY replica_id
5239            ) AS statuses
5240            ON mz_catalog.mz_cluster_replicas.id = statuses.replica_id
5241        LEFT JOIN mz_internal.mz_comments comments
5242            ON mz_catalog.mz_cluster_replicas.id = comments.id
5243WHERE (comments.object_type = 'cluster-replica' OR comments.object_type IS NULL)
5244ORDER BY 1, 2"#,
5245    access: vec![PUBLIC_SELECT],
5246    ontology: None,
5247});
5248
5249/// Lightweight data product discovery for MCP (Model Context Protocol).
5250///
5251/// Lists materialized views and indexed views that the current user has
5252/// SELECT privileges on. Non-indexed regular views are excluded because
5253/// querying them would trigger a full recompute. Comments are optional
5254/// enrichment.
5255/// Used by the `get_data_products` and `read_data_product` MCP tools.
5256/// Does not include schema details: use `mz_mcp_data_product_details` for that.
5257pub static MZ_MCP_DATA_PRODUCTS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
5258    name: "mz_mcp_data_products",
5259    schema: MZ_INTERNAL_SCHEMA,
5260    oid: oid::VIEW_MZ_MCP_DATA_PRODUCTS_OID,
5261    desc: RelationDesc::builder()
5262        .with_column("object_name", SqlScalarType::String.nullable(false))
5263        .with_column("cluster", SqlScalarType::String.nullable(true))
5264        .with_column("description", SqlScalarType::String.nullable(true))
5265        .with_key(vec![0, 1, 2])
5266        .finish(),
5267    column_comments: BTreeMap::from_iter([
5268        (
5269            "object_name",
5270            "Fully qualified object name (database.schema.name).",
5271        ),
5272        (
5273            "cluster",
5274            "Cluster where the object computes or its index is hosted. The object can be read from any cluster.",
5275        ),
5276        (
5277            "description",
5278            "Index comment if available, otherwise object comment. Used as data product description.",
5279        ),
5280    ]),
5281    sql: r#"
5282SELECT DISTINCT
5283    '"' || op.database || '"."' || op.schema || '"."' || op.name || '"' AS object_name,
5284    COALESCE(c_idx.name, c_obj.name) AS cluster,
5285    COALESCE(cts_idx.comment, cts_obj.comment) AS description
5286FROM mz_internal.mz_show_my_object_privileges op
5287JOIN mz_objects o ON op.name = o.name AND op.object_type = o.type
5288JOIN mz_schemas s ON s.name = op.schema AND s.id = o.schema_id
5289JOIN mz_databases d ON d.name = op.database AND d.id = s.database_id
5290LEFT JOIN mz_indexes i ON i.on_id = o.id
5291LEFT JOIN mz_clusters c_idx ON c_idx.id = i.cluster_id
5292LEFT JOIN mz_clusters c_obj ON c_obj.id = o.cluster_id
5293LEFT JOIN mz_internal.mz_comments cts_idx ON cts_idx.id = i.id AND cts_idx.object_sub_id IS NULL
5294LEFT JOIN mz_internal.mz_comments cts_obj ON cts_obj.id = o.id AND cts_obj.object_sub_id IS NULL
5295WHERE op.privilege_type = 'SELECT'
5296  AND (o.type = 'materialized-view' OR (o.type = 'view' AND i.id IS NOT NULL))
5297  AND s.name NOT IN ('mz_catalog', 'mz_internal', 'pg_catalog', 'information_schema', 'mz_introspection')
5298"#,
5299    access: vec![PUBLIC_SELECT],
5300    ontology: None,
5301});
5302
5303/// Full data product details with JSON Schema for MCP agents.
5304///
5305/// Extends `mz_mcp_data_products` with column types, index keys (when
5306/// available), and column comments, formatted as a JSON Schema object.
5307/// Used by the `get_data_product_details` MCP tool. Lists materialized
5308/// views and indexed views; non-indexed regular views are excluded to
5309/// avoid triggering full recompute on query. Comments are optional
5310/// enrichment.
5311pub static MZ_MCP_DATA_PRODUCT_DETAILS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
5312    name: "mz_mcp_data_product_details",
5313    schema: MZ_INTERNAL_SCHEMA,
5314    oid: oid::VIEW_MZ_MCP_DATA_PRODUCT_DETAILS_OID,
5315    desc: RelationDesc::builder()
5316        .with_column("object_name", SqlScalarType::String.nullable(false))
5317        .with_column("cluster", SqlScalarType::String.nullable(true))
5318        .with_column("description", SqlScalarType::String.nullable(true))
5319        .with_column("schema", SqlScalarType::Jsonb.nullable(false))
5320        .with_key(vec![0, 1, 2])
5321        .finish(),
5322    column_comments: BTreeMap::from_iter([
5323        (
5324            "object_name",
5325            "Fully qualified object name (database.schema.name).",
5326        ),
5327        (
5328            "cluster",
5329            "Cluster where the object computes or its index is hosted. The object can be read from any cluster.",
5330        ),
5331        (
5332            "description",
5333            "Index comment if available, otherwise object comment. Used as data product description.",
5334        ),
5335        (
5336            "schema",
5337            "JSON Schema describing the object's columns and types.",
5338        ),
5339    ]),
5340    sql: r#"
5341SELECT * FROM (
5342    SELECT
5343        '"' || op.database || '"."' || op.schema || '"."' || op.name || '"' AS object_name,
5344        COALESCE(c_idx.name, c_obj.name) AS cluster,
5345        COALESCE(cts_idx.comment, cts_obj.comment) AS description,
5346        COALESCE(jsonb_build_object(
5347        'type', 'object',
5348        'required', jsonb_agg(distinct ccol.name) FILTER (WHERE ccol.position = ic.on_position),
5349        'properties', jsonb_strip_nulls(jsonb_object_agg(
5350            ccol.name,
5351            CASE
5352                WHEN ccol.type IN (
5353                    'uint2', 'uint4','uint8', 'int', 'integer', 'smallint',
5354                    'double', 'double precision', 'bigint', 'float',
5355                    'numeric', 'real'
5356                ) THEN jsonb_build_object(
5357                    'type', 'number',
5358                    'description', cts_col.comment
5359                )
5360                WHEN ccol.type = 'boolean' THEN jsonb_build_object(
5361                    'type', 'boolean',
5362                    'description', cts_col.comment
5363                )
5364                WHEN ccol.type = 'bytea' THEN jsonb_build_object(
5365                    'type', 'string',
5366                    'description', cts_col.comment,
5367                    'contentEncoding', 'base64',
5368                    'contentMediaType', 'application/octet-stream'
5369                )
5370                WHEN ccol.type = 'date' THEN jsonb_build_object(
5371                    'type', 'string',
5372                    'format', 'date',
5373                    'description', cts_col.comment
5374                )
5375                WHEN ccol.type = 'time' THEN jsonb_build_object(
5376                    'type', 'string',
5377                    'format', 'time',
5378                    'description', cts_col.comment
5379                )
5380                WHEN ccol.type ilike 'timestamp%%' THEN jsonb_build_object(
5381                    'type', 'string',
5382                    'format', 'date-time',
5383                    'description', cts_col.comment
5384                )
5385                WHEN ccol.type = 'jsonb' THEN jsonb_build_object(
5386                    'type', 'object',
5387                    'description', cts_col.comment
5388                )
5389                WHEN ccol.type = 'uuid' THEN jsonb_build_object(
5390                    'type', 'string',
5391                    'format', 'uuid',
5392                    'description', cts_col.comment
5393                )
5394                ELSE jsonb_build_object(
5395                    'type', 'string',
5396                    'description', cts_col.comment
5397                )
5398            END
5399        ))
5400    ), '{"type": "object", "properties": {}}'::jsonb) AS schema
5401FROM mz_internal.mz_show_my_object_privileges op
5402JOIN mz_objects o ON op.name = o.name AND op.object_type = o.type
5403JOIN mz_schemas s ON s.name = op.schema AND s.id = o.schema_id
5404JOIN mz_databases d ON d.name = op.database AND d.id = s.database_id
5405JOIN mz_columns ccol ON ccol.id = o.id
5406LEFT JOIN mz_indexes i ON i.on_id = o.id
5407LEFT JOIN mz_index_columns ic ON i.id = ic.index_id
5408LEFT JOIN mz_clusters c_idx ON c_idx.id = i.cluster_id
5409LEFT JOIN mz_clusters c_obj ON c_obj.id = o.cluster_id
5410LEFT JOIN mz_internal.mz_comments cts_idx ON cts_idx.id = i.id AND cts_idx.object_sub_id IS NULL
5411LEFT JOIN mz_internal.mz_comments cts_obj ON cts_obj.id = o.id AND cts_obj.object_sub_id IS NULL
5412LEFT JOIN mz_internal.mz_comments cts_col ON cts_col.id = o.id AND cts_col.object_sub_id = ccol.position
5413WHERE op.privilege_type = 'SELECT'
5414  AND (o.type = 'materialized-view' OR (o.type = 'view' AND i.id IS NOT NULL))
5415  AND s.name NOT IN ('mz_catalog', 'mz_internal', 'pg_catalog', 'information_schema', 'mz_introspection')
5416GROUP BY 1, 2, 3
5417)
5418"#,
5419    access: vec![PUBLIC_SELECT],
5420    ontology: None,
5421});
5422
5423pub static MZ_SHOW_ROLE_MEMBERS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
5424    name: "mz_show_role_members",
5425    schema: MZ_INTERNAL_SCHEMA,
5426    oid: oid::VIEW_MZ_SHOW_ROLE_MEMBERS_OID,
5427    desc: RelationDesc::builder()
5428        .with_column("role", SqlScalarType::String.nullable(false))
5429        .with_column("member", SqlScalarType::String.nullable(false))
5430        .with_column("grantor", SqlScalarType::String.nullable(false))
5431        .finish(),
5432    column_comments: BTreeMap::from_iter([
5433        ("role", "The role that `member` is a member of."),
5434        ("member", "The role that is a member of `role`."),
5435        (
5436            "grantor",
5437            "The role that granted membership of `member` to `role`.",
5438        ),
5439    ]),
5440    sql: r#"SELECT
5441    r1.name AS role,
5442    r2.name AS member,
5443    r3.name AS grantor
5444FROM mz_catalog.mz_role_members rm
5445JOIN mz_catalog.mz_roles r1 ON r1.id = rm.role_id
5446JOIN mz_catalog.mz_roles r2 ON r2.id = rm.member
5447JOIN mz_catalog.mz_roles r3 ON r3.id = rm.grantor
5448ORDER BY role"#,
5449    access: vec![PUBLIC_SELECT],
5450    ontology: None,
5451});
5452
5453pub static MZ_SHOW_MY_ROLE_MEMBERS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
5454    name: "mz_show_my_role_members",
5455    schema: MZ_INTERNAL_SCHEMA,
5456    oid: oid::VIEW_MZ_SHOW_MY_ROLE_MEMBERS_OID,
5457    desc: RelationDesc::builder()
5458        .with_column("role", SqlScalarType::String.nullable(false))
5459        .with_column("member", SqlScalarType::String.nullable(false))
5460        .with_column("grantor", SqlScalarType::String.nullable(false))
5461        .finish(),
5462    column_comments: BTreeMap::from_iter([
5463        ("role", "The role that `member` is a member of."),
5464        ("member", "The role that is a member of `role`."),
5465        (
5466            "grantor",
5467            "The role that granted membership of `member` to `role`.",
5468        ),
5469    ]),
5470    sql: r#"SELECT role, member, grantor
5471FROM mz_internal.mz_show_role_members
5472WHERE pg_has_role(member, 'USAGE')"#,
5473    access: vec![PUBLIC_SELECT],
5474    ontology: None,
5475});
5476
5477pub static MZ_SHOW_SYSTEM_PRIVILEGES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
5478    name: "mz_show_system_privileges",
5479    schema: MZ_INTERNAL_SCHEMA,
5480    oid: oid::VIEW_MZ_SHOW_SYSTEM_PRIVILEGES_OID,
5481    desc: RelationDesc::builder()
5482        .with_column("grantor", SqlScalarType::String.nullable(true))
5483        .with_column("grantee", SqlScalarType::String.nullable(true))
5484        .with_column("privilege_type", SqlScalarType::String.nullable(false))
5485        .finish(),
5486    column_comments: BTreeMap::from_iter([
5487        ("grantor", "The role that granted the privilege."),
5488        ("grantee", "The role that the privilege was granted to."),
5489        ("privilege_type", "They type of privilege granted."),
5490    ]),
5491    sql: r#"SELECT
5492    grantor.name AS grantor,
5493    CASE privileges.grantee
5494        WHEN 'p' THEN 'PUBLIC'
5495        ELSE grantee.name
5496    END AS grantee,
5497    privileges.privilege_type AS privilege_type
5498FROM
5499    (SELECT mz_internal.mz_aclexplode(ARRAY[privileges]).*
5500    FROM mz_catalog.mz_system_privileges) AS privileges
5501LEFT JOIN mz_catalog.mz_roles grantor ON privileges.grantor = grantor.id
5502LEFT JOIN mz_catalog.mz_roles grantee ON privileges.grantee = grantee.id
5503WHERE privileges.grantee NOT LIKE 's%'"#,
5504    access: vec![PUBLIC_SELECT],
5505    ontology: None,
5506});
5507
5508pub static MZ_SHOW_MY_SYSTEM_PRIVILEGES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
5509    name: "mz_show_my_system_privileges",
5510    schema: MZ_INTERNAL_SCHEMA,
5511    oid: oid::VIEW_MZ_SHOW_MY_SYSTEM_PRIVILEGES_OID,
5512    desc: RelationDesc::builder()
5513        .with_column("grantor", SqlScalarType::String.nullable(true))
5514        .with_column("grantee", SqlScalarType::String.nullable(true))
5515        .with_column("privilege_type", SqlScalarType::String.nullable(false))
5516        .finish(),
5517    column_comments: BTreeMap::from_iter([
5518        ("grantor", "The role that granted the privilege."),
5519        ("grantee", "The role that the privilege was granted to."),
5520        ("privilege_type", "They type of privilege granted."),
5521    ]),
5522    sql: r#"SELECT grantor, grantee, privilege_type
5523FROM mz_internal.mz_show_system_privileges
5524WHERE
5525    CASE
5526        WHEN grantee = 'PUBLIC' THEN true
5527        ELSE pg_has_role(grantee, 'USAGE')
5528    END"#,
5529    access: vec![PUBLIC_SELECT],
5530    ontology: None,
5531});
5532
5533pub static MZ_SHOW_CLUSTER_PRIVILEGES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
5534    name: "mz_show_cluster_privileges",
5535    schema: MZ_INTERNAL_SCHEMA,
5536    oid: oid::VIEW_MZ_SHOW_CLUSTER_PRIVILEGES_OID,
5537    desc: RelationDesc::builder()
5538        .with_column("grantor", SqlScalarType::String.nullable(true))
5539        .with_column("grantee", SqlScalarType::String.nullable(true))
5540        .with_column("name", SqlScalarType::String.nullable(false))
5541        .with_column("privilege_type", SqlScalarType::String.nullable(false))
5542        .finish(),
5543    column_comments: BTreeMap::from_iter([
5544        ("grantor", "The role that granted the privilege."),
5545        ("grantee", "The role that the privilege was granted to."),
5546        ("name", "The name of the cluster."),
5547        ("privilege_type", "They type of privilege granted."),
5548    ]),
5549    sql: r#"SELECT
5550    grantor.name AS grantor,
5551    CASE privileges.grantee
5552        WHEN 'p' THEN 'PUBLIC'
5553        ELSE grantee.name
5554    END AS grantee,
5555    privileges.name AS name,
5556    privileges.privilege_type AS privilege_type
5557FROM
5558    (SELECT mz_internal.mz_aclexplode(privileges).*, name
5559    FROM mz_catalog.mz_clusters
5560    WHERE id NOT LIKE 's%') AS privileges
5561LEFT JOIN mz_catalog.mz_roles grantor ON privileges.grantor = grantor.id
5562LEFT JOIN mz_catalog.mz_roles grantee ON privileges.grantee = grantee.id
5563WHERE privileges.grantee NOT LIKE 's%'"#,
5564    access: vec![PUBLIC_SELECT],
5565    ontology: None,
5566});
5567
5568pub static MZ_SHOW_MY_CLUSTER_PRIVILEGES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
5569    name: "mz_show_my_cluster_privileges",
5570    schema: MZ_INTERNAL_SCHEMA,
5571    oid: oid::VIEW_MZ_SHOW_MY_CLUSTER_PRIVILEGES_OID,
5572    desc: RelationDesc::builder()
5573        .with_column("grantor", SqlScalarType::String.nullable(true))
5574        .with_column("grantee", SqlScalarType::String.nullable(true))
5575        .with_column("name", SqlScalarType::String.nullable(false))
5576        .with_column("privilege_type", SqlScalarType::String.nullable(false))
5577        .finish(),
5578    column_comments: BTreeMap::from_iter([
5579        ("grantor", "The role that granted the privilege."),
5580        ("grantee", "The role that the privilege was granted to."),
5581        ("name", "The name of the cluster."),
5582        ("privilege_type", "They type of privilege granted."),
5583    ]),
5584    sql: r#"SELECT grantor, grantee, name, privilege_type
5585FROM mz_internal.mz_show_cluster_privileges
5586WHERE
5587    CASE
5588        WHEN grantee = 'PUBLIC' THEN true
5589        ELSE pg_has_role(grantee, 'USAGE')
5590    END"#,
5591    access: vec![PUBLIC_SELECT],
5592    ontology: None,
5593});
5594
5595pub static MZ_SHOW_DATABASE_PRIVILEGES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
5596    name: "mz_show_database_privileges",
5597    schema: MZ_INTERNAL_SCHEMA,
5598    oid: oid::VIEW_MZ_SHOW_DATABASE_PRIVILEGES_OID,
5599    desc: RelationDesc::builder()
5600        .with_column("grantor", SqlScalarType::String.nullable(true))
5601        .with_column("grantee", SqlScalarType::String.nullable(true))
5602        .with_column("name", SqlScalarType::String.nullable(false))
5603        .with_column("privilege_type", SqlScalarType::String.nullable(false))
5604        .finish(),
5605    column_comments: BTreeMap::from_iter([
5606        ("grantor", "The role that granted the privilege."),
5607        ("grantee", "The role that the privilege was granted to."),
5608        ("name", "The name of the database."),
5609        ("privilege_type", "They type of privilege granted."),
5610    ]),
5611    sql: r#"SELECT
5612    grantor.name AS grantor,
5613    CASE privileges.grantee
5614        WHEN 'p' THEN 'PUBLIC'
5615        ELSE grantee.name
5616    END AS grantee,
5617    privileges.name AS name,
5618    privileges.privilege_type AS privilege_type
5619FROM
5620    (SELECT mz_internal.mz_aclexplode(privileges).*, name
5621    FROM mz_catalog.mz_databases
5622    WHERE id NOT LIKE 's%') AS privileges
5623LEFT JOIN mz_catalog.mz_roles grantor ON privileges.grantor = grantor.id
5624LEFT JOIN mz_catalog.mz_roles grantee ON privileges.grantee = grantee.id
5625WHERE privileges.grantee NOT LIKE 's%'"#,
5626    access: vec![PUBLIC_SELECT],
5627    ontology: None,
5628});
5629
5630pub static MZ_SHOW_MY_DATABASE_PRIVILEGES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
5631    name: "mz_show_my_database_privileges",
5632    schema: MZ_INTERNAL_SCHEMA,
5633    oid: oid::VIEW_MZ_SHOW_MY_DATABASE_PRIVILEGES_OID,
5634    desc: RelationDesc::builder()
5635        .with_column("grantor", SqlScalarType::String.nullable(true))
5636        .with_column("grantee", SqlScalarType::String.nullable(true))
5637        .with_column("name", SqlScalarType::String.nullable(false))
5638        .with_column("privilege_type", SqlScalarType::String.nullable(false))
5639        .finish(),
5640    column_comments: BTreeMap::from_iter([
5641        ("grantor", "The role that granted the privilege."),
5642        ("grantee", "The role that the privilege was granted to."),
5643        ("name", "The name of the cluster."),
5644        ("privilege_type", "They type of privilege granted."),
5645    ]),
5646    sql: r#"SELECT grantor, grantee, name, privilege_type
5647FROM mz_internal.mz_show_database_privileges
5648WHERE
5649    CASE
5650        WHEN grantee = 'PUBLIC' THEN true
5651        ELSE pg_has_role(grantee, 'USAGE')
5652    END"#,
5653    access: vec![PUBLIC_SELECT],
5654    ontology: None,
5655});
5656
5657pub static MZ_SHOW_SCHEMA_PRIVILEGES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
5658    name: "mz_show_schema_privileges",
5659    schema: MZ_INTERNAL_SCHEMA,
5660    oid: oid::VIEW_MZ_SHOW_SCHEMA_PRIVILEGES_OID,
5661    desc: RelationDesc::builder()
5662        .with_column("grantor", SqlScalarType::String.nullable(true))
5663        .with_column("grantee", SqlScalarType::String.nullable(true))
5664        .with_column("database", SqlScalarType::String.nullable(true))
5665        .with_column("name", SqlScalarType::String.nullable(false))
5666        .with_column("privilege_type", SqlScalarType::String.nullable(false))
5667        .finish(),
5668    column_comments: BTreeMap::from_iter([
5669        ("grantor", "The role that granted the privilege."),
5670        ("grantee", "The role that the privilege was granted to."),
5671        (
5672            "database",
5673            "The name of the database containing the schema.",
5674        ),
5675        ("name", "The name of the schema."),
5676        ("privilege_type", "They type of privilege granted."),
5677    ]),
5678    sql: r#"SELECT
5679    grantor.name AS grantor,
5680    CASE privileges.grantee
5681        WHEN 'p' THEN 'PUBLIC'
5682        ELSE grantee.name
5683    END AS grantee,
5684    databases.name AS database,
5685    privileges.name AS name,
5686    privileges.privilege_type AS privilege_type
5687FROM
5688    (SELECT mz_internal.mz_aclexplode(privileges).*, database_id, name
5689    FROM mz_catalog.mz_schemas
5690    WHERE id NOT LIKE 's%') AS privileges
5691LEFT JOIN mz_catalog.mz_roles grantor ON privileges.grantor = grantor.id
5692LEFT JOIN mz_catalog.mz_roles grantee ON privileges.grantee = grantee.id
5693LEFT JOIN mz_catalog.mz_databases databases ON privileges.database_id = databases.id
5694WHERE privileges.grantee NOT LIKE 's%'"#,
5695    access: vec![PUBLIC_SELECT],
5696    ontology: None,
5697});
5698
5699pub static MZ_SHOW_MY_SCHEMA_PRIVILEGES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
5700    name: "mz_show_my_schema_privileges",
5701    schema: MZ_INTERNAL_SCHEMA,
5702    oid: oid::VIEW_MZ_SHOW_MY_SCHEMA_PRIVILEGES_OID,
5703    desc: RelationDesc::builder()
5704        .with_column("grantor", SqlScalarType::String.nullable(true))
5705        .with_column("grantee", SqlScalarType::String.nullable(true))
5706        .with_column("database", SqlScalarType::String.nullable(true))
5707        .with_column("name", SqlScalarType::String.nullable(false))
5708        .with_column("privilege_type", SqlScalarType::String.nullable(false))
5709        .finish(),
5710    column_comments: BTreeMap::from_iter([
5711        ("grantor", "The role that granted the privilege."),
5712        ("grantee", "The role that the privilege was granted to."),
5713        (
5714            "database",
5715            "The name of the database containing the schema.",
5716        ),
5717        ("name", "The name of the schema."),
5718        ("privilege_type", "They type of privilege granted."),
5719    ]),
5720    sql: r#"SELECT grantor, grantee, database, name, privilege_type
5721FROM mz_internal.mz_show_schema_privileges
5722WHERE
5723    CASE
5724        WHEN grantee = 'PUBLIC' THEN true
5725        ELSE pg_has_role(grantee, 'USAGE')
5726    END"#,
5727    access: vec![PUBLIC_SELECT],
5728    ontology: None,
5729});
5730
5731pub static MZ_SHOW_OBJECT_PRIVILEGES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
5732    name: "mz_show_object_privileges",
5733    schema: MZ_INTERNAL_SCHEMA,
5734    oid: oid::VIEW_MZ_SHOW_OBJECT_PRIVILEGES_OID,
5735    desc: RelationDesc::builder()
5736        .with_column("grantor", SqlScalarType::String.nullable(true))
5737        .with_column("grantee", SqlScalarType::String.nullable(true))
5738        .with_column("database", SqlScalarType::String.nullable(true))
5739        .with_column("schema", SqlScalarType::String.nullable(true))
5740        .with_column("name", SqlScalarType::String.nullable(false))
5741        .with_column("object_type", SqlScalarType::String.nullable(false))
5742        .with_column("privilege_type", SqlScalarType::String.nullable(false))
5743        .finish(),
5744    column_comments: BTreeMap::from_iter([
5745        ("grantor", "The role that granted the privilege."),
5746        ("grantee", "The role that the privilege was granted to."),
5747        (
5748            "database",
5749            "The name of the database containing the object.",
5750        ),
5751        ("schema", "The name of the schema containing the object."),
5752        ("name", "The name of the object."),
5753        (
5754            "object_type",
5755            "The type of object the privilege is granted on.",
5756        ),
5757        ("privilege_type", "They type of privilege granted."),
5758    ]),
5759    sql: r#"SELECT
5760    grantor.name AS grantor,
5761    CASE privileges.grantee
5762            WHEN 'p' THEN 'PUBLIC'
5763            ELSE grantee.name
5764        END AS grantee,
5765    databases.name AS database,
5766    schemas.name AS schema,
5767    privileges.name AS name,
5768    privileges.type AS object_type,
5769    privileges.privilege_type AS privilege_type
5770FROM
5771    (SELECT mz_internal.mz_aclexplode(privileges).*, schema_id, name, type
5772    FROM mz_catalog.mz_objects
5773    WHERE id NOT LIKE 's%') AS privileges
5774LEFT JOIN mz_catalog.mz_roles grantor ON privileges.grantor = grantor.id
5775LEFT JOIN mz_catalog.mz_roles grantee ON privileges.grantee = grantee.id
5776LEFT JOIN mz_catalog.mz_schemas schemas ON privileges.schema_id = schemas.id
5777LEFT JOIN mz_catalog.mz_databases databases ON schemas.database_id = databases.id
5778WHERE privileges.grantee NOT LIKE 's%'"#,
5779    access: vec![PUBLIC_SELECT],
5780    ontology: None,
5781});
5782
5783pub static MZ_SHOW_MY_OBJECT_PRIVILEGES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
5784    name: "mz_show_my_object_privileges",
5785    schema: MZ_INTERNAL_SCHEMA,
5786    oid: oid::VIEW_MZ_SHOW_MY_OBJECT_PRIVILEGES_OID,
5787    desc: RelationDesc::builder()
5788        .with_column("grantor", SqlScalarType::String.nullable(true))
5789        .with_column("grantee", SqlScalarType::String.nullable(true))
5790        .with_column("database", SqlScalarType::String.nullable(true))
5791        .with_column("schema", SqlScalarType::String.nullable(true))
5792        .with_column("name", SqlScalarType::String.nullable(false))
5793        .with_column("object_type", SqlScalarType::String.nullable(false))
5794        .with_column("privilege_type", SqlScalarType::String.nullable(false))
5795        .finish(),
5796    column_comments: BTreeMap::from_iter([
5797        ("grantor", "The role that granted the privilege."),
5798        ("grantee", "The role that the privilege was granted to."),
5799        (
5800            "database",
5801            "The name of the database containing the object.",
5802        ),
5803        ("schema", "The name of the schema containing the object."),
5804        ("name", "The name of the object."),
5805        (
5806            "object_type",
5807            "The type of object the privilege is granted on.",
5808        ),
5809        ("privilege_type", "They type of privilege granted."),
5810    ]),
5811    sql: r#"SELECT grantor, grantee, database, schema, name, object_type, privilege_type
5812FROM mz_internal.mz_show_object_privileges
5813WHERE
5814    CASE
5815        WHEN grantee = 'PUBLIC' THEN true
5816        ELSE pg_has_role(grantee, 'USAGE')
5817    END"#,
5818    access: vec![PUBLIC_SELECT],
5819    ontology: None,
5820});
5821
5822pub static MZ_SHOW_ALL_PRIVILEGES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
5823    name: "mz_show_all_privileges",
5824    schema: MZ_INTERNAL_SCHEMA,
5825    oid: oid::VIEW_MZ_SHOW_ALL_PRIVILEGES_OID,
5826    desc: RelationDesc::builder()
5827        .with_column("grantor", SqlScalarType::String.nullable(true))
5828        .with_column("grantee", SqlScalarType::String.nullable(true))
5829        .with_column("database", SqlScalarType::String.nullable(true))
5830        .with_column("schema", SqlScalarType::String.nullable(true))
5831        .with_column("name", SqlScalarType::String.nullable(true))
5832        .with_column("object_type", SqlScalarType::String.nullable(false))
5833        .with_column("privilege_type", SqlScalarType::String.nullable(false))
5834        .finish(),
5835    column_comments: BTreeMap::from_iter([
5836        ("grantor", "The role that granted the privilege."),
5837        ("grantee", "The role that the privilege was granted to."),
5838        (
5839            "database",
5840            "The name of the database containing the object.",
5841        ),
5842        ("schema", "The name of the schema containing the object."),
5843        ("name", "The name of the privilege target."),
5844        (
5845            "object_type",
5846            "The type of object the privilege is granted on.",
5847        ),
5848        ("privilege_type", "They type of privilege granted."),
5849    ]),
5850    sql: r#"SELECT grantor, grantee, NULL AS database, NULL AS schema, NULL AS name, 'system' AS object_type, privilege_type
5851FROM mz_internal.mz_show_system_privileges
5852UNION ALL
5853SELECT grantor, grantee, NULL AS database, NULL AS schema, name, 'cluster' AS object_type, privilege_type
5854FROM mz_internal.mz_show_cluster_privileges
5855UNION ALL
5856SELECT grantor, grantee, NULL AS database, NULL AS schema, name, 'database' AS object_type, privilege_type
5857FROM mz_internal.mz_show_database_privileges
5858UNION ALL
5859SELECT grantor, grantee, database, NULL AS schema, name, 'schema' AS object_type, privilege_type
5860FROM mz_internal.mz_show_schema_privileges
5861UNION ALL
5862SELECT grantor, grantee, database, schema, name, object_type, privilege_type
5863FROM mz_internal.mz_show_object_privileges"#,
5864    access: vec![PUBLIC_SELECT],
5865    ontology: None,
5866});
5867
5868pub static MZ_SHOW_ALL_MY_PRIVILEGES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
5869    name: "mz_show_all_my_privileges",
5870    schema: MZ_INTERNAL_SCHEMA,
5871    oid: oid::VIEW_MZ_SHOW_ALL_MY_PRIVILEGES_OID,
5872    desc: RelationDesc::builder()
5873        .with_column("grantor", SqlScalarType::String.nullable(true))
5874        .with_column("grantee", SqlScalarType::String.nullable(true))
5875        .with_column("database", SqlScalarType::String.nullable(true))
5876        .with_column("schema", SqlScalarType::String.nullable(true))
5877        .with_column("name", SqlScalarType::String.nullable(true))
5878        .with_column("object_type", SqlScalarType::String.nullable(false))
5879        .with_column("privilege_type", SqlScalarType::String.nullable(false))
5880        .finish(),
5881    column_comments: BTreeMap::from_iter([
5882        ("grantor", "The role that granted the privilege."),
5883        ("grantee", "The role that the privilege was granted to."),
5884        (
5885            "database",
5886            "The name of the database containing the object.",
5887        ),
5888        ("schema", "The name of the schema containing the object."),
5889        ("name", "The name of the privilege target."),
5890        (
5891            "object_type",
5892            "The type of object the privilege is granted on.",
5893        ),
5894        ("privilege_type", "They type of privilege granted."),
5895    ]),
5896    sql: r#"SELECT grantor, grantee, database, schema, name, object_type, privilege_type
5897FROM mz_internal.mz_show_all_privileges
5898WHERE
5899    CASE
5900        WHEN grantee = 'PUBLIC' THEN true
5901        ELSE pg_has_role(grantee, 'USAGE')
5902    END"#,
5903    access: vec![PUBLIC_SELECT],
5904    ontology: None,
5905});
5906
5907pub static MZ_SHOW_DEFAULT_PRIVILEGES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
5908    name: "mz_show_default_privileges",
5909    schema: MZ_INTERNAL_SCHEMA,
5910    oid: oid::VIEW_MZ_SHOW_DEFAULT_PRIVILEGES_OID,
5911    desc: RelationDesc::builder()
5912        .with_column("object_owner", SqlScalarType::String.nullable(true))
5913        .with_column("database", SqlScalarType::String.nullable(true))
5914        .with_column("schema", SqlScalarType::String.nullable(true))
5915        .with_column("object_type", SqlScalarType::String.nullable(false))
5916        .with_column("grantee", SqlScalarType::String.nullable(true))
5917        .with_column("privilege_type", SqlScalarType::String.nullable(true))
5918        .finish(),
5919    column_comments: BTreeMap::from_iter([
5920        (
5921            "object_owner",
5922            "Privileges described in this row will be granted on objects created by `object_owner`.",
5923        ),
5924        (
5925            "database",
5926            "Privileges described in this row will be granted only on objects created in `database` if non-null.",
5927        ),
5928        (
5929            "schema",
5930            "Privileges described in this row will be granted only on objects created in `schema` if non-null.",
5931        ),
5932        (
5933            "object_type",
5934            "Privileges described in this row will be granted only on objects of type `object_type`.",
5935        ),
5936        (
5937            "grantee",
5938            "Privileges described in this row will be granted to `grantee`.",
5939        ),
5940        ("privilege_type", "They type of privilege to be granted."),
5941    ]),
5942    sql: r#"SELECT
5943    CASE defaults.role_id
5944        WHEN 'p' THEN 'PUBLIC'
5945        ELSE object_owner.name
5946    END AS object_owner,
5947    databases.name AS database,
5948    schemas.name AS schema,
5949    object_type,
5950    CASE defaults.grantee
5951        WHEN 'p' THEN 'PUBLIC'
5952        ELSE grantee.name
5953    END AS grantee,
5954    unnest(mz_internal.mz_format_privileges(defaults.privileges)) AS privilege_type
5955FROM mz_catalog.mz_default_privileges defaults
5956LEFT JOIN mz_catalog.mz_roles AS object_owner ON defaults.role_id = object_owner.id
5957LEFT JOIN mz_catalog.mz_roles AS grantee ON defaults.grantee = grantee.id
5958LEFT JOIN mz_catalog.mz_databases AS databases ON defaults.database_id = databases.id
5959LEFT JOIN mz_catalog.mz_schemas AS schemas ON defaults.schema_id = schemas.id
5960WHERE defaults.grantee NOT LIKE 's%'
5961    AND defaults.database_id IS NULL OR defaults.database_id NOT LIKE 's%'
5962    AND defaults.schema_id IS NULL OR defaults.schema_id NOT LIKE 's%'"#,
5963    access: vec![PUBLIC_SELECT],
5964    ontology: None,
5965});
5966
5967pub static MZ_SHOW_MY_DEFAULT_PRIVILEGES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
5968    name: "mz_show_my_default_privileges",
5969    schema: MZ_INTERNAL_SCHEMA,
5970    oid: oid::VIEW_MZ_SHOW_MY_DEFAULT_PRIVILEGES_OID,
5971    desc: RelationDesc::builder()
5972        .with_column("object_owner", SqlScalarType::String.nullable(true))
5973        .with_column("database", SqlScalarType::String.nullable(true))
5974        .with_column("schema", SqlScalarType::String.nullable(true))
5975        .with_column("object_type", SqlScalarType::String.nullable(false))
5976        .with_column("grantee", SqlScalarType::String.nullable(true))
5977        .with_column("privilege_type", SqlScalarType::String.nullable(true))
5978        .finish(),
5979    column_comments: BTreeMap::from_iter([
5980        (
5981            "object_owner",
5982            "Privileges described in this row will be granted on objects created by `object_owner`.",
5983        ),
5984        (
5985            "database",
5986            "Privileges described in this row will be granted only on objects created in `database` if non-null.",
5987        ),
5988        (
5989            "schema",
5990            "Privileges described in this row will be granted only on objects created in `schema` if non-null.",
5991        ),
5992        (
5993            "object_type",
5994            "Privileges described in this row will be granted only on objects of type `object_type`.",
5995        ),
5996        (
5997            "grantee",
5998            "Privileges described in this row will be granted to `grantee`.",
5999        ),
6000        ("privilege_type", "They type of privilege to be granted."),
6001    ]),
6002    sql: r#"SELECT object_owner, database, schema, object_type, grantee, privilege_type
6003FROM mz_internal.mz_show_default_privileges
6004WHERE
6005    CASE
6006        WHEN grantee = 'PUBLIC' THEN true
6007        ELSE pg_has_role(grantee, 'USAGE')
6008    END"#,
6009    access: vec![PUBLIC_SELECT],
6010    ontology: None,
6011});
6012
6013pub static MZ_SHOW_NETWORK_POLICIES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
6014    name: "mz_show_network_policies",
6015    schema: MZ_INTERNAL_SCHEMA,
6016    oid: oid::VIEW_MZ_SHOW_NETWORK_POLICIES_OID,
6017    desc: RelationDesc::builder()
6018        .with_column("name", SqlScalarType::String.nullable(false))
6019        .with_column("rules", SqlScalarType::String.nullable(true))
6020        .with_column("comment", SqlScalarType::String.nullable(false))
6021        .finish(),
6022    column_comments: BTreeMap::new(),
6023    sql: "
6024WITH comments AS (
6025    SELECT id, comment
6026    FROM mz_internal.mz_comments
6027    WHERE object_type = 'network-policy' AND object_sub_id IS NULL
6028)
6029SELECT
6030    policy.name,
6031    pg_catalog.string_agg(rule.name,',' ORDER BY rule.name) as rules,
6032    COALESCE(comment, '') as comment
6033FROM
6034    mz_internal.mz_network_policies as policy
6035LEFT JOIN
6036    mz_internal.mz_network_policy_rules as rule ON policy.id = rule.policy_id
6037LEFT JOIN
6038    comments ON policy.id = comments.id
6039WHERE
6040    policy.id NOT LIKE 's%'
6041AND
6042    policy.id NOT LIKE 'g%'
6043GROUP BY policy.name, comments.comment;",
6044    access: vec![PUBLIC_SELECT],
6045    ontology: None,
6046});
6047
6048pub static MZ_CLUSTER_REPLICA_HISTORY: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
6049    name: "mz_cluster_replica_history",
6050    schema: MZ_INTERNAL_SCHEMA,
6051    oid: oid::VIEW_MZ_CLUSTER_REPLICA_HISTORY_OID,
6052    desc: RelationDesc::builder()
6053        .with_column("replica_id", SqlScalarType::String.nullable(true))
6054        .with_column("size", SqlScalarType::String.nullable(true))
6055        .with_column("cluster_id", SqlScalarType::String.nullable(true))
6056        .with_column("cluster_name", SqlScalarType::String.nullable(true))
6057        .with_column("replica_name", SqlScalarType::String.nullable(true))
6058        .with_column(
6059            "created_at",
6060            SqlScalarType::TimestampTz { precision: None }.nullable(false),
6061        )
6062        .with_column(
6063            "dropped_at",
6064            SqlScalarType::TimestampTz { precision: None }.nullable(true),
6065        )
6066        .with_column(
6067            "credits_per_hour",
6068            SqlScalarType::Numeric { max_scale: None }.nullable(true),
6069        )
6070        .finish(),
6071    column_comments: BTreeMap::from_iter([
6072        ("replica_id", "The ID of a cluster replica."),
6073        (
6074            "size",
6075            "The size of the cluster replica. Corresponds to `mz_cluster_replica_sizes.size`.",
6076        ),
6077        (
6078            "cluster_id",
6079            "The ID of the cluster associated with the replica.",
6080        ),
6081        (
6082            "cluster_name",
6083            "The name of the cluster associated with the replica.",
6084        ),
6085        ("replica_name", "The name of the replica."),
6086        ("created_at", "The time at which the replica was created."),
6087        (
6088            "dropped_at",
6089            "The time at which the replica was dropped, or `NULL` if it still exists.",
6090        ),
6091        (
6092            "credits_per_hour",
6093            "The number of compute credits consumed per hour. Corresponds to `mz_cluster_replica_sizes.credits_per_hour`.",
6094        ),
6095    ]),
6096    sql: r#"
6097        WITH
6098            creates AS
6099            (
6100                SELECT
6101                    details ->> 'logical_size' AS size,
6102                    details ->> 'replica_id' AS replica_id,
6103                    details ->> 'replica_name' AS replica_name,
6104                    details ->> 'cluster_name' AS cluster_name,
6105                    details ->> 'cluster_id' AS cluster_id,
6106                    occurred_at
6107                FROM mz_catalog.mz_audit_events
6108                WHERE
6109                    object_type = 'cluster-replica' AND event_type = 'create'
6110                        AND
6111                    details ->> 'replica_id' IS NOT NULL
6112                        AND
6113                    details ->> 'cluster_id' !~~ 's%'
6114            ),
6115            drops AS
6116            (
6117                SELECT details ->> 'replica_id' AS replica_id, occurred_at
6118                FROM mz_catalog.mz_audit_events
6119                WHERE object_type = 'cluster-replica' AND event_type = 'drop'
6120            )
6121        SELECT
6122            creates.replica_id,
6123            creates.size,
6124            creates.cluster_id,
6125            creates.cluster_name,
6126            creates.replica_name,
6127            creates.occurred_at AS created_at,
6128            drops.occurred_at AS dropped_at,
6129            mz_cluster_replica_sizes.credits_per_hour as credits_per_hour
6130        FROM
6131            creates
6132                LEFT JOIN drops ON creates.replica_id = drops.replica_id
6133                LEFT JOIN
6134                    mz_catalog.mz_cluster_replica_sizes
6135                    ON mz_cluster_replica_sizes.size = creates.size"#,
6136    access: vec![PUBLIC_SELECT],
6137    ontology: Some(Ontology {
6138        entity_name: "replica_history",
6139        description: "Historical record of replica creation/drops",
6140        links: &const { [] },
6141        column_semantic_types: &[],
6142    }),
6143});
6144
6145pub static MZ_CLUSTER_REPLICA_NAME_HISTORY: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
6146    name: "mz_cluster_replica_name_history",
6147    schema: MZ_INTERNAL_SCHEMA,
6148    oid: oid::VIEW_MZ_CLUSTER_REPLICA_NAME_HISTORY_OID,
6149    desc: RelationDesc::builder()
6150        .with_column(
6151            "occurred_at",
6152            SqlScalarType::TimestampTz { precision: None }.nullable(true),
6153        )
6154        .with_column("id", SqlScalarType::String.nullable(true))
6155        .with_column("previous_name", SqlScalarType::String.nullable(true))
6156        .with_column("new_name", SqlScalarType::String.nullable(true))
6157        .finish(),
6158    column_comments: BTreeMap::from_iter([
6159        (
6160            "occurred_at",
6161            "The time at which the cluster replica was created or renamed. `NULL` if it's a built in system cluster replica.",
6162        ),
6163        ("id", "The ID of the cluster replica."),
6164        (
6165            "previous_name",
6166            "The previous name of the cluster replica. `NULL` if there was no previous name.",
6167        ),
6168        ("new_name", "The new name of the cluster replica."),
6169    ]),
6170    sql: r#"WITH user_replica_alter_history AS (
6171  SELECT occurred_at,
6172    audit_events.details->>'replica_id' AS id,
6173    audit_events.details->>'old_name' AS previous_name,
6174    audit_events.details->>'new_name' AS new_name
6175  FROM mz_catalog.mz_audit_events AS audit_events
6176  WHERE object_type = 'cluster-replica'
6177    AND audit_events.event_type = 'alter'
6178    AND audit_events.details->>'replica_id' like 'u%'
6179),
6180user_replica_create_history AS (
6181  SELECT occurred_at,
6182    audit_events.details->>'replica_id' AS id,
6183    NULL AS previous_name,
6184    audit_events.details->>'replica_name' AS new_name
6185  FROM mz_catalog.mz_audit_events AS audit_events
6186  WHERE object_type = 'cluster-replica'
6187    AND audit_events.event_type = 'create'
6188    AND audit_events.details->>'replica_id' like 'u%'
6189),
6190-- Because built in system cluster replicas don't have audit events, we need to manually add them
6191system_replicas AS (
6192  -- We assume that the system cluster replicas were created at the beginning of time
6193  SELECT NULL::timestamptz AS occurred_at,
6194    id,
6195    NULL AS previous_name,
6196    name AS new_name
6197  FROM mz_catalog.mz_cluster_replicas
6198  WHERE id LIKE 's%'
6199)
6200SELECT *
6201FROM user_replica_alter_history
6202UNION ALL
6203SELECT *
6204FROM user_replica_create_history
6205UNION ALL
6206SELECT *
6207FROM system_replicas"#,
6208    access: vec![PUBLIC_SELECT],
6209    ontology: Some(Ontology {
6210        entity_name: "replica_name_history",
6211        description: "Historical replica names",
6212        links: &const { [] },
6213        column_semantic_types: &[("id", SemanticType::CatalogItemId)],
6214    }),
6215});
6216
6217pub static MZ_HYDRATION_STATUSES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
6218    name: "mz_hydration_statuses",
6219    schema: MZ_INTERNAL_SCHEMA,
6220    oid: oid::VIEW_MZ_HYDRATION_STATUSES_OID,
6221    desc: RelationDesc::builder()
6222        .with_column("object_id", SqlScalarType::String.nullable(false))
6223        .with_column("replica_id", SqlScalarType::String.nullable(true))
6224        .with_column("hydrated", SqlScalarType::Bool.nullable(true))
6225        .finish(),
6226    column_comments: BTreeMap::from_iter([
6227        (
6228            "object_id",
6229            "The ID of a dataflow-powered object. Corresponds to `mz_catalog.mz_indexes.id`, `mz_catalog.mz_materialized_views.id`, `mz_internal.mz_subscriptions`, `mz_catalog.mz_sources.id`, or `mz_catalog.mz_sinks.id`.",
6230        ),
6231        ("replica_id", "The ID of a cluster replica."),
6232        ("hydrated", "Whether the object is hydrated on the replica."),
6233    ]),
6234    sql: r#"WITH
6235-- Joining against the linearizable catalog tables ensures that this view
6236-- always contains the set of installed objects, even when it depends
6237-- on introspection relations that may received delayed updates.
6238--
6239-- Note that this view only includes objects that are maintained by dataflows.
6240-- In particular, some source types (webhook, introspection, ...) are not and
6241-- are therefore omitted.
6242indexes AS (
6243    SELECT
6244        i.id AS object_id,
6245        h.replica_id,
6246        COALESCE(h.hydrated, false) AS hydrated
6247    FROM mz_catalog.mz_indexes i
6248    LEFT JOIN mz_internal.mz_compute_hydration_statuses h
6249        ON (h.object_id = i.id)
6250),
6251materialized_views AS (
6252    SELECT
6253        i.id AS object_id,
6254        h.replica_id,
6255        COALESCE(h.hydrated, false) AS hydrated
6256    FROM mz_catalog.mz_materialized_views i
6257    LEFT JOIN mz_internal.mz_compute_hydration_statuses h
6258        ON (h.object_id = i.id)
6259),
6260-- Hydration is a dataflow concept and not all sources are maintained by
6261-- dataflows, so we need to find the ones that are. Generally, sources that
6262-- have a cluster ID are maintained by a dataflow running on that cluster.
6263-- Webhook sources are an exception to this rule.
6264sources_with_clusters AS (
6265    SELECT id, cluster_id
6266    FROM mz_catalog.mz_sources
6267    WHERE cluster_id IS NOT NULL AND type != 'webhook'
6268),
6269sources AS (
6270    SELECT
6271        s.id AS object_id,
6272        ss.replica_id AS replica_id,
6273        ss.rehydration_latency IS NOT NULL AS hydrated
6274    FROM sources_with_clusters s
6275    LEFT JOIN mz_internal.mz_source_statistics ss USING (id)
6276),
6277-- We don't yet report sink hydration status (database-issues#8331), so we do a best effort attempt here and
6278-- define a sink as hydrated when it's both "running" and has a frontier greater than the minimum.
6279-- There is likely still a possibility of FPs.
6280sinks AS (
6281    SELECT
6282        s.id AS object_id,
6283        r.id AS replica_id,
6284        ss.status = 'running' AND COALESCE(f.write_frontier, 0) > 0 AS hydrated
6285    FROM mz_catalog.mz_sinks s
6286    LEFT JOIN mz_internal.mz_sink_statuses ss USING (id)
6287    JOIN mz_catalog.mz_cluster_replicas r
6288        ON (r.cluster_id = s.cluster_id)
6289    LEFT JOIN mz_catalog.mz_cluster_replica_frontiers f
6290        ON (f.object_id = s.id AND f.replica_id = r.id)
6291)
6292SELECT * FROM indexes
6293UNION ALL
6294SELECT * FROM materialized_views
6295UNION ALL
6296SELECT * FROM sources
6297UNION ALL
6298SELECT * FROM sinks"#,
6299    access: vec![PUBLIC_SELECT],
6300    ontology: Some(Ontology {
6301        entity_name: "hydration_status",
6302        description: "Overall hydration status per object",
6303        links: &const {
6304            [
6305                OntologyLink {
6306                    name: "hydration_of",
6307                    target: "object",
6308                    properties: LinkProperties::fk_typed(
6309                        "object_id",
6310                        "id",
6311                        Cardinality::OneToOne,
6312                        mz_repr::SemanticType::CatalogItemId,
6313                    ),
6314                },
6315                OntologyLink {
6316                    name: "hydration_on_replica",
6317                    target: "replica",
6318                    properties: LinkProperties::fk("replica_id", "id", Cardinality::ManyToOne),
6319                },
6320            ]
6321        },
6322        column_semantic_types: &const {
6323            [
6324                ("object_id", SemanticType::CatalogItemId),
6325                ("replica_id", SemanticType::ReplicaId),
6326            ]
6327        },
6328    }),
6329});
6330
6331pub const MZ_HYDRATION_STATUSES_IND: BuiltinIndex = BuiltinIndex {
6332    name: "mz_hydration_statuses_ind",
6333    schema: MZ_INTERNAL_SCHEMA,
6334    oid: oid::INDEX_MZ_HYDRATION_STATUSES_IND_OID,
6335    sql: "IN CLUSTER mz_catalog_server
6336ON mz_internal.mz_hydration_statuses (object_id, replica_id)",
6337    is_retained_metrics_object: false,
6338};
6339
6340pub static MZ_MATERIALIZATION_DEPENDENCIES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
6341    name: "mz_materialization_dependencies",
6342    schema: MZ_INTERNAL_SCHEMA,
6343    oid: oid::VIEW_MZ_MATERIALIZATION_DEPENDENCIES_OID,
6344    desc: RelationDesc::builder()
6345        .with_column("object_id", SqlScalarType::String.nullable(false))
6346        .with_column("dependency_id", SqlScalarType::String.nullable(false))
6347        .finish(),
6348    column_comments: BTreeMap::from_iter([
6349        (
6350            "object_id",
6351            "The ID of a materialization. Corresponds to `mz_catalog.mz_indexes.id`, `mz_catalog.mz_materialized_views.id`, or `mz_catalog.mz_sinks.id`.",
6352        ),
6353        (
6354            "dependency_id",
6355            "The ID of a dataflow dependency. Corresponds to `mz_catalog.mz_indexes.id`, `mz_catalog.mz_materialized_views.id`, `mz_catalog.mz_sources.id`, or `mz_catalog.mz_tables.id`.",
6356        ),
6357    ]),
6358    sql: "
6359SELECT object_id, dependency_id
6360FROM mz_internal.mz_compute_dependencies
6361UNION ALL
6362SELECT s.id, d.referenced_object_id AS dependency_id
6363FROM mz_internal.mz_object_dependencies d
6364JOIN mz_catalog.mz_sinks s ON (s.id = d.object_id)
6365JOIN mz_catalog.mz_relations r ON (r.id = d.referenced_object_id)",
6366    access: vec![PUBLIC_SELECT],
6367    ontology: Some(Ontology {
6368        entity_name: "materialization_dep",
6369        description: "Dependencies between materializations",
6370        links: &const {
6371            [
6372                OntologyLink {
6373                    name: "depends_on",
6374                    target: "object",
6375                    properties: LinkProperties::DependsOn {
6376                        source_column: "object_id",
6377                        target_column: "id",
6378                        source_id_type: Some(mz_repr::SemanticType::CatalogItemId),
6379                        requires_mapping: None,
6380                    },
6381                },
6382                OntologyLink {
6383                    name: "dependency_is",
6384                    target: "object",
6385                    properties: LinkProperties::fk("dependency_id", "id", Cardinality::ManyToOne),
6386                },
6387            ]
6388        },
6389        column_semantic_types: &const {
6390            [
6391                ("object_id", SemanticType::CatalogItemId),
6392                ("dependency_id", SemanticType::CatalogItemId),
6393            ]
6394        },
6395    }),
6396});
6397
6398pub static MZ_MATERIALIZATION_LAG: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
6399    name: "mz_materialization_lag",
6400    schema: MZ_INTERNAL_SCHEMA,
6401    oid: oid::VIEW_MZ_MATERIALIZATION_LAG_OID,
6402    desc: RelationDesc::builder()
6403        .with_column("object_id", SqlScalarType::String.nullable(false))
6404        .with_column("local_lag", SqlScalarType::Interval.nullable(true))
6405        .with_column("global_lag", SqlScalarType::Interval.nullable(true))
6406        .with_column(
6407            "slowest_local_input_id",
6408            SqlScalarType::String.nullable(false),
6409        )
6410        .with_column(
6411            "slowest_global_input_id",
6412            SqlScalarType::String.nullable(false),
6413        )
6414        .finish(),
6415    column_comments: BTreeMap::from_iter([
6416        (
6417            "object_id",
6418            "The ID of the materialized view, index, or sink.",
6419        ),
6420        (
6421            "local_lag",
6422            "The amount of time the materialization lags behind its direct inputs.",
6423        ),
6424        (
6425            "global_lag",
6426            "The amount of time the materialization lags behind its root inputs (sources and tables).",
6427        ),
6428        (
6429            "slowest_local_input_id",
6430            "The ID of the slowest direct input.",
6431        ),
6432        (
6433            "slowest_global_input_id",
6434            "The ID of the slowest root input.",
6435        ),
6436    ]),
6437    sql: "
6438WITH MUTUALLY RECURSIVE
6439    -- IDs of objects for which we want to know the lag.
6440    materializations (id text) AS (
6441        SELECT id FROM mz_catalog.mz_indexes
6442        UNION ALL
6443        SELECT id FROM mz_catalog.mz_materialized_views
6444        UNION ALL
6445        SELECT id FROM mz_catalog.mz_sinks
6446    ),
6447    -- Direct dependencies of materializations.
6448    direct_dependencies (id text, dep_id text) AS (
6449        SELECT m.id, d.dependency_id
6450        FROM materializations m
6451        JOIN mz_internal.mz_materialization_dependencies d ON (m.id = d.object_id)
6452    ),
6453    -- All transitive dependencies of materializations.
6454    transitive_dependencies (id text, dep_id text) AS (
6455        SELECT id, dep_id FROM direct_dependencies
6456        UNION
6457        SELECT td.id, dd.dep_id
6458        FROM transitive_dependencies td
6459        JOIN direct_dependencies dd ON (dd.id = td.dep_id)
6460    ),
6461    -- Root dependencies of materializations (sources and tables).
6462    root_dependencies (id text, dep_id text) AS (
6463        SELECT *
6464        FROM transitive_dependencies td
6465        WHERE NOT EXISTS (
6466            SELECT 1
6467            FROM direct_dependencies dd
6468            WHERE dd.id = td.dep_id
6469        )
6470    ),
6471    -- Write progress times of materializations.
6472    materialization_times (id text, time timestamptz) AS (
6473        SELECT m.id, to_timestamp(f.write_frontier::text::double / 1000)
6474        FROM materializations m
6475        JOIN mz_internal.mz_frontiers f ON (m.id = f.object_id)
6476    ),
6477    -- Write progress times of direct dependencies of materializations.
6478    input_times (id text, slowest_dep text, time timestamptz) AS (
6479        SELECT DISTINCT ON (d.id)
6480            d.id,
6481            d.dep_id,
6482            to_timestamp(f.write_frontier::text::double / 1000)
6483        FROM direct_dependencies d
6484        JOIN mz_internal.mz_frontiers f ON (d.dep_id = f.object_id)
6485        ORDER BY d.id, f.write_frontier ASC
6486    ),
6487    -- Write progress times of root dependencies of materializations.
6488    root_times (id text, slowest_dep text, time timestamptz) AS (
6489        SELECT DISTINCT ON (d.id)
6490            d.id,
6491            d.dep_id,
6492            to_timestamp(f.write_frontier::text::double / 1000)
6493        FROM root_dependencies d
6494        JOIN mz_internal.mz_frontiers f ON (d.dep_id = f.object_id)
6495        ORDER BY d.id, f.write_frontier ASC
6496    )
6497SELECT
6498    id AS object_id,
6499    -- Ensure that lag values are always NULL for materializations that have reached the empty
6500    -- frontier, as those have processed all their input data.
6501    -- Also make sure that lag values are never negative, even when input frontiers are before
6502    -- output frontiers (as can happen during hydration).
6503    CASE
6504        WHEN m.time IS NULL THEN INTERVAL '0'
6505        WHEN i.time IS NULL THEN NULL
6506        ELSE greatest(i.time - m.time, INTERVAL '0')
6507    END AS local_lag,
6508    CASE
6509        WHEN m.time IS NULL THEN INTERVAL '0'
6510        WHEN r.time IS NULL THEN NULL
6511        ELSE greatest(r.time - m.time, INTERVAL '0')
6512    END AS global_lag,
6513    i.slowest_dep AS slowest_local_input_id,
6514    r.slowest_dep AS slowest_global_input_id
6515FROM materialization_times m
6516JOIN input_times i USING (id)
6517JOIN root_times r USING (id)",
6518    access: vec![PUBLIC_SELECT],
6519    ontology: Some(Ontology {
6520        entity_name: "materialization_lag",
6521        description: "Lag between a materialization and its inputs",
6522        links: &const {
6523            [
6524                OntologyLink {
6525                    name: "measures_materialization_lag",
6526                    target: "object",
6527                    properties: LinkProperties::measures("object_id", "id", "materialization_lag"),
6528                },
6529                OntologyLink {
6530                    name: "slowest_local_input",
6531                    target: "object",
6532                    properties: LinkProperties::fk(
6533                        "slowest_local_input_id",
6534                        "id",
6535                        Cardinality::ManyToOne,
6536                    ),
6537                },
6538                OntologyLink {
6539                    name: "slowest_global_input",
6540                    target: "object",
6541                    properties: LinkProperties::fk(
6542                        "slowest_global_input_id",
6543                        "id",
6544                        Cardinality::ManyToOne,
6545                    ),
6546                },
6547            ]
6548        },
6549        column_semantic_types: &const {
6550            [
6551                ("object_id", SemanticType::CatalogItemId),
6552                ("slowest_local_input_id", SemanticType::CatalogItemId),
6553                ("slowest_global_input_id", SemanticType::CatalogItemId),
6554            ]
6555        },
6556    }),
6557});
6558/**
6559 * This view is used to display the cluster utilization over 14 days bucketed by 8 hours.
6560 * It's specifically for the Console's environment overview page to speed up load times.
6561 * This query should be kept in sync with MaterializeInc/console/src/api/materialize/cluster/replicaUtilizationHistory.ts
6562 */
6563pub static MZ_CONSOLE_CLUSTER_UTILIZATION_OVERVIEW: LazyLock<BuiltinView> = LazyLock::new(|| {
6564    BuiltinView {
6565        name: "mz_console_cluster_utilization_overview",
6566        schema: MZ_INTERNAL_SCHEMA,
6567        oid: oid::VIEW_MZ_CONSOLE_CLUSTER_UTILIZATION_OVERVIEW_OID,
6568        desc: RelationDesc::builder()
6569            .with_column(
6570                "bucket_start",
6571                SqlScalarType::TimestampTz { precision: None }.nullable(false),
6572            )
6573            .with_column("replica_id", SqlScalarType::String.nullable(false))
6574            .with_column("memory_percent", SqlScalarType::Float64.nullable(true))
6575            .with_column(
6576                "max_memory_at",
6577                SqlScalarType::TimestampTz { precision: None }.nullable(false),
6578            )
6579            .with_column("disk_percent", SqlScalarType::Float64.nullable(true))
6580            .with_column(
6581                "max_disk_at",
6582                SqlScalarType::TimestampTz { precision: None }.nullable(false),
6583            )
6584            .with_column(
6585                "memory_and_disk_percent",
6586                SqlScalarType::Float64.nullable(true),
6587            )
6588            .with_column(
6589                "max_memory_and_disk_memory_percent",
6590                SqlScalarType::Float64.nullable(true),
6591            )
6592            .with_column(
6593                "max_memory_and_disk_disk_percent",
6594                SqlScalarType::Float64.nullable(true),
6595            )
6596            .with_column(
6597                "max_memory_and_disk_at",
6598                SqlScalarType::TimestampTz { precision: None }.nullable(false),
6599            )
6600            .with_column("heap_percent", SqlScalarType::Float64.nullable(true))
6601            .with_column(
6602                "max_heap_at",
6603                SqlScalarType::TimestampTz { precision: None }.nullable(false),
6604            )
6605            .with_column("max_cpu_percent", SqlScalarType::Float64.nullable(true))
6606            .with_column(
6607                "max_cpu_at",
6608                SqlScalarType::TimestampTz { precision: None }.nullable(false),
6609            )
6610            .with_column("offline_events", SqlScalarType::Jsonb.nullable(true))
6611            .with_column(
6612                "bucket_end",
6613                SqlScalarType::TimestampTz { precision: None }.nullable(false),
6614            )
6615            .with_column("name", SqlScalarType::String.nullable(true))
6616            .with_column("cluster_id", SqlScalarType::String.nullable(true))
6617            .with_column("size", SqlScalarType::String.nullable(true))
6618            .finish(),
6619        column_comments: BTreeMap::new(),
6620        sql: r#"WITH replica_history AS (
6621  SELECT replica_id,
6622    size,
6623    cluster_id
6624  FROM mz_internal.mz_cluster_replica_history
6625  UNION
6626  -- We need to union the current set of cluster replicas since mz_cluster_replica_history doesn't include system clusters
6627  SELECT id AS replica_id,
6628    size,
6629    cluster_id
6630  FROM mz_catalog.mz_cluster_replicas
6631),
6632replica_metrics_history AS (
6633  SELECT
6634    m.occurred_at,
6635    m.replica_id,
6636    r.size,
6637    (SUM(m.cpu_nano_cores::float8) / NULLIF(s.cpu_nano_cores, 0)) / NULLIF(s.processes, 0) AS cpu_percent,
6638    (SUM(m.memory_bytes::float8) / NULLIF(s.memory_bytes, 0)) / NULLIF(s.processes, 0) AS memory_percent,
6639    (SUM(m.disk_bytes::float8) / NULLIF(s.disk_bytes, 0)) / NULLIF(s.processes, 0) AS disk_percent,
6640    (SUM(m.heap_bytes::float8) / NULLIF(m.heap_limit, 0)) / NULLIF(s.processes, 0) AS heap_percent,
6641    SUM(m.disk_bytes::float8) AS disk_bytes,
6642    SUM(m.memory_bytes::float8) AS memory_bytes,
6643    s.disk_bytes::numeric * s.processes AS total_disk_bytes,
6644    s.memory_bytes::numeric * s.processes AS total_memory_bytes
6645  FROM
6646    replica_history AS r
6647    INNER JOIN mz_catalog.mz_cluster_replica_sizes AS s ON r.size = s.size
6648    INNER JOIN mz_internal.mz_cluster_replica_metrics_history AS m ON m.replica_id = r.replica_id
6649  GROUP BY
6650    m.occurred_at,
6651    m.replica_id,
6652    r.size,
6653    s.cpu_nano_cores,
6654    s.memory_bytes,
6655    s.disk_bytes,
6656    m.heap_limit,
6657    s.processes
6658),
6659replica_utilization_history_binned AS (
6660  SELECT m.occurred_at,
6661    m.replica_id,
6662    m.cpu_percent,
6663    m.memory_percent,
6664    m.memory_bytes,
6665    m.disk_percent,
6666    m.disk_bytes,
6667    m.heap_percent,
6668    m.total_disk_bytes,
6669    m.total_memory_bytes,
6670    m.size,
6671    date_bin(
6672      '8 HOURS',
6673      occurred_at,
6674      '1970-01-01'::timestamp
6675    ) AS bucket_start
6676  FROM replica_history AS r
6677    JOIN replica_metrics_history AS m ON m.replica_id = r.replica_id
6678  WHERE mz_now() <= date_bin(
6679      '8 HOURS',
6680      occurred_at,
6681      '1970-01-01'::timestamp
6682    ) + INTERVAL '14 DAYS'
6683),
6684-- For each (replica, bucket), take the (replica, bucket) with the highest memory
6685max_memory AS (
6686  SELECT DISTINCT ON (bucket_start, replica_id) bucket_start,
6687    replica_id,
6688    memory_percent,
6689    occurred_at
6690  FROM replica_utilization_history_binned
6691  OPTIONS (DISTINCT ON INPUT GROUP SIZE = 480)
6692  ORDER BY bucket_start,
6693    replica_id,
6694    COALESCE(memory_bytes, 0) DESC
6695),
6696max_disk AS (
6697  SELECT DISTINCT ON (bucket_start, replica_id) bucket_start,
6698    replica_id,
6699    disk_percent,
6700    occurred_at
6701  FROM replica_utilization_history_binned
6702  OPTIONS (DISTINCT ON INPUT GROUP SIZE = 480)
6703  ORDER BY bucket_start,
6704    replica_id,
6705    COALESCE(disk_bytes, 0) DESC
6706),
6707max_cpu AS (
6708  SELECT DISTINCT ON (bucket_start, replica_id) bucket_start,
6709    replica_id,
6710    cpu_percent,
6711    occurred_at
6712  FROM replica_utilization_history_binned
6713  OPTIONS (DISTINCT ON INPUT GROUP SIZE = 480)
6714  ORDER BY bucket_start,
6715    replica_id,
6716    COALESCE(cpu_percent, 0) DESC
6717),
6718/*
6719 This is different
6720 from adding max_memory
6721 and max_disk per bucket because both
6722 values may not occur at the same time if the bucket interval is large.
6723 */
6724max_memory_and_disk AS (
6725  SELECT DISTINCT ON (bucket_start, replica_id) bucket_start,
6726    replica_id,
6727    memory_percent,
6728    disk_percent,
6729    memory_and_disk_percent,
6730    occurred_at
6731  FROM (
6732      SELECT *,
6733        CASE
6734          WHEN disk_bytes IS NULL
6735          AND memory_bytes IS NULL THEN NULL
6736          ELSE (COALESCE(disk_bytes, 0) + COALESCE(memory_bytes, 0))
6737               / (total_disk_bytes::numeric + total_memory_bytes::numeric)
6738        END AS memory_and_disk_percent
6739      FROM replica_utilization_history_binned
6740    ) AS max_memory_and_disk_inner
6741  OPTIONS (DISTINCT ON INPUT GROUP SIZE = 480)
6742  ORDER BY bucket_start,
6743    replica_id,
6744    COALESCE(memory_and_disk_percent, 0) DESC
6745),
6746max_heap AS (
6747  SELECT DISTINCT ON (bucket_start, replica_id)
6748    bucket_start,
6749    replica_id,
6750    heap_percent,
6751    occurred_at
6752  FROM replica_utilization_history_binned
6753  OPTIONS (DISTINCT ON INPUT GROUP SIZE = 480)
6754  ORDER BY bucket_start, replica_id, COALESCE(heap_percent, 0) DESC
6755),
6756-- For each (replica, bucket), get its offline events at that time
6757replica_offline_event_history AS (
6758  SELECT date_bin(
6759      '8 HOURS',
6760      occurred_at,
6761      '1970-01-01'::timestamp
6762    ) AS bucket_start,
6763    replica_id,
6764    jsonb_agg(
6765      jsonb_build_object(
6766        'replicaId',
6767        rsh.replica_id,
6768        'occurredAt',
6769        rsh.occurred_at,
6770        'status',
6771        rsh.status,
6772        'reason',
6773        rsh.reason
6774      )
6775    ) AS offline_events
6776  FROM mz_internal.mz_cluster_replica_status_history AS rsh -- We assume the statuses for process 0 are the same as all processes
6777  WHERE process_id = '0'
6778    AND status = 'offline'
6779    AND mz_now() <= date_bin(
6780      '8 HOURS',
6781      occurred_at,
6782      '1970-01-01'::timestamp
6783    ) + INTERVAL '14 DAYS'
6784  GROUP BY bucket_start,
6785    replica_id
6786)
6787SELECT
6788  bucket_start,
6789  replica_id,
6790  max_memory.memory_percent,
6791  max_memory.occurred_at as max_memory_at,
6792  max_disk.disk_percent,
6793  max_disk.occurred_at as max_disk_at,
6794  max_memory_and_disk.memory_and_disk_percent as memory_and_disk_percent,
6795  max_memory_and_disk.memory_percent as max_memory_and_disk_memory_percent,
6796  max_memory_and_disk.disk_percent as max_memory_and_disk_disk_percent,
6797  max_memory_and_disk.occurred_at as max_memory_and_disk_at,
6798  max_heap.heap_percent,
6799  max_heap.occurred_at as max_heap_at,
6800  max_cpu.cpu_percent as max_cpu_percent,
6801  max_cpu.occurred_at as max_cpu_at,
6802  replica_offline_event_history.offline_events,
6803  bucket_start + INTERVAL '8 HOURS' as bucket_end,
6804  replica_name_history.new_name AS name,
6805  replica_history.cluster_id,
6806  replica_history.size
6807FROM max_memory
6808JOIN max_disk USING (bucket_start, replica_id)
6809JOIN max_cpu USING (bucket_start, replica_id)
6810JOIN max_memory_and_disk USING (bucket_start, replica_id)
6811JOIN max_heap USING (bucket_start, replica_id)
6812JOIN replica_history USING (replica_id)
6813CROSS JOIN LATERAL (
6814  SELECT new_name
6815  FROM mz_internal.mz_cluster_replica_name_history as replica_name_history
6816  WHERE replica_id = replica_name_history.id -- We treat NULLs as the beginning of time
6817    AND bucket_start + INTERVAL '8 HOURS' >= COALESCE(
6818      replica_name_history.occurred_at,
6819      '1970-01-01'::timestamp
6820    )
6821  ORDER BY replica_name_history.occurred_at DESC
6822  LIMIT '1'
6823) AS replica_name_history
6824LEFT JOIN replica_offline_event_history USING (bucket_start, replica_id)"#,
6825        access: vec![PUBLIC_SELECT],
6826        ontology: None,
6827    }
6828});
6829/**
6830 * Traces the blue/green deployment lineage in the audit log to determine all cluster
6831 * IDs that are logically the same cluster.
6832 * cluster_id: The ID of a cluster.
6833 * current_deployment_cluster_id: The cluster ID of the last cluster in
6834 *   cluster_id's blue/green lineage.
6835 * cluster_name: The name of the cluster.
6836 * The approach taken is as follows. First, find all extant clusters and add them
6837 * to the result set. Per cluster, we do the following:
6838 * 1. Find the most recent create or rename event. This moment represents when the
6839 *    cluster took on its final logical identity.
6840 * 2. Look for a cluster that had the same name (or the same name with `_dbt_deploy`
6841 *    appended) that was dropped within one minute of that moment. That cluster is
6842 *    almost certainly the logical predecessor of the current cluster. Add the cluster
6843 *    to the result set.
6844 * 3. Repeat the procedure until a cluster with no logical predecessor is discovered.
6845 * Limiting the search for a dropped cluster to a window of one minute is a heuristic,
6846 * but one that's likely to be pretty good one. If a name is reused after more
6847 * than one minute, that's a good sign that it wasn't an automatic blue/green
6848 * process, but someone turning on a new use case that happens to have the same
6849 * name as a previous but logically distinct use case.
6850 */
6851pub static MZ_CLUSTER_DEPLOYMENT_LINEAGE: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
6852    name: "mz_cluster_deployment_lineage",
6853    schema: MZ_INTERNAL_SCHEMA,
6854    oid: oid::VIEW_MZ_CLUSTER_DEPLOYMENT_LINEAGE_OID,
6855    desc: RelationDesc::builder()
6856        .with_column("cluster_id", SqlScalarType::String.nullable(true))
6857        .with_column(
6858            "current_deployment_cluster_id",
6859            SqlScalarType::String.nullable(false),
6860        )
6861        .with_column("cluster_name", SqlScalarType::String.nullable(false))
6862        .with_key(vec![0, 1, 2])
6863        .finish(),
6864    column_comments: BTreeMap::from_iter([
6865        (
6866            "cluster_id",
6867            "The ID of the cluster. Corresponds to `mz_clusters.id` (though the cluster may no longer exist).",
6868        ),
6869        (
6870            "current_deployment_cluster_id",
6871            "The cluster ID of the last cluster in `cluster_id`'s blue/green lineage (the cluster is guaranteed to exist).",
6872        ),
6873        ("cluster_name", "The name of the cluster"),
6874    ]),
6875    sql: r#"WITH MUTUALLY RECURSIVE cluster_events (
6876  cluster_id text,
6877  cluster_name text,
6878  event_type text,
6879  occurred_at timestamptz
6880) AS (
6881  SELECT coalesce(details->>'id', details->>'cluster_id') AS cluster_id,
6882    coalesce(details->>'name', details->>'new_name') AS cluster_name,
6883    event_type,
6884    occurred_at
6885  FROM mz_audit_events
6886  WHERE (
6887      event_type IN ('create', 'drop')
6888      OR (
6889        event_type = 'alter'
6890        AND details ? 'new_name'
6891      )
6892    )
6893    AND object_type = 'cluster'
6894    AND mz_now() < occurred_at + INTERVAL '30 days'
6895),
6896mz_cluster_deployment_lineage (
6897  cluster_id text,
6898  current_deployment_cluster_id text,
6899  cluster_name text
6900) AS (
6901  SELECT c.id,
6902    c.id,
6903    c.name
6904  FROM mz_clusters c
6905  WHERE c.id LIKE 'u%'
6906  UNION
6907  SELECT *
6908  FROM dropped_clusters
6909),
6910-- Closest create or rename event based on the current clusters in the result set
6911most_recent_create_or_rename (
6912  cluster_id text,
6913  current_deployment_cluster_id text,
6914  cluster_name text,
6915  occurred_at timestamptz
6916) AS (
6917  SELECT DISTINCT ON (e.cluster_id) e.cluster_id,
6918    c.current_deployment_cluster_id,
6919    e.cluster_name,
6920    e.occurred_at
6921  FROM mz_cluster_deployment_lineage c
6922    JOIN cluster_events e ON c.cluster_id = e.cluster_id
6923    AND c.cluster_name = e.cluster_name
6924  WHERE e.event_type <> 'drop'
6925  ORDER BY e.cluster_id,
6926    e.occurred_at DESC
6927),
6928-- Clusters that were dropped most recently within 1 minute of most_recent_create_or_rename
6929dropped_clusters (
6930  cluster_id text,
6931  current_deployment_cluster_id text,
6932  cluster_name text
6933) AS (
6934  SELECT DISTINCT ON (cr.cluster_id) e.cluster_id,
6935    cr.current_deployment_cluster_id,
6936    cr.cluster_name
6937  FROM most_recent_create_or_rename cr
6938    JOIN cluster_events e ON e.occurred_at BETWEEN cr.occurred_at - interval '1 minute'
6939    AND cr.occurred_at + interval '1 minute'
6940    AND (
6941      e.cluster_name = cr.cluster_name
6942      OR e.cluster_name = cr.cluster_name || '_dbt_deploy'
6943    )
6944  WHERE e.event_type = 'drop'
6945  ORDER BY cr.cluster_id,
6946    abs(
6947      extract(
6948        epoch
6949        FROM cr.occurred_at - e.occurred_at
6950      )
6951    )
6952)
6953SELECT *
6954FROM mz_cluster_deployment_lineage"#,
6955    access: vec![PUBLIC_SELECT],
6956    ontology: Some(Ontology {
6957        entity_name: "cluster_deployment",
6958        description: "Cluster deployment lineage information",
6959        links: &const {
6960            [
6961                OntologyLink {
6962                    name: "deployment_of",
6963                    target: "cluster",
6964                    properties: LinkProperties::fk("cluster_id", "id", Cardinality::ManyToOne),
6965                },
6966                OntologyLink {
6967                    name: "current_deployment",
6968                    target: "cluster",
6969                    properties: LinkProperties::fk(
6970                        "current_deployment_cluster_id",
6971                        "id",
6972                        Cardinality::ManyToOne,
6973                    ),
6974                },
6975            ]
6976        },
6977        column_semantic_types: &[],
6978    }),
6979});
6980
6981pub const MZ_SHOW_DATABASES_IND: BuiltinIndex = BuiltinIndex {
6982    name: "mz_show_databases_ind",
6983    schema: MZ_INTERNAL_SCHEMA,
6984    oid: oid::INDEX_MZ_SHOW_DATABASES_IND_OID,
6985    sql: "IN CLUSTER mz_catalog_server
6986ON mz_internal.mz_show_databases (name)",
6987    is_retained_metrics_object: false,
6988};
6989
6990pub const MZ_SHOW_SCHEMAS_IND: BuiltinIndex = BuiltinIndex {
6991    name: "mz_show_schemas_ind",
6992    schema: MZ_INTERNAL_SCHEMA,
6993    oid: oid::INDEX_MZ_SHOW_SCHEMAS_IND_OID,
6994    sql: "IN CLUSTER mz_catalog_server
6995ON mz_internal.mz_show_schemas (database_id)",
6996    is_retained_metrics_object: false,
6997};
6998
6999pub const MZ_SHOW_CONNECTIONS_IND: BuiltinIndex = BuiltinIndex {
7000    name: "mz_show_connections_ind",
7001    schema: MZ_INTERNAL_SCHEMA,
7002    oid: oid::INDEX_MZ_SHOW_CONNECTIONS_IND_OID,
7003    sql: "IN CLUSTER mz_catalog_server
7004ON mz_internal.mz_show_connections (schema_id)",
7005    is_retained_metrics_object: false,
7006};
7007
7008pub const MZ_SHOW_TABLES_IND: BuiltinIndex = BuiltinIndex {
7009    name: "mz_show_tables_ind",
7010    schema: MZ_INTERNAL_SCHEMA,
7011    oid: oid::INDEX_MZ_SHOW_TABLES_IND_OID,
7012    sql: "IN CLUSTER mz_catalog_server
7013ON mz_internal.mz_show_tables (schema_id)",
7014    is_retained_metrics_object: false,
7015};
7016
7017pub const MZ_SHOW_SOURCES_IND: BuiltinIndex = BuiltinIndex {
7018    name: "mz_show_sources_ind",
7019    schema: MZ_INTERNAL_SCHEMA,
7020    oid: oid::INDEX_MZ_SHOW_SOURCES_IND_OID,
7021    sql: "IN CLUSTER mz_catalog_server
7022ON mz_internal.mz_show_sources (schema_id)",
7023    is_retained_metrics_object: false,
7024};
7025
7026pub const MZ_SHOW_VIEWS_IND: BuiltinIndex = BuiltinIndex {
7027    name: "mz_show_views_ind",
7028    schema: MZ_INTERNAL_SCHEMA,
7029    oid: oid::INDEX_MZ_SHOW_VIEWS_IND_OID,
7030    sql: "IN CLUSTER mz_catalog_server
7031ON mz_internal.mz_show_views (schema_id)",
7032    is_retained_metrics_object: false,
7033};
7034
7035pub const MZ_SHOW_MATERIALIZED_VIEWS_IND: BuiltinIndex = BuiltinIndex {
7036    name: "mz_show_materialized_views_ind",
7037    schema: MZ_INTERNAL_SCHEMA,
7038    oid: oid::INDEX_MZ_SHOW_MATERIALIZED_VIEWS_IND_OID,
7039    sql: "IN CLUSTER mz_catalog_server
7040ON mz_internal.mz_show_materialized_views (schema_id)",
7041    is_retained_metrics_object: false,
7042};
7043
7044pub const MZ_SHOW_SINKS_IND: BuiltinIndex = BuiltinIndex {
7045    name: "mz_show_sinks_ind",
7046    schema: MZ_INTERNAL_SCHEMA,
7047    oid: oid::INDEX_MZ_SHOW_SINKS_IND_OID,
7048    sql: "IN CLUSTER mz_catalog_server
7049ON mz_internal.mz_show_sinks (schema_id)",
7050    is_retained_metrics_object: false,
7051};
7052
7053pub const MZ_SHOW_TYPES_IND: BuiltinIndex = BuiltinIndex {
7054    name: "mz_show_types_ind",
7055    schema: MZ_INTERNAL_SCHEMA,
7056    oid: oid::INDEX_MZ_SHOW_TYPES_IND_OID,
7057    sql: "IN CLUSTER mz_catalog_server
7058ON mz_internal.mz_show_types (schema_id)",
7059    is_retained_metrics_object: false,
7060};
7061
7062pub const MZ_SHOW_ROLES_IND: BuiltinIndex = BuiltinIndex {
7063    name: "mz_show_roles_ind",
7064    schema: MZ_INTERNAL_SCHEMA,
7065    oid: oid::INDEX_MZ_SHOW_ROLES_IND_OID,
7066    sql: "IN CLUSTER mz_catalog_server
7067ON mz_internal.mz_show_roles (name)",
7068    is_retained_metrics_object: false,
7069};
7070
7071pub const MZ_SHOW_ALL_OBJECTS_IND: BuiltinIndex = BuiltinIndex {
7072    name: "mz_show_all_objects_ind",
7073    schema: MZ_INTERNAL_SCHEMA,
7074    oid: oid::INDEX_MZ_SHOW_ALL_OBJECTS_IND_OID,
7075    sql: "IN CLUSTER mz_catalog_server
7076ON mz_internal.mz_show_all_objects (schema_id)",
7077    is_retained_metrics_object: false,
7078};
7079
7080pub const MZ_SHOW_INDEXES_IND: BuiltinIndex = BuiltinIndex {
7081    name: "mz_show_indexes_ind",
7082    schema: MZ_INTERNAL_SCHEMA,
7083    oid: oid::INDEX_MZ_SHOW_INDEXES_IND_OID,
7084    sql: "IN CLUSTER mz_catalog_server
7085ON mz_internal.mz_show_indexes (schema_id)",
7086    is_retained_metrics_object: false,
7087};
7088
7089pub const MZ_SHOW_COLUMNS_IND: BuiltinIndex = BuiltinIndex {
7090    name: "mz_show_columns_ind",
7091    schema: MZ_INTERNAL_SCHEMA,
7092    oid: oid::INDEX_MZ_SHOW_COLUMNS_IND_OID,
7093    sql: "IN CLUSTER mz_catalog_server
7094ON mz_internal.mz_show_columns (id)",
7095    is_retained_metrics_object: false,
7096};
7097
7098pub const MZ_SHOW_CLUSTERS_IND: BuiltinIndex = BuiltinIndex {
7099    name: "mz_show_clusters_ind",
7100    schema: MZ_INTERNAL_SCHEMA,
7101    oid: oid::INDEX_MZ_SHOW_CLUSTERS_IND_OID,
7102    sql: "IN CLUSTER mz_catalog_server
7103ON mz_internal.mz_show_clusters (name)",
7104    is_retained_metrics_object: false,
7105};
7106
7107pub const MZ_SHOW_CLUSTER_REPLICAS_IND: BuiltinIndex = BuiltinIndex {
7108    name: "mz_show_cluster_replicas_ind",
7109    schema: MZ_INTERNAL_SCHEMA,
7110    oid: oid::INDEX_MZ_SHOW_CLUSTER_REPLICAS_IND_OID,
7111    sql: "IN CLUSTER mz_catalog_server
7112ON mz_internal.mz_show_cluster_replicas (cluster)",
7113    is_retained_metrics_object: false,
7114};
7115
7116pub const MZ_SHOW_SECRETS_IND: BuiltinIndex = BuiltinIndex {
7117    name: "mz_show_secrets_ind",
7118    schema: MZ_INTERNAL_SCHEMA,
7119    oid: oid::INDEX_MZ_SHOW_SECRETS_IND_OID,
7120    sql: "IN CLUSTER mz_catalog_server
7121ON mz_internal.mz_show_secrets (schema_id)",
7122    is_retained_metrics_object: false,
7123};
7124
7125pub const MZ_CONSOLE_CLUSTER_UTILIZATION_OVERVIEW_IND: BuiltinIndex = BuiltinIndex {
7126    name: "mz_console_cluster_utilization_overview_ind",
7127    schema: MZ_INTERNAL_SCHEMA,
7128    oid: oid::INDEX_MZ_CONSOLE_CLUSTER_UTILIZATION_OVERVIEW_IND_OID,
7129    sql: "IN CLUSTER mz_catalog_server
7130ON mz_internal.mz_console_cluster_utilization_overview (cluster_id)",
7131    is_retained_metrics_object: false,
7132};
7133
7134pub const MZ_CLUSTER_DEPLOYMENT_LINEAGE_IND: BuiltinIndex = BuiltinIndex {
7135    name: "mz_cluster_deployment_lineage_ind",
7136    schema: MZ_INTERNAL_SCHEMA,
7137    oid: oid::INDEX_MZ_CLUSTER_DEPLOYMENT_LINEAGE_IND_OID,
7138    sql: "IN CLUSTER mz_catalog_server
7139ON mz_internal.mz_cluster_deployment_lineage (cluster_id)",
7140    is_retained_metrics_object: false,
7141};
7142
7143pub const MZ_SOURCE_STATUSES_IND: BuiltinIndex = BuiltinIndex {
7144    name: "mz_source_statuses_ind",
7145    schema: MZ_INTERNAL_SCHEMA,
7146    oid: oid::INDEX_MZ_SOURCE_STATUSES_IND_OID,
7147    sql: "IN CLUSTER mz_catalog_server
7148ON mz_internal.mz_source_statuses (id)",
7149    is_retained_metrics_object: false,
7150};
7151
7152pub const MZ_SINK_STATUSES_IND: BuiltinIndex = BuiltinIndex {
7153    name: "mz_sink_statuses_ind",
7154    schema: MZ_INTERNAL_SCHEMA,
7155    oid: oid::INDEX_MZ_SINK_STATUSES_IND_OID,
7156    sql: "IN CLUSTER mz_catalog_server
7157ON mz_internal.mz_sink_statuses (id)",
7158    is_retained_metrics_object: false,
7159};
7160
7161pub const MZ_SOURCE_STATUS_HISTORY_IND: BuiltinIndex = BuiltinIndex {
7162    name: "mz_source_status_history_ind",
7163    schema: MZ_INTERNAL_SCHEMA,
7164    oid: oid::INDEX_MZ_SOURCE_STATUS_HISTORY_IND_OID,
7165    sql: "IN CLUSTER mz_catalog_server
7166ON mz_internal.mz_source_status_history (source_id)",
7167    is_retained_metrics_object: false,
7168};
7169
7170pub const MZ_SINK_STATUS_HISTORY_IND: BuiltinIndex = BuiltinIndex {
7171    name: "mz_sink_status_history_ind",
7172    schema: MZ_INTERNAL_SCHEMA,
7173    oid: oid::INDEX_MZ_SINK_STATUS_HISTORY_IND_OID,
7174    sql: "IN CLUSTER mz_catalog_server
7175ON mz_internal.mz_sink_status_history (sink_id)",
7176    is_retained_metrics_object: false,
7177};
7178
7179// In both `mz_source_statistics` and `mz_sink_statistics` we cast the `SUM` of
7180// uint8's to `uint8` instead of leaving them as `numeric`. This is because we want to
7181// save index space, and we don't expect the sum to be > 2^63
7182// (even if a source with 2000 workers, that each produce 400 terabytes in a month ~ 2^61).
7183//
7184//
7185// These aggregations are just to make `GROUP BY` happy. Each id has a single row in the
7186// underlying relation.
7187//
7188// We append WITH_HISTORY because we want to build a separate view + index that doesn't
7189// retain history. This is because retaining its history causes MZ_SOURCE_STATISTICS_WITH_HISTORY_IND
7190// to hold all records/updates, which causes CPU and latency of querying it to spike.
7191pub static MZ_SOURCE_STATISTICS_WITH_HISTORY: LazyLock<BuiltinView> =
7192    LazyLock::new(|| BuiltinView {
7193        name: "mz_source_statistics_with_history",
7194        schema: MZ_INTERNAL_SCHEMA,
7195        oid: oid::VIEW_MZ_SOURCE_STATISTICS_WITH_HISTORY_OID,
7196        desc: RelationDesc::builder()
7197            .with_column("id", SqlScalarType::String.nullable(false))
7198            .with_column("replica_id", SqlScalarType::String.nullable(true))
7199            .with_column("messages_received", SqlScalarType::UInt64.nullable(false))
7200            .with_column("bytes_received", SqlScalarType::UInt64.nullable(false))
7201            .with_column("updates_staged", SqlScalarType::UInt64.nullable(false))
7202            .with_column("updates_committed", SqlScalarType::UInt64.nullable(false))
7203            .with_column("records_indexed", SqlScalarType::UInt64.nullable(false))
7204            .with_column("bytes_indexed", SqlScalarType::UInt64.nullable(false))
7205            .with_column(
7206                "rehydration_latency",
7207                SqlScalarType::Interval.nullable(true),
7208            )
7209            .with_column(
7210                "snapshot_records_known",
7211                SqlScalarType::UInt64.nullable(true),
7212            )
7213            .with_column(
7214                "snapshot_records_staged",
7215                SqlScalarType::UInt64.nullable(true),
7216            )
7217            .with_column("snapshot_committed", SqlScalarType::Bool.nullable(false))
7218            .with_column("offset_known", SqlScalarType::UInt64.nullable(true))
7219            .with_column("offset_committed", SqlScalarType::UInt64.nullable(true))
7220            .with_key(vec![0, 1])
7221            .finish(),
7222        column_comments: BTreeMap::new(),
7223        sql: "
7224WITH
7225    -- For each subsource, statistics are reported as its parent source
7226    subsource_to_parent AS
7227    (
7228        SELECT subsource.id AS id, parent.id AS report_id
7229        FROM mz_catalog.mz_sources AS subsource
7230            JOIN mz_internal.mz_object_dependencies AS dep ON subsource.id = dep.object_id
7231            JOIN mz_catalog.mz_sources AS parent ON parent.id = dep.referenced_object_id
7232        WHERE subsource.type = 'subsource'
7233    ),
7234    -- For each table from source, statistics are reported as its parent source
7235    table_to_parent AS
7236    (
7237        SELECT id, source_id AS report_id
7238        FROM mz_catalog.mz_tables
7239        WHERE source_id IS NOT NULL
7240    ),
7241    -- For each source and subsource, statistics are reported as itself
7242    source_refl AS
7243    (
7244        SELECT id, id AS report_id
7245        FROM mz_catalog.mz_sources
7246        WHERE type NOT IN ('progress', 'log')
7247    ),
7248    -- For each table from source, statistics are reported as itself
7249    table_refl AS
7250    (
7251        SELECT id, id AS report_id
7252        FROM mz_catalog.mz_tables
7253        WHERE source_id IS NOT NULL
7254    ),
7255    report_paths AS
7256    (
7257        SELECT id, report_id FROM subsource_to_parent
7258        UNION ALL SELECT id, report_id FROM table_to_parent
7259        UNION ALL SELECT id, report_id FROM source_refl
7260        UNION ALL SELECT id, report_id FROM table_refl
7261    )
7262SELECT
7263    report_paths.report_id AS id,
7264    replica_id,
7265    -- Counters
7266    SUM(messages_received)::uint8 AS messages_received,
7267    SUM(bytes_received)::uint8 AS bytes_received,
7268    SUM(updates_staged)::uint8 AS updates_staged,
7269    SUM(updates_committed)::uint8 AS updates_committed,
7270    -- Resetting Gauges
7271    SUM(records_indexed)::uint8 AS records_indexed,
7272    SUM(bytes_indexed)::uint8 AS bytes_indexed,
7273    -- Ensure we aggregate to NULL when not all workers are done rehydrating.
7274    CASE
7275        WHEN bool_or(rehydration_latency IS NULL) THEN NULL
7276        ELSE MAX(rehydration_latency)::interval
7277    END AS rehydration_latency,
7278    SUM(snapshot_records_known)::uint8 AS snapshot_records_known,
7279    SUM(snapshot_records_staged)::uint8 AS snapshot_records_staged,
7280    bool_and(snapshot_committed) as snapshot_committed,
7281    -- Gauges
7282    MAX(offset_known)::uint8 AS offset_known,
7283    MIN(offset_committed)::uint8 AS offset_committed
7284FROM mz_internal.mz_source_statistics_raw
7285    JOIN report_paths USING (id)
7286GROUP BY report_paths.report_id, replica_id",
7287        access: vec![PUBLIC_SELECT],
7288        ontology: None,
7289    });
7290
7291pub const MZ_SOURCE_STATISTICS_WITH_HISTORY_IND: BuiltinIndex = BuiltinIndex {
7292    name: "mz_source_statistics_with_history_ind",
7293    schema: MZ_INTERNAL_SCHEMA,
7294    oid: oid::INDEX_MZ_SOURCE_STATISTICS_WITH_HISTORY_IND_OID,
7295    sql: "IN CLUSTER mz_catalog_server
7296ON mz_internal.mz_source_statistics_with_history (id, replica_id)",
7297    is_retained_metrics_object: true,
7298};
7299
7300// The non historical version of MZ_SOURCE_STATISTICS_WITH_HISTORY.
7301// Used to query MZ_SOURCE_STATISTICS at the current time.
7302pub static MZ_SOURCE_STATISTICS: LazyLock<BuiltinView> = LazyLock::new(|| {
7303    BuiltinView {
7304        name: "mz_source_statistics",
7305        schema: MZ_INTERNAL_SCHEMA,
7306        oid: oid::VIEW_MZ_SOURCE_STATISTICS_OID,
7307        // We need to add a redundant where clause for a new dataflow to be created.
7308        desc: RelationDesc::builder()
7309            .with_column("id", SqlScalarType::String.nullable(false))
7310            .with_column("replica_id", SqlScalarType::String.nullable(true))
7311            .with_column("messages_received", SqlScalarType::UInt64.nullable(false))
7312            .with_column("bytes_received", SqlScalarType::UInt64.nullable(false))
7313            .with_column("updates_staged", SqlScalarType::UInt64.nullable(false))
7314            .with_column("updates_committed", SqlScalarType::UInt64.nullable(false))
7315            .with_column("records_indexed", SqlScalarType::UInt64.nullable(false))
7316            .with_column("bytes_indexed", SqlScalarType::UInt64.nullable(false))
7317            .with_column(
7318                "rehydration_latency",
7319                SqlScalarType::Interval.nullable(true),
7320            )
7321            .with_column(
7322                "snapshot_records_known",
7323                SqlScalarType::UInt64.nullable(true),
7324            )
7325            .with_column(
7326                "snapshot_records_staged",
7327                SqlScalarType::UInt64.nullable(true),
7328            )
7329            .with_column("snapshot_committed", SqlScalarType::Bool.nullable(false))
7330            .with_column("offset_known", SqlScalarType::UInt64.nullable(true))
7331            .with_column("offset_committed", SqlScalarType::UInt64.nullable(true))
7332            .with_key(vec![0, 1])
7333            .finish(),
7334        column_comments: BTreeMap::from_iter([
7335            (
7336                "id",
7337                "The ID of the source. Corresponds to `mz_catalog.mz_sources.id`.",
7338            ),
7339            (
7340                "replica_id",
7341                "The ID of a replica running the source. Corresponds to `mz_catalog.mz_cluster_replicas.id`.",
7342            ),
7343            (
7344                "messages_received",
7345                "The number of messages the source has received from the external system. Messages are counted in a source type-specific manner. Messages do not correspond directly to updates: some messages produce multiple updates, while other messages may be coalesced into a single update.",
7346            ),
7347            (
7348                "bytes_received",
7349                "The number of bytes the source has read from the external system. Bytes are counted in a source type-specific manner and may or may not include protocol overhead.",
7350            ),
7351            (
7352                "updates_staged",
7353                "The number of updates (insertions plus deletions) the source has written but not yet committed to the storage layer.",
7354            ),
7355            (
7356                "updates_committed",
7357                "The number of updates (insertions plus deletions) the source has committed to the storage layer.",
7358            ),
7359            (
7360                "records_indexed",
7361                "The number of individual records indexed in the source envelope state.",
7362            ),
7363            (
7364                "bytes_indexed",
7365                "The number of bytes stored in the source's internal index, if any.",
7366            ),
7367            (
7368                "rehydration_latency",
7369                "The amount of time it took for the source to rehydrate its internal index, if any, after the source last restarted.",
7370            ),
7371            (
7372                "snapshot_records_known",
7373                "The size of the source's snapshot, measured in number of records. See below to learn what constitutes a record.",
7374            ),
7375            (
7376                "snapshot_records_staged",
7377                "The number of records in the source's snapshot that Materialize has read. See below to learn what constitutes a record.",
7378            ),
7379            (
7380                "snapshot_committed",
7381                "Whether the source has committed the initial snapshot for a source.",
7382            ),
7383            (
7384                "offset_known",
7385                "The offset of the most recent data in the source's upstream service that Materialize knows about. See below to learn what constitutes an offset.",
7386            ),
7387            (
7388                "offset_committed",
7389                "The offset of the the data that Materialize has durably ingested. See below to learn what constitutes an offset.",
7390            ),
7391        ]),
7392        sql: "SELECT * FROM mz_internal.mz_source_statistics_with_history WHERE length(id) > 0",
7393        access: vec![PUBLIC_SELECT],
7394        ontology: Some(Ontology {
7395            entity_name: "source_statistics",
7396            description: "Aggregated source ingestion statistics",
7397            links: &const {
7398                [OntologyLink {
7399                    name: "statistics_of_source",
7400                    target: "source",
7401                    properties: LinkProperties::measures("id", "id", "ingestion_statistics"),
7402                }]
7403            },
7404            column_semantic_types: &const {
7405                [
7406                    ("id", SemanticType::CatalogItemId),
7407                    ("replica_id", SemanticType::ReplicaId),
7408                    ("messages_received", SemanticType::RecordCount),
7409                    ("bytes_received", SemanticType::ByteCount),
7410                    ("updates_staged", SemanticType::RecordCount),
7411                    ("updates_committed", SemanticType::RecordCount),
7412                    ("records_indexed", SemanticType::RecordCount),
7413                    ("bytes_indexed", SemanticType::ByteCount),
7414                    ("snapshot_records_known", SemanticType::RecordCount),
7415                    ("snapshot_records_staged", SemanticType::RecordCount),
7416                ]
7417            },
7418        }),
7419    }
7420});
7421
7422pub const MZ_SOURCE_STATISTICS_IND: BuiltinIndex = BuiltinIndex {
7423    name: "mz_source_statistics_ind",
7424    schema: MZ_INTERNAL_SCHEMA,
7425    oid: oid::INDEX_MZ_SOURCE_STATISTICS_IND_OID,
7426    sql: "IN CLUSTER mz_catalog_server
7427ON mz_internal.mz_source_statistics (id, replica_id)",
7428    is_retained_metrics_object: false,
7429};
7430
7431pub static MZ_SINK_STATISTICS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
7432    name: "mz_sink_statistics",
7433    schema: MZ_INTERNAL_SCHEMA,
7434    oid: oid::VIEW_MZ_SINK_STATISTICS_OID,
7435    desc: RelationDesc::builder()
7436        .with_column("id", SqlScalarType::String.nullable(false))
7437        .with_column("replica_id", SqlScalarType::String.nullable(true))
7438        .with_column("messages_staged", SqlScalarType::UInt64.nullable(false))
7439        .with_column("messages_committed", SqlScalarType::UInt64.nullable(false))
7440        .with_column("bytes_staged", SqlScalarType::UInt64.nullable(false))
7441        .with_column("bytes_committed", SqlScalarType::UInt64.nullable(false))
7442        .with_key(vec![0, 1])
7443        .finish(),
7444    column_comments: BTreeMap::from_iter([
7445        (
7446            "id",
7447            "The ID of the sink. Corresponds to `mz_catalog.mz_sinks.id`.",
7448        ),
7449        (
7450            "replica_id",
7451            "The ID of a replica running the sink. Corresponds to `mz_catalog.mz_cluster_replicas.id`.",
7452        ),
7453        (
7454            "messages_staged",
7455            "The number of messages staged but possibly not committed to the sink.",
7456        ),
7457        (
7458            "messages_committed",
7459            "The number of messages committed to the sink.",
7460        ),
7461        (
7462            "bytes_staged",
7463            "The number of bytes staged but possibly not committed to the sink. This counts both keys and values, if applicable.",
7464        ),
7465        (
7466            "bytes_committed",
7467            "The number of bytes committed to the sink. This counts both keys and values, if applicable.",
7468        ),
7469    ]),
7470    sql: "
7471SELECT
7472    id,
7473    replica_id,
7474    SUM(messages_staged)::uint8 AS messages_staged,
7475    SUM(messages_committed)::uint8 AS messages_committed,
7476    SUM(bytes_staged)::uint8 AS bytes_staged,
7477    SUM(bytes_committed)::uint8 AS bytes_committed
7478FROM mz_internal.mz_sink_statistics_raw
7479GROUP BY id, replica_id",
7480    access: vec![PUBLIC_SELECT],
7481    ontology: Some(Ontology {
7482        entity_name: "sink_statistics",
7483        description: "Aggregated sink export statistics",
7484        links: &const {
7485            [OntologyLink {
7486                name: "statistics_of_sink",
7487                target: "sink",
7488                properties: LinkProperties::measures("id", "id", "export_statistics"),
7489            }]
7490        },
7491        column_semantic_types: &const {
7492            [
7493                ("id", SemanticType::CatalogItemId),
7494                ("replica_id", SemanticType::ReplicaId),
7495                ("messages_staged", SemanticType::RecordCount),
7496                ("messages_committed", SemanticType::RecordCount),
7497                ("bytes_staged", SemanticType::ByteCount),
7498                ("bytes_committed", SemanticType::ByteCount),
7499            ]
7500        },
7501    }),
7502});
7503
7504pub const MZ_SINK_STATISTICS_IND: BuiltinIndex = BuiltinIndex {
7505    name: "mz_sink_statistics_ind",
7506    schema: MZ_INTERNAL_SCHEMA,
7507    oid: oid::INDEX_MZ_SINK_STATISTICS_IND_OID,
7508    sql: "IN CLUSTER mz_catalog_server
7509ON mz_internal.mz_sink_statistics (id, replica_id)",
7510    is_retained_metrics_object: true,
7511};
7512
7513pub const MZ_CLUSTER_REPLICA_STATUSES_IND: BuiltinIndex = BuiltinIndex {
7514    name: "mz_cluster_replica_statuses_ind",
7515    schema: MZ_INTERNAL_SCHEMA,
7516    oid: oid::INDEX_MZ_CLUSTER_REPLICA_STATUSES_IND_OID,
7517    sql: "IN CLUSTER mz_catalog_server
7518ON mz_internal.mz_cluster_replica_statuses (replica_id)",
7519    is_retained_metrics_object: false,
7520};
7521
7522pub const MZ_CLUSTER_REPLICA_STATUS_HISTORY_IND: BuiltinIndex = BuiltinIndex {
7523    name: "mz_cluster_replica_status_history_ind",
7524    schema: MZ_INTERNAL_SCHEMA,
7525    oid: oid::INDEX_MZ_CLUSTER_REPLICA_STATUS_HISTORY_IND_OID,
7526    sql: "IN CLUSTER mz_catalog_server
7527ON mz_internal.mz_cluster_replica_status_history (replica_id)",
7528    is_retained_metrics_object: false,
7529};
7530
7531pub const MZ_CLUSTER_REPLICA_METRICS_IND: BuiltinIndex = BuiltinIndex {
7532    name: "mz_cluster_replica_metrics_ind",
7533    schema: MZ_INTERNAL_SCHEMA,
7534    oid: oid::INDEX_MZ_CLUSTER_REPLICA_METRICS_IND_OID,
7535    sql: "IN CLUSTER mz_catalog_server
7536ON mz_internal.mz_cluster_replica_metrics (replica_id)",
7537    is_retained_metrics_object: false,
7538};
7539
7540pub const MZ_CLUSTER_REPLICA_METRICS_HISTORY_IND: BuiltinIndex = BuiltinIndex {
7541    name: "mz_cluster_replica_metrics_history_ind",
7542    schema: MZ_INTERNAL_SCHEMA,
7543    oid: oid::INDEX_MZ_CLUSTER_REPLICA_METRICS_HISTORY_IND_OID,
7544    sql: "IN CLUSTER mz_catalog_server
7545ON mz_internal.mz_cluster_replica_metrics_history (replica_id)",
7546    is_retained_metrics_object: false,
7547};
7548
7549pub const MZ_CLUSTER_REPLICA_HISTORY_IND: BuiltinIndex = BuiltinIndex {
7550    name: "mz_cluster_replica_history_ind",
7551    schema: MZ_INTERNAL_SCHEMA,
7552    oid: oid::INDEX_MZ_CLUSTER_REPLICA_HISTORY_IND_OID,
7553    sql: "IN CLUSTER mz_catalog_server
7554ON mz_internal.mz_cluster_replica_history (dropped_at)",
7555    is_retained_metrics_object: true,
7556};
7557
7558pub const MZ_CLUSTER_REPLICA_NAME_HISTORY_IND: BuiltinIndex = BuiltinIndex {
7559    name: "mz_cluster_replica_name_history_ind",
7560    schema: MZ_INTERNAL_SCHEMA,
7561    oid: oid::INDEX_MZ_CLUSTER_REPLICA_NAME_HISTORY_IND_OID,
7562    sql: "IN CLUSTER mz_catalog_server
7563ON mz_internal.mz_cluster_replica_name_history (id)",
7564    is_retained_metrics_object: false,
7565};
7566
7567pub const MZ_OBJECT_LIFETIMES_IND: BuiltinIndex = BuiltinIndex {
7568    name: "mz_object_lifetimes_ind",
7569    schema: MZ_INTERNAL_SCHEMA,
7570    oid: oid::INDEX_MZ_OBJECT_LIFETIMES_IND_OID,
7571    sql: "IN CLUSTER mz_catalog_server
7572ON mz_internal.mz_object_lifetimes (id)",
7573    is_retained_metrics_object: false,
7574};
7575
7576pub const MZ_OBJECT_HISTORY_IND: BuiltinIndex = BuiltinIndex {
7577    name: "mz_object_history_ind",
7578    schema: MZ_INTERNAL_SCHEMA,
7579    oid: oid::INDEX_MZ_OBJECT_HISTORY_IND_OID,
7580    sql: "IN CLUSTER mz_catalog_server
7581ON mz_internal.mz_object_history (id)",
7582    is_retained_metrics_object: false,
7583};
7584
7585pub const MZ_OBJECT_DEPENDENCIES_IND: BuiltinIndex = BuiltinIndex {
7586    name: "mz_object_dependencies_ind",
7587    schema: MZ_INTERNAL_SCHEMA,
7588    oid: oid::INDEX_MZ_OBJECT_DEPENDENCIES_IND_OID,
7589    sql: "IN CLUSTER mz_catalog_server
7590ON mz_internal.mz_object_dependencies (object_id)",
7591    is_retained_metrics_object: true,
7592};
7593
7594pub const MZ_COMPUTE_DEPENDENCIES_IND: BuiltinIndex = BuiltinIndex {
7595    name: "mz_compute_dependencies_ind",
7596    schema: MZ_INTERNAL_SCHEMA,
7597    oid: oid::INDEX_MZ_COMPUTE_DEPENDENCIES_IND_OID,
7598    sql: "IN CLUSTER mz_catalog_server
7599ON mz_internal.mz_compute_dependencies (dependency_id)",
7600    is_retained_metrics_object: false,
7601};
7602
7603pub const MZ_OBJECT_TRANSITIVE_DEPENDENCIES_IND: BuiltinIndex = BuiltinIndex {
7604    name: "mz_object_transitive_dependencies_ind",
7605    schema: MZ_INTERNAL_SCHEMA,
7606    oid: oid::INDEX_MZ_OBJECT_TRANSITIVE_DEPENDENCIES_IND_OID,
7607    sql: "IN CLUSTER mz_catalog_server
7608ON mz_internal.mz_object_transitive_dependencies (object_id)",
7609    is_retained_metrics_object: false,
7610};
7611
7612pub const MZ_FRONTIERS_IND: BuiltinIndex = BuiltinIndex {
7613    name: "mz_frontiers_ind",
7614    schema: MZ_INTERNAL_SCHEMA,
7615    oid: oid::INDEX_MZ_FRONTIERS_IND_OID,
7616    sql: "IN CLUSTER mz_catalog_server
7617ON mz_internal.mz_frontiers (object_id)",
7618    is_retained_metrics_object: false,
7619};
7620
7621pub const MZ_WALLCLOCK_GLOBAL_LAG_RECENT_HISTORY_IND: BuiltinIndex = BuiltinIndex {
7622    name: "mz_wallclock_global_lag_recent_history_ind",
7623    schema: MZ_INTERNAL_SCHEMA,
7624    oid: oid::INDEX_MZ_WALLCLOCK_GLOBAL_LAG_RECENT_HISTORY_IND_OID,
7625    sql: "IN CLUSTER mz_catalog_server
7626ON mz_internal.mz_wallclock_global_lag_recent_history (object_id)",
7627    is_retained_metrics_object: false,
7628};
7629
7630pub const MZ_RECENT_ACTIVITY_LOG_THINNED_IND: BuiltinIndex = BuiltinIndex {
7631    name: "mz_recent_activity_log_thinned_ind",
7632    schema: MZ_INTERNAL_SCHEMA,
7633    oid: oid::INDEX_MZ_RECENT_ACTIVITY_LOG_THINNED_IND_OID,
7634    sql: "IN CLUSTER mz_catalog_server
7635-- sql_hash because we plan to join
7636-- this against mz_internal.mz_sql_text
7637ON mz_internal.mz_recent_activity_log_thinned (sql_hash)",
7638    is_retained_metrics_object: false,
7639};
7640
7641pub const MZ_WEBHOOK_SOURCES_IND: BuiltinIndex = BuiltinIndex {
7642    name: "mz_webhook_sources_ind",
7643    schema: MZ_INTERNAL_SCHEMA,
7644    oid: oid::INDEX_MZ_WEBHOOK_SOURCES_IND_OID,
7645    sql: "IN CLUSTER mz_catalog_server
7646ON mz_internal.mz_webhook_sources (id)",
7647    is_retained_metrics_object: true,
7648};
7649
7650pub const MZ_COMMENTS_IND: BuiltinIndex = BuiltinIndex {
7651    name: "mz_comments_ind",
7652    schema: MZ_INTERNAL_SCHEMA,
7653    oid: oid::INDEX_MZ_COMMENTS_IND_OID,
7654    sql: "IN CLUSTER mz_catalog_server
7655ON mz_internal.mz_comments (id)",
7656    is_retained_metrics_object: true,
7657};
7658
7659pub static MZ_ANALYTICS: BuiltinConnection = BuiltinConnection {
7660    name: "mz_analytics",
7661    schema: MZ_INTERNAL_SCHEMA,
7662    oid: oid::CONNECTION_MZ_ANALYTICS_OID,
7663    sql: "CREATE CONNECTION mz_internal.mz_analytics TO AWS (ASSUME ROLE ARN = '')",
7664    access: &[MzAclItem {
7665        grantee: MZ_SYSTEM_ROLE_ID,
7666        grantor: MZ_ANALYTICS_ROLE_ID,
7667        acl_mode: rbac::all_object_privileges(SystemObjectType::Object(ObjectType::Connection)),
7668    }],
7669    owner_id: &MZ_ANALYTICS_ROLE_ID,
7670    runtime_alterable: true,
7671};