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