1use 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, RUNTIME_ALTERABLE_FINGERPRINT_SENTINEL,
38 SUPPORT_SELECT,
39};
40
41pub static MZ_CATALOG_RAW: LazyLock<BuiltinSource> = LazyLock::new(|| BuiltinSource {
42 name: "mz_catalog_raw",
43 schema: MZ_INTERNAL_SCHEMA,
44 oid: oid::SOURCE_MZ_CATALOG_RAW_OID,
45 data_source: DataSourceDesc::Catalog,
46 desc: crate::durable::persist_desc(),
47 column_comments: BTreeMap::new(),
48 is_retained_metrics_object: false,
49 access: vec![],
51 ontology: None,
52});
53pub static MZ_POSTGRES_SOURCES: LazyLock<BuiltinMaterializedView> = LazyLock::new(|| {
54 BuiltinMaterializedView {
55 name: "mz_postgres_sources",
56 schema: MZ_INTERNAL_SCHEMA,
57 oid: oid::MV_MZ_POSTGRES_SOURCES_OID,
58 desc: RelationDesc::builder()
59 .with_column("id", SqlScalarType::String.nullable(false))
60 .with_column("replication_slot", SqlScalarType::String.nullable(false))
61 .with_column("timeline_id", SqlScalarType::UInt64.nullable(true))
62 .with_key(vec![0])
63 .finish(),
64 column_comments: BTreeMap::from_iter([
65 (
66 "id",
67 "The ID of the source. Corresponds to `mz_catalog.mz_sources.id`.",
68 ),
69 (
70 "replication_slot",
71 "The name of the replication slot in the PostgreSQL database that Materialize will create and stream data from.",
72 ),
73 (
74 "timeline_id",
75 "The PostgreSQL timeline ID determined on source creation.",
76 ),
77 ]),
78 sql: "
84IN CLUSTER mz_catalog_server
85WITH (
86 ASSERT NOT NULL id,
87 ASSERT NOT NULL replication_slot
88) AS
89SELECT
90 mz_internal.parse_catalog_id(data->'key'->'gid') AS id,
91 details->>'slot' AS replication_slot,
92 (details->>'timeline_id')::uint8 AS timeline_id
93FROM
94 mz_internal.mz_catalog_raw,
95 LATERAL (
96 SELECT mz_internal.parse_catalog_create_sql(data->'value'->'definition'->'V1'->>'create_sql')
97 ) AS l(parsed),
98 LATERAL (
99 SELECT mz_internal.parse_postgres_source_details(data->'value'->'definition'->'V1'->>'create_sql')
100 ) AS d(details)
101WHERE
102 data->>'kind' = 'Item' AND
103 parsed->>'source_type' = 'postgres'",
104 is_retained_metrics_object: false,
105 access: vec![PUBLIC_SELECT],
106 ontology: Some(Ontology {
107 entity_name: "postgres_source",
108 description: "Postgres source-level details",
109 links: &const {
110 [OntologyLink {
111 name: "details_of",
112 target: "source",
113 properties: LinkProperties::fk("id", "id", Cardinality::OneToOne),
114 }]
115 },
116 column_semantic_types: &[("id", SemanticType::CatalogItemId)],
117 }),
118 }
119});
120pub static MZ_POSTGRES_SOURCE_TABLES: LazyLock<BuiltinMaterializedView> = LazyLock::new(|| {
129 BuiltinMaterializedView {
130 name: "mz_postgres_source_tables",
131 schema: MZ_INTERNAL_SCHEMA,
132 oid: oid::MV_MZ_POSTGRES_SOURCE_TABLES_OID,
133 desc: RelationDesc::builder()
134 .with_column("id", SqlScalarType::String.nullable(false))
135 .with_column("schema_name", SqlScalarType::String.nullable(false))
136 .with_column("table_name", SqlScalarType::String.nullable(false))
137 .with_key(vec![0])
138 .finish(),
139 column_comments: BTreeMap::from_iter([
140 (
141 "id",
142 "The ID of the subsource or table. Corresponds to `mz_catalog.mz_sources.id` or `mz_catalog.mz_tables.id`.",
143 ),
144 (
145 "schema_name",
146 "The schema of the upstream table being ingested.",
147 ),
148 (
149 "table_name",
150 "The name of the upstream table being ingested.",
151 ),
152 ]),
153 sql: "
154IN CLUSTER mz_catalog_server
155WITH (
156 ASSERT NOT NULL id,
157 ASSERT NOT NULL schema_name,
158 ASSERT NOT NULL table_name
159) AS
160SELECT
161 mz_internal.parse_catalog_id(r.data->'key'->'gid') AS id,
162 details->'external_reference'->>1 AS schema_name,
163 details->'external_reference'->>2 AS table_name
164FROM
165 mz_internal.mz_catalog_raw r,
166 LATERAL (
167 SELECT mz_internal.parse_source_export_details(
168 r.data->'value'->'definition'->'V1'->>'create_sql')
169 ) AS d(details)
170 JOIN mz_catalog.mz_sources s
171 ON s.id = details->>'source_id' AND s.type = 'postgres'
172WHERE
173 r.data->>'kind' = 'Item' AND
174 details IS NOT NULL",
175 is_retained_metrics_object: true,
176 access: vec![PUBLIC_SELECT],
177 ontology: Some(Ontology {
178 entity_name: "postgres_source_table",
179 description: "Postgres source table-level details",
180 links: &const {
181 [OntologyLink {
182 name: "describes_source_table",
183 target: "table",
184 properties: LinkProperties::fk("id", "id", Cardinality::OneToOne),
185 }]
186 },
187 column_semantic_types: &[("id", SemanticType::CatalogItemId)],
188 }),
189 }
190});
191pub static MZ_MYSQL_SOURCE_TABLES: LazyLock<BuiltinMaterializedView> = LazyLock::new(|| {
192 BuiltinMaterializedView {
193 name: "mz_mysql_source_tables",
194 schema: MZ_INTERNAL_SCHEMA,
195 oid: oid::MV_MZ_MYSQL_SOURCE_TABLES_OID,
196 desc: RelationDesc::builder()
197 .with_column("id", SqlScalarType::String.nullable(false))
198 .with_column("schema_name", SqlScalarType::String.nullable(false))
199 .with_column("table_name", SqlScalarType::String.nullable(false))
200 .with_key(vec![0])
201 .finish(),
202 column_comments: BTreeMap::from_iter([
203 (
204 "id",
205 "The ID of the subsource or table. Corresponds to `mz_catalog.mz_sources.id` or `mz_catalog.mz_tables.id`.",
206 ),
207 (
208 "schema_name",
209 "The schema (or, database) of the upstream table being ingested.",
210 ),
211 (
212 "table_name",
213 "The name of the upstream table being ingested.",
214 ),
215 ]),
216 sql: "
217IN CLUSTER mz_catalog_server
218WITH (
219 ASSERT NOT NULL id,
220 ASSERT NOT NULL schema_name,
221 ASSERT NOT NULL table_name
222) AS
223SELECT
224 mz_internal.parse_catalog_id(r.data->'key'->'gid') AS id,
225 details->'external_reference'->>0 AS schema_name,
226 details->'external_reference'->>1 AS table_name
227FROM
228 mz_internal.mz_catalog_raw r,
229 LATERAL (
230 SELECT mz_internal.parse_source_export_details(
231 r.data->'value'->'definition'->'V1'->>'create_sql')
232 ) AS d(details)
233 JOIN mz_catalog.mz_sources s
234 ON s.id = details->>'source_id' AND s.type = 'mysql'
235WHERE
236 r.data->>'kind' = 'Item' AND
237 details IS NOT NULL",
238 is_retained_metrics_object: true,
239 access: vec![PUBLIC_SELECT],
240 ontology: Some(Ontology {
241 entity_name: "mysql_source_table",
242 description: "MySQL source table-level details",
243 links: &const {
244 [OntologyLink {
245 name: "describes_source_table",
246 target: "table",
247 properties: LinkProperties::fk("id", "id", Cardinality::OneToOne),
248 }]
249 },
250 column_semantic_types: &[("id", SemanticType::CatalogItemId)],
251 }),
252 }
253});
254pub static MZ_SQL_SERVER_SOURCE_TABLES: LazyLock<BuiltinMaterializedView> = LazyLock::new(|| {
255 BuiltinMaterializedView {
256 name: "mz_sql_server_source_tables",
257 schema: MZ_INTERNAL_SCHEMA,
258 oid: oid::MV_MZ_SQL_SERVER_SOURCE_TABLES_OID,
259 desc: RelationDesc::builder()
260 .with_column("id", SqlScalarType::String.nullable(false))
261 .with_column("schema_name", SqlScalarType::String.nullable(false))
262 .with_column("table_name", SqlScalarType::String.nullable(false))
263 .with_key(vec![0])
264 .finish(),
265 column_comments: BTreeMap::from_iter([
266 (
267 "id",
268 "The ID of the subsource or table. Corresponds to `mz_catalog.mz_sources.id` or `mz_catalog.mz_tables.id`.",
269 ),
270 (
271 "schema_name",
272 "The schema of the upstream table being ingested.",
273 ),
274 (
275 "table_name",
276 "The name of the upstream table being ingested.",
277 ),
278 ]),
279 sql: "
280IN CLUSTER mz_catalog_server
281WITH (
282 ASSERT NOT NULL id,
283 ASSERT NOT NULL schema_name,
284 ASSERT NOT NULL table_name
285) AS
286SELECT
287 mz_internal.parse_catalog_id(r.data->'key'->'gid') AS id,
288 details->'external_reference'->>1 AS schema_name,
289 details->'external_reference'->>2 AS table_name
290FROM
291 mz_internal.mz_catalog_raw r,
292 LATERAL (
293 SELECT mz_internal.parse_source_export_details(
294 r.data->'value'->'definition'->'V1'->>'create_sql')
295 ) AS d(details)
296 JOIN mz_catalog.mz_sources s
297 ON s.id = details->>'source_id' AND s.type = 'sql-server'
298WHERE
299 r.data->>'kind' = 'Item' AND
300 details IS NOT NULL",
301 is_retained_metrics_object: true,
302 access: vec![PUBLIC_SELECT],
303 ontology: Some(Ontology {
304 entity_name: "sql_server_source_table",
305 description: "SQL Server source table-level details",
306 links: &const {
307 [OntologyLink {
308 name: "describes_source_table",
309 target: "table",
310 properties: LinkProperties::fk("id", "id", Cardinality::OneToOne),
311 }]
312 },
313 column_semantic_types: &[("id", SemanticType::CatalogItemId)],
314 }),
315 }
316});
317pub static MZ_KAFKA_SOURCE_TABLES: LazyLock<BuiltinMaterializedView> = LazyLock::new(|| {
318 BuiltinMaterializedView {
319 name: "mz_kafka_source_tables",
320 schema: MZ_INTERNAL_SCHEMA,
321 oid: oid::MV_MZ_KAFKA_SOURCE_TABLES_OID,
322 desc: RelationDesc::builder()
323 .with_column("id", SqlScalarType::String.nullable(false))
324 .with_column("topic", SqlScalarType::String.nullable(false))
325 .with_column("envelope_type", SqlScalarType::String.nullable(false))
326 .with_column("key_format", SqlScalarType::String.nullable(true))
327 .with_column("value_format", SqlScalarType::String.nullable(true))
328 .with_key(vec![0])
329 .finish(),
330 column_comments: BTreeMap::from_iter([
331 (
332 "id",
333 "The ID of the table. Corresponds to `mz_catalog.mz_tables.id`.",
334 ),
335 ("topic", "The topic being ingested."),
336 (
337 "envelope_type",
338 "The envelope type: `none`, `upsert`, or `debezium`. Defaults to `none` when the source table omits an explicit envelope.",
339 ),
340 (
341 "key_format",
342 "The format of the Kafka message key: `avro`, `csv`, `regex`, `bytes`, `json`, `text`, or `NULL`.",
343 ),
344 (
345 "value_format",
346 "The format of the Kafka message value: `avro`, `csv`, `regex`, `bytes`, `json`, `text`. `NULL` for other source types.",
347 ),
348 ]),
349 sql: "
357IN CLUSTER mz_catalog_server
358WITH (
359 ASSERT NOT NULL id,
360 ASSERT NOT NULL topic
361) AS
362SELECT
363 mz_internal.parse_catalog_id(r.data->'key'->'gid') AS id,
364 details->'external_reference'->>0 AS topic,
365 -- Kafka defaults to ENVELOPE NONE when the clause is omitted. The parser
366 -- helper is source-type agnostic and reports NULL for that case, so default
367 -- to 'none' here, where the join has already scoped rows to kafka.
368 COALESCE(details->>'envelope_type', 'none') AS envelope_type,
369 details->>'key_format' AS key_format,
370 details->>'value_format' AS value_format
371FROM
372 mz_internal.mz_catalog_raw r,
373 LATERAL (
374 SELECT mz_internal.parse_source_export_details(
375 r.data->'value'->'definition'->'V1'->>'create_sql')
376 ) AS d(details)
377 JOIN mz_catalog.mz_sources s
378 ON s.id = details->>'source_id' AND s.type = 'kafka'
379WHERE
380 r.data->>'kind' = 'Item' AND
381 details IS NOT NULL",
382 is_retained_metrics_object: true,
383 access: vec![PUBLIC_SELECT],
384 ontology: Some(Ontology {
385 entity_name: "kafka_source_table",
386 description: "Kafka source table-level details",
387 links: &const {
388 [OntologyLink {
389 name: "describes_source_table",
390 target: "table",
391 properties: LinkProperties::fk("id", "id", Cardinality::OneToOne),
392 }]
393 },
394 column_semantic_types: &[("id", SemanticType::CatalogItemId)],
395 }),
396 }
397});
398
399pub static MZ_COMPUTE_DEPENDENCIES: LazyLock<BuiltinSource> = LazyLock::new(|| BuiltinSource {
400 name: "mz_compute_dependencies",
401 schema: MZ_INTERNAL_SCHEMA,
402 oid: oid::SOURCE_MZ_COMPUTE_DEPENDENCIES_OID,
403 data_source: IntrospectionType::ComputeDependencies.into(),
404 desc: RelationDesc::builder()
405 .with_column("object_id", SqlScalarType::String.nullable(false))
406 .with_column("dependency_id", SqlScalarType::String.nullable(false))
407 .finish(),
408 column_comments: BTreeMap::from_iter([
409 (
410 "object_id",
411 "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`.",
412 ),
413 (
414 "dependency_id",
415 "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`.",
416 ),
417 ]),
418 is_retained_metrics_object: false,
419 access: vec![PUBLIC_SELECT],
420 ontology: Some(Ontology {
421 entity_name: "compute_dependency",
422 description: "Dependency edge from a compute object (index, materialized view, or subscription) to one of the sources of its data",
423 links: &const {
424 [
425 OntologyLink {
426 name: "depends_on",
427 target: "object",
428 properties: LinkProperties::DependsOn {
429 source_column: "object_id",
430 target_column: "id",
431 source_id_type: Some(mz_repr::SemanticType::GlobalId),
432 requires_mapping: Some("mz_internal.mz_object_global_ids"),
433 },
434 },
435 OntologyLink {
436 name: "dependency_is",
437 target: "object",
438 properties: LinkProperties::DependsOn {
439 source_column: "dependency_id",
440 target_column: "id",
441 source_id_type: Some(mz_repr::SemanticType::GlobalId),
442 requires_mapping: Some("mz_internal.mz_object_global_ids"),
443 },
444 },
445 ]
446 },
447 column_semantic_types: &const {
448 [
449 ("object_id", SemanticType::GlobalId),
450 ("dependency_id", SemanticType::GlobalId),
451 ]
452 },
453 }),
454});
455
456pub static MZ_MATERIALIZED_VIEW_REFRESH_STRATEGIES: LazyLock<BuiltinTable> = LazyLock::new(|| {
457 BuiltinTable {
458 name: "mz_materialized_view_refresh_strategies",
459 schema: MZ_INTERNAL_SCHEMA,
460 oid: oid::TABLE_MZ_MATERIALIZED_VIEW_REFRESH_STRATEGIES_OID,
461 desc: RelationDesc::builder()
462 .with_column(
463 "materialized_view_id",
464 SqlScalarType::String.nullable(false),
465 )
466 .with_column("type", SqlScalarType::String.nullable(false))
467 .with_column("interval", SqlScalarType::Interval.nullable(true))
468 .with_column(
469 "aligned_to",
470 SqlScalarType::TimestampTz { precision: None }.nullable(true),
471 )
472 .with_column(
473 "at",
474 SqlScalarType::TimestampTz { precision: None }.nullable(true),
475 )
476 .finish(),
477 column_comments: BTreeMap::from_iter([
478 (
479 "materialized_view_id",
480 "The ID of the materialized view. Corresponds to `mz_catalog.mz_materialized_views.id`",
481 ),
482 (
483 "type",
484 "`at`, `every`, or `on-commit`. Default: `on-commit`",
485 ),
486 (
487 "interval",
488 "The refresh interval of a `REFRESH EVERY` option, or `NULL` if the `type` is not `every`.",
489 ),
490 (
491 "aligned_to",
492 "The `ALIGNED TO` option of a `REFRESH EVERY` option, or `NULL` if the `type` is not `every`.",
493 ),
494 (
495 "at",
496 "The time of a `REFRESH AT`, or `NULL` if the `type` is not `at`.",
497 ),
498 ]),
499 is_retained_metrics_object: false,
500 access: vec![PUBLIC_SELECT],
501 ontology: None,
502 }
503});
504
505pub static MZ_NETWORK_POLICIES: LazyLock<BuiltinMaterializedView> = LazyLock::new(|| {
506 BuiltinMaterializedView {
507 name: "mz_network_policies",
508 schema: MZ_INTERNAL_SCHEMA,
509 oid: oid::MV_MZ_NETWORK_POLICIES_OID,
510 desc: RelationDesc::builder()
511 .with_column("id", SqlScalarType::String.nullable(false))
512 .with_column("name", SqlScalarType::String.nullable(false))
513 .with_column("owner_id", SqlScalarType::String.nullable(false))
514 .with_column(
515 "privileges",
516 SqlScalarType::Array(Box::new(SqlScalarType::MzAclItem)).nullable(false),
517 )
518 .with_column("oid", SqlScalarType::Oid.nullable(false))
519 .with_key(vec![0])
520 .with_key(vec![4])
521 .finish(),
522 column_comments: BTreeMap::from_iter([
523 ("id", "The ID of the network policy."),
524 ("name", "The name of the network policy."),
525 (
526 "owner_id",
527 "The role ID of the owner of the network policy. Corresponds to `mz_catalog.mz_roles.id`.",
528 ),
529 (
530 "privileges",
531 "The privileges belonging to the network policy.",
532 ),
533 ("oid", "A PostgreSQL-compatible OID for the network policy."),
534 ]),
535 sql: "
536IN CLUSTER mz_catalog_server
537WITH (
538 ASSERT NOT NULL id,
539 ASSERT NOT NULL name,
540 ASSERT NOT NULL owner_id,
541 ASSERT NOT NULL privileges,
542 ASSERT NOT NULL oid
543) AS
544SELECT
545 mz_internal.parse_catalog_id(data->'key'->'id') AS id,
546 data->'value'->>'name' AS name,
547 mz_internal.parse_catalog_id(data->'value'->'owner_id') AS owner_id,
548 mz_internal.parse_catalog_privileges(data->'value'->'privileges') AS privileges,
549 (data->'value'->>'oid')::oid AS oid
550FROM mz_internal.mz_catalog_raw
551WHERE data->>'kind' = 'NetworkPolicy'",
552 is_retained_metrics_object: false,
553 access: vec![PUBLIC_SELECT],
554 ontology: Some(Ontology {
555 entity_name: "network_policy",
556 description: "Network access policies",
557 links: &const {
558 [OntologyLink {
559 name: "owned_by",
560 target: "role",
561 properties: LinkProperties::fk("owner_id", "id", Cardinality::ManyToOne),
562 }]
563 },
564 column_semantic_types: &const {
565 [
566 ("id", SemanticType::NetworkPolicyId),
567 ("owner_id", SemanticType::RoleId),
568 ("oid", SemanticType::OID),
569 ]
570 },
571 }),
572 }
573});
574
575pub static MZ_NETWORK_POLICY_RULES: LazyLock<BuiltinMaterializedView> = LazyLock::new(|| {
576 BuiltinMaterializedView {
577 name: "mz_network_policy_rules",
578 schema: MZ_INTERNAL_SCHEMA,
579 oid: oid::MV_MZ_NETWORK_POLICY_RULES_OID,
580 desc: RelationDesc::builder()
581 .with_column("name", SqlScalarType::String.nullable(false))
582 .with_column("policy_id", SqlScalarType::String.nullable(false))
583 .with_column("action", SqlScalarType::String.nullable(false))
584 .with_column("address", SqlScalarType::String.nullable(false))
585 .with_column("direction", SqlScalarType::String.nullable(false))
586 .finish(),
587 column_comments: BTreeMap::from_iter([
588 (
589 "name",
590 "The name of the network policy rule. Can be combined with `policy_id` to form a unique identifier.",
591 ),
592 (
593 "policy_id",
594 "The ID the network policy the rule is part of. Corresponds to `mz_internal.mz_network_policies.id`.",
595 ),
596 (
597 "action",
598 "The action of the rule. `allow` is the only supported action.",
599 ),
600 ("address", "The address the rule will take action on."),
601 (
602 "direction",
603 "The direction of traffic the rule applies to. `ingress` is the only supported direction.",
604 ),
605 ]),
606 sql: "
607IN CLUSTER mz_catalog_server
608WITH (
609 ASSERT NOT NULL name,
610 ASSERT NOT NULL policy_id,
611 ASSERT NOT NULL action,
612 ASSERT NOT NULL address,
613 ASSERT NOT NULL direction
614) AS
615SELECT
616 rule->>'name' AS name,
617 mz_internal.parse_catalog_id(data->'key'->'id') AS policy_id,
618 lower(rule->>'action') AS action,
619 rule->>'address' AS address,
620 lower(rule->>'direction') AS direction
621FROM
622 mz_internal.mz_catalog_raw,
623 jsonb_array_elements(data->'value'->'rules') AS rule
624WHERE data->>'kind' = 'NetworkPolicy'",
625 is_retained_metrics_object: false,
626 access: vec![PUBLIC_SELECT],
627 ontology: Some(Ontology {
628 entity_name: "network_policy_rule",
629 description: "Individual rules within a network policy",
630 links: &const {
631 [OntologyLink {
632 name: "belongs_to_policy",
633 target: "network_policy",
634 properties: LinkProperties::fk("policy_id", "id", Cardinality::ManyToOne),
635 }]
636 },
637 column_semantic_types: &[],
638 }),
639 }
640});
641
642pub static MZ_TYPE_PG_METADATA: LazyLock<BuiltinTable> = LazyLock::new(|| BuiltinTable {
645 name: "mz_type_pg_metadata",
646 schema: MZ_INTERNAL_SCHEMA,
647 oid: oid::TABLE_MZ_TYPE_PG_METADATA_OID,
648 desc: RelationDesc::builder()
649 .with_column("id", SqlScalarType::String.nullable(false))
650 .with_column("typinput", SqlScalarType::Oid.nullable(false))
651 .with_column("typreceive", SqlScalarType::Oid.nullable(false))
652 .with_column("typsend", SqlScalarType::Oid.nullable(false))
656 .finish(),
657 column_comments: BTreeMap::new(),
658 is_retained_metrics_object: false,
659 access: vec![PUBLIC_SELECT],
660 ontology: None,
661});
662pub static MZ_AGGREGATES: LazyLock<BuiltinTable> = LazyLock::new(|| BuiltinTable {
663 name: "mz_aggregates",
664 schema: MZ_INTERNAL_SCHEMA,
665 oid: oid::TABLE_MZ_AGGREGATES_OID,
666 desc: RelationDesc::builder()
667 .with_column("oid", SqlScalarType::Oid.nullable(false))
668 .with_column("agg_kind", SqlScalarType::String.nullable(false))
669 .with_column("agg_num_direct_args", SqlScalarType::Int16.nullable(false))
670 .finish(),
671 column_comments: BTreeMap::new(),
672 is_retained_metrics_object: false,
673 access: vec![PUBLIC_SELECT],
674 ontology: Some(Ontology {
675 entity_name: "aggregate",
676 description: "Aggregate function metadata",
677 links: &const { [] },
678 column_semantic_types: &[("oid", SemanticType::OID)],
679 }),
680});
681
682pub static MZ_CLUSTER_WORKLOAD_CLASSES: LazyLock<BuiltinMaterializedView> =
683 LazyLock::new(|| BuiltinMaterializedView {
684 name: "mz_cluster_workload_classes",
685 schema: MZ_INTERNAL_SCHEMA,
686 oid: oid::MV_MZ_CLUSTER_WORKLOAD_CLASSES_OID,
687 desc: RelationDesc::builder()
688 .with_column("id", SqlScalarType::String.nullable(false))
689 .with_column("workload_class", SqlScalarType::String.nullable(true))
690 .with_key(vec![0])
691 .finish(),
692 column_comments: BTreeMap::new(),
693 sql: "
694IN CLUSTER mz_catalog_server
695WITH (
696 ASSERT NOT NULL id
697) AS
698SELECT
699 mz_internal.parse_catalog_id(data->'key'->'id') AS id,
700 CASE WHEN data->'value'->'config'->'workload_class' != 'null'
701 THEN data->'value'->'config'->>'workload_class'
702 END AS workload_class
703FROM mz_internal.mz_catalog_raw
704WHERE data->>'kind' = 'Cluster'",
705 is_retained_metrics_object: false,
706 access: vec![PUBLIC_SELECT],
707 ontology: None,
708 });
709
710pub const MZ_CLUSTER_WORKLOAD_CLASSES_IND: BuiltinIndex = BuiltinIndex {
711 name: "mz_cluster_workload_classes_ind",
712 schema: MZ_INTERNAL_SCHEMA,
713 oid: oid::INDEX_MZ_CLUSTER_WORKLOAD_CLASSES_IND_OID,
714 sql: "IN CLUSTER mz_catalog_server
715ON mz_internal.mz_cluster_workload_classes (id)",
716 is_retained_metrics_object: false,
717};
718
719pub static MZ_CLUSTER_SCHEDULES: LazyLock<BuiltinMaterializedView> = LazyLock::new(|| {
720 BuiltinMaterializedView {
721 name: "mz_cluster_schedules",
722 schema: MZ_INTERNAL_SCHEMA,
723 oid: oid::MV_MZ_CLUSTER_SCHEDULES_OID,
724 desc: RelationDesc::builder()
725 .with_column("cluster_id", SqlScalarType::String.nullable(false))
726 .with_column("type", SqlScalarType::String.nullable(false))
727 .with_column(
728 "refresh_hydration_time_estimate",
729 SqlScalarType::Interval.nullable(true),
730 )
731 .with_key(vec![0])
732 .finish(),
733 column_comments: BTreeMap::from_iter([
734 (
735 "cluster_id",
736 "The ID of the cluster. Corresponds to `mz_clusters.id`.",
737 ),
738 ("type", "`on-refresh`, or `manual`. Default: `manual`"),
739 (
740 "refresh_hydration_time_estimate",
741 "The interval given in the `HYDRATION TIME ESTIMATE` option.",
742 ),
743 ]),
744 sql: "
751IN CLUSTER mz_catalog_server
752WITH (
753 ASSERT NOT NULL cluster_id,
754 ASSERT NOT NULL type
755) AS
756SELECT
757 mz_internal.parse_catalog_id(data->'key'->'id') AS cluster_id,
758 CASE
759 WHEN data->'value'->'config'->'variant'->'Managed'->'schedule' = '\"Manual\"'::jsonb
760 THEN 'manual'
761 WHEN data->'value'->'config'->'variant'->'Managed'->'schedule' ? 'Refresh'
762 THEN 'on-refresh'
763 END AS type,
764 CASE
765 WHEN data->'value'->'config'->'variant'->'Managed'->'schedule' ? 'Refresh' THEN
766 (
767 (data->'value'->'config'->'variant'->'Managed'->'schedule'->'Refresh'->'rehydration_time_estimate'->>'secs')
768 || ' seconds '
769 || ((data->'value'->'config'->'variant'->'Managed'->'schedule'->'Refresh'->'rehydration_time_estimate'->>'nanos')::bigint / 1000)::text
770 || ' microseconds'
771 )::interval
772 END AS refresh_hydration_time_estimate
773FROM mz_internal.mz_catalog_raw
774WHERE
775 data->>'kind' = 'Cluster' AND
776 jsonb_typeof(data->'value'->'config'->'variant') = 'object'",
777 is_retained_metrics_object: false,
778 access: vec![PUBLIC_SELECT],
779 ontology: Some(Ontology {
780 entity_name: "cluster_schedule",
781 description: "Cluster scheduling configuration",
782 links: &const {
783 [OntologyLink {
784 name: "belongs_to_cluster",
785 target: "cluster",
786 properties: LinkProperties::fk("cluster_id", "id", Cardinality::ManyToOne),
787 }]
788 },
789 column_semantic_types: &[("cluster_id", SemanticType::ClusterId)],
790 }),
791 }
792});
793
794pub static MZ_CLUSTER_RECONFIGURATIONS: LazyLock<BuiltinMaterializedView> = LazyLock::new(|| {
795 BuiltinMaterializedView {
796 name: "mz_cluster_reconfigurations",
797 schema: MZ_INTERNAL_SCHEMA,
798 oid: oid::MV_MZ_CLUSTER_RECONFIGURATIONS_OID,
799 desc: RelationDesc::builder()
800 .with_column("cluster_id", SqlScalarType::String.nullable(false))
801 .with_column("status", SqlScalarType::String.nullable(false))
802 .with_column("deadline", SqlScalarType::MzTimestamp.nullable(false))
803 .with_column("on_timeout", SqlScalarType::String.nullable(false))
804 .with_column("target", SqlScalarType::Jsonb.nullable(false))
805 .with_column("changes", SqlScalarType::Jsonb.nullable(false))
806 .with_key(vec![0])
807 .finish(),
808 column_comments: BTreeMap::from_iter([
809 (
810 "cluster_id",
811 "The ID of the cluster. Corresponds to `mz_clusters.id`.",
812 ),
813 (
814 "status",
815 "The lifecycle status of the reconfiguration: `in-progress` while the controller converges on the target, then a terminal `finalized`, `timed-out`, `cancelled`, or `resource-exhausted`. The record is retained after it settles, so the latest outcome stays inspectable until a later reconfiguration overwrites it.",
816 ),
817 (
818 "deadline",
819 "The deadline by which the reconfiguration must complete. After it passes, the `on_timeout` action applies.",
820 ),
821 (
822 "on_timeout",
823 "The action applied if `deadline` passes before the target hydrates: `commit` (cut over to the not-yet-hydrated target) or `rollback` (revert to the pre-reconfiguration shape).",
824 ),
825 (
826 "target",
827 "The config shape the cluster is reconfiguring to, as JSON: `size`, `replication_factor`, `availability_zones`, `logging`, and `arrangement_compression`. The realized (current) shape is in `mz_clusters`.",
828 ),
829 (
830 "changes",
831 "The dimensions in which `target` differs from the cluster's realized configuration, as a JSON object holding the target value per changed dimension. Empty (`{}`) once a record settles with its target applied. A rolled-back record keeps the abandoned diff.",
832 ),
833 ]),
834 sql: "
852IN CLUSTER mz_catalog_server
853WITH (
854 ASSERT NOT NULL cluster_id,
855 ASSERT NOT NULL status,
856 ASSERT NOT NULL deadline,
857 ASSERT NOT NULL on_timeout,
858 ASSERT NOT NULL target,
859 ASSERT NOT NULL changes
860) AS
861WITH
862 managed AS (
863 SELECT
864 mz_internal.parse_catalog_id(data->'key'->'id') AS cluster_id,
865 data->'value'->'config'->'variant'->'Managed' AS config
866 FROM mz_internal.mz_catalog_raw
867 WHERE
868 data->>'kind' = 'Cluster' AND
869 data->'value'->'config'->'variant'->'Managed' IS NOT NULL
870 ),
871 records AS (
872 SELECT
873 cluster_id,
874 config,
875 config->'reconfiguration' AS reconfiguration,
876 config->'reconfiguration'->'target' AS target
877 FROM managed
878 WHERE config->'reconfiguration' != 'null'
879 )
880SELECT
881 r.cluster_id,
882 CASE r.reconfiguration->>'status'
883 WHEN 'InProgress' THEN 'in-progress'
884 WHEN 'Finalized' THEN 'finalized'
885 WHEN 'TimedOut' THEN 'timed-out'
886 WHEN 'Cancelled' THEN 'cancelled'
887 WHEN 'ResourceExhausted' THEN 'resource-exhausted'
888 ELSE r.reconfiguration->>'status'
889 END AS status,
890 (r.reconfiguration->>'deadline')::mz_timestamp AS deadline,
891 CASE r.reconfiguration->>'on_timeout'
892 WHEN 'Commit' THEN 'commit'
893 WHEN 'Rollback' THEN 'rollback'
894 ELSE r.reconfiguration->>'on_timeout'
895 END AS on_timeout,
896 r.target,
897 CASE WHEN r.target->'size' != r.config->'size'
898 THEN jsonb_build_object('size', r.target->'size') ELSE '{}'::jsonb END ||
899 CASE WHEN r.target->'replication_factor' != r.config->'replication_factor'
900 THEN jsonb_build_object('replication_factor', r.target->'replication_factor') ELSE '{}'::jsonb END ||
901 CASE WHEN r.target->'availability_zones' != r.config->'availability_zones'
902 THEN jsonb_build_object('availability_zones', r.target->'availability_zones') ELSE '{}'::jsonb END ||
903 CASE WHEN r.target->'logging' != r.config->'logging'
904 THEN jsonb_build_object('logging', r.target->'logging') ELSE '{}'::jsonb END ||
905 CASE WHEN r.target->'arrangement_compression' != r.config->'arrangement_compression'
906 THEN jsonb_build_object('arrangement_compression', r.target->'arrangement_compression') ELSE '{}'::jsonb END
907 AS changes
908FROM records r",
909 is_retained_metrics_object: false,
910 access: vec![PUBLIC_SELECT],
911 ontology: Some(Ontology {
912 entity_name: "cluster_reconfiguration",
913 description: "Latest graceful cluster reconfiguration",
914 links: &const {
915 [OntologyLink {
916 name: "belongs_to_cluster",
919 target: "cluster",
920 properties: LinkProperties::fk("cluster_id", "id", Cardinality::OneToOne),
921 }]
922 },
923 column_semantic_types: &[("cluster_id", SemanticType::ClusterId)],
924 }),
925 }
926});
927
928pub const MZ_CLUSTER_RECONFIGURATIONS_IND: BuiltinIndex = BuiltinIndex {
929 name: "mz_cluster_reconfigurations_ind",
930 schema: MZ_INTERNAL_SCHEMA,
931 oid: oid::INDEX_MZ_CLUSTER_RECONFIGURATIONS_IND_OID,
932 sql: "IN CLUSTER mz_catalog_server
933ON mz_internal.mz_cluster_reconfigurations (cluster_id)",
934 is_retained_metrics_object: false,
935};
936
937pub static MZ_CLUSTER_AUTO_SCALING_STRATEGIES: LazyLock<BuiltinMaterializedView> = LazyLock::new(
938 || {
939 BuiltinMaterializedView {
940 name: "mz_cluster_auto_scaling_strategies",
941 schema: MZ_INTERNAL_SCHEMA,
942 oid: oid::MV_MZ_CLUSTER_AUTO_SCALING_STRATEGIES_OID,
943 desc: RelationDesc::builder()
944 .with_column("cluster_id", SqlScalarType::String.nullable(false))
945 .with_column("strategy", SqlScalarType::Jsonb.nullable(false))
946 .with_column("state", SqlScalarType::Jsonb.nullable(true))
947 .with_key(vec![0])
948 .finish(),
949 column_comments: BTreeMap::from_iter([
950 (
951 "cluster_id",
952 "The ID of the cluster. Corresponds to `mz_clusters.id`.",
953 ),
954 (
955 "strategy",
956 "**Unstable** The configured autoscaling policy, as JSON. Currently an `on_hydration` sub-policy carrying its `hydration_size` and optional `linger_duration`.",
957 ),
958 (
959 "state",
960 "**Unstable** The in-flight autoscaling runtime state, as JSON keyed by strategy, or `NULL` when nothing is running. Currently a `burst` key carrying the active hydration burst: its `burst_size`, `linger_duration`, and `steady_hydrated_at`.",
961 ),
962 ]),
963 sql: "
969IN CLUSTER mz_catalog_server
970WITH (
971 ASSERT NOT NULL cluster_id,
972 ASSERT NOT NULL strategy
973) AS
974WITH
975 managed AS (
976 SELECT
977 mz_internal.parse_catalog_id(data->'key'->'id') AS cluster_id,
978 data->'value'->'config'->'variant'->'Managed'->'auto_scaling_strategy' AS strategy,
979 data->'value'->'config'->'variant'->'Managed'->'burst' AS burst
980 FROM mz_internal.mz_catalog_raw
981 WHERE
982 data->>'kind' = 'Cluster' AND
983 data->'value'->'config'->'variant'->'Managed' IS NOT NULL
984 )
985SELECT
986 m.cluster_id,
987 COALESCE(m.strategy, 'null'::jsonb) AS strategy,
988 CASE WHEN m.burst != 'null' THEN jsonb_build_object('burst', m.burst) END AS state
989FROM managed m
990WHERE m.strategy != 'null' OR m.burst != 'null'",
991 is_retained_metrics_object: false,
992 access: vec![PUBLIC_SELECT],
993 ontology: Some(Ontology {
994 entity_name: "cluster_auto_scaling_strategy",
995 description: "Configured cluster autoscaling strategy and in-flight state",
996 links: &const {
997 [OntologyLink {
998 name: "belongs_to_cluster",
1001 target: "cluster",
1002 properties: LinkProperties::fk("cluster_id", "id", Cardinality::OneToOne),
1003 }]
1004 },
1005 column_semantic_types: &[("cluster_id", SemanticType::ClusterId)],
1006 }),
1007 }
1008 },
1009);
1010
1011pub const MZ_CLUSTER_AUTO_SCALING_STRATEGIES_IND: BuiltinIndex = BuiltinIndex {
1012 name: "mz_cluster_auto_scaling_strategies_ind",
1013 schema: MZ_INTERNAL_SCHEMA,
1014 oid: oid::INDEX_MZ_CLUSTER_AUTO_SCALING_STRATEGIES_IND_OID,
1015 sql: "IN CLUSTER mz_catalog_server
1016ON mz_internal.mz_cluster_auto_scaling_strategies (cluster_id)",
1017 is_retained_metrics_object: false,
1018};
1019
1020pub static MZ_INTERNAL_CLUSTER_REPLICAS: LazyLock<BuiltinMaterializedView> =
1021 LazyLock::new(|| BuiltinMaterializedView {
1022 name: "mz_internal_cluster_replicas",
1023 schema: MZ_INTERNAL_SCHEMA,
1024 oid: oid::MV_MZ_INTERNAL_CLUSTER_REPLICAS_OID,
1025 desc: RelationDesc::builder()
1026 .with_column("id", SqlScalarType::String.nullable(false))
1027 .with_key(vec![0])
1028 .finish(),
1029 column_comments: BTreeMap::from_iter([(
1030 "id",
1031 "The ID of a cluster replica. Corresponds to `mz_cluster_replicas.id`.",
1032 )]),
1033 sql: "
1034IN CLUSTER mz_catalog_server
1035WITH (
1036 ASSERT NOT NULL id
1037) AS
1038SELECT mz_internal.parse_catalog_id(data->'key'->'id') AS id
1039FROM mz_internal.mz_catalog_raw
1040WHERE
1041 data->>'kind' = 'ClusterReplica' AND
1042 (data->'value'->'config'->'location'->'Managed'->>'internal')::bool = true",
1043 is_retained_metrics_object: false,
1044 access: vec![PUBLIC_SELECT],
1045 ontology: None,
1046 });
1047
1048pub static MZ_PENDING_CLUSTER_REPLICAS: LazyLock<BuiltinMaterializedView> =
1049 LazyLock::new(|| BuiltinMaterializedView {
1050 name: "mz_pending_cluster_replicas",
1051 schema: MZ_INTERNAL_SCHEMA,
1052 oid: oid::MV_MZ_PENDING_CLUSTER_REPLICAS_OID,
1053 desc: RelationDesc::builder()
1054 .with_column("id", SqlScalarType::String.nullable(false))
1055 .with_key(vec![0])
1056 .finish(),
1057 column_comments: BTreeMap::from_iter([(
1058 "id",
1059 "The ID of a cluster replica. Corresponds to `mz_cluster_replicas.id`.",
1060 )]),
1061 sql: "
1062IN CLUSTER mz_catalog_server
1063WITH (
1064 ASSERT NOT NULL id
1065) AS
1066SELECT mz_internal.parse_catalog_id(data->'key'->'id') AS id
1067FROM mz_internal.mz_catalog_raw
1068WHERE
1069 data->>'kind' = 'ClusterReplica' AND
1070 (data->'value'->'config'->'location'->'Managed'->>'pending')::bool = true",
1071 is_retained_metrics_object: false,
1072 access: vec![PUBLIC_SELECT],
1073 ontology: None,
1074 });
1075
1076pub static MZ_CLUSTER_REPLICA_SIZE_INTERNAL: LazyLock<BuiltinTable> = LazyLock::new(|| {
1094 BuiltinTable {
1095 name: "mz_cluster_replica_size_internal",
1096 schema: MZ_INTERNAL_SCHEMA,
1097 oid: oid::TABLE_MZ_CLUSTER_REPLICA_SIZE_INTERNAL_OID,
1098 desc: RelationDesc::builder()
1099 .with_column("size", SqlScalarType::String.nullable(false))
1100 .with_column("swap_enabled", SqlScalarType::Bool.nullable(false))
1101 .with_column("disk_bytes", SqlScalarType::UInt64.nullable(false))
1102 .with_key(vec![0])
1103 .finish(),
1104 column_comments: BTreeMap::from_iter([
1105 ("size", "The human-readable replica size."),
1106 (
1107 "swap_enabled",
1108 "Whether the replica size's pods are configured to allow swap. Used internally to compute the public `disk` column.",
1109 ),
1110 (
1111 "disk_bytes",
1112 "The replica size's disk limit in bytes (0 if explicitly disabled). Used internally to compute the public `disk` column.",
1113 ),
1114 ]),
1115 is_retained_metrics_object: true,
1116 access: vec![],
1117 ontology: None,
1118 }
1119});
1120
1121pub const MZ_CLUSTER_REPLICA_SIZE_INTERNAL_IND: BuiltinIndex = BuiltinIndex {
1122 name: "mz_cluster_replica_size_internal_ind",
1123 schema: MZ_INTERNAL_SCHEMA,
1124 oid: oid::INDEX_MZ_CLUSTER_REPLICA_SIZE_INTERNAL_IND_OID,
1125 sql: "IN CLUSTER mz_catalog_server
1126ON mz_internal.mz_cluster_replica_size_internal (size)",
1127 is_retained_metrics_object: true,
1128};
1129
1130pub static MZ_CLUSTER_REPLICA_STATUS_HISTORY: LazyLock<BuiltinSource> = LazyLock::new(|| {
1131 BuiltinSource {
1132 name: "mz_cluster_replica_status_history",
1133 schema: MZ_INTERNAL_SCHEMA,
1134 oid: oid::SOURCE_MZ_CLUSTER_REPLICA_STATUS_HISTORY_OID,
1135 data_source: IntrospectionType::ReplicaStatusHistory.into(),
1136 desc: REPLICA_STATUS_HISTORY_DESC.clone(),
1137 column_comments: BTreeMap::from_iter([
1138 ("replica_id", "The ID of a cluster replica."),
1139 ("process_id", "The ID of a process within the replica."),
1140 (
1141 "status",
1142 "The status of the cluster replica: `online` or `offline`.",
1143 ),
1144 (
1145 "reason",
1146 "If the cluster replica is in an `offline` state, the reason (if available). For example, `oom-killed`.",
1147 ),
1148 (
1149 "occurred_at",
1150 "Wall-clock timestamp at which the event occurred.",
1151 ),
1152 ]),
1153 is_retained_metrics_object: false,
1154 access: vec![PUBLIC_SELECT],
1155 ontology: Some(Ontology {
1156 entity_name: "replica_status_event",
1157 description: "Historical replica status events (ready, not-ready, etc.)",
1158 links: &const {
1159 [OntologyLink {
1160 name: "status_event_of_replica",
1161 target: "replica",
1162 properties: LinkProperties::fk_typed(
1163 "replica_id",
1164 "id",
1165 Cardinality::ManyToOne,
1166 mz_repr::SemanticType::CatalogItemId,
1167 ),
1168 }]
1169 },
1170 column_semantic_types: &[("replica_id", SemanticType::ReplicaId)],
1171 }),
1172 }
1173});
1174
1175pub static MZ_CLUSTER_REPLICA_STATUSES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
1176 name: "mz_cluster_replica_statuses",
1177 schema: MZ_INTERNAL_SCHEMA,
1178 oid: oid::VIEW_MZ_CLUSTER_REPLICA_STATUSES_OID,
1179 desc: RelationDesc::builder()
1180 .with_column("replica_id", SqlScalarType::String.nullable(false))
1181 .with_column("process_id", SqlScalarType::UInt64.nullable(false))
1182 .with_column("status", SqlScalarType::String.nullable(false))
1183 .with_column("reason", SqlScalarType::String.nullable(true))
1184 .with_column(
1185 "updated_at",
1186 SqlScalarType::TimestampTz { precision: None }.nullable(false),
1187 )
1188 .with_key(vec![0, 1])
1189 .finish(),
1190 column_comments: BTreeMap::from_iter([
1191 (
1192 "replica_id",
1193 "Materialize's unique ID for the cluster replica.",
1194 ),
1195 (
1196 "process_id",
1197 "The ID of the process within the cluster replica.",
1198 ),
1199 (
1200 "status",
1201 "The status of the cluster replica: `online` or `offline`.",
1202 ),
1203 (
1204 "reason",
1205 "If the cluster replica is in a `offline` state, the reason (if available). For example, `oom-killed`.",
1206 ),
1207 (
1208 "updated_at",
1209 "The time at which the status was last updated.",
1210 ),
1211 ]),
1212 sql: "
1213SELECT
1214 DISTINCT ON (replica_id, process_id)
1215 replica_id,
1216 process_id,
1217 status,
1218 reason,
1219 occurred_at as updated_at
1220FROM mz_internal.mz_cluster_replica_status_history
1221JOIN mz_cluster_replicas r ON r.id = replica_id
1222ORDER BY replica_id, process_id, occurred_at DESC",
1223 access: vec![PUBLIC_SELECT],
1224 ontology: Some(Ontology {
1225 entity_name: "replica_status",
1226 description: "Current status of each replica",
1227 links: &const {
1228 [OntologyLink {
1229 name: "status_of_replica",
1230 target: "replica",
1231 properties: LinkProperties::fk_typed(
1232 "replica_id",
1233 "id",
1234 Cardinality::ManyToOne,
1235 mz_repr::SemanticType::ReplicaId,
1236 ),
1237 }]
1238 },
1239 column_semantic_types: &const {
1240 [
1241 ("replica_id", SemanticType::ReplicaId),
1242 ("updated_at", SemanticType::WallclockTimestamp),
1243 ]
1244 },
1245 }),
1246});
1247
1248pub static MZ_SOURCE_STATUS_HISTORY: LazyLock<BuiltinSource> = LazyLock::new(|| BuiltinSource {
1249 name: "mz_source_status_history",
1250 schema: MZ_INTERNAL_SCHEMA,
1251 oid: oid::SOURCE_MZ_SOURCE_STATUS_HISTORY_OID,
1252 data_source: IntrospectionType::SourceStatusHistory.into(),
1253 desc: MZ_SOURCE_STATUS_HISTORY_DESC.clone(),
1254 column_comments: BTreeMap::from_iter([
1255 (
1256 "occurred_at",
1257 "Wall-clock timestamp of the source status change.",
1258 ),
1259 (
1260 "source_id",
1261 "The ID of the source. Corresponds to `mz_catalog.mz_sources.id`.",
1262 ),
1263 (
1264 "status",
1265 "The status of the source: one of `starting`, `running`, `paused`, `stalled`, or `dropped`.",
1266 ),
1267 (
1268 "error",
1269 "If the source is in an error state, the error message.",
1270 ),
1271 (
1272 "details",
1273 "Additional metadata provided by the source. In case of error, may contain a `hint` field with helpful suggestions.",
1274 ),
1275 (
1276 "replica_id",
1277 "The ID of the replica that an instance of a source is running on.",
1278 ),
1279 ]),
1280 is_retained_metrics_object: false,
1281 access: vec![PUBLIC_SELECT],
1282 ontology: Some(Ontology {
1283 entity_name: "source_status_event",
1284 description: "Historical source status events",
1285 links: &const {
1286 [
1287 OntologyLink {
1288 name: "status_event_of_source",
1289 target: "source",
1290 properties: LinkProperties::fk_mapped(
1291 "source_id",
1292 "id",
1293 Cardinality::ManyToOne,
1294 mz_repr::SemanticType::GlobalId,
1295 "mz_internal.mz_object_global_ids",
1296 ),
1297 },
1298 OntologyLink {
1299 name: "on_replica",
1300 target: "replica",
1301 properties: LinkProperties::fk_nullable(
1302 "replica_id",
1303 "id",
1304 Cardinality::ManyToOne,
1305 ),
1306 },
1307 ]
1308 },
1309 column_semantic_types: &const {
1310 [
1311 ("occurred_at", SemanticType::WallclockTimestamp),
1312 ("source_id", SemanticType::GlobalId),
1313 ("replica_id", SemanticType::ReplicaId),
1314 ]
1315 },
1316 }),
1317});
1318
1319pub static MZ_AWS_PRIVATELINK_CONNECTION_STATUS_HISTORY: LazyLock<BuiltinSource> = LazyLock::new(
1320 || BuiltinSource {
1321 name: "mz_aws_privatelink_connection_status_history",
1322 schema: MZ_INTERNAL_SCHEMA,
1323 oid: oid::SOURCE_MZ_AWS_PRIVATELINK_CONNECTION_STATUS_HISTORY_OID,
1324 data_source: DataSourceDesc::Introspection(
1325 IntrospectionType::PrivatelinkConnectionStatusHistory,
1326 ),
1327 desc: MZ_AWS_PRIVATELINK_CONNECTION_STATUS_HISTORY_DESC.clone(),
1328 column_comments: BTreeMap::from_iter([
1329 ("occurred_at", "Wall-clock timestamp of the status change."),
1330 (
1331 "connection_id",
1332 "The unique identifier of the AWS PrivateLink connection. Corresponds to `mz_catalog.mz_connections.id`.",
1333 ),
1334 (
1335 "status",
1336 "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`.",
1337 ),
1338 ]),
1339 is_retained_metrics_object: false,
1340 access: vec![PUBLIC_SELECT],
1341 ontology: None,
1342 },
1343);
1344
1345pub static MZ_AWS_PRIVATELINK_CONNECTION_STATUSES: LazyLock<BuiltinView> = LazyLock::new(|| {
1346 BuiltinView {
1347 name: "mz_aws_privatelink_connection_statuses",
1348 schema: MZ_INTERNAL_SCHEMA,
1349 oid: oid::VIEW_MZ_AWS_PRIVATELINK_CONNECTION_STATUSES_OID,
1350 desc: RelationDesc::builder()
1351 .with_column("id", SqlScalarType::String.nullable(false))
1352 .with_column("name", SqlScalarType::String.nullable(false))
1353 .with_column(
1354 "last_status_change_at",
1355 SqlScalarType::TimestampTz { precision: None }.nullable(true),
1356 )
1357 .with_column("status", SqlScalarType::String.nullable(true))
1358 .with_key(vec![0])
1359 .finish(),
1360 column_comments: BTreeMap::from_iter([
1361 (
1362 "id",
1363 "The ID of the connection. Corresponds to `mz_catalog.mz_connections.id`.",
1364 ),
1365 ("name", "The name of the connection."),
1366 (
1367 "last_status_change_at",
1368 "Wall-clock timestamp of the connection status change.",
1369 ),
1370 (
1371 "status",
1372 "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`.",
1373 ),
1374 ]),
1375 sql: "
1376 WITH statuses_w_last_status AS (
1377 SELECT
1378 connection_id,
1379 occurred_at,
1380 status,
1381 lag(status) OVER (PARTITION BY connection_id ORDER BY occurred_at) AS last_status
1382 FROM mz_internal.mz_aws_privatelink_connection_status_history
1383 ),
1384 latest_events AS (
1385 -- Only take the most recent transition for each ID
1386 SELECT DISTINCT ON(connection_id) connection_id, occurred_at, status
1387 FROM statuses_w_last_status
1388 -- Only keep first status transitions
1389 WHERE status <> last_status OR last_status IS NULL
1390 ORDER BY connection_id, occurred_at DESC
1391 )
1392 SELECT
1393 conns.id,
1394 name,
1395 occurred_at as last_status_change_at,
1396 status
1397 FROM latest_events
1398 JOIN mz_catalog.mz_connections AS conns
1399 ON conns.id = latest_events.connection_id",
1400 access: vec![PUBLIC_SELECT],
1401 ontology: Some(Ontology {
1402 entity_name: "privatelink_status",
1403 description: "PrivateLink connection health status",
1404 links: &const {
1405 [OntologyLink {
1406 name: "status_of",
1407 target: "connection",
1408 properties: LinkProperties::fk("id", "id", Cardinality::OneToOne),
1409 }]
1410 },
1411 column_semantic_types: &[("id", SemanticType::CatalogItemId)],
1412 }),
1413 }
1414});
1415
1416pub static MZ_STATEMENT_EXECUTION_HISTORY: LazyLock<BuiltinSource> =
1417 LazyLock::new(|| BuiltinSource {
1418 name: "mz_statement_execution_history",
1419 schema: MZ_INTERNAL_SCHEMA,
1420 oid: oid::SOURCE_MZ_STATEMENT_EXECUTION_HISTORY_OID,
1421 data_source: IntrospectionType::StatementExecutionHistory.into(),
1422 desc: MZ_STATEMENT_EXECUTION_HISTORY_DESC.clone(),
1423 column_comments: BTreeMap::new(),
1424 is_retained_metrics_object: false,
1425 access: vec![MONITOR_SELECT],
1426 ontology: None,
1427 });
1428
1429pub static MZ_STATEMENT_EXECUTION_HISTORY_REDACTED: LazyLock<BuiltinView> = LazyLock::new(|| {
1430 BuiltinView {
1431 name: "mz_statement_execution_history_redacted",
1432 schema: MZ_INTERNAL_SCHEMA,
1433 oid: oid::VIEW_MZ_STATEMENT_EXECUTION_HISTORY_REDACTED_OID,
1434 desc: RelationDesc::builder()
1436 .with_column("id", SqlScalarType::Uuid.nullable(false))
1437 .with_column("prepared_statement_id", SqlScalarType::Uuid.nullable(false))
1438 .with_column("sample_rate", SqlScalarType::Float64.nullable(false))
1439 .with_column("cluster_id", SqlScalarType::String.nullable(true))
1440 .with_column("application_name", SqlScalarType::String.nullable(false))
1441 .with_column("cluster_name", SqlScalarType::String.nullable(true))
1442 .with_column("database_name", SqlScalarType::String.nullable(false))
1443 .with_column("search_path", SqlScalarType::List { element_type: Box::new(SqlScalarType::String), custom_id: None }.nullable(false))
1444 .with_column("transaction_isolation", SqlScalarType::String.nullable(false))
1445 .with_column("execution_timestamp", SqlScalarType::UInt64.nullable(true))
1446 .with_column("transaction_id", SqlScalarType::UInt64.nullable(false))
1447 .with_column("transient_index_id", SqlScalarType::String.nullable(true))
1448 .with_column("mz_version", SqlScalarType::String.nullable(false))
1449 .with_column("began_at", SqlScalarType::TimestampTz { precision: None }.nullable(false))
1450 .with_column("finished_at", SqlScalarType::TimestampTz { precision: None }.nullable(true))
1451 .with_column("finished_status", SqlScalarType::String.nullable(true))
1452 .with_column("result_size", SqlScalarType::Int64.nullable(true))
1453 .with_column("rows_returned", SqlScalarType::Int64.nullable(true))
1454 .with_column("execution_strategy", SqlScalarType::String.nullable(true))
1455 .finish(),
1456 column_comments: BTreeMap::new(),
1457 sql: "
1458SELECT id, prepared_statement_id, sample_rate, cluster_id, application_name,
1459cluster_name, database_name, search_path, transaction_isolation, execution_timestamp, transaction_id,
1460transient_index_id, mz_version, began_at, finished_at, finished_status,
1461result_size, rows_returned, execution_strategy
1462FROM mz_internal.mz_statement_execution_history",
1463 access: vec![SUPPORT_SELECT, ANALYTICS_SELECT, MONITOR_REDACTED_SELECT, MONITOR_SELECT],
1464 ontology: None,
1465}
1466});
1467
1468pub static MZ_PREPARED_STATEMENT_HISTORY: LazyLock<BuiltinSource> =
1469 LazyLock::new(|| BuiltinSource {
1470 name: "mz_prepared_statement_history",
1471 schema: MZ_INTERNAL_SCHEMA,
1472 oid: oid::SOURCE_MZ_PREPARED_STATEMENT_HISTORY_OID,
1473 data_source: IntrospectionType::PreparedStatementHistory.into(),
1474 desc: MZ_PREPARED_STATEMENT_HISTORY_DESC.clone(),
1475 column_comments: BTreeMap::new(),
1476 is_retained_metrics_object: false,
1477 access: vec![
1478 SUPPORT_SELECT,
1479 ANALYTICS_SELECT,
1480 MONITOR_REDACTED_SELECT,
1481 MONITOR_SELECT,
1482 ],
1483 ontology: None,
1484 });
1485
1486pub static MZ_SQL_TEXT: LazyLock<BuiltinSource> = LazyLock::new(|| BuiltinSource {
1487 name: "mz_sql_text",
1488 schema: MZ_INTERNAL_SCHEMA,
1489 oid: oid::SOURCE_MZ_SQL_TEXT_OID,
1490 desc: MZ_SQL_TEXT_DESC.clone(),
1491 data_source: IntrospectionType::SqlText.into(),
1492 column_comments: BTreeMap::new(),
1493 is_retained_metrics_object: false,
1494 access: vec![MONITOR_SELECT],
1495 ontology: Some(Ontology {
1496 entity_name: "sql_text",
1497 description: "Raw SQL text of executed statements",
1498 links: &const { [] },
1499 column_semantic_types: &[],
1500 }),
1501});
1502
1503pub static MZ_SQL_TEXT_REDACTED: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
1504 name: "mz_sql_text_redacted",
1505 schema: MZ_INTERNAL_SCHEMA,
1506 oid: oid::VIEW_MZ_SQL_TEXT_REDACTED_OID,
1507 desc: RelationDesc::builder()
1508 .with_column("sql_hash", SqlScalarType::Bytes.nullable(false))
1509 .with_column("redacted_sql", SqlScalarType::String.nullable(false))
1510 .finish(),
1511 column_comments: BTreeMap::new(),
1512 sql: "SELECT sql_hash, redacted_sql FROM mz_internal.mz_sql_text",
1513 access: vec![
1514 MONITOR_SELECT,
1515 MONITOR_REDACTED_SELECT,
1516 SUPPORT_SELECT,
1517 ANALYTICS_SELECT,
1518 ],
1519 ontology: None,
1520});
1521
1522pub static MZ_RECENT_SQL_TEXT: LazyLock<BuiltinView> = LazyLock::new(|| {
1523 BuiltinView {
1524 name: "mz_recent_sql_text",
1525 schema: MZ_INTERNAL_SCHEMA,
1526 oid: oid::VIEW_MZ_RECENT_SQL_TEXT_OID,
1527 desc: RelationDesc::builder()
1532 .with_column("sql_hash", SqlScalarType::Bytes.nullable(false))
1533 .with_column("sql", SqlScalarType::String.nullable(false))
1534 .with_column("redacted_sql", SqlScalarType::String.nullable(false))
1535 .with_key(vec![0, 1, 2])
1536 .finish(),
1537 column_comments: BTreeMap::new(),
1538 sql: "SELECT DISTINCT sql_hash, sql, redacted_sql FROM mz_internal.mz_sql_text WHERE prepared_day + INTERVAL '4 days' >= mz_now()",
1539 access: vec![MONITOR_SELECT],
1540 ontology: Some(Ontology {
1541 entity_name: "recent_sql_text",
1542 description: "Recent SQL text (indexed, last ~3-4 days)",
1543 links: &const { [] },
1544 column_semantic_types: &[("sql", SemanticType::SqlDefinition)],
1545 }),
1546 }
1547});
1548
1549pub static MZ_RECENT_SQL_TEXT_REDACTED: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
1550 name: "mz_recent_sql_text_redacted",
1551 schema: MZ_INTERNAL_SCHEMA,
1552 oid: oid::VIEW_MZ_RECENT_SQL_TEXT_REDACTED_OID,
1553 desc: RelationDesc::builder()
1554 .with_column("sql_hash", SqlScalarType::Bytes.nullable(false))
1555 .with_column("redacted_sql", SqlScalarType::String.nullable(false))
1556 .finish(),
1557 column_comments: BTreeMap::new(),
1558 sql: "SELECT sql_hash, redacted_sql FROM mz_internal.mz_recent_sql_text",
1559 access: vec![
1560 MONITOR_SELECT,
1561 MONITOR_REDACTED_SELECT,
1562 SUPPORT_SELECT,
1563 ANALYTICS_SELECT,
1564 ],
1565 ontology: None,
1566});
1567
1568pub static MZ_RECENT_SQL_TEXT_IND: LazyLock<BuiltinIndex> = LazyLock::new(|| BuiltinIndex {
1569 name: "mz_recent_sql_text_ind",
1570 schema: MZ_INTERNAL_SCHEMA,
1571 oid: oid::INDEX_MZ_RECENT_SQL_TEXT_IND_OID,
1572 sql: "IN CLUSTER mz_catalog_server ON mz_internal.mz_recent_sql_text (sql_hash)",
1573 is_retained_metrics_object: false,
1574});
1575
1576pub static MZ_SESSION_HISTORY: LazyLock<BuiltinSource> = LazyLock::new(|| BuiltinSource {
1577 name: "mz_session_history",
1578 schema: MZ_INTERNAL_SCHEMA,
1579 oid: oid::SOURCE_MZ_SESSION_HISTORY_OID,
1580 data_source: IntrospectionType::SessionHistory.into(),
1581 desc: MZ_SESSION_HISTORY_DESC.clone(),
1582 column_comments: BTreeMap::from_iter([
1583 (
1584 "session_id",
1585 "The globally unique ID of the session. Corresponds to `mz_sessions.id`.",
1586 ),
1587 (
1588 "connected_at",
1589 "The time at which the session was established.",
1590 ),
1591 (
1592 "initial_application_name",
1593 "The `application_name` session metadata field.",
1594 ),
1595 (
1596 "authenticated_user",
1597 "The name of the user for which the session was established.",
1598 ),
1599 ]),
1600 is_retained_metrics_object: false,
1601 access: vec![PUBLIC_SELECT],
1602 ontology: Some(Ontology {
1603 entity_name: "session",
1604 description: "Historical session connection events",
1605 links: &const {
1606 [OntologyLink {
1607 name: "active_as",
1608 target: "active_session",
1609 properties: LinkProperties::fk_nullable("session_id", "id", Cardinality::ManyToOne),
1610 }]
1611 },
1612 column_semantic_types: &[("connected_at", SemanticType::WallclockTimestamp)],
1613 }),
1614});
1615
1616pub static MZ_ACTIVITY_LOG_THINNED: LazyLock<BuiltinView> = LazyLock::new(|| {
1617 BuiltinView {
1618 name: "mz_activity_log_thinned",
1619 schema: MZ_INTERNAL_SCHEMA,
1620 oid: oid::VIEW_MZ_ACTIVITY_LOG_THINNED_OID,
1621 desc: RelationDesc::builder()
1622 .with_column("execution_id", SqlScalarType::Uuid.nullable(false))
1623 .with_column("sample_rate", SqlScalarType::Float64.nullable(false))
1624 .with_column("cluster_id", SqlScalarType::String.nullable(true))
1625 .with_column("application_name", SqlScalarType::String.nullable(false))
1626 .with_column("cluster_name", SqlScalarType::String.nullable(true))
1627 .with_column("database_name", SqlScalarType::String.nullable(false))
1628 .with_column("search_path", SqlScalarType::List { element_type: Box::new(SqlScalarType::String), custom_id: None }.nullable(false))
1629 .with_column("transaction_isolation", SqlScalarType::String.nullable(false))
1630 .with_column("execution_timestamp", SqlScalarType::UInt64.nullable(true))
1631 .with_column("transient_index_id", SqlScalarType::String.nullable(true))
1632 .with_column("params", SqlScalarType::Array(Box::new(SqlScalarType::String)).nullable(false))
1633 .with_column("mz_version", SqlScalarType::String.nullable(false))
1634 .with_column("began_at", SqlScalarType::TimestampTz { precision: None }.nullable(false))
1635 .with_column("finished_at", SqlScalarType::TimestampTz { precision: None }.nullable(true))
1636 .with_column("finished_status", SqlScalarType::String.nullable(true))
1637 .with_column("error_message", SqlScalarType::String.nullable(true))
1638 .with_column("result_size", SqlScalarType::Int64.nullable(true))
1639 .with_column("rows_returned", SqlScalarType::Int64.nullable(true))
1640 .with_column("execution_strategy", SqlScalarType::String.nullable(true))
1641 .with_column("transaction_id", SqlScalarType::UInt64.nullable(false))
1642 .with_column("prepared_statement_id", SqlScalarType::Uuid.nullable(false))
1643 .with_column("sql_hash", SqlScalarType::Bytes.nullable(false))
1644 .with_column("prepared_statement_name", SqlScalarType::String.nullable(false))
1645 .with_column("session_id", SqlScalarType::Uuid.nullable(false))
1646 .with_column("prepared_at", SqlScalarType::TimestampTz { precision: None }.nullable(false))
1647 .with_column("statement_type", SqlScalarType::String.nullable(true))
1648 .with_column("throttled_count", SqlScalarType::UInt64.nullable(false))
1649 .with_column("connected_at", SqlScalarType::TimestampTz { precision: None }.nullable(false))
1650 .with_column("initial_application_name", SqlScalarType::String.nullable(false))
1651 .with_column("authenticated_user", SqlScalarType::String.nullable(false))
1652 .finish(),
1653 column_comments: BTreeMap::new(),
1654 sql: "
1655SELECT mseh.id AS execution_id, sample_rate, cluster_id, application_name, cluster_name, database_name, search_path,
1656transaction_isolation, execution_timestamp, transient_index_id, params, mz_version, began_at, finished_at, finished_status,
1657error_message, result_size, rows_returned, execution_strategy, transaction_id,
1658mpsh.id AS prepared_statement_id, sql_hash, mpsh.name AS prepared_statement_name,
1659mpsh.session_id, prepared_at, statement_type, throttled_count,
1660connected_at, initial_application_name, authenticated_user
1661FROM mz_internal.mz_statement_execution_history mseh,
1662 mz_internal.mz_prepared_statement_history mpsh,
1663 mz_internal.mz_session_history msh
1664WHERE mseh.prepared_statement_id = mpsh.id
1665AND mpsh.session_id = msh.session_id",
1666 access: vec![MONITOR_SELECT],
1667 ontology: None,
1668 }
1669});
1670
1671pub static MZ_RECENT_ACTIVITY_LOG_THINNED: LazyLock<BuiltinView> = LazyLock::new(|| {
1672 BuiltinView {
1673 name: "mz_recent_activity_log_thinned",
1674 schema: MZ_INTERNAL_SCHEMA,
1675 oid: oid::VIEW_MZ_RECENT_ACTIVITY_LOG_THINNED_OID,
1676 desc: RelationDesc::builder()
1677 .with_column("execution_id", SqlScalarType::Uuid.nullable(false))
1678 .with_column("sample_rate", SqlScalarType::Float64.nullable(false))
1679 .with_column("cluster_id", SqlScalarType::String.nullable(true))
1680 .with_column("application_name", SqlScalarType::String.nullable(false))
1681 .with_column("cluster_name", SqlScalarType::String.nullable(true))
1682 .with_column("database_name", SqlScalarType::String.nullable(false))
1683 .with_column("search_path", SqlScalarType::List { element_type: Box::new(SqlScalarType::String), custom_id: None }.nullable(false))
1684 .with_column("transaction_isolation", SqlScalarType::String.nullable(false))
1685 .with_column("execution_timestamp", SqlScalarType::UInt64.nullable(true))
1686 .with_column("transient_index_id", SqlScalarType::String.nullable(true))
1687 .with_column("params", SqlScalarType::Array(Box::new(SqlScalarType::String)).nullable(false))
1688 .with_column("mz_version", SqlScalarType::String.nullable(false))
1689 .with_column("began_at", SqlScalarType::TimestampTz { precision: None }.nullable(false))
1690 .with_column("finished_at", SqlScalarType::TimestampTz { precision: None }.nullable(true))
1691 .with_column("finished_status", SqlScalarType::String.nullable(true))
1692 .with_column("error_message", SqlScalarType::String.nullable(true))
1693 .with_column("result_size", SqlScalarType::Int64.nullable(true))
1694 .with_column("rows_returned", SqlScalarType::Int64.nullable(true))
1695 .with_column("execution_strategy", SqlScalarType::String.nullable(true))
1696 .with_column("transaction_id", SqlScalarType::UInt64.nullable(false))
1697 .with_column("prepared_statement_id", SqlScalarType::Uuid.nullable(false))
1698 .with_column("sql_hash", SqlScalarType::Bytes.nullable(false))
1699 .with_column("prepared_statement_name", SqlScalarType::String.nullable(false))
1700 .with_column("session_id", SqlScalarType::Uuid.nullable(false))
1701 .with_column("prepared_at", SqlScalarType::TimestampTz { precision: None }.nullable(false))
1702 .with_column("statement_type", SqlScalarType::String.nullable(true))
1703 .with_column("throttled_count", SqlScalarType::UInt64.nullable(false))
1704 .with_column("connected_at", SqlScalarType::TimestampTz { precision: None }.nullable(false))
1705 .with_column("initial_application_name", SqlScalarType::String.nullable(false))
1706 .with_column("authenticated_user", SqlScalarType::String.nullable(false))
1707 .finish(),
1708 column_comments: BTreeMap::new(),
1709 sql:
1712 "SELECT * FROM mz_internal.mz_activity_log_thinned WHERE prepared_at + INTERVAL '1 day' > mz_now()
1713AND began_at + INTERVAL '1 day' > mz_now() AND connected_at + INTERVAL '2 days' > mz_now()",
1714 access: vec![MONITOR_SELECT],
1715 ontology: None,
1716 }
1717});
1718
1719pub static MZ_RECENT_ACTIVITY_LOG: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
1720 name: "mz_recent_activity_log",
1721 schema: MZ_INTERNAL_SCHEMA,
1722 oid: oid::VIEW_MZ_RECENT_ACTIVITY_LOG_OID,
1723 desc: RelationDesc::builder()
1724 .with_column("execution_id", SqlScalarType::Uuid.nullable(false))
1725 .with_column("sample_rate", SqlScalarType::Float64.nullable(false))
1726 .with_column("cluster_id", SqlScalarType::String.nullable(true))
1727 .with_column("application_name", SqlScalarType::String.nullable(false))
1728 .with_column("cluster_name", SqlScalarType::String.nullable(true))
1729 .with_column("database_name", SqlScalarType::String.nullable(false))
1730 .with_column(
1731 "search_path",
1732 SqlScalarType::List {
1733 element_type: Box::new(SqlScalarType::String),
1734 custom_id: None,
1735 }
1736 .nullable(false),
1737 )
1738 .with_column(
1739 "transaction_isolation",
1740 SqlScalarType::String.nullable(false),
1741 )
1742 .with_column("execution_timestamp", SqlScalarType::UInt64.nullable(true))
1743 .with_column("transient_index_id", SqlScalarType::String.nullable(true))
1744 .with_column(
1745 "params",
1746 SqlScalarType::Array(Box::new(SqlScalarType::String)).nullable(false),
1747 )
1748 .with_column("mz_version", SqlScalarType::String.nullable(false))
1749 .with_column(
1750 "began_at",
1751 SqlScalarType::TimestampTz { precision: None }.nullable(false),
1752 )
1753 .with_column(
1754 "finished_at",
1755 SqlScalarType::TimestampTz { precision: None }.nullable(true),
1756 )
1757 .with_column("finished_status", SqlScalarType::String.nullable(true))
1758 .with_column("error_message", SqlScalarType::String.nullable(true))
1759 .with_column("result_size", SqlScalarType::Int64.nullable(true))
1760 .with_column("rows_returned", SqlScalarType::Int64.nullable(true))
1761 .with_column("execution_strategy", SqlScalarType::String.nullable(true))
1762 .with_column("transaction_id", SqlScalarType::UInt64.nullable(false))
1763 .with_column("prepared_statement_id", SqlScalarType::Uuid.nullable(false))
1764 .with_column("sql_hash", SqlScalarType::Bytes.nullable(false))
1765 .with_column(
1766 "prepared_statement_name",
1767 SqlScalarType::String.nullable(false),
1768 )
1769 .with_column("session_id", SqlScalarType::Uuid.nullable(false))
1770 .with_column(
1771 "prepared_at",
1772 SqlScalarType::TimestampTz { precision: None }.nullable(false),
1773 )
1774 .with_column("statement_type", SqlScalarType::String.nullable(true))
1775 .with_column("throttled_count", SqlScalarType::UInt64.nullable(false))
1776 .with_column(
1777 "connected_at",
1778 SqlScalarType::TimestampTz { precision: None }.nullable(false),
1779 )
1780 .with_column(
1781 "initial_application_name",
1782 SqlScalarType::String.nullable(false),
1783 )
1784 .with_column("authenticated_user", SqlScalarType::String.nullable(false))
1785 .with_column("sql", SqlScalarType::String.nullable(false))
1786 .finish(),
1787 column_comments: BTreeMap::from_iter([
1788 (
1789 "execution_id",
1790 "An ID that is unique for each executed statement.",
1791 ),
1792 (
1793 "sample_rate",
1794 "The actual rate at which the statement was sampled.",
1795 ),
1796 (
1797 "cluster_id",
1798 "The ID of the cluster the statement execution was directed to. Corresponds to mz_clusters.id.",
1799 ),
1800 (
1801 "application_name",
1802 "The value of the `application_name` configuration parameter at execution time.",
1803 ),
1804 (
1805 "cluster_name",
1806 "The name of the cluster with ID `cluster_id` at execution time.",
1807 ),
1808 (
1809 "database_name",
1810 "The value of the `database` configuration parameter at execution time.",
1811 ),
1812 (
1813 "search_path",
1814 "The value of the `search_path` configuration parameter at execution time.",
1815 ),
1816 (
1817 "transaction_isolation",
1818 "The value of the `transaction_isolation` configuration parameter at execution time.",
1819 ),
1820 (
1821 "execution_timestamp",
1822 "The logical timestamp at which execution was scheduled.",
1823 ),
1824 (
1825 "transient_index_id",
1826 "The internal index of the compute dataflow created for the query, if any.",
1827 ),
1828 (
1829 "params",
1830 "The parameters with which the statement was executed.",
1831 ),
1832 (
1833 "mz_version",
1834 "The version of Materialize that was running when the statement was executed.",
1835 ),
1836 (
1837 "began_at",
1838 "The wall-clock time at which the statement began executing.",
1839 ),
1840 (
1841 "finished_at",
1842 "The wall-clock time at which the statement finished executing.",
1843 ),
1844 (
1845 "finished_status",
1846 "The final status of the statement (e.g., `success`, `canceled`, `error`, or `aborted`). \
1847 `aborted` means that the client disconnected before the statement finished executing.",
1848 ),
1849 (
1850 "error_message",
1851 "The error message, if the statement failed.",
1852 ),
1853 (
1854 "result_size",
1855 "The size in bytes of the result, for statements that return rows.",
1856 ),
1857 (
1858 "rows_returned",
1859 "The number of rows returned, for statements that return rows.",
1860 ),
1861 (
1862 "execution_strategy",
1863 "For `SELECT` statements (and similar statement types), the strategy for executing the query. \
1864 `standard` means computed by a temporary dataflow, \
1865 `fast-path` means read by a cluster directly from an in-memory index, \
1866 `persist-fast-path` means read a source, table, or materialized view from blob storage (without an index or dataflow), \
1867 and `constant` means computed in the control plane without the involvement of a cluster. \
1868 (It's `NULL` for statements that errored/canceled/aborted and for non-query-like statement types.)",
1869 ),
1870 (
1871 "transaction_id",
1872 "The ID of the transaction that the statement was part of. Note that transaction IDs are only unique per session.",
1873 ),
1874 (
1875 "prepared_statement_id",
1876 "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`).",
1877 ),
1878 (
1879 "sql_hash",
1880 "An opaque value uniquely identifying the text of the query.",
1881 ),
1882 (
1883 "prepared_statement_name",
1884 "The name given by the client library to the prepared statement.",
1885 ),
1886 (
1887 "session_id",
1888 "An ID that is unique for each session. Corresponds to mz_sessions.id.",
1889 ),
1890 (
1891 "prepared_at",
1892 "The time at which the statement was prepared.",
1893 ),
1894 (
1895 "statement_type",
1896 "The _type_ of the statement, e.g. `select` for a `SELECT` query, or `NULL` if the statement was empty.",
1897 ),
1898 (
1899 "throttled_count",
1900 "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.",
1901 ),
1902 (
1903 "connected_at",
1904 "The time at which the session was established.",
1905 ),
1906 (
1907 "initial_application_name",
1908 "The initial value of `application_name` at the beginning of the session.",
1909 ),
1910 (
1911 "authenticated_user",
1912 "The name of the user for which the session was established.",
1913 ),
1914 ("sql", "The SQL text of the statement."),
1915 ]),
1916 sql: "SELECT mralt.*, mrst.sql
1917FROM mz_internal.mz_recent_activity_log_thinned mralt,
1918 mz_internal.mz_recent_sql_text mrst
1919WHERE mralt.sql_hash = mrst.sql_hash",
1920 access: vec![MONITOR_SELECT],
1921 ontology: Some(Ontology {
1922 entity_name: "activity_log",
1923 description: "Recent query activity with execution stats",
1924 links: &const {
1925 [
1926 OntologyLink {
1927 name: "in_session",
1928 target: "session",
1929 properties: LinkProperties::fk("session_id", "id", Cardinality::ManyToOne),
1930 },
1931 OntologyLink {
1932 name: "in_active_session",
1933 target: "active_session",
1934 properties: LinkProperties::fk_nullable(
1935 "session_id",
1936 "id",
1937 Cardinality::ManyToOne,
1938 ),
1939 },
1940 OntologyLink {
1941 name: "ran_on_cluster",
1942 target: "cluster",
1943 properties: LinkProperties::fk_nullable(
1944 "cluster_id",
1945 "id",
1946 Cardinality::ManyToOne,
1947 ),
1948 },
1949 OntologyLink {
1950 name: "used_transient_index",
1951 target: "object",
1952 properties: LinkProperties::ForeignKey {
1953 source_column: "transient_index_id",
1954 target_column: "id",
1955 cardinality: Cardinality::ManyToOne,
1956 source_id_type: Some(mz_repr::SemanticType::GlobalId),
1957 requires_mapping: Some("mz_internal.mz_object_global_ids"),
1958 nullable: true,
1959 note: None,
1960 extra_key_columns: None,
1961 },
1962 },
1963 ]
1964 },
1965 column_semantic_types: &const {
1966 [
1967 ("cluster_id", SemanticType::ClusterId),
1968 ("execution_timestamp", SemanticType::MzTimestamp),
1969 ("transient_index_id", SemanticType::GlobalId),
1970 ("began_at", SemanticType::WallclockTimestamp),
1971 ("finished_at", SemanticType::WallclockTimestamp),
1972 ("prepared_at", SemanticType::WallclockTimestamp),
1973 ("connected_at", SemanticType::WallclockTimestamp),
1974 ("sql", SemanticType::SqlDefinition),
1975 ]
1976 },
1977 }),
1978});
1979
1980pub static MZ_RECENT_ACTIVITY_LOG_REDACTED: LazyLock<BuiltinView> = LazyLock::new(|| {
1981 BuiltinView {
1982 name: "mz_recent_activity_log_redacted",
1983 schema: MZ_INTERNAL_SCHEMA,
1984 oid: oid::VIEW_MZ_RECENT_ACTIVITY_LOG_REDACTED_OID,
1985 desc: RelationDesc::builder()
1987 .with_column("execution_id", SqlScalarType::Uuid.nullable(false))
1988 .with_column("sample_rate", SqlScalarType::Float64.nullable(false))
1989 .with_column("cluster_id", SqlScalarType::String.nullable(true))
1990 .with_column("application_name", SqlScalarType::String.nullable(false))
1991 .with_column("cluster_name", SqlScalarType::String.nullable(true))
1992 .with_column("database_name", SqlScalarType::String.nullable(false))
1993 .with_column("search_path", SqlScalarType::List { element_type: Box::new(SqlScalarType::String), custom_id: None }.nullable(false))
1994 .with_column("transaction_isolation", SqlScalarType::String.nullable(false))
1995 .with_column("execution_timestamp", SqlScalarType::UInt64.nullable(true))
1996 .with_column("transient_index_id", SqlScalarType::String.nullable(true))
1997 .with_column("mz_version", SqlScalarType::String.nullable(false))
1998 .with_column("began_at", SqlScalarType::TimestampTz { precision: None }.nullable(false))
1999 .with_column("finished_at", SqlScalarType::TimestampTz { precision: None }.nullable(true))
2000 .with_column("finished_status", SqlScalarType::String.nullable(true))
2001 .with_column("result_size", SqlScalarType::Int64.nullable(true))
2002 .with_column("rows_returned", SqlScalarType::Int64.nullable(true))
2003 .with_column("execution_strategy", SqlScalarType::String.nullable(true))
2004 .with_column("transaction_id", SqlScalarType::UInt64.nullable(false))
2005 .with_column("prepared_statement_id", SqlScalarType::Uuid.nullable(false))
2006 .with_column("sql_hash", SqlScalarType::Bytes.nullable(false))
2007 .with_column("prepared_statement_name", SqlScalarType::String.nullable(false))
2008 .with_column("session_id", SqlScalarType::Uuid.nullable(false))
2009 .with_column("prepared_at", SqlScalarType::TimestampTz { precision: None }.nullable(false))
2010 .with_column("statement_type", SqlScalarType::String.nullable(true))
2011 .with_column("throttled_count", SqlScalarType::UInt64.nullable(false))
2012 .with_column("initial_application_name", SqlScalarType::String.nullable(false))
2013 .with_column("authenticated_user", SqlScalarType::String.nullable(false))
2014 .with_column("redacted_sql", SqlScalarType::String.nullable(false))
2015 .finish(),
2016 column_comments: BTreeMap::new(),
2017 sql: "SELECT mralt.execution_id, mralt.sample_rate, mralt.cluster_id, mralt.application_name,
2018 mralt.cluster_name, mralt.database_name, mralt.search_path, mralt.transaction_isolation, mralt.execution_timestamp,
2019 mralt.transient_index_id, mralt.mz_version, mralt.began_at, mralt.finished_at,
2020 mralt.finished_status, mralt.result_size, mralt.rows_returned, mralt.execution_strategy, mralt.transaction_id,
2021 mralt.prepared_statement_id, mralt.sql_hash, mralt.prepared_statement_name, mralt.session_id,
2022 mralt.prepared_at, mralt.statement_type, mralt.throttled_count,
2023 mralt.initial_application_name, mralt.authenticated_user,
2024 mrst.redacted_sql
2025FROM mz_internal.mz_recent_activity_log_thinned mralt,
2026 mz_internal.mz_recent_sql_text mrst
2027WHERE mralt.sql_hash = mrst.sql_hash",
2028 access: vec![MONITOR_SELECT, MONITOR_REDACTED_SELECT, SUPPORT_SELECT, ANALYTICS_SELECT],
2029 ontology: None,
2030}
2031});
2032
2033pub static MZ_STATEMENT_LIFECYCLE_HISTORY: LazyLock<BuiltinSource> = LazyLock::new(|| {
2034 BuiltinSource {
2035 name: "mz_statement_lifecycle_history",
2036 schema: MZ_INTERNAL_SCHEMA,
2037 oid: oid::SOURCE_MZ_STATEMENT_LIFECYCLE_HISTORY_OID,
2038 desc: RelationDesc::builder()
2039 .with_column("statement_id", SqlScalarType::Uuid.nullable(false))
2040 .with_column("event_type", SqlScalarType::String.nullable(false))
2041 .with_column(
2042 "occurred_at",
2043 SqlScalarType::TimestampTz { precision: None }.nullable(false),
2044 )
2045 .finish(),
2046 data_source: IntrospectionType::StatementLifecycleHistory.into(),
2047 column_comments: BTreeMap::from_iter([
2048 (
2049 "statement_id",
2050 "The ID of the execution event. Corresponds to `mz_recent_activity_log.execution_id`",
2051 ),
2052 (
2053 "event_type",
2054 "The type of lifecycle event, e.g. `'execution-began'`, `'storage-dependencies-finished'`, `'compute-dependencies-finished'`, or `'execution-finished'`",
2055 ),
2056 ("occurred_at", "The time at which the event took place."),
2057 ]),
2058 is_retained_metrics_object: false,
2059 access: vec![
2063 SUPPORT_SELECT,
2064 ANALYTICS_SELECT,
2065 MONITOR_REDACTED_SELECT,
2066 MONITOR_SELECT,
2067 ],
2068 ontology: Some(Ontology {
2069 entity_name: "statement_lifecycle_event",
2070 description: "Statement lifecycle events (parse, bind, execute)",
2071 links: &const {
2072 [OntologyLink {
2073 name: "for_execution",
2074 target: "activity_log",
2075 properties: LinkProperties::fk(
2076 "statement_id",
2077 "execution_id",
2078 Cardinality::ManyToOne,
2079 ),
2080 }]
2081 },
2082 column_semantic_types: &[],
2083 }),
2084 }
2085});
2086
2087pub static MZ_SOURCE_STATUSES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
2088 name: "mz_source_statuses",
2089 schema: MZ_INTERNAL_SCHEMA,
2090 oid: oid::VIEW_MZ_SOURCE_STATUSES_OID,
2091 desc: RelationDesc::builder()
2092 .with_column("id", SqlScalarType::String.nullable(false))
2093 .with_column("name", SqlScalarType::String.nullable(false))
2094 .with_column("type", SqlScalarType::String.nullable(false))
2095 .with_column(
2096 "last_status_change_at",
2097 SqlScalarType::TimestampTz { precision: None }.nullable(true),
2098 )
2099 .with_column("status", SqlScalarType::String.nullable(false))
2100 .with_column("error", SqlScalarType::String.nullable(true))
2101 .with_column("details", SqlScalarType::Jsonb.nullable(true))
2102 .finish(),
2103 column_comments: BTreeMap::from_iter([
2104 (
2105 "id",
2106 "The ID of the source. Corresponds to `mz_catalog.mz_sources.id`.",
2107 ),
2108 ("name", "The name of the source."),
2109 ("type", "The type of the source."),
2110 (
2111 "last_status_change_at",
2112 "Wall-clock timestamp of the source status change.",
2113 ),
2114 (
2115 "status",
2116 "The status of the source: one of `created`, `starting`, `running`, `paused`, `stalled`, or `dropped`.",
2117 ),
2118 (
2119 "error",
2120 "If the source is in an error state, the error message.",
2121 ),
2122 (
2123 "details",
2124 "Additional metadata provided by the source. In case of error, may contain a `hint` field with helpful suggestions.",
2125 ),
2126 ]),
2127 sql: "
2128 WITH
2129 -- The status history contains per-replica events and source-global events.
2130 -- For the latter, replica_id is NULL. We turn these into '<source>', so that
2131 -- we can treat them uniformly below.
2132 uniform_status_history AS
2133 (
2134 SELECT
2135 s.source_id,
2136 COALESCE(s.replica_id, '<source>') as replica_id,
2137 s.occurred_at,
2138 s.status,
2139 s.error,
2140 s.details
2141 FROM mz_internal.mz_source_status_history s
2142 ),
2143 -- For getting the latest events, we first determine the latest per-replica
2144 -- events here and then apply precedence rules below.
2145 --
2146 -- We ignore per-replica events from replicas that no longer exist. A dropped
2147 -- replica's last reported status is stale: without this filter a defunct
2148 -- replica's lingering 'running' can outrank (see precedence below) a live
2149 -- replica's 'stalled', hiding a genuinely broken source. We always retain
2150 -- source-global events ('<source>' is the sentinel for replica_id NULL)
2151 -- and 'paused' events. A per-replica 'paused' is only written when the
2152 -- replica is dropped, so it is a terminal drop marker, not a stale report.
2153 latest_per_replica_events AS
2154 (
2155 SELECT DISTINCT ON (source_id, replica_id)
2156 occurred_at, source_id, replica_id, status, error, details
2157 FROM uniform_status_history
2158 WHERE replica_id = '<source>'
2159 OR replica_id IN (SELECT id FROM mz_catalog.mz_cluster_replicas)
2160 OR status = 'paused'
2161 ORDER BY source_id, replica_id, occurred_at DESC
2162 ),
2163 -- We have a precedence list that determines the overall status in case
2164 -- there is differing per-replica (including source-global) statuses. If
2165 -- there is no 'dropped' status, and any replica reports 'running', the
2166 -- overall status is 'running' even if there might be some replica that has
2167 -- errors or is paused. Precedence ties are broken by recency, so a dropped
2168 -- replica's 'paused' wins over an older source-global 'paused'.
2169 latest_events AS
2170 (
2171 SELECT DISTINCT ON (source_id)
2172 source_id,
2173 occurred_at,
2174 status,
2175 error,
2176 details
2177 FROM latest_per_replica_events
2178 ORDER BY source_id, CASE status
2179 WHEN 'dropped' THEN 1
2180 WHEN 'running' THEN 2
2181 WHEN 'stalled' THEN 3
2182 WHEN 'starting' THEN 4
2183 WHEN 'paused' THEN 5
2184 WHEN 'ceased' THEN 6
2185 ELSE 7 -- For any other status values
2186 END, occurred_at DESC
2187 ),
2188 -- Determine which sources are subsources and which are parent sources
2189 subsources AS
2190 (
2191 SELECT subsources.id AS self, sources.id AS parent
2192 FROM
2193 mz_catalog.mz_sources AS subsources
2194 JOIN
2195 mz_internal.mz_object_dependencies AS deps
2196 ON subsources.id = deps.object_id
2197 JOIN mz_catalog.mz_sources AS sources ON sources.id = deps.referenced_object_id
2198 ),
2199 -- Determine which sources are source tables
2200 tables AS
2201 (
2202 SELECT tables.id AS self, tables.source_id AS parent, tables.name
2203 FROM mz_catalog.mz_tables AS tables
2204 WHERE tables.source_id IS NOT NULL
2205 ),
2206 -- Determine which collection's ID to use for the status
2207 id_of_status_to_use AS
2208 (
2209 SELECT
2210 self_events.source_id,
2211 -- If self not errored, but parent is, use parent; else self
2212 CASE
2213 WHEN
2214 self_events.status <> 'ceased' AND
2215 parent_events.status = 'stalled'
2216 THEN parent_events.source_id
2217 ELSE self_events.source_id
2218 END AS id_to_use
2219 FROM
2220 latest_events AS self_events
2221 LEFT JOIN subsources ON self_events.source_id = subsources.self
2222 LEFT JOIN tables ON self_events.source_id = tables.self
2223 LEFT JOIN
2224 latest_events AS parent_events
2225 ON parent_events.source_id = COALESCE(subsources.parent, tables.parent)
2226 ),
2227 -- Swap out events for the ID of the event we plan to use instead
2228 latest_events_to_use AS
2229 (
2230 SELECT occurred_at, s.source_id, status, error, details
2231 FROM
2232 id_of_status_to_use AS s
2233 JOIN latest_events AS e ON e.source_id = s.id_to_use
2234 ),
2235 combined AS (
2236 SELECT
2237 mz_sources.id,
2238 mz_sources.name,
2239 mz_sources.type,
2240 occurred_at,
2241 status,
2242 error,
2243 details
2244 FROM
2245 mz_catalog.mz_sources
2246 LEFT JOIN latest_events_to_use AS e ON mz_sources.id = e.source_id
2247 UNION ALL
2248 SELECT
2249 tables.self AS id,
2250 tables.name,
2251 'table' AS type,
2252 occurred_at,
2253 status,
2254 error,
2255 details
2256 FROM
2257 tables
2258 LEFT JOIN latest_events_to_use AS e ON tables.self = e.source_id
2259 )
2260SELECT
2261 id,
2262 name,
2263 type,
2264 occurred_at AS last_status_change_at,
2265 -- TODO(parkmycar): Report status of webhook source once database-issues#5986 is closed.
2266 CASE
2267 WHEN
2268 type = 'webhook' OR
2269 type = 'progress'
2270 THEN 'running'
2271 ELSE COALESCE(status, 'created')
2272 END AS status,
2273 error,
2274 details
2275FROM combined
2276WHERE id NOT LIKE 's%';",
2277 access: vec![PUBLIC_SELECT],
2278 ontology: Some(Ontology {
2279 entity_name: "source_status",
2280 description: "Current source status (running, stalled, etc.)",
2281 links: &const {
2282 [OntologyLink {
2283 name: "status_of_source",
2284 target: "source",
2285 properties: LinkProperties::fk("id", "id", Cardinality::OneToOne),
2286 }]
2287 },
2288 column_semantic_types: &const {
2289 [
2290 ("id", SemanticType::CatalogItemId),
2291 ("type", SemanticType::SourceType),
2292 ("last_status_change_at", SemanticType::WallclockTimestamp),
2293 ]
2294 },
2295 }),
2296});
2297
2298pub static MZ_SINK_STATUS_HISTORY: LazyLock<BuiltinSource> = LazyLock::new(|| BuiltinSource {
2299 name: "mz_sink_status_history",
2300 schema: MZ_INTERNAL_SCHEMA,
2301 oid: oid::SOURCE_MZ_SINK_STATUS_HISTORY_OID,
2302 data_source: IntrospectionType::SinkStatusHistory.into(),
2303 desc: MZ_SINK_STATUS_HISTORY_DESC.clone(),
2304 column_comments: BTreeMap::from_iter([
2305 (
2306 "occurred_at",
2307 "Wall-clock timestamp of the sink status change.",
2308 ),
2309 (
2310 "sink_id",
2311 "The ID of the sink. Corresponds to `mz_catalog.mz_sinks.id`.",
2312 ),
2313 (
2314 "status",
2315 "The status of the sink: one of `starting`, `running`, `paused`, `stalled`, or `dropped`.",
2316 ),
2317 (
2318 "error",
2319 "If the sink is in an error state, the error message.",
2320 ),
2321 (
2322 "details",
2323 "Additional metadata provided by the sink. In case of error, may contain a `hint` field with helpful suggestions.",
2324 ),
2325 (
2326 "replica_id",
2327 "The ID of the replica that an instance of a sink is running on.",
2328 ),
2329 ]),
2330 is_retained_metrics_object: false,
2331 access: vec![PUBLIC_SELECT],
2332 ontology: Some(Ontology {
2333 entity_name: "sink_status_event",
2334 description: "Historical sink status events",
2335 links: &const {
2336 [
2337 OntologyLink {
2338 name: "status_event_of_sink",
2339 target: "sink",
2340 properties: LinkProperties::fk_mapped(
2341 "sink_id",
2342 "id",
2343 Cardinality::ManyToOne,
2344 mz_repr::SemanticType::GlobalId,
2345 "mz_internal.mz_object_global_ids",
2346 ),
2347 },
2348 OntologyLink {
2349 name: "on_replica",
2350 target: "replica",
2351 properties: LinkProperties::fk_nullable(
2352 "replica_id",
2353 "id",
2354 Cardinality::ManyToOne,
2355 ),
2356 },
2357 ]
2358 },
2359 column_semantic_types: &const {
2360 [
2361 ("occurred_at", SemanticType::WallclockTimestamp),
2362 ("sink_id", SemanticType::GlobalId),
2363 ("replica_id", SemanticType::ReplicaId),
2364 ]
2365 },
2366 }),
2367});
2368
2369pub static MZ_SINK_STATUSES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
2370 name: "mz_sink_statuses",
2371 schema: MZ_INTERNAL_SCHEMA,
2372 oid: oid::VIEW_MZ_SINK_STATUSES_OID,
2373 desc: RelationDesc::builder()
2374 .with_column("id", SqlScalarType::String.nullable(false))
2375 .with_column("name", SqlScalarType::String.nullable(false))
2376 .with_column("type", SqlScalarType::String.nullable(false))
2377 .with_column(
2378 "last_status_change_at",
2379 SqlScalarType::TimestampTz { precision: None }.nullable(true),
2380 )
2381 .with_column("status", SqlScalarType::String.nullable(false))
2382 .with_column("error", SqlScalarType::String.nullable(true))
2383 .with_column("details", SqlScalarType::Jsonb.nullable(true))
2384 .finish(),
2385 column_comments: BTreeMap::from_iter([
2386 (
2387 "id",
2388 "The ID of the sink. Corresponds to `mz_catalog.mz_sinks.id`.",
2389 ),
2390 ("name", "The name of the sink."),
2391 ("type", "The type of the sink."),
2392 (
2393 "last_status_change_at",
2394 "Wall-clock timestamp of the sink status change.",
2395 ),
2396 (
2397 "status",
2398 "The status of the sink: one of `created`, `starting`, `running`, `paused`, `stalled`, or `dropped`.",
2399 ),
2400 (
2401 "error",
2402 "If the sink is in an error state, the error message.",
2403 ),
2404 (
2405 "details",
2406 "Additional metadata provided by the sink. In case of error, may contain a `hint` field with helpful suggestions.",
2407 ),
2408 ]),
2409 sql: "
2410WITH
2411-- The status history contains per-replica events and sink-global events.
2412-- For the latter, replica_id is NULL. We turn these into '<sink>', so that
2413-- we can treat them uniformly below.
2414uniform_status_history AS
2415(
2416 SELECT
2417 s.sink_id,
2418 COALESCE(s.replica_id, '<sink>') as replica_id,
2419 s.occurred_at,
2420 s.status,
2421 s.error,
2422 s.details
2423 FROM mz_internal.mz_sink_status_history s
2424),
2425-- For getting the latest events, we first determine the latest per-replica
2426-- events here and then apply precedence rules below.
2427--
2428-- We ignore per-replica events from replicas that no longer exist. A dropped
2429-- replica's last reported status is stale: without this filter a defunct
2430-- replica's lingering 'running' can outrank (see precedence below) a live
2431-- replica's 'stalled', hiding a genuinely broken sink. We always retain
2432-- sink-global events ('<sink>' is the sentinel for replica_id NULL)
2433-- and 'paused' events. A per-replica 'paused' is only written when the
2434-- replica is dropped, so it is a terminal drop marker, not a stale report.
2435latest_per_replica_events AS
2436(
2437 SELECT DISTINCT ON (sink_id, replica_id)
2438 occurred_at, sink_id, replica_id, status, error, details
2439 FROM uniform_status_history
2440 WHERE replica_id = '<sink>'
2441 OR replica_id IN (SELECT id FROM mz_catalog.mz_cluster_replicas)
2442 OR status = 'paused'
2443 ORDER BY sink_id, replica_id, occurred_at DESC
2444),
2445-- We have a precedence list that determines the overall status in case
2446-- there is differing per-replica (including sink-global) statuses. If
2447-- there is no 'dropped' status, and any replica reports 'running', the
2448-- overall status is 'running' even if there might be some replica that has
2449-- errors or is paused. Precedence ties are broken by recency, so a dropped
2450-- replica's 'paused' wins over an older sink-global 'paused'.
2451latest_events AS
2452(
2453 SELECT DISTINCT ON (sink_id)
2454 sink_id,
2455 occurred_at,
2456 status,
2457 error,
2458 details
2459 FROM latest_per_replica_events
2460 ORDER BY sink_id, CASE status
2461 WHEN 'dropped' THEN 1
2462 WHEN 'running' THEN 2
2463 WHEN 'stalled' THEN 3
2464 WHEN 'starting' THEN 4
2465 WHEN 'paused' THEN 5
2466 WHEN 'ceased' THEN 6
2467 ELSE 7 -- For any other status values
2468 END, occurred_at DESC
2469)
2470SELECT
2471 mz_sinks.id,
2472 name,
2473 mz_sinks.type,
2474 occurred_at as last_status_change_at,
2475 coalesce(status, 'created') as status,
2476 error,
2477 details
2478FROM mz_catalog.mz_sinks
2479LEFT JOIN latest_events ON mz_sinks.id = latest_events.sink_id
2480WHERE
2481 -- This is a convenient way to filter out system sinks, like the status_history table itself.
2482 mz_sinks.id NOT LIKE 's%'",
2483 access: vec![PUBLIC_SELECT],
2484 ontology: Some(Ontology {
2485 entity_name: "sink_status",
2486 description: "Current sink status",
2487 links: &const {
2488 [OntologyLink {
2489 name: "status_of_sink",
2490 target: "sink",
2491 properties: LinkProperties::fk_typed(
2492 "id",
2493 "id",
2494 Cardinality::OneToOne,
2495 mz_repr::SemanticType::CatalogItemId,
2496 ),
2497 }]
2498 },
2499 column_semantic_types: &const {
2500 [
2501 ("id", SemanticType::CatalogItemId),
2502 ("last_status_change_at", SemanticType::WallclockTimestamp),
2503 ]
2504 },
2505 }),
2506});
2507
2508pub static MZ_STORAGE_USAGE_BY_SHARD: LazyLock<BuiltinTable> = LazyLock::new(|| BuiltinTable {
2509 name: "mz_storage_usage_by_shard",
2510 schema: MZ_INTERNAL_SCHEMA,
2511 oid: oid::TABLE_MZ_STORAGE_USAGE_BY_SHARD_OID,
2512 desc: RelationDesc::builder()
2513 .with_column("id", SqlScalarType::UInt64.nullable(false))
2514 .with_column("shard_id", SqlScalarType::String.nullable(true))
2515 .with_column("size_bytes", SqlScalarType::UInt64.nullable(false))
2516 .with_column(
2517 "collection_timestamp",
2518 SqlScalarType::TimestampTz { precision: None }.nullable(false),
2519 )
2520 .finish(),
2521 column_comments: BTreeMap::new(),
2522 is_retained_metrics_object: false,
2523 access: vec![PUBLIC_SELECT],
2524 ontology: Some(Ontology {
2525 entity_name: "storage_usage_by_shard",
2526 description: "Storage usage broken down by shard",
2527 links: &const { [] },
2528 column_semantic_types: &const {
2529 [
2530 ("shard_id", SemanticType::ShardId),
2531 ("size_bytes", SemanticType::ByteCount),
2532 ("collection_timestamp", SemanticType::WallclockTimestamp),
2533 ]
2534 },
2535 }),
2536});
2537
2538pub static MZ_AWS_CONNECTIONS: LazyLock<BuiltinMaterializedView> = LazyLock::new(|| {
2551 BuiltinMaterializedView {
2552 name: "mz_aws_connections",
2553 schema: MZ_INTERNAL_SCHEMA,
2554 oid: oid::MV_MZ_AWS_CONNECTIONS_OID,
2555 desc: RelationDesc::builder()
2556 .with_column("id", SqlScalarType::String.nullable(false))
2557 .with_column("endpoint", SqlScalarType::String.nullable(true))
2558 .with_column("region", SqlScalarType::String.nullable(true))
2559 .with_column("access_key_id", SqlScalarType::String.nullable(true))
2560 .with_column(
2561 "access_key_id_secret_id",
2562 SqlScalarType::String.nullable(true),
2563 )
2564 .with_column(
2565 "secret_access_key_secret_id",
2566 SqlScalarType::String.nullable(true),
2567 )
2568 .with_column("session_token", SqlScalarType::String.nullable(true))
2569 .with_column(
2570 "session_token_secret_id",
2571 SqlScalarType::String.nullable(true),
2572 )
2573 .with_column("assume_role_arn", SqlScalarType::String.nullable(true))
2574 .with_column(
2575 "assume_role_session_name",
2576 SqlScalarType::String.nullable(true),
2577 )
2578 .with_column("principal", SqlScalarType::String.nullable(true))
2579 .with_column("external_id", SqlScalarType::String.nullable(true))
2580 .with_column("example_trust_policy", SqlScalarType::Jsonb.nullable(true))
2581 .with_key(vec![0])
2582 .finish(),
2583 column_comments: BTreeMap::from_iter([
2584 ("id", "The ID of the connection."),
2585 ("endpoint", "The value of the `ENDPOINT` option, if set."),
2586 ("region", "The value of the `REGION` option, if set."),
2587 (
2588 "access_key_id",
2589 "The value of the `ACCESS KEY ID` option, if provided in line.",
2590 ),
2591 (
2592 "access_key_id_secret_id",
2593 "The ID of the secret referenced by the `ACCESS KEY ID` option, if provided via a secret.",
2594 ),
2595 (
2596 "secret_access_key_secret_id",
2597 "The ID of the secret referenced by the `SECRET ACCESS KEY` option, if set.",
2598 ),
2599 (
2600 "session_token",
2601 "The value of the `SESSION TOKEN` option, if provided in line.",
2602 ),
2603 (
2604 "session_token_secret_id",
2605 "The ID of the secret referenced by the `SESSION TOKEN` option, if provided via a secret.",
2606 ),
2607 (
2608 "assume_role_arn",
2609 "The value of the `ASSUME ROLE ARN` option, if set.",
2610 ),
2611 (
2612 "assume_role_session_name",
2613 "The value of the `ASSUME ROLE SESSION NAME` option, if set.",
2614 ),
2615 (
2616 "principal",
2617 "The ARN of the AWS principal Materialize will use when assuming the provided role, if the connection is configured to use role assumption.",
2618 ),
2619 (
2620 "external_id",
2621 "The external ID Materialize will use when assuming the provided role, if the connection is configured to use role assumption.",
2622 ),
2623 (
2624 "example_trust_policy",
2625 "An example of an IAM role trust policy that allows this connection's principal and external ID to assume the role.",
2626 ),
2627 ]),
2628 sql: "
2632IN CLUSTER mz_catalog_server
2633WITH (
2634 ASSERT NOT NULL id
2635) AS
2636SELECT
2637 mz_internal.parse_catalog_id(r.data->'key'->'gid') AS id,
2638 details->>'endpoint' AS endpoint,
2639 details->>'region' AS region,
2640 details->>'access_key_id' AS access_key_id,
2641 details->>'access_key_id_secret_id' AS access_key_id_secret_id,
2642 details->>'secret_access_key_secret_id' AS secret_access_key_secret_id,
2643 details->>'session_token' AS session_token,
2644 details->>'session_token_secret_id' AS session_token_secret_id,
2645 details->>'assume_role_arn' AS assume_role_arn,
2646 details->>'assume_role_session_name' AS assume_role_session_name,
2647 CASE WHEN details->>'auth_kind' = 'assume-role'
2648 THEN mz_aws_connection_role_arn()
2649 END AS principal,
2650 CASE WHEN details->>'auth_kind' = 'assume-role'
2651 THEN 'mz_' || mz_aws_external_id_prefix() || '_'
2652 || mz_internal.parse_catalog_id(r.data->'key'->'gid')
2653 END AS external_id,
2654 CASE WHEN details->>'auth_kind' = 'assume-role'
2655 THEN jsonb_build_object(
2656 'Version', '2012-10-17',
2657 'Statement', jsonb_build_array(jsonb_build_object(
2658 'Effect', 'Allow',
2659 'Principal', jsonb_build_object('AWS', mz_aws_connection_role_arn()),
2660 'Action', 'sts:AssumeRole',
2661 'Condition', jsonb_build_object(
2662 'StringEquals', jsonb_build_object(
2663 'sts:ExternalId',
2664 'mz_' || mz_aws_external_id_prefix() || '_'
2665 || mz_internal.parse_catalog_id(r.data->'key'->'gid')
2666 )
2667 )
2668 ))
2669 )
2670 END AS example_trust_policy
2671FROM
2672 mz_internal.mz_catalog_raw r,
2673 LATERAL (
2674 SELECT mz_internal.parse_connection_details(
2675 r.data->'value'->'definition'->'V1'->>'create_sql')
2676 ) AS d(details)
2677WHERE
2678 r.data->>'kind' = 'Item' AND
2679 -- The connection_type filter selects the kind. A non-matching row yields a
2680 -- NULL connection_type and is dropped here, so no `details IS NOT NULL` is
2681 -- needed (parse_connection_details returns jsonb null, which passes it).
2682 mz_internal.parse_catalog_create_sql(
2683 r.data->'value'->'definition'->'V1'->>'create_sql')->>'connection_type' = 'aws' AND
2684 -- Drop assume-role connections when the AWS context is absent, matching the
2685 -- packer this view replaces. `AwsAssumeRole::external_id` needs the external
2686 -- ID prefix and `example_trust_policy` needs the connection role ARN. Either
2687 -- one missing made the packer bail and write no row. Without this guard the
2688 -- view would instead emit a row whose `example_trust_policy` is a non-NULL
2689 -- JSON object full of nulls, because `jsonb_build_object` keeps null values.
2690 (
2691 details->>'auth_kind' IS DISTINCT FROM 'assume-role' OR (
2692 mz_aws_external_id_prefix() IS NOT NULL AND
2693 mz_aws_connection_role_arn() IS NOT NULL
2694 )
2695 )",
2696 is_retained_metrics_object: false,
2697 access: vec![PUBLIC_SELECT],
2698 ontology: Some(Ontology {
2699 entity_name: "aws_connection",
2700 description: "AWS connection configuration details",
2701 links: &const {
2702 [OntologyLink {
2703 name: "details_of",
2704 target: "connection",
2705 properties: LinkProperties::fk("id", "id", Cardinality::OneToOne),
2706 }]
2707 },
2708 column_semantic_types: &[],
2709 }),
2710 }
2711});
2712
2713pub static MZ_CLUSTER_REPLICA_METRICS_HISTORY: LazyLock<BuiltinSource> =
2714 LazyLock::new(|| BuiltinSource {
2715 name: "mz_cluster_replica_metrics_history",
2716 schema: MZ_INTERNAL_SCHEMA,
2717 oid: oid::SOURCE_MZ_CLUSTER_REPLICA_METRICS_HISTORY_OID,
2718 data_source: IntrospectionType::ReplicaMetricsHistory.into(),
2719 desc: REPLICA_METRICS_HISTORY_DESC.clone(),
2720 column_comments: BTreeMap::from_iter([
2721 ("replica_id", "The ID of a cluster replica."),
2722 ("process_id", "The ID of a process within the replica."),
2723 (
2724 "cpu_nano_cores",
2725 "Approximate CPU usage, in billionths of a vCPU core.",
2726 ),
2727 ("memory_bytes", "Approximate memory usage, in bytes."),
2728 ("disk_bytes", "Approximate disk usage, in bytes."),
2729 (
2730 "occurred_at",
2731 "Wall-clock timestamp at which the event occurred.",
2732 ),
2733 (
2734 "heap_bytes",
2735 "Approximate heap (RAM + swap) usage, in bytes.",
2736 ),
2737 ("heap_limit", "Available heap (RAM + swap) space, in bytes."),
2738 ("swap_bytes", "Approximate swap usage, in bytes."),
2739 ]),
2740 is_retained_metrics_object: false,
2741 access: vec![PUBLIC_SELECT],
2742 ontology: None,
2743 });
2744
2745pub static MZ_CLUSTER_REPLICA_METRICS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
2746 name: "mz_cluster_replica_metrics",
2747 schema: MZ_INTERNAL_SCHEMA,
2748 oid: oid::VIEW_MZ_CLUSTER_REPLICA_METRICS_OID,
2749 desc: RelationDesc::builder()
2750 .with_column("replica_id", SqlScalarType::String.nullable(false))
2751 .with_column("process_id", SqlScalarType::UInt64.nullable(false))
2752 .with_column("cpu_nano_cores", SqlScalarType::UInt64.nullable(true))
2753 .with_column("memory_bytes", SqlScalarType::UInt64.nullable(true))
2754 .with_column("disk_bytes", SqlScalarType::UInt64.nullable(true))
2755 .with_column("heap_bytes", SqlScalarType::UInt64.nullable(true))
2756 .with_column("heap_limit", SqlScalarType::UInt64.nullable(true))
2757 .with_column("swap_bytes", SqlScalarType::UInt64.nullable(true))
2758 .with_key(vec![0, 1])
2759 .finish(),
2760 column_comments: BTreeMap::from_iter([
2761 ("replica_id", "The ID of a cluster replica."),
2762 ("process_id", "The ID of a process within the replica."),
2763 (
2764 "cpu_nano_cores",
2765 "Approximate CPU usage, in billionths of a vCPU core.",
2766 ),
2767 ("memory_bytes", "Approximate RAM usage, in bytes."),
2768 ("disk_bytes", "Approximate disk usage, in bytes."),
2769 (
2770 "heap_bytes",
2771 "Approximate heap (RAM + swap) usage, in bytes.",
2772 ),
2773 ("heap_limit", "Available heap (RAM + swap) space, in bytes."),
2774 ("swap_bytes", "Approximate swap usage, in bytes."),
2775 ]),
2776 sql: "
2777SELECT
2778 DISTINCT ON (replica_id, process_id)
2779 replica_id,
2780 process_id,
2781 cpu_nano_cores,
2782 memory_bytes,
2783 disk_bytes,
2784 heap_bytes,
2785 heap_limit,
2786 swap_bytes
2787FROM mz_internal.mz_cluster_replica_metrics_history
2788JOIN mz_cluster_replicas r ON r.id = replica_id
2789ORDER BY replica_id, process_id, occurred_at DESC",
2790 access: vec![PUBLIC_SELECT],
2791 ontology: Some(Ontology {
2792 entity_name: "replica_metrics",
2793 description: "CPU and memory metrics per replica",
2794 links: &const {
2795 [OntologyLink {
2796 name: "metrics_of_replica",
2797 target: "replica",
2798 properties: LinkProperties::fk_typed(
2799 "replica_id",
2800 "id",
2801 Cardinality::OneToOne,
2802 mz_repr::SemanticType::CatalogItemId,
2803 ),
2804 }]
2805 },
2806 column_semantic_types: &const {
2807 [
2808 ("replica_id", SemanticType::ReplicaId),
2809 ("memory_bytes", SemanticType::ByteCount),
2810 ("disk_bytes", SemanticType::ByteCount),
2811 ("heap_bytes", SemanticType::ByteCount),
2812 ("heap_limit", SemanticType::ByteCount),
2813 ("swap_bytes", SemanticType::ByteCount),
2814 ]
2815 },
2816 }),
2817});
2818
2819pub static MZ_FRONTIERS: LazyLock<BuiltinSource> = LazyLock::new(|| BuiltinSource {
2820 name: "mz_frontiers",
2821 schema: MZ_INTERNAL_SCHEMA,
2822 oid: oid::SOURCE_MZ_FRONTIERS_OID,
2823 data_source: IntrospectionType::Frontiers.into(),
2824 desc: RelationDesc::builder()
2825 .with_column("object_id", SqlScalarType::String.nullable(false))
2826 .with_column("read_frontier", SqlScalarType::MzTimestamp.nullable(true))
2827 .with_column("write_frontier", SqlScalarType::MzTimestamp.nullable(true))
2828 .finish(),
2829 column_comments: BTreeMap::from_iter([
2830 (
2831 "object_id",
2832 "The ID of the source, sink, table, index, materialized view, or subscription.",
2833 ),
2834 (
2835 "read_frontier",
2836 "The earliest timestamp at which the output is still readable.",
2837 ),
2838 (
2839 "write_frontier",
2840 "The next timestamp at which the output may change.",
2841 ),
2842 ]),
2843 is_retained_metrics_object: false,
2844 access: vec![PUBLIC_SELECT],
2845 ontology: Some(Ontology {
2846 entity_name: "frontier",
2847 description: "Current read/write frontiers for sources, sinks, tables, materialized views, indexes, and subscriptions",
2848 links: &const {
2849 [OntologyLink {
2850 name: "frontier_of",
2851 target: "object",
2852 properties: LinkProperties::fk_mapped(
2853 "object_id",
2854 "id",
2855 Cardinality::ManyToOne,
2856 mz_repr::SemanticType::GlobalId,
2857 "mz_internal.mz_object_global_ids",
2858 ),
2859 }]
2860 },
2861 column_semantic_types: &const {
2862 [
2863 ("object_id", SemanticType::GlobalId),
2864 ("read_frontier", SemanticType::MzTimestamp),
2865 ("write_frontier", SemanticType::MzTimestamp),
2866 ]
2867 },
2868 }),
2869});
2870
2871pub static MZ_GLOBAL_FRONTIERS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
2873 name: "mz_global_frontiers",
2874 schema: MZ_INTERNAL_SCHEMA,
2875 oid: oid::VIEW_MZ_GLOBAL_FRONTIERS_OID,
2876 desc: RelationDesc::builder()
2877 .with_column("object_id", SqlScalarType::String.nullable(false))
2878 .with_column("time", SqlScalarType::MzTimestamp.nullable(false))
2879 .finish(),
2880 column_comments: BTreeMap::new(),
2881 sql: "
2882SELECT object_id, write_frontier AS time
2883FROM mz_internal.mz_frontiers
2884WHERE write_frontier IS NOT NULL",
2885 access: vec![PUBLIC_SELECT],
2886 ontology: None,
2887});
2888
2889pub static MZ_WALLCLOCK_LAG_HISTORY: LazyLock<BuiltinSource> = LazyLock::new(|| BuiltinSource {
2890 name: "mz_wallclock_lag_history",
2891 schema: MZ_INTERNAL_SCHEMA,
2892 oid: oid::SOURCE_MZ_WALLCLOCK_LAG_HISTORY_OID,
2893 desc: WALLCLOCK_LAG_HISTORY_DESC.clone(),
2894 data_source: IntrospectionType::WallclockLagHistory.into(),
2895 column_comments: BTreeMap::from_iter([
2896 (
2897 "object_id",
2898 "The ID of the table, source, materialized view, index, or sink. Corresponds to `mz_objects.id`.",
2899 ),
2900 (
2901 "replica_id",
2902 "The ID of a replica computing the object, or `NULL` for persistent objects. Corresponds to `mz_cluster_replicas.id`.",
2903 ),
2904 (
2905 "lag",
2906 "The amount of time the object's write frontier lags behind wallclock time.",
2907 ),
2908 (
2909 "occurred_at",
2910 "Wall-clock timestamp at which the event occurred.",
2911 ),
2912 ]),
2913 is_retained_metrics_object: false,
2914 access: vec![PUBLIC_SELECT],
2915 ontology: Some(Ontology {
2916 entity_name: "wallclock_lag_event",
2917 description: "Historical wallclock lag per object",
2918 links: &const {
2919 [
2920 OntologyLink {
2921 name: "measures_lag_of",
2922 target: "object",
2923 properties: LinkProperties::measures_mapped(
2924 "object_id",
2925 "id",
2926 "wallclock_lag",
2927 mz_repr::SemanticType::GlobalId,
2928 "mz_internal.mz_object_global_ids",
2929 ),
2930 },
2931 OntologyLink {
2932 name: "on_replica",
2933 target: "replica",
2934 properties: LinkProperties::fk_nullable(
2935 "replica_id",
2936 "id",
2937 Cardinality::ManyToOne,
2938 ),
2939 },
2940 ]
2941 },
2942 column_semantic_types: &const {
2943 [
2944 ("object_id", SemanticType::GlobalId),
2945 ("replica_id", SemanticType::ReplicaId),
2946 ("occurred_at", SemanticType::WallclockTimestamp),
2947 ]
2948 },
2949 }),
2950});
2951
2952pub static MZ_WALLCLOCK_GLOBAL_LAG_HISTORY: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
2953 name: "mz_wallclock_global_lag_history",
2954 schema: MZ_INTERNAL_SCHEMA,
2955 oid: oid::VIEW_MZ_WALLCLOCK_GLOBAL_LAG_HISTORY_OID,
2956 desc: RelationDesc::builder()
2957 .with_column("object_id", SqlScalarType::String.nullable(false))
2958 .with_column("lag", SqlScalarType::Interval.nullable(true))
2959 .with_column(
2960 "occurred_at",
2961 SqlScalarType::TimestampTz { precision: None }.nullable(false),
2962 )
2963 .with_key(vec![0, 2])
2964 .finish(),
2965 column_comments: BTreeMap::from_iter([
2966 (
2967 "object_id",
2968 "The ID of the table, source, materialized view, index, or sink. Corresponds to `mz_objects.id`.",
2969 ),
2970 (
2971 "lag",
2972 "The minimum wallclock lag observed for the object during the minute.",
2973 ),
2974 (
2975 "occurred_at",
2976 "The minute-aligned timestamp of the observation.",
2977 ),
2978 ]),
2979 sql: "
2980WITH times_binned AS (
2981 SELECT
2982 object_id,
2983 lag,
2984 date_trunc('minute', occurred_at) AS occurred_at
2985 FROM mz_internal.mz_wallclock_lag_history
2986)
2987SELECT
2988 object_id,
2989 min(lag) AS lag,
2990 occurred_at
2991FROM times_binned
2992GROUP BY object_id, occurred_at
2993OPTIONS (AGGREGATE INPUT GROUP SIZE = 1)",
2994 access: vec![PUBLIC_SELECT],
2995 ontology: Some(Ontology {
2996 entity_name: "wallclock_global_lag_event",
2997 description: "Historical global wallclock lag",
2998 links: &const {
2999 [OntologyLink {
3000 name: "lag_of",
3001 target: "object_global_id",
3002 properties: LinkProperties::fk("object_id", "global_id", Cardinality::ManyToOne),
3003 }]
3004 },
3005 column_semantic_types: &const {
3006 [
3007 ("object_id", SemanticType::GlobalId),
3008 ("occurred_at", SemanticType::WallclockTimestamp),
3009 ]
3010 },
3011 }),
3012});
3013
3014pub static MZ_WALLCLOCK_GLOBAL_LAG_RECENT_HISTORY: LazyLock<BuiltinView> = LazyLock::new(|| {
3015 BuiltinView {
3016 name: "mz_wallclock_global_lag_recent_history",
3017 schema: MZ_INTERNAL_SCHEMA,
3018 oid: oid::VIEW_MZ_WALLCLOCK_GLOBAL_LAG_RECENT_HISTORY_OID,
3019 desc: RelationDesc::builder()
3020 .with_column("object_id", SqlScalarType::String.nullable(false))
3021 .with_column("lag", SqlScalarType::Interval.nullable(true))
3022 .with_column(
3023 "occurred_at",
3024 SqlScalarType::TimestampTz { precision: None }.nullable(false),
3025 )
3026 .with_key(vec![0, 2])
3027 .finish(),
3028 column_comments: BTreeMap::from_iter([
3029 (
3030 "object_id",
3031 "The ID of the table, source, materialized view, index, or sink. Corresponds to `mz_objects.id`.",
3032 ),
3033 (
3034 "lag",
3035 "The minimum wallclock lag observed for the object during the minute.",
3036 ),
3037 (
3038 "occurred_at",
3039 "The minute-aligned timestamp of the observation.",
3040 ),
3041 ]),
3042 sql: "
3043SELECT object_id, lag, occurred_at
3044FROM mz_internal.mz_wallclock_global_lag_history
3045WHERE occurred_at + '1 day' > mz_now()",
3046 access: vec![PUBLIC_SELECT],
3047 ontology: None,
3048 }
3049});
3050
3051pub static MZ_WALLCLOCK_GLOBAL_LAG: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
3052 name: "mz_wallclock_global_lag",
3053 schema: MZ_INTERNAL_SCHEMA,
3054 oid: oid::VIEW_MZ_WALLCLOCK_GLOBAL_LAG_OID,
3055 desc: RelationDesc::builder()
3056 .with_column("object_id", SqlScalarType::String.nullable(false))
3057 .with_column("lag", SqlScalarType::Interval.nullable(true))
3058 .with_key(vec![0])
3059 .finish(),
3060 column_comments: BTreeMap::from_iter([
3061 (
3062 "object_id",
3063 "The ID of the table, source, materialized view, index, or sink. Corresponds to `mz_objects.id`.",
3064 ),
3065 (
3066 "lag",
3067 "The amount of time the object's write frontier lags behind wallclock time.",
3068 ),
3069 ]),
3070 sql: "
3071SELECT DISTINCT ON (object_id) object_id, lag
3072FROM mz_internal.mz_wallclock_global_lag_recent_history
3073WHERE occurred_at + '5 minutes' > mz_now()
3074ORDER BY object_id, occurred_at DESC",
3075 access: vec![PUBLIC_SELECT],
3076 ontology: Some(Ontology {
3077 entity_name: "wallclock_global_lag",
3078 description: "Current wallclock lag aggregated across replicas",
3079 links: &const {
3080 [OntologyLink {
3081 name: "measures_global_lag_of",
3082 target: "object",
3083 properties: LinkProperties::measures_mapped(
3084 "object_id",
3085 "id",
3086 "wallclock_lag_global",
3087 mz_repr::SemanticType::GlobalId,
3088 "mz_internal.mz_object_global_ids",
3089 ),
3090 }]
3091 },
3092 column_semantic_types: &[("object_id", SemanticType::GlobalId)],
3093 }),
3094});
3095
3096pub static MZ_WALLCLOCK_GLOBAL_LAG_HISTOGRAM_RAW: LazyLock<BuiltinSource> =
3097 LazyLock::new(|| BuiltinSource {
3098 name: "mz_wallclock_global_lag_histogram_raw",
3099 schema: MZ_INTERNAL_SCHEMA,
3100 oid: oid::SOURCE_MZ_WALLCLOCK_GLOBAL_LAG_HISTOGRAM_RAW_OID,
3101 desc: WALLCLOCK_GLOBAL_LAG_HISTOGRAM_RAW_DESC.clone(),
3102 column_comments: BTreeMap::new(),
3103 data_source: IntrospectionType::WallclockLagHistogram.into(),
3104 is_retained_metrics_object: false,
3105 access: vec![PUBLIC_SELECT],
3106 ontology: None,
3107 });
3108
3109pub static MZ_WALLCLOCK_GLOBAL_LAG_HISTOGRAM: LazyLock<BuiltinView> =
3110 LazyLock::new(|| BuiltinView {
3111 name: "mz_wallclock_global_lag_histogram",
3112 schema: MZ_INTERNAL_SCHEMA,
3113 oid: oid::VIEW_MZ_WALLCLOCK_GLOBAL_LAG_HISTOGRAM_OID,
3114 desc: RelationDesc::builder()
3115 .with_column(
3116 "period_start",
3117 SqlScalarType::TimestampTz { precision: None }.nullable(false),
3118 )
3119 .with_column(
3120 "period_end",
3121 SqlScalarType::TimestampTz { precision: None }.nullable(false),
3122 )
3123 .with_column("object_id", SqlScalarType::String.nullable(false))
3124 .with_column("lag_seconds", SqlScalarType::UInt64.nullable(true))
3125 .with_column("labels", SqlScalarType::Jsonb.nullable(false))
3126 .with_column("count", SqlScalarType::Int64.nullable(false))
3127 .with_key(vec![0, 1, 2, 3, 4])
3128 .finish(),
3129 column_comments: BTreeMap::new(),
3130 sql: "
3131SELECT *, count(*) AS count
3132FROM mz_internal.mz_wallclock_global_lag_histogram_raw
3133GROUP BY period_start, period_end, object_id, lag_seconds, labels",
3134 access: vec![PUBLIC_SELECT],
3135 ontology: None,
3136 });
3137
3138pub static MZ_MATERIALIZED_VIEW_REFRESHES: LazyLock<BuiltinSource> = LazyLock::new(|| {
3139 BuiltinSource {
3140 name: "mz_materialized_view_refreshes",
3141 schema: MZ_INTERNAL_SCHEMA,
3142 oid: oid::SOURCE_MZ_MATERIALIZED_VIEW_REFRESHES_OID,
3143 data_source: DataSourceDesc::Introspection(
3144 IntrospectionType::ComputeMaterializedViewRefreshes,
3145 ),
3146 desc: RelationDesc::builder()
3147 .with_column(
3148 "materialized_view_id",
3149 SqlScalarType::String.nullable(false),
3150 )
3151 .with_column(
3152 "last_completed_refresh",
3153 SqlScalarType::MzTimestamp.nullable(true),
3154 )
3155 .with_column("next_refresh", SqlScalarType::MzTimestamp.nullable(true))
3156 .finish(),
3157 column_comments: BTreeMap::from_iter([
3158 (
3159 "materialized_view_id",
3160 "The ID of the materialized view. Corresponds to `mz_catalog.mz_materialized_views.id`",
3161 ),
3162 (
3163 "last_completed_refresh",
3164 "The time of the last successfully completed refresh. `NULL` if the materialized view hasn't completed any refreshes yet.",
3165 ),
3166 (
3167 "next_refresh",
3168 "The time of the next scheduled refresh. `NULL` if the materialized view has no future scheduled refreshes.",
3169 ),
3170 ]),
3171 is_retained_metrics_object: false,
3172 access: vec![PUBLIC_SELECT],
3173 ontology: None,
3174 }
3175});
3176
3177pub static MZ_SUBSCRIPTIONS: LazyLock<BuiltinTable> = LazyLock::new(|| BuiltinTable {
3178 name: "mz_subscriptions",
3179 schema: MZ_INTERNAL_SCHEMA,
3180 oid: oid::TABLE_MZ_SUBSCRIPTIONS_OID,
3181 desc: RelationDesc::builder()
3182 .with_column("id", SqlScalarType::String.nullable(false))
3183 .with_column("session_id", SqlScalarType::Uuid.nullable(false))
3184 .with_column("cluster_id", SqlScalarType::String.nullable(false))
3185 .with_column(
3186 "created_at",
3187 SqlScalarType::TimestampTz { precision: None }.nullable(false),
3188 )
3189 .with_column(
3190 "referenced_object_ids",
3191 SqlScalarType::List {
3192 element_type: Box::new(SqlScalarType::String),
3193 custom_id: None,
3194 }
3195 .nullable(false),
3196 )
3197 .finish(),
3198 column_comments: BTreeMap::from_iter([
3199 ("id", "The ID of the subscription."),
3200 (
3201 "session_id",
3202 "The ID of the session that runs the subscription. Corresponds to `mz_sessions.id`.",
3203 ),
3204 (
3205 "cluster_id",
3206 "The ID of the cluster on which the subscription is running. Corresponds to `mz_clusters.id`.",
3207 ),
3208 (
3209 "created_at",
3210 "The time at which the subscription was created.",
3211 ),
3212 (
3213 "referenced_object_ids",
3214 "The IDs of objects referenced by the subscription. Corresponds to `mz_objects.id`",
3215 ),
3216 ]),
3217 is_retained_metrics_object: false,
3218 access: vec![PUBLIC_SELECT],
3219 ontology: Some(Ontology {
3220 entity_name: "subscription",
3221 description: "Active SUBSCRIBE operations",
3222 links: &const {
3223 [
3224 OntologyLink {
3225 name: "uses_session",
3226 target: "session",
3227 properties: LinkProperties::fk("session_id", "id", Cardinality::ManyToOne),
3228 },
3229 OntologyLink {
3230 name: "in_active_session",
3231 target: "active_session",
3232 properties: LinkProperties::fk_nullable(
3233 "session_id",
3234 "id",
3235 Cardinality::ManyToOne,
3236 ),
3237 },
3238 OntologyLink {
3239 name: "belongs_to_cluster",
3240 target: "cluster",
3241 properties: LinkProperties::fk("cluster_id", "id", Cardinality::ManyToOne),
3242 },
3243 ]
3244 },
3245 column_semantic_types: &const {
3246 [
3247 ("id", SemanticType::CatalogItemId),
3248 ("cluster_id", SemanticType::ClusterId),
3249 ]
3250 },
3251 }),
3252});
3253
3254pub static MZ_SESSIONS: LazyLock<BuiltinTable> = LazyLock::new(|| BuiltinTable {
3255 name: "mz_sessions",
3256 schema: MZ_INTERNAL_SCHEMA,
3257 oid: oid::TABLE_MZ_SESSIONS_OID,
3258 desc: RelationDesc::builder()
3259 .with_column("id", SqlScalarType::Uuid.nullable(false))
3260 .with_column("connection_id", SqlScalarType::UInt32.nullable(false))
3261 .with_column("role_id", SqlScalarType::String.nullable(false))
3262 .with_column("client_ip", SqlScalarType::String.nullable(true))
3263 .with_column(
3264 "connected_at",
3265 SqlScalarType::TimestampTz { precision: None }.nullable(false),
3266 )
3267 .finish(),
3268 column_comments: BTreeMap::from_iter([
3269 ("id", "The globally unique ID of the session."),
3270 (
3271 "connection_id",
3272 "The connection ID of the session. Unique only for active sessions and can be recycled. Corresponds to `pg_backend_pid()`.",
3273 ),
3274 (
3275 "role_id",
3276 "The role ID of the role that the session is logged in as. Corresponds to `mz_catalog.mz_roles`.",
3277 ),
3278 (
3279 "client_ip",
3280 "The IP address of the client that initiated the session.",
3281 ),
3282 (
3283 "connected_at",
3284 "The time at which the session connected to the system.",
3285 ),
3286 ]),
3287 is_retained_metrics_object: false,
3288 access: vec![PUBLIC_SELECT],
3289 ontology: Some(Ontology {
3290 entity_name: "active_session",
3291 description: "Currently active sessions",
3292 links: &const {
3293 [OntologyLink {
3294 name: "logged_in_as",
3295 target: "role",
3296 properties: LinkProperties::fk("role_id", "id", Cardinality::ManyToOne),
3297 }]
3298 },
3299 column_semantic_types: &[("role_id", SemanticType::RoleId)],
3300 }),
3301});
3302
3303pub static MZ_OVERRIDDEN_SYSTEM_PARAMETERS: LazyLock<BuiltinMaterializedView> =
3304 LazyLock::new(|| BuiltinMaterializedView {
3305 name: "mz_overridden_system_parameters",
3306 schema: MZ_INTERNAL_SCHEMA,
3307 oid: oid::MV_MZ_OVERRIDDEN_SYSTEM_PARAMETERS_OID,
3308 desc: RelationDesc::builder()
3309 .with_column("name", SqlScalarType::String.nullable(false))
3310 .with_column("value", SqlScalarType::String.nullable(false))
3311 .finish(),
3312 column_comments: BTreeMap::from_iter([
3313 ("name", "The name of the system parameter."),
3314 (
3315 "value",
3316 "The environment-wide value of the system parameter.",
3317 ),
3318 ]),
3319 sql: "
3326IN CLUSTER mz_catalog_server
3327WITH (
3328 ASSERT NOT NULL name,
3329 ASSERT NOT NULL value
3330) AS
3331SELECT
3332 data->'key'->>'name' AS name,
3333 data->'value'->>'value' AS value
3334FROM mz_internal.mz_catalog_raw
3335WHERE data->>'kind' = 'ServerConfiguration'",
3336 is_retained_metrics_object: false,
3337 access: vec![PUBLIC_SELECT],
3338 ontology: Some(Ontology {
3339 entity_name: "system_parameter",
3340 description: "Environment-wide system parameter overrides",
3341 links: &const { [] },
3342 column_semantic_types: &[],
3343 }),
3344 });
3345
3346pub static MZ_CLUSTER_SYSTEM_PARAMETERS: LazyLock<BuiltinMaterializedView> =
3347 LazyLock::new(|| BuiltinMaterializedView {
3348 name: "mz_cluster_system_parameters",
3349 schema: MZ_INTERNAL_SCHEMA,
3350 oid: oid::MV_MZ_CLUSTER_SYSTEM_PARAMETERS_OID,
3351 desc: RelationDesc::builder()
3352 .with_column("cluster_id", SqlScalarType::String.nullable(false))
3353 .with_column("name", SqlScalarType::String.nullable(false))
3354 .with_column("value", SqlScalarType::String.nullable(false))
3355 .finish(),
3356 column_comments: BTreeMap::from_iter([
3357 (
3358 "cluster_id",
3359 "The ID of the cluster. Corresponds to `mz_clusters.id`.",
3360 ),
3361 ("name", "The name of the cluster-coherent system parameter."),
3362 ("value", "The cluster-scoped value of the system parameter."),
3363 ]),
3364 sql: "
3368IN CLUSTER mz_catalog_server
3369WITH (
3370 ASSERT NOT NULL cluster_id,
3371 ASSERT NOT NULL name,
3372 ASSERT NOT NULL value
3373) AS
3374SELECT
3375 mz_internal.parse_catalog_id(data->'key'->'cluster_id') AS cluster_id,
3376 data->'key'->>'name' AS name,
3377 data->'value'->>'value' AS value
3378FROM mz_internal.mz_catalog_raw
3379WHERE data->>'kind' = 'ClusterSystemConfiguration'",
3380 is_retained_metrics_object: false,
3381 access: vec![PUBLIC_SELECT],
3382 ontology: Some(Ontology {
3383 entity_name: "cluster_system_parameter",
3384 description: "Cluster-coherent system parameter overrides",
3385 links: &const {
3386 [OntologyLink {
3387 name: "scoped_to_cluster",
3388 target: "cluster",
3389 properties: LinkProperties::fk_typed(
3390 "cluster_id",
3391 "id",
3392 Cardinality::ManyToOne,
3393 mz_repr::SemanticType::ClusterId,
3394 ),
3395 }]
3396 },
3397 column_semantic_types: &[("cluster_id", SemanticType::ClusterId)],
3398 }),
3399 });
3400
3401pub static MZ_REPLICA_SYSTEM_PARAMETERS: LazyLock<BuiltinMaterializedView> =
3402 LazyLock::new(|| BuiltinMaterializedView {
3403 name: "mz_replica_system_parameters",
3404 schema: MZ_INTERNAL_SCHEMA,
3405 oid: oid::MV_MZ_REPLICA_SYSTEM_PARAMETERS_OID,
3406 desc: RelationDesc::builder()
3407 .with_column("replica_id", SqlScalarType::String.nullable(false))
3408 .with_column("name", SqlScalarType::String.nullable(false))
3409 .with_column("value", SqlScalarType::String.nullable(false))
3410 .finish(),
3411 column_comments: BTreeMap::from_iter([
3412 (
3413 "replica_id",
3414 "The ID of the cluster replica. Corresponds to `mz_cluster_replicas.id`.",
3415 ),
3416 ("name", "The name of the replica-local system parameter."),
3417 ("value", "The replica-scoped value of the system parameter."),
3418 ]),
3419 sql: "
3423IN CLUSTER mz_catalog_server
3424WITH (
3425 ASSERT NOT NULL replica_id,
3426 ASSERT NOT NULL name,
3427 ASSERT NOT NULL value
3428) AS
3429SELECT
3430 mz_internal.parse_catalog_id(data->'key'->'replica_id') AS replica_id,
3431 data->'key'->>'name' AS name,
3432 data->'value'->>'value' AS value
3433FROM mz_internal.mz_catalog_raw
3434WHERE data->>'kind' = 'ReplicaSystemConfiguration'",
3435 is_retained_metrics_object: false,
3436 access: vec![PUBLIC_SELECT],
3437 ontology: Some(Ontology {
3438 entity_name: "replica_system_parameter",
3439 description: "Replica-local system parameter overrides",
3440 links: &const {
3441 [OntologyLink {
3442 name: "scoped_to_replica",
3443 target: "replica",
3444 properties: LinkProperties::fk_typed(
3445 "replica_id",
3446 "id",
3447 Cardinality::ManyToOne,
3448 mz_repr::SemanticType::ReplicaId,
3449 ),
3450 }]
3451 },
3452 column_semantic_types: &[("replica_id", SemanticType::ReplicaId)],
3453 }),
3454 });
3455
3456pub static MZ_COMMENTS: LazyLock<BuiltinMaterializedView> = LazyLock::new(|| {
3457 BuiltinMaterializedView {
3458 name: "mz_comments",
3459 schema: MZ_INTERNAL_SCHEMA,
3460 oid: oid::MV_MZ_COMMENTS_OID,
3461 desc: RelationDesc::builder()
3462 .with_column("id", SqlScalarType::String.nullable(false))
3463 .with_column("object_type", SqlScalarType::String.nullable(false))
3464 .with_column("object_sub_id", SqlScalarType::Int32.nullable(true))
3465 .with_column("comment", SqlScalarType::String.nullable(false))
3466 .finish(),
3467 column_comments: BTreeMap::from_iter([
3468 (
3469 "id",
3470 "The ID of the object. Corresponds to `mz_objects.id`.",
3471 ),
3472 (
3473 "object_type",
3474 "The type of object the comment is associated with.",
3475 ),
3476 (
3477 "object_sub_id",
3478 "For a comment on a column of a relation, the column number. `NULL` for other object types.",
3479 ),
3480 ("comment", "The comment itself."),
3481 ]),
3482 sql: "
3495IN CLUSTER mz_catalog_server
3496WITH (
3497 ASSERT NOT NULL id,
3498 ASSERT NOT NULL object_type,
3499 ASSERT NOT NULL comment
3500) AS
3501WITH commented AS (
3502 SELECT data->'key'->'object' AS obj,
3503 data->'key'->'sub_component' AS sub,
3504 data->'value'->>'comment' AS comment
3505 FROM mz_internal.mz_catalog_raw
3506 WHERE data->>'kind' = 'Comment'
3507)
3508SELECT
3509 CASE
3510 WHEN obj ? 'Table' THEN mz_internal.parse_catalog_id(obj->'Table')
3511 WHEN obj ? 'View' THEN mz_internal.parse_catalog_id(obj->'View')
3512 WHEN obj ? 'MaterializedView' THEN mz_internal.parse_catalog_id(obj->'MaterializedView')
3513 WHEN obj ? 'Source' THEN mz_internal.parse_catalog_id(obj->'Source')
3514 WHEN obj ? 'Sink' THEN mz_internal.parse_catalog_id(obj->'Sink')
3515 WHEN obj ? 'Index' THEN mz_internal.parse_catalog_id(obj->'Index')
3516 WHEN obj ? 'Func' THEN mz_internal.parse_catalog_id(obj->'Func')
3517 WHEN obj ? 'Connection' THEN mz_internal.parse_catalog_id(obj->'Connection')
3518 WHEN obj ? 'Type' THEN mz_internal.parse_catalog_id(obj->'Type')
3519 WHEN obj ? 'Secret' THEN mz_internal.parse_catalog_id(obj->'Secret')
3520 WHEN obj ? 'Role' THEN mz_internal.parse_catalog_id(obj->'Role')
3521 WHEN obj ? 'Database' THEN mz_internal.parse_catalog_id(obj->'Database')
3522 WHEN obj ? 'Schema' THEN mz_internal.parse_catalog_id(obj->'Schema'->'schema'->'Id')
3523 WHEN obj ? 'Cluster' THEN mz_internal.parse_catalog_id(obj->'Cluster')
3524 WHEN obj ? 'ClusterReplica' THEN mz_internal.parse_catalog_id(obj->'ClusterReplica'->'replica_id')
3525 WHEN obj ? 'NetworkPolicy' THEN mz_internal.parse_catalog_id(obj->'NetworkPolicy')
3526 END AS id,
3527 CASE
3528 WHEN obj ? 'Table' THEN 'table'
3529 WHEN obj ? 'View' THEN 'view'
3530 WHEN obj ? 'MaterializedView' THEN 'materialized-view'
3531 WHEN obj ? 'Source' THEN 'source'
3532 WHEN obj ? 'Sink' THEN 'sink'
3533 WHEN obj ? 'Index' THEN 'index'
3534 WHEN obj ? 'Func' THEN 'func'
3535 WHEN obj ? 'Connection' THEN 'connection'
3536 WHEN obj ? 'Type' THEN 'type'
3537 WHEN obj ? 'Secret' THEN 'secret'
3538 WHEN obj ? 'Role' THEN 'role'
3539 WHEN obj ? 'Database' THEN 'database'
3540 WHEN obj ? 'Schema' THEN 'schema'
3541 WHEN obj ? 'Cluster' THEN 'cluster'
3542 WHEN obj ? 'ClusterReplica' THEN 'cluster-replica'
3543 WHEN obj ? 'NetworkPolicy' THEN 'network-policy'
3544 END AS object_type,
3545 (sub->'ColumnPos')::int4 AS object_sub_id,
3546 comment
3547FROM commented",
3548 is_retained_metrics_object: false,
3549 access: vec![PUBLIC_SELECT],
3550 ontology: Some(Ontology {
3551 entity_name: "comment",
3552 description: "A COMMENT ON annotation for a catalog object or column",
3553 links: &const {
3554 [OntologyLink {
3555 name: "comment_on",
3556 target: "object",
3557 properties: LinkProperties::fk_typed(
3558 "id",
3559 "id",
3560 Cardinality::ManyToOne,
3561 mz_repr::SemanticType::CatalogItemId,
3562 ),
3563 }]
3564 },
3565 column_semantic_types: &const {
3566 [
3567 ("id", SemanticType::CatalogItemId),
3568 ("object_type", SemanticType::ObjectType),
3569 ]
3570 },
3571 }),
3572 }
3573});
3574
3575pub static MZ_SOURCE_REFERENCES: LazyLock<BuiltinMaterializedView> =
3576 LazyLock::new(|| BuiltinMaterializedView {
3577 name: "mz_source_references",
3578 schema: MZ_INTERNAL_SCHEMA,
3579 oid: oid::MV_MZ_SOURCE_REFERENCES_OID,
3580 desc: RelationDesc::builder()
3581 .with_column("source_id", SqlScalarType::String.nullable(false))
3582 .with_column("namespace", SqlScalarType::String.nullable(true))
3583 .with_column("name", SqlScalarType::String.nullable(false))
3584 .with_column(
3585 "updated_at",
3586 SqlScalarType::TimestampTz { precision: None }.nullable(false),
3587 )
3588 .with_column(
3589 "columns",
3590 SqlScalarType::Array(Box::new(SqlScalarType::String)).nullable(true),
3591 )
3592 .finish(),
3593 column_comments: BTreeMap::new(),
3594 sql: "
3595IN CLUSTER mz_catalog_server
3596WITH (
3597 ASSERT NOT NULL source_id,
3598 ASSERT NOT NULL name,
3599 ASSERT NOT NULL updated_at
3600) AS
3601-- `refs` projects away usage of the `data` column before the `columns` subquery.
3602-- Without the CTE, each row would need a copy of `data` which contains all source
3603-- references, leading to memory growing quadratically.
3604WITH refs AS (
3605 SELECT
3606 mz_internal.parse_catalog_id(data->'key'->'source') AS source_id,
3607 -- `updated_at` is an `EpochMillis`, serialized as `{\"millis\": <u64>}`
3608 to_timestamp(((data->'value'->'updated_at'->>'millis')::double) / 1000.0) AS updated_at,
3609 reference
3610 FROM
3611 mz_internal.mz_catalog_raw,
3612 jsonb_array_elements(data->'value'->'references') AS reference
3613 WHERE data->>'kind' = 'SourceReferences'
3614)
3615SELECT
3616 source_id,
3617 reference->>'namespace' AS namespace,
3618 reference->>'name' AS name,
3619 updated_at,
3620 (
3621 SELECT array_agg(c.value ORDER BY c.ord)
3622 FROM jsonb_array_elements_text(reference->'columns')
3623 WITH ORDINALITY AS c(value, ord)
3624 ) AS columns
3625FROM refs",
3626 is_retained_metrics_object: false,
3627 access: vec![PUBLIC_SELECT],
3628 ontology: Some(Ontology {
3629 entity_name: "source_reference",
3630 description: "External references tracked by sources",
3631 links: &const {
3632 [OntologyLink {
3633 name: "references_source",
3634 target: "source",
3635 properties: LinkProperties::fk("source_id", "id", Cardinality::ManyToOne),
3636 }]
3637 },
3638 column_semantic_types: &[("source_id", SemanticType::CatalogItemId)],
3639 }),
3640 });
3641
3642pub static MZ_WEBHOOKS_SOURCES: LazyLock<BuiltinTable> = LazyLock::new(|| BuiltinTable {
3643 name: "mz_webhook_sources",
3644 schema: MZ_INTERNAL_SCHEMA,
3645 oid: oid::TABLE_MZ_WEBHOOK_SOURCES_OID,
3646 desc: RelationDesc::builder()
3647 .with_column("id", SqlScalarType::String.nullable(false))
3648 .with_column("name", SqlScalarType::String.nullable(false))
3649 .with_column("url", SqlScalarType::String.nullable(false))
3650 .finish(),
3651 column_comments: BTreeMap::from_iter([
3652 (
3653 "id",
3654 "The ID of the webhook source. Corresponds to `mz_sources.id`.",
3655 ),
3656 ("name", "The name of the webhook source."),
3657 (
3658 "url",
3659 "The URL which can be used to send events to the source.",
3660 ),
3661 ]),
3662 is_retained_metrics_object: false,
3663 access: vec![PUBLIC_SELECT],
3664 ontology: Some(Ontology {
3665 entity_name: "webhook_source",
3666 description: "Webhook source configuration",
3667 links: &const {
3668 [OntologyLink {
3669 name: "details_of",
3670 target: "source",
3671 properties: LinkProperties::fk("id", "id", Cardinality::OneToOne),
3672 }]
3673 },
3674 column_semantic_types: &[("id", SemanticType::CatalogItemId)],
3675 }),
3676});
3677
3678pub static MZ_METRIC_SINKS: LazyLock<BuiltinMaterializedView> = LazyLock::new(|| {
3679 BuiltinMaterializedView {
3680 name: "mz_metric_sinks",
3681 schema: MZ_INTERNAL_SCHEMA,
3682 oid: oid::MV_MZ_METRIC_SINKS_OID,
3683 desc: RelationDesc::builder()
3684 .with_column("id", SqlScalarType::String.nullable(false))
3685 .with_column("oid", SqlScalarType::Oid.nullable(false))
3686 .with_column("schema_id", SqlScalarType::String.nullable(false))
3687 .with_column("name", SqlScalarType::String.nullable(false))
3688 .with_column("from_id", SqlScalarType::String.nullable(false))
3689 .with_column("cluster_id", SqlScalarType::String.nullable(false))
3690 .with_column("owner_id", SqlScalarType::String.nullable(false))
3691 .with_key(vec![0])
3692 .with_key(vec![1])
3693 .finish(),
3694 column_comments: BTreeMap::from_iter([
3695 ("id", "Materialize's unique ID for the metric sink."),
3696 ("oid", "A PostgreSQL-compatible OID for the metric sink."),
3697 (
3698 "schema_id",
3699 "The ID of the schema to which the metric sink belongs. Corresponds to `mz_schemas.id`.",
3700 ),
3701 ("name", "The name of the metric sink."),
3702 (
3703 "from_id",
3704 "The ID of the relation the metric sink reads. Corresponds to `mz_objects.id`.",
3705 ),
3706 (
3707 "cluster_id",
3708 "The ID of the cluster maintaining the metric sink. Corresponds to `mz_clusters.id`.",
3709 ),
3710 (
3711 "owner_id",
3712 "The role ID of the owner of the metric sink. Corresponds to `mz_roles.id`.",
3713 ),
3714 ]),
3715 sql: "
3716IN CLUSTER mz_catalog_server
3717WITH (
3718 ASSERT NOT NULL id,
3719 ASSERT NOT NULL oid,
3720 ASSERT NOT NULL schema_id,
3721 ASSERT NOT NULL name,
3722 ASSERT NOT NULL from_id,
3723 ASSERT NOT NULL cluster_id,
3724 ASSERT NOT NULL owner_id
3725) AS
3726SELECT
3727 mz_internal.parse_catalog_id(data->'key'->'gid') AS id,
3728 (data->'value'->>'oid')::oid AS oid,
3729 mz_internal.parse_catalog_id(data->'value'->'schema_id') AS schema_id,
3730 data->'value'->>'name' AS name,
3731 parsed->>'from_id' AS from_id,
3732 parsed->>'cluster_id' AS cluster_id,
3733 mz_internal.parse_catalog_id(data->'value'->'owner_id') AS owner_id
3734FROM
3735 mz_internal.mz_catalog_raw
3736 CROSS JOIN LATERAL (
3737 SELECT mz_internal.parse_catalog_create_sql(data->'value'->'definition'->'V1'->>'create_sql')
3738 ) AS l(parsed)
3739WHERE
3740 data->>'kind' = 'Item' AND
3741 parsed->>'type' = 'metric-sink'",
3742 is_retained_metrics_object: false,
3743 access: vec![PUBLIC_SELECT],
3744 ontology: Some(Ontology {
3745 entity_name: "metric-sink",
3746 description: "A sink that exports metrics about a relation",
3747 links: &const {
3748 [
3749 OntologyLink {
3750 name: "in_schema",
3751 target: "schema",
3752 properties: LinkProperties::fk("schema_id", "id", Cardinality::ManyToOne),
3753 },
3754 OntologyLink {
3755 name: "reads_relation",
3756 target: "relation",
3757 properties: LinkProperties::fk("from_id", "id", Cardinality::ManyToOne),
3758 },
3759 OntologyLink {
3760 name: "runs_on_cluster",
3761 target: "cluster",
3762 properties: LinkProperties::fk("cluster_id", "id", Cardinality::ManyToOne),
3763 },
3764 OntologyLink {
3765 name: "owned_by",
3766 target: "role",
3767 properties: LinkProperties::fk("owner_id", "id", Cardinality::ManyToOne),
3768 },
3769 ]
3770 },
3771 column_semantic_types: &const {
3772 [
3773 ("id", SemanticType::CatalogItemId),
3774 ("oid", SemanticType::OID),
3775 ("schema_id", SemanticType::SchemaId),
3776 ("from_id", SemanticType::CatalogItemId),
3777 ("cluster_id", SemanticType::ClusterId),
3778 ("owner_id", SemanticType::RoleId),
3779 ]
3780 },
3781 }),
3782 }
3783});
3784
3785pub const MZ_METRIC_SINKS_IND: BuiltinIndex = BuiltinIndex {
3786 name: "mz_metric_sinks_ind",
3787 schema: MZ_INTERNAL_SCHEMA,
3788 oid: oid::INDEX_MZ_METRIC_SINKS_IND_OID,
3789 sql: "IN CLUSTER mz_catalog_server
3790ON mz_internal.mz_metric_sinks (id)",
3791 is_retained_metrics_object: false,
3792};
3793
3794pub static MZ_HISTORY_RETENTION_STRATEGIES: LazyLock<BuiltinTable> = LazyLock::new(|| {
3795 BuiltinTable {
3796 name: "mz_history_retention_strategies",
3797 schema: MZ_INTERNAL_SCHEMA,
3798 oid: oid::TABLE_MZ_HISTORY_RETENTION_STRATEGIES_OID,
3799 desc: RelationDesc::builder()
3800 .with_column("id", SqlScalarType::String.nullable(false))
3801 .with_column("strategy", SqlScalarType::String.nullable(false))
3802 .with_column("value", SqlScalarType::Jsonb.nullable(false))
3803 .finish(),
3804 column_comments: BTreeMap::from_iter([
3805 ("id", "The ID of the object."),
3806 (
3807 "strategy",
3808 "The strategy. `FOR` is the only strategy, and means the object's compaction window is the duration of the `value` field.",
3809 ),
3810 (
3811 "value",
3812 "The value of the strategy. For `FOR`, is a number of milliseconds.",
3813 ),
3814 ]),
3815 is_retained_metrics_object: false,
3816 access: vec![PUBLIC_SELECT],
3817 ontology: Some(Ontology {
3818 entity_name: "history_retention",
3819 description: "History retention strategy for an object",
3820 links: &const { [] },
3821 column_semantic_types: &[("id", SemanticType::CatalogItemId)],
3822 }),
3823 }
3824});
3825
3826pub static MZ_LICENSE_KEYS: LazyLock<BuiltinTable> = LazyLock::new(|| BuiltinTable {
3827 name: "mz_license_keys",
3828 schema: MZ_INTERNAL_SCHEMA,
3829 oid: oid::TABLE_MZ_LICENSE_KEYS_OID,
3830 desc: RelationDesc::builder()
3831 .with_column("id", SqlScalarType::String.nullable(false))
3832 .with_column("organization", SqlScalarType::String.nullable(false))
3833 .with_column("environment_id", SqlScalarType::String.nullable(false))
3834 .with_column(
3835 "expiration",
3836 SqlScalarType::TimestampTz { precision: None }.nullable(false),
3837 )
3838 .with_column(
3839 "not_before",
3840 SqlScalarType::TimestampTz { precision: None }.nullable(false),
3841 )
3842 .finish(),
3843 column_comments: BTreeMap::from_iter([
3844 ("id", "The identifier of the license key."),
3845 (
3846 "organization",
3847 "The name of the organization that this license key was issued to.",
3848 ),
3849 (
3850 "environment_id",
3851 "The environment ID that this license key was issued for.",
3852 ),
3853 (
3854 "expiration",
3855 "The date and time when this license key expires.",
3856 ),
3857 (
3858 "not_before",
3859 "The start of the validity period for this license key.",
3860 ),
3861 ]),
3862 is_retained_metrics_object: false,
3863 access: vec![PUBLIC_SELECT],
3864 ontology: Some(Ontology {
3865 entity_name: "license_key",
3866 description: "License key metadata",
3867 links: &const { [] },
3868 column_semantic_types: &[("id", SemanticType::CatalogItemId)],
3869 }),
3870});
3871
3872pub static MZ_REPLACEMENTS: LazyLock<BuiltinTable> = LazyLock::new(|| BuiltinTable {
3873 name: "mz_replacements",
3874 schema: MZ_INTERNAL_SCHEMA,
3875 oid: oid::TABLE_MZ_REPLACEMENTS_OID,
3876 desc: RelationDesc::builder()
3877 .with_column("id", SqlScalarType::String.nullable(false))
3878 .with_column("target_id", SqlScalarType::String.nullable(false))
3879 .finish(),
3880 column_comments: BTreeMap::from_iter([
3881 (
3882 "id",
3883 "The ID of the replacement object. Corresponds to `mz_objects.id`.",
3884 ),
3885 (
3886 "target_id",
3887 "The ID of the replacement target. Corresponds to `mz_objects.id`.",
3888 ),
3889 ]),
3890 is_retained_metrics_object: false,
3891 access: vec![PUBLIC_SELECT],
3892 ontology: Some(Ontology {
3893 entity_name: "replacement",
3894 description: "A record of an object replacement (ALTER ... SWAP)",
3895 links: &const {
3896 [
3897 OntologyLink {
3898 name: "replacement_object",
3899 target: "object",
3900 properties: LinkProperties::fk("id", "id", Cardinality::ManyToOne),
3901 },
3902 OntologyLink {
3903 name: "replacement_target",
3904 target: "object",
3905 properties: LinkProperties::fk("target_id", "id", Cardinality::ManyToOne),
3906 },
3907 ]
3908 },
3909 column_semantic_types: &[("id", SemanticType::CatalogItemId)],
3910 }),
3911});
3912
3913pub static MZ_SOURCE_STATISTICS_RAW: LazyLock<BuiltinSource> = LazyLock::new(|| BuiltinSource {
3916 name: "mz_source_statistics_raw",
3917 schema: MZ_INTERNAL_SCHEMA,
3918 oid: oid::SOURCE_MZ_SOURCE_STATISTICS_RAW_OID,
3919 data_source: IntrospectionType::StorageSourceStatistics.into(),
3920 desc: MZ_SOURCE_STATISTICS_RAW_DESC.clone(),
3921 column_comments: BTreeMap::new(),
3922 is_retained_metrics_object: true,
3923 access: vec![PUBLIC_SELECT],
3924 ontology: None,
3925});
3926pub static MZ_SINK_STATISTICS_RAW: LazyLock<BuiltinSource> = LazyLock::new(|| BuiltinSource {
3927 name: "mz_sink_statistics_raw",
3928 schema: MZ_INTERNAL_SCHEMA,
3929 oid: oid::SOURCE_MZ_SINK_STATISTICS_RAW_OID,
3930 data_source: IntrospectionType::StorageSinkStatistics.into(),
3931 desc: MZ_SINK_STATISTICS_RAW_DESC.clone(),
3932 column_comments: BTreeMap::new(),
3933 is_retained_metrics_object: true,
3934 access: vec![PUBLIC_SELECT],
3935 ontology: None,
3936});
3937
3938pub static MZ_STORAGE_SHARDS: LazyLock<BuiltinSource> = LazyLock::new(|| BuiltinSource {
3939 name: "mz_storage_shards",
3940 schema: MZ_INTERNAL_SCHEMA,
3941 oid: oid::SOURCE_MZ_STORAGE_SHARDS_OID,
3942 data_source: IntrospectionType::ShardMapping.into(),
3943 desc: RelationDesc::builder()
3944 .with_column("object_id", SqlScalarType::String.nullable(false))
3945 .with_column("shard_id", SqlScalarType::String.nullable(false))
3946 .finish(),
3947 column_comments: BTreeMap::new(),
3948 is_retained_metrics_object: false,
3949 access: vec![PUBLIC_SELECT],
3950 ontology: Some(Ontology {
3951 entity_name: "storage_shard",
3952 description: "Persist shards used by storage objects",
3953 links: &const {
3954 [OntologyLink {
3955 name: "shard_of",
3956 target: "object",
3957 properties: LinkProperties::fk_mapped(
3958 "object_id",
3959 "id",
3960 Cardinality::ManyToOne,
3961 mz_repr::SemanticType::GlobalId,
3962 "mz_internal.mz_object_global_ids",
3963 ),
3964 }]
3965 },
3966 column_semantic_types: &const {
3967 [
3968 ("object_id", SemanticType::GlobalId),
3969 ("shard_id", SemanticType::ShardId),
3970 ]
3971 },
3972 }),
3973});
3974
3975pub static MZ_OBJECTS_ID_NAMESPACE_TYPES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
3976 name: "mz_objects_id_namespace_types",
3977 schema: MZ_INTERNAL_SCHEMA,
3978 oid: oid::VIEW_MZ_OBJECTS_ID_NAMESPACE_TYPES_OID,
3979 desc: RelationDesc::builder()
3980 .with_column("object_type", SqlScalarType::String.nullable(false))
3981 .with_key(vec![0])
3982 .finish(),
3983 column_comments: BTreeMap::new(),
3984 sql: r#"SELECT *
3985 FROM (
3986 VALUES
3987 ('table'),
3988 ('view'),
3989 ('materialized-view'),
3990 ('source'),
3991 ('sink'),
3992 ('metric-sink'),
3993 ('index'),
3994 ('connection'),
3995 ('type'),
3996 ('function'),
3997 ('secret')
3998 )
3999 AS _ (object_type)"#,
4000 access: vec![PUBLIC_SELECT],
4001 ontology: None,
4002});
4003
4004pub static MZ_OBJECT_GRAPH_EDGES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
4015 name: "mz_object_graph_edges",
4016 schema: MZ_INTERNAL_SCHEMA,
4017 oid: oid::VIEW_MZ_OBJECT_GRAPH_EDGES_OID,
4018 desc: RelationDesc::builder()
4019 .with_column("object_id", SqlScalarType::String.nullable(false))
4020 .with_column("dependency_id", SqlScalarType::String.nullable(false))
4021 .with_key(vec![0, 1])
4022 .finish(),
4023 column_comments: BTreeMap::from_iter([
4024 (
4025 "object_id",
4026 "The ID of the dependent object. Corresponds to `mz_objects.id`.",
4027 ),
4028 (
4029 "dependency_id",
4030 "The ID of the object it depends on. Corresponds to `mz_objects.id`.",
4031 ),
4032 ]),
4033 sql: "
4034SELECT md.object_id, md.dependency_id
4035FROM mz_internal.mz_materialization_dependencies md
4036JOIN mz_catalog.mz_objects po ON po.id = md.dependency_id
4037 AND po.type IN ('index', 'materialized-view', 'sink', 'source', 'table')
4038JOIN mz_catalog.mz_objects co ON co.id = md.object_id
4039 AND co.type IN ('index', 'materialized-view', 'sink', 'source', 'table')
4040UNION
4041-- Subsource -> parent-source edges: a subsource depends on the (user) source it
4042-- belongs to, an edge mz_materialization_dependencies doesn't carry.
4043SELECT od.object_id, od.referenced_object_id
4044FROM mz_internal.mz_object_dependencies od
4045JOIN mz_catalog.mz_sources ps ON ps.id = od.referenced_object_id
4046JOIN mz_catalog.mz_sources cs ON cs.id = od.object_id
4047-- Progress collections are deliberately left out: their dependency edge points
4048-- source -> progress, and they only exist for old-syntax sources, which the
4049-- source-table migration is removing.
4050WHERE ps.id LIKE 'u%' AND cs.type = 'subsource'
4051UNION
4052-- Select the (non-null) source id from the join rather than the nullable
4053-- mz_tables.source_id, so dependency_id is non-null across all branches.
4054SELECT t.id, ps.id
4055FROM mz_catalog.mz_tables t
4056JOIN mz_catalog.mz_sources ps ON ps.id = t.source_id",
4057 access: vec![PUBLIC_SELECT],
4058 ontology: None,
4062});
4063
4064pub static MZ_OBJECT_OID_ALIAS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
4065 name: "mz_object_oid_alias",
4066 schema: MZ_INTERNAL_SCHEMA,
4067 oid: oid::VIEW_MZ_OBJECT_OID_ALIAS_OID,
4068 desc: RelationDesc::builder()
4069 .with_column("object_type", SqlScalarType::String.nullable(false))
4070 .with_column("oid_alias", SqlScalarType::String.nullable(false))
4071 .with_key(vec![0])
4072 .finish(),
4073 column_comments: BTreeMap::new(),
4074 sql: "SELECT object_type, oid_alias
4075 FROM (
4076 VALUES
4077 (
4078 'table'::pg_catalog.text,
4079 'regclass'::pg_catalog.text
4080 ),
4081 ('source', 'regclass'),
4082 ('view', 'regclass'),
4083 ('materialized-view', 'regclass'),
4084 ('index', 'regclass'),
4085 ('type', 'regtype'),
4086 ('function', 'regproc')
4087 )
4088 AS _ (object_type, oid_alias);",
4089 access: vec![PUBLIC_SELECT],
4090 ontology: None,
4091});
4092
4093pub static MZ_OBJECT_FULLY_QUALIFIED_NAMES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
4094 name: "mz_object_fully_qualified_names",
4095 schema: MZ_INTERNAL_SCHEMA,
4096 oid: oid::VIEW_MZ_OBJECT_FULLY_QUALIFIED_NAMES_OID,
4097 desc: RelationDesc::builder()
4098 .with_column("id", SqlScalarType::String.nullable(false))
4099 .with_column("name", SqlScalarType::String.nullable(false))
4100 .with_column("object_type", SqlScalarType::String.nullable(false))
4101 .with_column("schema_id", SqlScalarType::String.nullable(false))
4102 .with_column("schema_name", SqlScalarType::String.nullable(false))
4103 .with_column("database_id", SqlScalarType::String.nullable(true))
4104 .with_column("database_name", SqlScalarType::String.nullable(true))
4105 .with_column("cluster_id", SqlScalarType::String.nullable(true))
4106 .finish(),
4107 column_comments: BTreeMap::from_iter([
4108 ("id", "Materialize's unique ID for the object."),
4109 ("name", "The name of the object."),
4110 (
4111 "object_type",
4112 "The type of the object: one of `table`, `source`, `view`, `materialized-view`, `sink`, `index`, `connection`, `secret`, `type`, or `function`.",
4113 ),
4114 (
4115 "schema_id",
4116 "The ID of the schema to which the object belongs. Corresponds to `mz_schemas.id`.",
4117 ),
4118 (
4119 "schema_name",
4120 "The name of the schema to which the object belongs. Corresponds to `mz_schemas.name`.",
4121 ),
4122 (
4123 "database_id",
4124 "The ID of the database to which the object belongs. Corresponds to `mz_databases.id`.",
4125 ),
4126 (
4127 "database_name",
4128 "The name of the database to which the object belongs. Corresponds to `mz_databases.name`.",
4129 ),
4130 (
4131 "cluster_id",
4132 "The ID of the cluster maintaining the source, materialized view, index, or sink. Corresponds to `mz_clusters.id`. `NULL` for other object types.",
4133 ),
4134 ]),
4135 sql: "
4136 SELECT o.id,
4137 o.name,
4138 o.type as object_type,
4139 sc.id as schema_id,
4140 sc.name as schema_name,
4141 db.id as database_id,
4142 db.name as database_name,
4143 o.cluster_id
4144 FROM mz_catalog.mz_objects o
4145 INNER JOIN mz_catalog.mz_schemas sc ON sc.id = o.schema_id
4146 -- LEFT JOIN accounts for objects in the ambient database.
4147 LEFT JOIN mz_catalog.mz_databases db ON db.id = sc.database_id",
4148 access: vec![PUBLIC_SELECT],
4149 ontology: Some(Ontology {
4150 entity_name: "object_fqn",
4151 description: "Fully qualified name (database.schema.name) for objects",
4152 links: &const {
4153 [
4154 OntologyLink {
4155 name: "details_of",
4156 target: "object",
4157 properties: LinkProperties::fk("id", "id", Cardinality::OneToOne),
4158 },
4159 OntologyLink {
4160 name: "in_schema",
4161 target: "schema",
4162 properties: LinkProperties::fk("schema_id", "id", Cardinality::ManyToOne),
4163 },
4164 OntologyLink {
4165 name: "in_database",
4166 target: "database",
4167 properties: LinkProperties::fk("database_id", "id", Cardinality::ManyToOne),
4168 },
4169 OntologyLink {
4170 name: "belongs_to_cluster",
4171 target: "cluster",
4172 properties: LinkProperties::fk("cluster_id", "id", Cardinality::ManyToOne),
4173 },
4174 ]
4175 },
4176 column_semantic_types: &const {
4177 [
4178 ("id", SemanticType::CatalogItemId),
4179 ("object_type", SemanticType::ObjectType),
4180 ("schema_id", SemanticType::SchemaId),
4181 ("database_id", SemanticType::DatabaseId),
4182 ("cluster_id", SemanticType::ClusterId),
4183 ]
4184 },
4185 }),
4186});
4187
4188pub static MZ_OBJECT_GLOBAL_IDS: LazyLock<BuiltinMaterializedView> =
4189 LazyLock::new(|| BuiltinMaterializedView {
4190 name: "mz_object_global_ids",
4191 schema: MZ_INTERNAL_SCHEMA,
4192 oid: oid::MV_MZ_OBJECT_GLOBAL_IDS_OID,
4193 desc: RelationDesc::builder()
4194 .with_column("id", SqlScalarType::String.nullable(false))
4195 .with_column("global_id", SqlScalarType::String.nullable(false))
4196 .finish(),
4197 column_comments: BTreeMap::from_iter([
4198 (
4199 "id",
4200 "The ID of the object. Corresponds to `mz_objects.id`.",
4201 ),
4202 ("global_id", "The global ID of the object."),
4203 ]),
4204 sql: Box::leak(
4205 format!(
4206 "
4207IN CLUSTER mz_catalog_server
4208WITH (
4209 ASSERT NOT NULL id,
4210 ASSERT NOT NULL global_id
4211) AS
4212WITH
4213 -- `Item` rows carry user items, temporary items, and runtime-alterable builtins
4214 items AS (
4215 SELECT
4216 mz_internal.parse_catalog_id(data->'key'->'gid') AS id,
4217 mz_internal.parse_catalog_id(data->'value'->'global_id') AS global_id,
4218 data->'value'->'extra_versions' AS extra_versions
4219 FROM mz_internal.mz_catalog_raw
4220 WHERE data->>'kind' = 'Item'
4221 ),
4222 -- Create a one to many mapping between an object and its global IDs. Tables and
4223 -- materialized views are the only objects with multiple global IDs.
4224 item_versions AS (
4225 SELECT i.id, mz_internal.parse_catalog_id(v.version->'global_id') AS global_id
4226 FROM items i
4227 CROSS JOIN LATERAL jsonb_array_elements(i.extra_versions) AS v(version)
4228 ),
4229 builtin_mappings AS (
4230 SELECT
4231 's' || (data->'value'->>'catalog_id') AS id,
4232 's' || (data->'value'->>'global_id') AS global_id
4233 FROM mz_internal.mz_catalog_raw
4234 WHERE
4235 data->>'kind' = 'GidMapping' AND
4236 -- Exclude runtime-alterable builtins since they're already included in `items`
4237 data->'value'->>'fingerprint' != '{RUNTIME_ALTERABLE_FINGERPRINT_SENTINEL}'
4238 ),
4239 introspection_source_indexes AS (
4240 SELECT
4241 'si' || (data->'value'->>'catalog_id') AS id,
4242 'si' || (data->'value'->>'global_id') AS global_id
4243 FROM mz_internal.mz_catalog_raw
4244 WHERE data->>'kind' = 'ClusterIntrospectionSourceIndex'
4245 )
4246SELECT id, global_id FROM items
4247UNION ALL
4248SELECT id, global_id FROM item_versions
4249UNION ALL
4250SELECT id, global_id FROM builtin_mappings
4251UNION ALL
4252SELECT id, global_id FROM introspection_source_indexes"
4253 )
4254 .into_boxed_str(),
4255 ),
4256 is_retained_metrics_object: false,
4257 access: vec![PUBLIC_SELECT],
4258 ontology: Some(Ontology {
4259 entity_name: "object_global_id",
4260 description: "Mapping between CatalogItemId (SQL layer) and GlobalId (runtime layer)",
4261 links: &const {
4262 [OntologyLink {
4263 name: "id_references",
4264 target: "object",
4265 properties: LinkProperties::fk("id", "id", Cardinality::ManyToOne),
4266 }]
4267 },
4268 column_semantic_types: &[("id", SemanticType::CatalogItemId)],
4269 }),
4270 });
4271
4272pub static MZ_OBJECT_LIFETIMES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
4274 name: "mz_object_lifetimes",
4275 schema: MZ_INTERNAL_SCHEMA,
4276 oid: oid::VIEW_MZ_OBJECT_LIFETIMES_OID,
4277 desc: RelationDesc::builder()
4278 .with_column("id", SqlScalarType::String.nullable(true))
4279 .with_column("previous_id", SqlScalarType::String.nullable(true))
4280 .with_column("object_type", SqlScalarType::String.nullable(false))
4281 .with_column("event_type", SqlScalarType::String.nullable(false))
4282 .with_column(
4283 "occurred_at",
4284 SqlScalarType::TimestampTz { precision: None }.nullable(false),
4285 )
4286 .finish(),
4287 column_comments: BTreeMap::from_iter([
4288 ("id", "Materialize's unique ID for the object."),
4289 ("previous_id", "The object's previous ID, if one exists."),
4290 (
4291 "object_type",
4292 "The type of the object: one of `table`, `source`, `view`, `materialized-view`, `sink`, `index`, `connection`, `secret`, `type`, or `function`.",
4293 ),
4294 (
4295 "event_type",
4296 "The lifetime event, either `create` or `drop`.",
4297 ),
4298 (
4299 "occurred_at",
4300 "Wall-clock timestamp of when the event occurred.",
4301 ),
4302 ]),
4303 sql: "
4304 SELECT
4305 CASE
4306 WHEN a.object_type = 'cluster-replica' THEN a.details ->> 'replica_id'
4307 ELSE a.details ->> 'id'
4308 END id,
4309 a.details ->> 'previous_id' as previous_id,
4310 a.object_type,
4311 a.event_type,
4312 a.occurred_at
4313 FROM mz_catalog.mz_audit_events a
4314 WHERE a.event_type = 'create' OR a.event_type = 'drop'",
4315 access: vec![PUBLIC_SELECT],
4316 ontology: Some(Ontology {
4317 entity_name: "object_lifetime_event",
4318 description: "Create or drop lifecycle event for a catalog object",
4319 links: &const {
4320 [OntologyLink {
4321 name: "lifetime_event_of",
4322 target: "object",
4323 properties: LinkProperties::fk_typed(
4324 "id",
4325 "id",
4326 Cardinality::ManyToOne,
4327 mz_repr::SemanticType::CatalogItemId,
4328 ),
4329 }]
4330 },
4331 column_semantic_types: &const {
4332 [
4333 ("id", SemanticType::CatalogItemId),
4334 ("object_type", SemanticType::ObjectType),
4335 ]
4336 },
4337 }),
4338});
4339
4340pub static MZ_OBJECT_HISTORY: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
4341 name: "mz_object_history",
4342 schema: MZ_INTERNAL_SCHEMA,
4343 oid: oid::VIEW_MZ_OBJECT_HISTORY_OID,
4344 desc: RelationDesc::builder()
4345 .with_column("id", SqlScalarType::String.nullable(true))
4346 .with_column("cluster_id", SqlScalarType::String.nullable(true))
4347 .with_column("object_type", SqlScalarType::String.nullable(false))
4348 .with_column(
4349 "created_at",
4350 SqlScalarType::TimestampTz { precision: None }.nullable(true),
4351 )
4352 .with_column(
4353 "dropped_at",
4354 SqlScalarType::TimestampTz { precision: None }.nullable(true),
4355 )
4356 .finish(),
4357 column_comments: BTreeMap::from_iter([
4358 ("id", "Materialize's unique ID for the object."),
4359 (
4360 "cluster_id",
4361 "The object's cluster ID. `NULL` if the object has no associated cluster.",
4362 ),
4363 (
4364 "object_type",
4365 "The type of the object: one of `table`, `source`, `view`, `materialized-view`, `sink`, `index`, `connection`, `secret`, `type`, or `function`.",
4366 ),
4367 (
4368 "created_at",
4369 "Wall-clock timestamp of when the object was created. `NULL` for built in system objects.",
4370 ),
4371 (
4372 "dropped_at",
4373 "Wall-clock timestamp of when the object was dropped. `NULL` for built in system objects or if the object hasn't been dropped.",
4374 ),
4375 ]),
4376 sql: r#"
4377 WITH
4378 creates AS
4379 (
4380 SELECT
4381 details ->> 'id' AS id,
4382 -- We need to backfill cluster_id since older object create events don't include the cluster ID in the audit log
4383 COALESCE(details ->> 'cluster_id', objects.cluster_id) AS cluster_id,
4384 object_type,
4385 occurred_at
4386 FROM
4387 mz_catalog.mz_audit_events AS events
4388 LEFT JOIN mz_catalog.mz_objects AS objects ON details ->> 'id' = objects.id
4389 WHERE event_type = 'create' AND object_type IN ( SELECT object_type FROM mz_internal.mz_objects_id_namespace_types )
4390 ),
4391 drops AS
4392 (
4393 SELECT details ->> 'id' AS id, occurred_at
4394 FROM mz_catalog.mz_audit_events
4395 WHERE event_type = 'drop' AND object_type IN ( SELECT object_type FROM mz_internal.mz_objects_id_namespace_types )
4396 ),
4397 user_object_history AS
4398 (
4399 SELECT
4400 creates.id,
4401 creates.cluster_id,
4402 creates.object_type,
4403 creates.occurred_at AS created_at,
4404 drops.occurred_at AS dropped_at
4405 FROM creates LEFT JOIN drops ON creates.id = drops.id
4406 WHERE creates.id LIKE 'u%'
4407 ),
4408 -- We need to union built in objects since they aren't in the audit log
4409 built_in_objects AS
4410 (
4411 -- Functions that accept different arguments have different oids but the same id. We deduplicate in this case.
4412 SELECT DISTINCT ON (objects.id)
4413 objects.id,
4414 objects.cluster_id,
4415 objects.type AS object_type,
4416 NULL::timestamptz AS created_at,
4417 NULL::timestamptz AS dropped_at
4418 FROM mz_catalog.mz_objects AS objects
4419 WHERE objects.id LIKE 's%'
4420 )
4421 SELECT * FROM user_object_history UNION ALL (SELECT * FROM built_in_objects)"#,
4422 access: vec![PUBLIC_SELECT],
4423 ontology: Some(Ontology {
4424 entity_name: "object_history",
4425 description: "Historical record of object creation and drops",
4426 links: &const {
4427 [OntologyLink {
4428 name: "history_of",
4429 target: "object",
4430 properties: LinkProperties::fk("id", "id", Cardinality::ManyToOne),
4431 }]
4432 },
4433 column_semantic_types: &[("id", SemanticType::CatalogItemId)],
4434 }),
4435});
4436
4437pub static MZ_OBJECT_TRANSITIVE_DEPENDENCIES: LazyLock<BuiltinView> = LazyLock::new(|| {
4438 BuiltinView {
4439 name: "mz_object_transitive_dependencies",
4440 schema: MZ_INTERNAL_SCHEMA,
4441 oid: oid::VIEW_MZ_OBJECT_TRANSITIVE_DEPENDENCIES_OID,
4442 desc: RelationDesc::builder()
4443 .with_column("object_id", SqlScalarType::String.nullable(false))
4444 .with_column(
4445 "referenced_object_id",
4446 SqlScalarType::String.nullable(false),
4447 )
4448 .with_key(vec![0, 1])
4449 .finish(),
4450 column_comments: BTreeMap::from_iter([
4451 (
4452 "object_id",
4453 "The ID of the dependent object. Corresponds to `mz_objects.id`.",
4454 ),
4455 (
4456 "referenced_object_id",
4457 "The ID of the (possibly transitively) referenced object. Corresponds to `mz_objects.id`.",
4458 ),
4459 ]),
4460 sql: "
4461WITH MUTUALLY RECURSIVE
4462 reach(object_id text, referenced_object_id text) AS (
4463 SELECT object_id, referenced_object_id FROM mz_internal.mz_object_dependencies
4464 UNION
4465 SELECT x, z FROM reach r1(x, y) JOIN reach r2(y, z) USING(y)
4466 )
4467SELECT object_id, referenced_object_id FROM reach;",
4468 access: vec![PUBLIC_SELECT],
4469 ontology: Some(Ontology {
4470 entity_name: "transitive_dependency",
4471 description: "Transitive closure of object dependencies — all direct and indirect dependencies",
4472 links: &const {
4473 [
4474 OntologyLink {
4475 name: "depends_on",
4476 target: "object",
4477 properties: LinkProperties::DependsOn {
4478 source_column: "object_id",
4479 target_column: "id",
4480 source_id_type: Some(mz_repr::SemanticType::CatalogItemId),
4481 requires_mapping: None,
4482 },
4483 },
4484 OntologyLink {
4485 name: "dependency_is",
4486 target: "object",
4487 properties: LinkProperties::DependsOn {
4488 source_column: "referenced_object_id",
4489 target_column: "id",
4490 source_id_type: Some(mz_repr::SemanticType::CatalogItemId),
4491 requires_mapping: None,
4492 },
4493 },
4494 ]
4495 },
4496 column_semantic_types: &const {
4497 [
4498 ("object_id", SemanticType::CatalogItemId),
4499 ("referenced_object_id", SemanticType::CatalogItemId),
4500 ]
4501 },
4502 }),
4503 }
4504});
4505
4506pub static PG_NAMESPACE_ALL_DATABASES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
4512 name: "pg_namespace_all_databases",
4513 schema: MZ_INTERNAL_SCHEMA,
4514 oid: oid::VIEW_PG_NAMESPACE_ALL_DATABASES_OID,
4515 desc: RelationDesc::builder()
4516 .with_column("oid", SqlScalarType::Oid.nullable(false))
4517 .with_column("nspname", SqlScalarType::String.nullable(false))
4518 .with_column("nspowner", SqlScalarType::Oid.nullable(false))
4519 .with_column(
4520 "nspacl",
4521 SqlScalarType::Array(Box::new(SqlScalarType::String)).nullable(true),
4522 )
4523 .with_column("database_name", SqlScalarType::String.nullable(true))
4524 .finish(),
4525 column_comments: BTreeMap::new(),
4526 sql: "
4527SELECT
4528 s.oid AS oid,
4529 s.name AS nspname,
4530 role_owner.oid AS nspowner,
4531 NULL::pg_catalog.text[] AS nspacl,
4532 d.name as database_name
4533FROM mz_catalog.mz_schemas s
4534LEFT JOIN mz_catalog.mz_databases d ON d.id = s.database_id
4535JOIN mz_catalog.mz_roles role_owner ON role_owner.id = s.owner_id",
4536 access: vec![PUBLIC_SELECT],
4537 ontology: None,
4538});
4539
4540pub const PG_NAMESPACE_ALL_DATABASES_IND: BuiltinIndex = BuiltinIndex {
4541 name: "pg_namespace_all_databases_ind",
4542 schema: MZ_INTERNAL_SCHEMA,
4543 oid: oid::INDEX_PG_NAMESPACE_ALL_DATABASES_IND_OID,
4544 sql: "IN CLUSTER mz_catalog_server
4545ON mz_internal.pg_namespace_all_databases (nspname)",
4546 is_retained_metrics_object: false,
4547};
4548
4549pub static PG_CLASS_ALL_DATABASES: LazyLock<BuiltinView> = LazyLock::new(|| {
4555 BuiltinView {
4556 name: "pg_class_all_databases",
4557 schema: MZ_INTERNAL_SCHEMA,
4558 oid: oid::VIEW_PG_CLASS_ALL_DATABASES_OID,
4559 desc: RelationDesc::builder()
4560 .with_column("oid", SqlScalarType::Oid.nullable(false))
4561 .with_column("relname", SqlScalarType::String.nullable(false))
4562 .with_column("relnamespace", SqlScalarType::Oid.nullable(false))
4563 .with_column("reloftype", SqlScalarType::Oid.nullable(false))
4564 .with_column("relowner", SqlScalarType::Oid.nullable(false))
4565 .with_column("relam", SqlScalarType::Oid.nullable(false))
4566 .with_column("reltablespace", SqlScalarType::Oid.nullable(false))
4567 .with_column("reltuples", SqlScalarType::Float32.nullable(false))
4568 .with_column("reltoastrelid", SqlScalarType::Oid.nullable(false))
4569 .with_column("relhasindex", SqlScalarType::Bool.nullable(false))
4570 .with_column("relpersistence", SqlScalarType::PgLegacyChar.nullable(false))
4571 .with_column("relkind", SqlScalarType::String.nullable(true))
4572 .with_column("relnatts", SqlScalarType::Int16.nullable(false))
4573 .with_column("relchecks", SqlScalarType::Int16.nullable(false))
4574 .with_column("relhasrules", SqlScalarType::Bool.nullable(false))
4575 .with_column("relhastriggers", SqlScalarType::Bool.nullable(false))
4576 .with_column("relhassubclass", SqlScalarType::Bool.nullable(false))
4577 .with_column("relrowsecurity", SqlScalarType::Bool.nullable(false))
4578 .with_column("relforcerowsecurity", SqlScalarType::Bool.nullable(false))
4579 .with_column("relreplident", SqlScalarType::PgLegacyChar.nullable(false))
4580 .with_column("relispartition", SqlScalarType::Bool.nullable(false))
4581 .with_column("relhasoids", SqlScalarType::Bool.nullable(false))
4582 .with_column("reloptions", SqlScalarType::Array(Box::new(SqlScalarType::String)).nullable(true))
4583 .with_column("database_name", SqlScalarType::String.nullable(true))
4584 .finish(),
4585 column_comments: BTreeMap::new(),
4586 sql: "
4587SELECT
4588 class_objects.oid,
4589 class_objects.name AS relname,
4590 mz_schemas.oid AS relnamespace,
4591 -- MZ doesn't support typed tables so reloftype is filled with 0
4592 0::pg_catalog.oid AS reloftype,
4593 role_owner.oid AS relowner,
4594 0::pg_catalog.oid AS relam,
4595 -- MZ doesn't have tablespaces so reltablespace is filled in with 0 implying the default tablespace
4596 0::pg_catalog.oid AS reltablespace,
4597 -- MZ doesn't support (estimated) row counts currently.
4598 -- Postgres defines a value of -1 as unknown.
4599 -1::float4 as reltuples,
4600 -- MZ doesn't use TOAST tables so reltoastrelid is filled with 0
4601 0::pg_catalog.oid AS reltoastrelid,
4602 EXISTS (SELECT id, oid, name, on_id, cluster_id FROM mz_catalog.mz_indexes where mz_indexes.on_id = class_objects.id) AS relhasindex,
4603 -- MZ doesn't have unlogged tables and because of (https://github.com/MaterializeInc/database-issues/issues/2689)
4604 -- temporary objects don't show up here, so relpersistence is filled with 'p' for permanent.
4605 -- TODO(jkosh44): update this column when issue is resolved.
4606 'p'::pg_catalog.\"char\" AS relpersistence,
4607 CASE
4608 WHEN class_objects.type = 'table' THEN 'r'
4609 WHEN class_objects.type = 'source' THEN 'r'
4610 WHEN class_objects.type = 'index' THEN 'i'
4611 WHEN class_objects.type = 'view' THEN 'v'
4612 WHEN class_objects.type = 'materialized-view' THEN 'm'
4613 END relkind,
4614 CASE
4615 WHEN class_objects.type = 'index' THEN COALESCE(
4616 (
4617 SELECT count(*)::pg_catalog.int2
4618 FROM mz_catalog.mz_index_columns
4619 WHERE mz_index_columns.index_id = class_objects.id
4620 ),
4621 0::pg_catalog.int2
4622 )
4623 ELSE COALESCE(
4624 (
4625 SELECT count(*)::pg_catalog.int2
4626 FROM mz_catalog.mz_columns
4627 WHERE mz_columns.id = class_objects.id
4628 ),
4629 0::pg_catalog.int2
4630 )
4631 END AS relnatts,
4632 -- MZ doesn't support CHECK constraints so relchecks is filled with 0
4633 0::pg_catalog.int2 AS relchecks,
4634 -- MZ doesn't support creating rules so relhasrules is filled with false
4635 false AS relhasrules,
4636 -- MZ doesn't support creating triggers so relhastriggers is filled with false
4637 false AS relhastriggers,
4638 -- MZ doesn't support table inheritance or partitions so relhassubclass is filled with false
4639 false AS relhassubclass,
4640 -- MZ doesn't have row level security so relrowsecurity and relforcerowsecurity is filled with false
4641 false AS relrowsecurity,
4642 false AS relforcerowsecurity,
4643 -- MZ doesn't support replication so relreplident is filled with 'd' for default
4644 'd'::pg_catalog.\"char\" AS relreplident,
4645 -- MZ doesn't support table partitioning so relispartition is filled with false
4646 false AS relispartition,
4647 -- PG removed relhasoids in v12 so it's filled with false
4648 false AS relhasoids,
4649 -- MZ doesn't support options for relations
4650 NULL::pg_catalog.text[] as reloptions,
4651 d.name as database_name
4652FROM (
4653 -- pg_class catalogs relations and indexes
4654 SELECT id, oid, schema_id, name, type, owner_id FROM mz_catalog.mz_relations
4655 UNION ALL
4656 SELECT mz_indexes.id, mz_indexes.oid, mz_relations.schema_id, mz_indexes.name, 'index' AS type, mz_indexes.owner_id
4657 FROM mz_catalog.mz_indexes
4658 JOIN mz_catalog.mz_relations ON mz_indexes.on_id = mz_relations.id
4659) AS class_objects
4660JOIN mz_catalog.mz_schemas ON mz_schemas.id = class_objects.schema_id
4661LEFT JOIN mz_catalog.mz_databases d ON d.id = mz_schemas.database_id
4662JOIN mz_catalog.mz_roles role_owner ON role_owner.id = class_objects.owner_id",
4663 access: vec![PUBLIC_SELECT],
4664 ontology: None,
4665 }
4666});
4667
4668pub const PG_CLASS_ALL_DATABASES_IND: BuiltinIndex = BuiltinIndex {
4669 name: "pg_class_all_databases_ind",
4670 schema: MZ_INTERNAL_SCHEMA,
4671 oid: oid::INDEX_PG_CLASS_ALL_DATABASES_IND_OID,
4672 sql: "IN CLUSTER mz_catalog_server
4673ON mz_internal.pg_class_all_databases (relname)",
4674 is_retained_metrics_object: false,
4675};
4676
4677pub static PG_DESCRIPTION_ALL_DATABASES: LazyLock<BuiltinView> = LazyLock::new(|| {
4683 BuiltinView {
4684 name: "pg_description_all_databases",
4685 schema: MZ_INTERNAL_SCHEMA,
4686 oid: oid::VIEW_PG_DESCRIPTION_ALL_DATABASES_OID,
4687 desc: RelationDesc::builder()
4688 .with_column("objoid", SqlScalarType::Oid.nullable(false))
4689 .with_column("classoid", SqlScalarType::Oid.nullable(true))
4690 .with_column("objsubid", SqlScalarType::Int32.nullable(false))
4691 .with_column("description", SqlScalarType::String.nullable(false))
4692 .with_column("oid_database_name", SqlScalarType::String.nullable(true))
4693 .with_column("class_database_name", SqlScalarType::String.nullable(true))
4694 .finish(),
4695 column_comments: BTreeMap::new(),
4696 sql: "
4697(
4698 -- The classoid of a comment is the oid of the pg_catalog system catalog
4699 -- that conceptually stores the commented object: pg_class for relations,
4700 -- pg_type for types, pg_namespace for schemas. We scope the lookup to the
4701 -- pg_catalog schema; otherwise a user-created object named e.g. `pg_class`
4702 -- makes the scalar subqueries below match multiple rows and the whole view
4703 -- errors for everyone. PostgreSQL's pg_description is a real catalog table
4704 -- and is unaffected by such user objects, and so are we.
4705 WITH pg_catalog_class AS (
4706 SELECT oid, relname, database_name
4707 FROM mz_internal.pg_class_all_databases
4708 WHERE relnamespace = (
4709 SELECT oid FROM mz_internal.pg_namespace_all_databases WHERE nspname = 'pg_catalog'
4710 )
4711 ),
4712 -- Gather all of the class oid's for objects that can have comments.
4713 pg_classoids AS (
4714 SELECT oid, database_name as oid_database_name,
4715 (SELECT oid FROM pg_catalog_class WHERE relname = 'pg_class') AS classoid,
4716 (SELECT database_name FROM pg_catalog_class WHERE relname = 'pg_class') AS class_database_name
4717 FROM mz_internal.pg_class_all_databases
4718 UNION ALL
4719 SELECT oid, database_name as oid_database_name,
4720 (SELECT oid FROM pg_catalog_class WHERE relname = 'pg_type') AS classoid,
4721 (SELECT database_name FROM pg_catalog_class WHERE relname = 'pg_type') AS class_database_name
4722 FROM mz_internal.pg_type_all_databases
4723 UNION ALL
4724 SELECT oid, database_name as oid_database_name,
4725 (SELECT oid FROM pg_catalog_class WHERE relname = 'pg_namespace') AS classoid,
4726 (SELECT database_name FROM pg_catalog_class WHERE relname = 'pg_namespace') AS class_database_name
4727 FROM mz_internal.pg_namespace_all_databases
4728 ),
4729
4730 -- Gather all of the MZ ids for objects that can have comments.
4731 mz_objects AS (
4732 SELECT id, oid, type FROM mz_catalog.mz_objects
4733 UNION ALL
4734 SELECT id, oid, 'schema' AS type FROM mz_catalog.mz_schemas
4735 )
4736 SELECT
4737 pg_classoids.oid AS objoid,
4738 pg_classoids.classoid as classoid,
4739 COALESCE(cmt.object_sub_id, 0) AS objsubid,
4740 cmt.comment AS description,
4741 -- Columns added because of the peeling. (Note that there are 2 of these here.)
4742 oid_database_name,
4743 class_database_name
4744 FROM
4745 pg_classoids
4746 JOIN
4747 mz_objects ON pg_classoids.oid = mz_objects.oid
4748 JOIN
4749 mz_internal.mz_comments AS cmt ON mz_objects.id = cmt.id AND lower(mz_objects.type) = lower(cmt.object_type)
4750)",
4751 access: vec![PUBLIC_SELECT],
4752 ontology: None,
4753 }
4754});
4755
4756pub const PG_DESCRIPTION_ALL_DATABASES_IND: BuiltinIndex = BuiltinIndex {
4757 name: "pg_description_all_databases_ind",
4758 schema: MZ_INTERNAL_SCHEMA,
4759 oid: oid::INDEX_PG_DESCRIPTION_ALL_DATABASES_IND_OID,
4760 sql: "IN CLUSTER mz_catalog_server
4761ON mz_internal.pg_description_all_databases (objoid, classoid, objsubid, description, oid_database_name, class_database_name)",
4762 is_retained_metrics_object: false,
4763};
4764
4765pub static PG_TYPE_ALL_DATABASES: LazyLock<BuiltinView> = LazyLock::new(|| {
4771 BuiltinView {
4772 name: "pg_type_all_databases",
4773 schema: MZ_INTERNAL_SCHEMA,
4774 oid: oid::VIEW_PG_TYPE_ALL_DATABASES_OID,
4775 desc: RelationDesc::builder()
4776 .with_column("oid", SqlScalarType::Oid.nullable(false))
4777 .with_column("typname", SqlScalarType::String.nullable(false))
4778 .with_column("typnamespace", SqlScalarType::Oid.nullable(false))
4779 .with_column("typowner", SqlScalarType::Oid.nullable(false))
4780 .with_column("typlen", SqlScalarType::Int16.nullable(true))
4781 .with_column("typtype", SqlScalarType::PgLegacyChar.nullable(false))
4782 .with_column("typcategory", SqlScalarType::PgLegacyChar.nullable(true))
4783 .with_column("typdelim", SqlScalarType::PgLegacyChar.nullable(false))
4784 .with_column("typrelid", SqlScalarType::Oid.nullable(false))
4785 .with_column("typelem", SqlScalarType::Oid.nullable(false))
4786 .with_column("typarray", SqlScalarType::Oid.nullable(false))
4787 .with_column("typinput", SqlScalarType::RegProc.nullable(true))
4788 .with_column("typreceive", SqlScalarType::Oid.nullable(false))
4789 .with_column("typnotnull", SqlScalarType::Bool.nullable(false))
4790 .with_column("typbasetype", SqlScalarType::Oid.nullable(false))
4791 .with_column("typtypmod", SqlScalarType::Int32.nullable(false))
4792 .with_column("typcollation", SqlScalarType::Oid.nullable(false))
4793 .with_column("typdefault", SqlScalarType::String.nullable(true))
4794 .with_column("database_name", SqlScalarType::String.nullable(true))
4795 .with_column("typsend", SqlScalarType::RegProc.nullable(false))
4796 .finish(),
4797 column_comments: BTreeMap::new(),
4798 sql: "
4799SELECT
4800 mz_types.oid,
4801 mz_types.name AS typname,
4802 mz_schemas.oid AS typnamespace,
4803 role_owner.oid AS typowner,
4804 NULL::pg_catalog.int2 AS typlen,
4805 -- 'a' is used internally to denote an array type, but in postgres they show up
4806 -- as 'b'.
4807 (CASE mztype WHEN 'a' THEN 'b' ELSE mztype END)::pg_catalog.char AS typtype,
4808 (CASE category
4809 WHEN 'array' THEN 'A'
4810 WHEN 'bit-string' THEN 'V'
4811 WHEN 'boolean' THEN 'B'
4812 WHEN 'composite' THEN 'C'
4813 WHEN 'date-time' THEN 'D'
4814 WHEN 'enum' THEN 'E'
4815 WHEN 'geometric' THEN 'G'
4816 WHEN 'list' THEN 'U' -- List types are user-defined from PostgreSQL's perspective.
4817 WHEN 'network-address' THEN 'I'
4818 WHEN 'numeric' THEN 'N'
4819 WHEN 'pseudo' THEN 'P'
4820 WHEN 'string' THEN 'S'
4821 WHEN 'timespan' THEN 'T'
4822 WHEN 'user-defined' THEN 'U'
4823 WHEN 'unknown' THEN 'X'
4824 END)::pg_catalog.char AS typcategory,
4825 -- In pg only the 'box' type is not ','.
4826 ','::pg_catalog.char AS typdelim,
4827 0::pg_catalog.oid AS typrelid,
4828 coalesce(
4829 (
4830 SELECT t.oid
4831 FROM mz_catalog.mz_array_types a
4832 JOIN mz_catalog.mz_types t ON a.element_id = t.id
4833 WHERE a.id = mz_types.id
4834 ),
4835 (
4836 SELECT t.oid
4837 FROM mz_catalog.mz_list_types l
4838 JOIN mz_catalog.mz_types t ON l.element_id = t.id
4839 WHERE l.id = mz_types.id
4840 ),
4841 0
4842 ) AS typelem,
4843 coalesce(
4844 (
4845 SELECT
4846 t.oid
4847 FROM
4848 mz_catalog.mz_array_types AS a
4849 JOIN mz_catalog.mz_types AS t ON a.id = t.id
4850 WHERE
4851 a.element_id = mz_types.id
4852 ),
4853 0
4854 )
4855 AS typarray,
4856 mz_internal.mz_type_pg_metadata.typinput::pg_catalog.regproc AS typinput,
4857 COALESCE(mz_internal.mz_type_pg_metadata.typreceive, 0) AS typreceive,
4858 false::pg_catalog.bool AS typnotnull,
4859 0::pg_catalog.oid AS typbasetype,
4860 -1::pg_catalog.int4 AS typtypmod,
4861 -- MZ doesn't support COLLATE so typcollation is filled with 0
4862 0::pg_catalog.oid AS typcollation,
4863 NULL::pg_catalog.text AS typdefault,
4864 d.name as database_name,
4865 COALESCE(mz_internal.mz_type_pg_metadata.typsend, 0)::pg_catalog.regproc AS typsend
4866FROM
4867 mz_catalog.mz_types
4868 LEFT JOIN mz_internal.mz_type_pg_metadata ON mz_catalog.mz_types.id = mz_internal.mz_type_pg_metadata.id
4869 JOIN mz_catalog.mz_schemas ON mz_schemas.id = mz_types.schema_id
4870 JOIN (
4871 -- 'a' is not a supported typtype, but we use it to denote an array. It is
4872 -- converted to the correct value above.
4873 SELECT id, 'a' AS mztype FROM mz_catalog.mz_array_types
4874 UNION ALL SELECT id, 'b' FROM mz_catalog.mz_base_types
4875 UNION ALL SELECT id, 'l' FROM mz_catalog.mz_list_types
4876 UNION ALL SELECT id, 'm' FROM mz_catalog.mz_map_types
4877 UNION ALL SELECT id, 'p' FROM mz_catalog.mz_pseudo_types
4878 )
4879 AS t ON mz_types.id = t.id
4880 LEFT JOIN mz_catalog.mz_databases d ON d.id = mz_schemas.database_id
4881 JOIN mz_catalog.mz_roles role_owner ON role_owner.id = mz_types.owner_id",
4882 access: vec![PUBLIC_SELECT],
4883 ontology: None,
4884 }
4885});
4886
4887pub const PG_TYPE_ALL_DATABASES_IND: BuiltinIndex = BuiltinIndex {
4888 name: "pg_type_all_databases_ind",
4889 schema: MZ_INTERNAL_SCHEMA,
4890 oid: oid::INDEX_PG_TYPE_ALL_DATABASES_IND_OID,
4891 sql: "IN CLUSTER mz_catalog_server
4892ON mz_internal.pg_type_all_databases (oid)",
4893 is_retained_metrics_object: false,
4894};
4895
4896pub static PG_ATTRIBUTE_ALL_DATABASES: LazyLock<BuiltinView> = LazyLock::new(|| {
4902 BuiltinView {
4903 name: "pg_attribute_all_databases",
4904 schema: MZ_INTERNAL_SCHEMA,
4905 oid: oid::VIEW_PG_ATTRIBUTE_ALL_DATABASES_OID,
4906 desc: RelationDesc::builder()
4907 .with_column("attrelid", SqlScalarType::Oid.nullable(false))
4908 .with_column("attname", SqlScalarType::String.nullable(false))
4909 .with_column("atttypid", SqlScalarType::Oid.nullable(false))
4910 .with_column("attlen", SqlScalarType::Int16.nullable(true))
4911 .with_column("attnum", SqlScalarType::Int16.nullable(false))
4912 .with_column("atttypmod", SqlScalarType::Int32.nullable(false))
4913 .with_column("attndims", SqlScalarType::Int16.nullable(false))
4914 .with_column("attnotnull", SqlScalarType::Bool.nullable(false))
4915 .with_column("atthasdef", SqlScalarType::Bool.nullable(false))
4916 .with_column("attidentity", SqlScalarType::PgLegacyChar.nullable(false))
4917 .with_column("attgenerated", SqlScalarType::PgLegacyChar.nullable(false))
4918 .with_column("attisdropped", SqlScalarType::Bool.nullable(false))
4919 .with_column("attcollation", SqlScalarType::Oid.nullable(false))
4920 .with_column("database_name", SqlScalarType::String.nullable(true))
4921 .with_column("pg_type_database_name", SqlScalarType::String.nullable(true))
4922 .finish(),
4923 column_comments: BTreeMap::new(),
4924 sql: "
4925SELECT
4926 class_objects.oid as attrelid,
4927 mz_columns.name as attname,
4928 mz_columns.type_oid AS atttypid,
4929 pg_type_all_databases.typlen AS attlen,
4930 position::int8::int2 as attnum,
4931 mz_columns.type_mod as atttypmod,
4932 -- dummy value, just to make go-jet's workaround work for now. Discussion:
4933 -- https://github.com/MaterializeInc/materialize/pull/34649#issuecomment-3714291409
4934 0::int2 as attndims,
4935 NOT nullable as attnotnull,
4936 mz_columns.default IS NOT NULL as atthasdef,
4937 ''::pg_catalog.\"char\" as attidentity,
4938 -- MZ doesn't support generated columns so attgenerated is filled with ''
4939 ''::pg_catalog.\"char\" as attgenerated,
4940 FALSE as attisdropped,
4941 -- MZ doesn't support COLLATE so attcollation is filled with 0
4942 0::pg_catalog.oid as attcollation,
4943 -- Columns added because of the peeling. (Note that there are 2 of these here.)
4944 d.name as database_name,
4945 pg_type_all_databases.database_name as pg_type_database_name
4946FROM (
4947 -- pg_attribute catalogs columns on relations and indexes
4948 SELECT id, oid, schema_id, name, type FROM mz_catalog.mz_relations
4949 UNION ALL
4950 SELECT mz_indexes.id, mz_indexes.oid, mz_relations.schema_id, mz_indexes.name, 'index' AS type
4951 FROM mz_catalog.mz_indexes
4952 JOIN mz_catalog.mz_relations ON mz_indexes.on_id = mz_relations.id
4953) AS class_objects
4954JOIN mz_catalog.mz_columns ON class_objects.id = mz_columns.id
4955JOIN mz_internal.pg_type_all_databases ON pg_type_all_databases.oid = mz_columns.type_oid
4956JOIN mz_catalog.mz_schemas ON mz_schemas.id = class_objects.schema_id
4957LEFT JOIN mz_catalog.mz_databases d ON d.id = mz_schemas.database_id",
4958 access: vec![PUBLIC_SELECT],
4961 ontology: None,
4962 }
4963});
4964
4965pub const PG_ATTRIBUTE_ALL_DATABASES_IND: BuiltinIndex = BuiltinIndex {
4966 name: "pg_attribute_all_databases_ind",
4967 schema: MZ_INTERNAL_SCHEMA,
4968 oid: oid::INDEX_PG_ATTRIBUTE_ALL_DATABASES_IND_OID,
4969 sql: "IN CLUSTER mz_catalog_server
4970ON mz_internal.pg_attribute_all_databases (
4971 attrelid, attname, atttypid, attlen, attnum, atttypmod, attnotnull, atthasdef, attidentity,
4972 attgenerated, attisdropped, attcollation, database_name, pg_type_database_name
4973)",
4974 is_retained_metrics_object: false,
4975};
4976
4977pub static PG_ATTRDEF_ALL_DATABASES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
4981 name: "pg_attrdef_all_databases",
4982 schema: MZ_INTERNAL_SCHEMA,
4983 oid: oid::VIEW_PG_ATTRDEF_ALL_DATABASES_OID,
4984 desc: RelationDesc::builder()
4985 .with_column("oid", SqlScalarType::Oid.nullable(true))
4986 .with_column("adrelid", SqlScalarType::Oid.nullable(false))
4987 .with_column("adnum", SqlScalarType::Int64.nullable(false))
4988 .with_column("adbin", SqlScalarType::String.nullable(false))
4989 .with_column("adsrc", SqlScalarType::String.nullable(false))
4990 .finish(),
4991 column_comments: BTreeMap::new(),
4992 sql: "
4993SELECT
4994 NULL::pg_catalog.oid AS oid,
4995 mz_objects.oid AS adrelid,
4996 mz_columns.position::int8 AS adnum,
4997 mz_columns.default AS adbin,
4998 mz_columns.default AS adsrc
4999FROM mz_catalog.mz_columns
5000 JOIN mz_catalog.mz_objects ON mz_columns.id = mz_objects.id
5001WHERE default IS NOT NULL",
5002 access: vec![PUBLIC_SELECT],
5003 ontology: None,
5004});
5005
5006pub const PG_ATTRDEF_ALL_DATABASES_IND: BuiltinIndex = BuiltinIndex {
5007 name: "pg_attrdef_all_databases_ind",
5008 schema: MZ_INTERNAL_SCHEMA,
5009 oid: oid::INDEX_PG_ATTRDEF_ALL_DATABASES_IND_OID,
5010 sql: "IN CLUSTER mz_catalog_server
5011ON mz_internal.pg_attrdef_all_databases (oid, adrelid, adnum, adbin, adsrc)",
5012 is_retained_metrics_object: false,
5013};
5014
5015pub static MZ_COMPUTE_ERROR_COUNTS_RAW_UNIFIED: LazyLock<BuiltinSource> =
5016 LazyLock::new(|| BuiltinSource {
5017 name: "mz_compute_error_counts_raw_unified",
5022 schema: MZ_INTERNAL_SCHEMA,
5023 oid: oid::SOURCE_MZ_COMPUTE_ERROR_COUNTS_RAW_UNIFIED_OID,
5024 desc: RelationDesc::builder()
5025 .with_column("replica_id", SqlScalarType::String.nullable(false))
5026 .with_column("object_id", SqlScalarType::String.nullable(false))
5027 .with_column(
5028 "count",
5029 SqlScalarType::Numeric { max_scale: None }.nullable(false),
5030 )
5031 .finish(),
5032 data_source: IntrospectionType::ComputeErrorCounts.into(),
5033 column_comments: BTreeMap::new(),
5034 is_retained_metrics_object: false,
5035 access: vec![PUBLIC_SELECT],
5036 ontology: None,
5037 });
5038
5039pub static MZ_COMPUTE_HYDRATION_TIMES: LazyLock<BuiltinSource> = LazyLock::new(|| BuiltinSource {
5040 name: "mz_compute_hydration_times",
5041 schema: MZ_INTERNAL_SCHEMA,
5042 oid: oid::SOURCE_MZ_COMPUTE_HYDRATION_TIMES_OID,
5043 desc: RelationDesc::builder()
5044 .with_column("replica_id", SqlScalarType::String.nullable(false))
5045 .with_column("object_id", SqlScalarType::String.nullable(false))
5046 .with_column("time_ns", SqlScalarType::UInt64.nullable(true))
5047 .finish(),
5048 data_source: IntrospectionType::ComputeHydrationTimes.into(),
5049 column_comments: BTreeMap::new(),
5050 is_retained_metrics_object: true,
5051 access: vec![PUBLIC_SELECT],
5052 ontology: Some(Ontology {
5053 entity_name: "compute_hydration_time",
5054 description: "Time to hydrate compute objects",
5055 links: &const { [] },
5056 column_semantic_types: &const {
5057 [
5058 ("replica_id", SemanticType::ReplicaId),
5059 ("object_id", SemanticType::CatalogItemId),
5060 ]
5061 },
5062 }),
5063});
5064
5065pub static MZ_COMPUTE_HYDRATION_TIMES_IND: LazyLock<BuiltinIndex> =
5066 LazyLock::new(|| BuiltinIndex {
5067 name: "mz_compute_hydration_times_ind",
5068 schema: MZ_INTERNAL_SCHEMA,
5069 oid: oid::INDEX_MZ_COMPUTE_HYDRATION_TIMES_IND_OID,
5070 sql: "IN CLUSTER mz_catalog_server
5071 ON mz_internal.mz_compute_hydration_times (replica_id)",
5072 is_retained_metrics_object: true,
5073 });
5074
5075pub static MZ_OBJECT_ARRANGEMENT_SIZES_UNIFIED: LazyLock<BuiltinSource> = LazyLock::new(|| {
5076 BuiltinSource {
5077 name: "mz_object_arrangement_sizes",
5078 schema: MZ_INTERNAL_SCHEMA,
5079 oid: oid::SOURCE_MZ_OBJECT_ARRANGEMENT_SIZES_OID,
5080 desc: RelationDesc::builder()
5081 .with_column("replica_id", SqlScalarType::String.nullable(false))
5082 .with_column("object_id", SqlScalarType::String.nullable(false))
5083 .with_column("size", SqlScalarType::Int64.nullable(true))
5084 .finish(),
5085 data_source: IntrospectionType::ComputeObjectArrangementSizes.into(),
5086 column_comments: BTreeMap::from_iter([
5087 (
5088 "replica_id",
5089 "The ID of the cluster replica. Corresponds to `mz_cluster_replicas.id`.",
5090 ),
5091 (
5092 "object_id",
5093 "The ID of the compute object (index or materialized view). Corresponds to `mz_objects.id`.",
5094 ),
5095 (
5096 "size",
5097 "The total arrangement heap and batcher size in bytes for this object on this replica, \
5098 rounded to the nearest 10 MiB boundary to reduce per-byte churn in the differential \
5099 collection. Objects with less than 5 MiB of arrangements report a size of 0.",
5100 ),
5101 ]),
5102 is_retained_metrics_object: true,
5103 access: vec![PUBLIC_SELECT],
5104 ontology: None,
5105 }
5106});
5107
5108pub static MZ_OBJECT_ARRANGEMENT_SIZES_IND: LazyLock<BuiltinIndex> =
5109 LazyLock::new(|| BuiltinIndex {
5110 name: "mz_object_arrangement_sizes_ind",
5111 schema: MZ_INTERNAL_SCHEMA,
5112 oid: oid::INDEX_MZ_OBJECT_ARRANGEMENT_SIZES_IND_OID,
5113 sql: "IN CLUSTER mz_catalog_server
5114 ON mz_internal.mz_object_arrangement_sizes (replica_id)",
5115 is_retained_metrics_object: true,
5116 });
5117
5118pub static MZ_OBJECT_ARRANGEMENT_SIZE_HISTORY: LazyLock<BuiltinTable> = LazyLock::new(|| {
5119 BuiltinTable {
5120 name: "mz_object_arrangement_size_history",
5121 schema: MZ_INTERNAL_SCHEMA,
5122 oid: oid::TABLE_MZ_OBJECT_ARRANGEMENT_SIZE_HISTORY_OID,
5123 desc: RelationDesc::builder()
5124 .with_column("replica_id", SqlScalarType::String.nullable(false))
5125 .with_column("object_id", SqlScalarType::String.nullable(false))
5126 .with_column("size", SqlScalarType::Int64.nullable(false))
5127 .with_column(
5128 "collection_timestamp",
5129 SqlScalarType::TimestampTz { precision: None }.nullable(false),
5130 )
5131 .with_column("hydration_complete", SqlScalarType::Bool.nullable(false))
5132 .finish(),
5133 column_comments: BTreeMap::from_iter([
5134 (
5135 "replica_id",
5136 "The ID of the cluster replica. Corresponds to `mz_cluster_replicas.id`.",
5137 ),
5138 (
5139 "object_id",
5140 "The ID of the compute object (index or materialized view). Corresponds to `mz_objects.id`.",
5141 ),
5142 (
5143 "size",
5144 "The total arrangement heap and batcher size in bytes for this object on this replica \
5145 at `collection_timestamp`, rounded to the nearest 10 MiB to reduce per-byte churn \
5146 in the underlying differential collection. Objects with less than 5 MiB of \
5147 arrangements are not recorded. May reflect a mid-build size if \
5148 `hydration_complete` is `false`.",
5149 ),
5150 (
5151 "collection_timestamp",
5152 "The timestamp when this snapshot was collected.",
5153 ),
5154 (
5155 "hydration_complete",
5156 "Whether the arrangement had finished its initial hydration on this replica when \
5157 the snapshot was collected. Filter for `true` to consider only stable, post-build \
5158 sizes.",
5159 ),
5160 ]),
5161 is_retained_metrics_object: true,
5162 access: vec![PUBLIC_SELECT],
5163 ontology: None,
5164 }
5165});
5166
5167pub static MZ_OBJECT_ARRANGEMENT_SIZE_HISTORY_OBJECT_IND: LazyLock<BuiltinIndex> =
5168 LazyLock::new(|| BuiltinIndex {
5169 name: "mz_object_arrangement_size_history_object_ind",
5170 schema: MZ_INTERNAL_SCHEMA,
5171 oid: oid::INDEX_MZ_OBJECT_ARRANGEMENT_SIZE_HISTORY_OBJECT_IND_OID,
5172 sql: "IN CLUSTER mz_catalog_server
5173 ON mz_internal.mz_object_arrangement_size_history (object_id)",
5174 is_retained_metrics_object: true,
5175 });
5176
5177pub static MZ_OBJECT_ARRANGEMENT_SIZE_HISTORY_TS_IND: LazyLock<BuiltinIndex> =
5178 LazyLock::new(|| BuiltinIndex {
5179 name: "mz_object_arrangement_size_history_ts_ind",
5180 schema: MZ_INTERNAL_SCHEMA,
5181 oid: oid::INDEX_MZ_OBJECT_ARRANGEMENT_SIZE_HISTORY_TS_IND_OID,
5182 sql: "IN CLUSTER mz_catalog_server
5183 ON mz_internal.mz_object_arrangement_size_history (collection_timestamp)",
5184 is_retained_metrics_object: true,
5185 });
5186
5187pub static MZ_OBJECT_HYDRATION_HISTORY: LazyLock<BuiltinTable> = LazyLock::new(|| BuiltinTable {
5194 name: "mz_object_hydration_history",
5195 schema: MZ_INTERNAL_SCHEMA,
5196 oid: oid::TABLE_MZ_OBJECT_HYDRATION_HISTORY_OID,
5197 desc: RelationDesc::builder()
5198 .with_column("object_id", SqlScalarType::String.nullable(false))
5199 .with_column("cluster_id", SqlScalarType::String.nullable(false))
5200 .with_column("replica_id", SqlScalarType::String.nullable(false))
5201 .with_column(
5202 "installed_at",
5203 SqlScalarType::TimestampTz { precision: None }.nullable(false),
5204 )
5205 .with_column(
5206 "started_at",
5207 SqlScalarType::TimestampTz { precision: None }.nullable(true),
5208 )
5209 .with_column(
5210 "hydrated_at",
5211 SqlScalarType::TimestampTz { precision: None }.nullable(true),
5212 )
5213 .with_column("status", SqlScalarType::String.nullable(false))
5214 .finish(),
5215 column_comments: BTreeMap::from_iter([
5216 (
5217 "object_id",
5218 "The ID of the object's dataflow, as reported by the replica. Join `mz_internal.mz_object_global_ids` to reach the index or materialized view while that mapping exists. Dropping the dataflow retracts the mapping, so historical IDs may no longer resolve.",
5219 ),
5220 ("cluster_id", "The ID of the object's cluster."),
5221 (
5222 "replica_id",
5223 "The ID of the cluster replica. May name a replica that no longer exists.",
5224 ),
5225 (
5226 "installed_at",
5227 "When the object's dataflow was installed on the replica.",
5228 ),
5229 (
5230 "started_at",
5231 "When hydration work began, or `NULL` if the replica reported none. A replica that observed no start reports the installation time instead, so a zero interval between the two does not mean the dataflow started immediately.",
5232 ),
5233 ("hydrated_at", "When hydration finished."),
5234 (
5235 "status",
5236 "The terminal status. Currently always `hydrated`.",
5237 ),
5238 ]),
5239 is_retained_metrics_object: false,
5243 access: vec![PUBLIC_SELECT],
5244 ontology: Some(Ontology {
5245 entity_name: "object_hydration_event",
5246 description: "Completed hydration of an index or materialized view on a replica",
5247 links: &const {
5251 [
5252 OntologyLink {
5253 name: "hydration_of_dataflow",
5254 target: "object_global_id",
5255 properties: LinkProperties::fk_typed(
5256 "object_id",
5257 "global_id",
5258 Cardinality::ManyToOne,
5259 mz_repr::SemanticType::GlobalId,
5260 ),
5261 },
5262 OntologyLink {
5263 name: "hydrated_on_cluster",
5264 target: "cluster",
5265 properties: LinkProperties::fk("cluster_id", "id", Cardinality::ManyToOne),
5266 },
5267 OntologyLink {
5268 name: "hydrated_on_replica",
5269 target: "replica",
5270 properties: LinkProperties::fk_typed(
5271 "replica_id",
5272 "id",
5273 Cardinality::ManyToOne,
5274 mz_repr::SemanticType::ReplicaId,
5275 ),
5276 },
5277 ]
5278 },
5279 column_semantic_types: &[
5280 ("object_id", SemanticType::GlobalId),
5281 ("cluster_id", SemanticType::ClusterId),
5282 ("replica_id", SemanticType::ReplicaId),
5283 ],
5284 }),
5285});
5286
5287pub static MZ_REPLICA_HYDRATION_HISTORY: LazyLock<BuiltinTable> = LazyLock::new(|| BuiltinTable {
5294 name: "mz_replica_hydration_history",
5295 schema: MZ_INTERNAL_SCHEMA,
5296 oid: oid::TABLE_MZ_REPLICA_HYDRATION_HISTORY_OID,
5297 desc: RelationDesc::builder()
5298 .with_column("replica_id", SqlScalarType::String.nullable(false))
5299 .with_column("cluster_id", SqlScalarType::String.nullable(false))
5300 .with_column(
5301 "started_at",
5302 SqlScalarType::TimestampTz { precision: None }.nullable(false),
5303 )
5304 .with_column(
5305 "finished_at",
5306 SqlScalarType::TimestampTz { precision: None }.nullable(true),
5307 )
5308 .with_column("object_count", SqlScalarType::UInt64.nullable(false))
5309 .with_column("peak_memory_bytes", SqlScalarType::UInt64.nullable(true))
5310 .with_column("peak_disk_bytes", SqlScalarType::UInt64.nullable(true))
5311 .with_column("status", SqlScalarType::String.nullable(false))
5312 .with_column("process_id", SqlScalarType::UInt64.nullable(true))
5313 .finish(),
5314 column_comments: BTreeMap::from_iter([
5315 (
5316 "replica_id",
5317 "The ID of the cluster replica. May name a replica that no longer exists.",
5318 ),
5319 ("cluster_id", "The ID of the replica's cluster."),
5320 (
5321 "started_at",
5322 "The earliest maintained compute dataflow installation in the hydration episode.",
5323 ),
5324 (
5325 "finished_at",
5326 "The latest maintained compute dataflow hydration in the hydration episode.",
5327 ),
5328 (
5329 "object_count",
5330 "The number of maintained compute dataflows in the hydration episode. Includes the replica's system introspection dataflows, so it exceeds the number of indexes and materialized views you created.",
5331 ),
5332 (
5333 "peak_memory_bytes",
5334 "The process-lifetime cgroup memory high-water mark when the collector recorded the episode. `NULL` if the platform reports no cgroup memory peak.",
5335 ),
5336 (
5337 "peak_disk_bytes",
5338 "The process-lifetime scratch-filesystem or swap high-water mark when the collector recorded the episode. Filesystem peaks are sampled lower bounds. `NULL` if neither measurement is available.",
5339 ),
5340 (
5341 "status",
5342 "The hydration episode's status. Currently always `hydrated`.",
5343 ),
5344 (
5345 "process_id",
5346 "The ID of a process within the replica. Episode timing and object_count are replica-wide and repeated for each process.",
5347 ),
5348 ]),
5349 is_retained_metrics_object: false,
5353 access: vec![PUBLIC_SELECT],
5354 ontology: Some(Ontology {
5355 entity_name: "replica_hydration_episode",
5356 description: "Successful hydration episode on a cluster replica",
5357 links: &const {
5358 [
5359 OntologyLink {
5360 name: "hydrated_on_cluster",
5361 target: "cluster",
5362 properties: LinkProperties::ForeignKey {
5363 source_column: "cluster_id",
5364 target_column: "id",
5365 cardinality: Cardinality::ManyToOne,
5366 source_id_type: None,
5367 requires_mapping: None,
5368 nullable: false,
5369 note: Some(
5370 "Hydration samples can outlive their cluster, so this reference may not resolve.",
5371 ),
5372 extra_key_columns: None,
5373 },
5374 },
5375 OntologyLink {
5376 name: "hydrated_on_replica",
5377 target: "replica",
5378 properties: LinkProperties::ForeignKey {
5379 source_column: "replica_id",
5380 target_column: "id",
5381 cardinality: Cardinality::ManyToOne,
5382 source_id_type: Some(mz_repr::SemanticType::ReplicaId),
5383 requires_mapping: None,
5384 nullable: false,
5385 note: Some(
5386 "Hydration samples can outlive their replica, so this reference may not resolve.",
5387 ),
5388 extra_key_columns: None,
5389 },
5390 },
5391 ]
5392 },
5393 column_semantic_types: &[
5394 ("replica_id", SemanticType::ReplicaId),
5395 ("cluster_id", SemanticType::ClusterId),
5396 ],
5397 }),
5398});
5399
5400pub static MZ_COMPUTE_HYDRATION_STATUSES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
5401 name: "mz_compute_hydration_statuses",
5402 schema: MZ_INTERNAL_SCHEMA,
5403 oid: oid::SOURCE_MZ_COMPUTE_HYDRATION_STATUSES_OID,
5404 desc: RelationDesc::builder()
5405 .with_column("object_id", SqlScalarType::String.nullable(false))
5406 .with_column("replica_id", SqlScalarType::String.nullable(false))
5407 .with_column("hydrated", SqlScalarType::Bool.nullable(false))
5408 .with_column("hydration_time", SqlScalarType::Interval.nullable(true))
5409 .finish(),
5410 column_comments: BTreeMap::from_iter([
5411 (
5412 "object_id",
5413 "The ID of a compute object. Corresponds to `mz_catalog.mz_indexes.id` or `mz_catalog.mz_materialized_views.id`",
5414 ),
5415 ("replica_id", "The ID of a cluster replica."),
5416 (
5417 "hydrated",
5418 "Whether the compute object is hydrated on the replica.",
5419 ),
5420 (
5421 "hydration_time",
5422 "The amount of time it took for the replica to hydrate the compute object.",
5423 ),
5424 ]),
5425 sql: "
5426WITH
5427 dataflows AS (
5428 SELECT
5429 object_id,
5430 replica_id,
5431 time_ns IS NOT NULL AS hydrated,
5432 ((time_ns / 1000) || 'microseconds')::interval AS hydration_time
5433 FROM mz_internal.mz_compute_hydration_times
5434 ),
5435 -- MVs that have advanced to the empty frontier don't have a dataflow installed anymore and
5436 -- therefore don't show up in `mz_compute_hydration_times`. We still want to show them here to
5437 -- avoid surprises for people joining `mz_materialized_views` against this relation (like the
5438 -- blue-green readiness query does), so we include them as 'hydrated'.
5439 complete_mvs AS (
5440 SELECT
5441 mv.id,
5442 f.replica_id,
5443 true AS hydrated,
5444 NULL::interval AS hydration_time
5445 FROM mz_materialized_views mv
5446 JOIN mz_catalog.mz_cluster_replica_frontiers f ON f.object_id = mv.id
5447 WHERE f.write_frontier IS NULL
5448 )
5449SELECT * FROM dataflows
5450UNION ALL
5451SELECT * FROM complete_mvs",
5452 access: vec![PUBLIC_SELECT],
5453 ontology: Some(Ontology {
5454 entity_name: "compute_hydration_status_view",
5455 description: "Computed hydration status per compute object",
5456 links: &const { [] },
5457 column_semantic_types: &const {
5458 [
5459 ("object_id", SemanticType::GlobalId),
5460 ("replica_id", SemanticType::ReplicaId),
5461 ]
5462 },
5463 }),
5464});
5465
5466pub static MZ_COMPUTE_OPERATOR_HYDRATION_STATUSES: LazyLock<BuiltinSource> = LazyLock::new(|| {
5467 BuiltinSource {
5468 name: "mz_compute_operator_hydration_statuses",
5469 schema: MZ_INTERNAL_SCHEMA,
5470 oid: oid::SOURCE_MZ_COMPUTE_OPERATOR_HYDRATION_STATUSES_OID,
5471 desc: RelationDesc::builder()
5472 .with_column("replica_id", SqlScalarType::String.nullable(false))
5473 .with_column("object_id", SqlScalarType::String.nullable(false))
5474 .with_column(
5475 "physical_plan_node_id",
5476 SqlScalarType::UInt64.nullable(false),
5477 )
5478 .with_column("hydrated", SqlScalarType::Bool.nullable(false))
5479 .with_key(vec![0, 1, 2])
5480 .finish(),
5481 data_source: IntrospectionType::ComputeOperatorHydrationStatus.into(),
5482 column_comments: BTreeMap::from_iter([
5483 ("replica_id", "The ID of a cluster replica."),
5484 (
5485 "object_id",
5486 "The ID of a compute object. Corresponds to `mz_catalog.mz_indexes.id` or `mz_catalog.mz_materialized_views.id`.",
5487 ),
5488 (
5489 "physical_plan_node_id",
5490 "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)`.",
5491 ),
5492 ("hydrated", "Whether the node is hydrated on the replica."),
5493 ]),
5494 is_retained_metrics_object: false,
5495 access: vec![PUBLIC_SELECT],
5496 ontology: Some(Ontology {
5497 entity_name: "compute_hydration_status",
5498 description: "Hydration status per compute operator",
5499 links: &const { [] },
5500 column_semantic_types: &const {
5501 [
5502 ("replica_id", SemanticType::ReplicaId),
5503 ("object_id", SemanticType::CatalogItemId),
5504 ]
5505 },
5506 }),
5507 }
5508});
5509
5510pub static MZ_CLUSTER_REPLICA_UTILIZATION: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
5511 name: "mz_cluster_replica_utilization",
5512 schema: MZ_INTERNAL_SCHEMA,
5513 oid: oid::VIEW_MZ_CLUSTER_REPLICA_UTILIZATION_OID,
5514 desc: RelationDesc::builder()
5515 .with_column("replica_id", SqlScalarType::String.nullable(false))
5516 .with_column("process_id", SqlScalarType::UInt64.nullable(false))
5517 .with_column("cpu_percent", SqlScalarType::Float64.nullable(true))
5518 .with_column("memory_percent", SqlScalarType::Float64.nullable(true))
5519 .with_column("disk_percent", SqlScalarType::Float64.nullable(true))
5520 .with_column("heap_percent", SqlScalarType::Float64.nullable(true))
5521 .with_column("swap_percent", SqlScalarType::Float64.nullable(true))
5522 .finish(),
5523 column_comments: BTreeMap::from_iter([
5524 ("replica_id", "The ID of a cluster replica."),
5525 ("process_id", "The ID of a process within the replica."),
5526 (
5527 "cpu_percent",
5528 "Approximate CPU usage, in percent of the total allocation.",
5529 ),
5530 (
5531 "memory_percent",
5532 "Approximate RAM usage, in percent of the total allocation.",
5533 ),
5534 (
5535 "disk_percent",
5536 "Approximate disk usage, in percent of the total allocation.",
5537 ),
5538 (
5539 "heap_percent",
5540 "Approximate heap (RAM + swap) usage, in percent of the total allocation.",
5541 ),
5542 (
5543 "swap_percent",
5544 "Approximate swap usage, in percent of the total heap allocation.",
5545 ),
5546 ]),
5547 sql: "
5548SELECT
5549 r.id AS replica_id,
5550 m.process_id,
5551 m.cpu_nano_cores::float8 / NULLIF(s.cpu_nano_cores, 0) * 100 AS cpu_percent,
5552 m.memory_bytes::float8 / NULLIF(s.memory_bytes, 0) * 100 AS memory_percent,
5553 m.disk_bytes::float8 / NULLIF(s.disk_bytes, 0) * 100 AS disk_percent,
5554 m.heap_bytes::float8 / NULLIF(m.heap_limit, 0) * 100 AS heap_percent,
5555 m.swap_bytes::float8 / NULLIF(m.heap_limit, 0) * 100 AS swap_percent
5556FROM
5557 mz_catalog.mz_cluster_replicas AS r
5558 JOIN mz_catalog.mz_cluster_replica_sizes AS s ON r.size = s.size
5559 JOIN mz_internal.mz_cluster_replica_metrics AS m ON m.replica_id = r.id",
5560 access: vec![PUBLIC_SELECT],
5561 ontology: Some(Ontology {
5562 entity_name: "replica_utilization",
5563 description: "Computed utilization metrics per replica",
5564 links: &const {
5565 [OntologyLink {
5566 name: "utilization_of_replica",
5567 target: "replica",
5568 properties: LinkProperties::fk_typed(
5569 "replica_id",
5570 "id",
5571 Cardinality::OneToOne,
5572 mz_repr::SemanticType::CatalogItemId,
5573 ),
5574 }]
5575 },
5576 column_semantic_types: &[("replica_id", SemanticType::ReplicaId)],
5577 }),
5578});
5579
5580pub static MZ_CLUSTER_REPLICA_UTILIZATION_HISTORY: LazyLock<BuiltinView> =
5581 LazyLock::new(|| BuiltinView {
5582 name: "mz_cluster_replica_utilization_history",
5583 schema: MZ_INTERNAL_SCHEMA,
5584 oid: oid::VIEW_MZ_CLUSTER_REPLICA_UTILIZATION_HISTORY_OID,
5585 desc: RelationDesc::builder()
5586 .with_column("replica_id", SqlScalarType::String.nullable(false))
5587 .with_column("process_id", SqlScalarType::UInt64.nullable(false))
5588 .with_column("cpu_percent", SqlScalarType::Float64.nullable(true))
5589 .with_column("memory_percent", SqlScalarType::Float64.nullable(true))
5590 .with_column("disk_percent", SqlScalarType::Float64.nullable(true))
5591 .with_column("heap_percent", SqlScalarType::Float64.nullable(true))
5592 .with_column("swap_percent", SqlScalarType::Float64.nullable(true))
5593 .with_column(
5594 "occurred_at",
5595 SqlScalarType::TimestampTz { precision: None }.nullable(false),
5596 )
5597 .finish(),
5598 column_comments: BTreeMap::from_iter([
5599 ("replica_id", "The ID of a cluster replica."),
5600 ("process_id", "The ID of a process within the replica."),
5601 (
5602 "cpu_percent",
5603 "Approximate CPU usage, in percent of the total allocation.",
5604 ),
5605 (
5606 "memory_percent",
5607 "Approximate RAM usage, in percent of the total allocation.",
5608 ),
5609 (
5610 "disk_percent",
5611 "Approximate disk usage, in percent of the total allocation.",
5612 ),
5613 (
5614 "heap_percent",
5615 "Approximate heap (RAM + swap) usage, in percent of the total allocation.",
5616 ),
5617 (
5618 "swap_percent",
5619 "Approximate swap usage, in percent of the total heap allocation.",
5620 ),
5621 (
5622 "occurred_at",
5623 "Wall-clock timestamp at which the event occurred.",
5624 ),
5625 ]),
5626 sql: "
5627SELECT
5628 r.id AS replica_id,
5629 m.process_id,
5630 m.cpu_nano_cores::float8 / NULLIF(s.cpu_nano_cores, 0) * 100 AS cpu_percent,
5631 m.memory_bytes::float8 / NULLIF(s.memory_bytes, 0) * 100 AS memory_percent,
5632 m.disk_bytes::float8 / NULLIF(s.disk_bytes, 0) * 100 AS disk_percent,
5633 m.heap_bytes::float8 / NULLIF(m.heap_limit, 0) * 100 AS heap_percent,
5634 m.swap_bytes::float8 / NULLIF(m.heap_limit, 0) * 100 AS swap_percent,
5635 m.occurred_at
5636FROM
5637 mz_catalog.mz_cluster_replicas AS r
5638 JOIN mz_catalog.mz_cluster_replica_sizes AS s ON r.size = s.size
5639 JOIN mz_internal.mz_cluster_replica_metrics_history AS m ON m.replica_id = r.id",
5640 access: vec![PUBLIC_SELECT],
5641 ontology: None,
5642 });
5643
5644pub static MZ_INDEX_ADVICE: LazyLock<BuiltinView> = LazyLock::new(|| {
5645 BuiltinView {
5646 name: "mz_index_advice",
5647 schema: MZ_INTERNAL_SCHEMA,
5648 oid: oid::VIEW_MZ_INDEX_ADVICE_OID,
5649 desc: RelationDesc::builder()
5650 .with_column("object_id", SqlScalarType::String.nullable(true))
5651 .with_column("hint", SqlScalarType::String.nullable(false))
5652 .with_column("details", SqlScalarType::String.nullable(false))
5653 .with_column("referenced_object_ids", SqlScalarType::List { element_type: Box::new(SqlScalarType::String), custom_id: None }.nullable(true))
5654 .finish(),
5655 column_comments: BTreeMap::from_iter([
5656 ("object_id", "The ID of the object. Corresponds to mz_objects.id."),
5657 ("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."),
5658 ("details", "Additional details on why the `hint` was proposed based on the dependencies of the object."),
5659 ("referenced_object_ids", "The IDs of objects referenced by `details`. Corresponds to mz_objects.id."),
5660 ]),
5661 sql: "
5662-- To avoid confusion with sources and sinks in the materialize sense,
5663-- the following uses the terms leafs (instead of sinks) and roots (instead of sources)
5664-- when referring to the object dependency graph.
5665--
5666-- The basic idea is to walk up the dependency graph to propagate the transitive dependencies
5667-- of maintained objected upwards. The leaves of the dependency graph are maintained objects
5668-- that are not depended on by other maintained objects and have a justification why they must
5669-- be maintained (e.g. a materialized view that is depended on by a sink).
5670-- Starting from these leaves, the dependencies are propagated upwards towards the roots according
5671-- to the object dependencies. Whenever there is a node that is being depended on by multiple
5672-- downstream objects, that node is marked to be converted into a maintained object and this
5673-- node is then propagated further up. Once completed, the list of objects that are marked as
5674-- maintained is checked against all objects to generate appropriate recommendations.
5675--
5676-- Note that the recommendations only incorporate dependencies between objects.
5677-- This can lead to bad recommendations, e.g. filters can no longer be pushed into (or close to)
5678-- a sink if an index is added in between the sink and the filter. For very selective filters,
5679-- this can lead to redundant work: the index is computing stuff only to discarded by the selective
5680-- filter later on. But these kind of aspects cannot be understood by merely looking at the
5681-- dependencies.
5682WITH MUTUALLY RECURSIVE
5683 -- for all objects, understand if they have an index on them and on which cluster they are running
5684 -- this avoids having different cases for views with an index and materialized views later on
5685 objects(id text, type text, cluster_id text, indexes text list) AS (
5686 -- views and materialized views without an index
5687 SELECT
5688 o.id,
5689 o.type,
5690 o.cluster_id,
5691 '{}'::text list AS indexes
5692 FROM mz_catalog.mz_objects o
5693 WHERE o.id LIKE 'u%' AND o.type IN ('materialized-view', 'view') AND NOT EXISTS (
5694 SELECT FROM mz_internal.mz_object_dependencies d
5695 JOIN mz_catalog.mz_objects AS i
5696 ON (i.id = d.object_id AND i.type = 'index')
5697 WHERE (o.id = d.referenced_object_id)
5698 )
5699
5700 UNION ALL
5701
5702 -- views and materialized views with an index
5703 SELECT
5704 o.id,
5705 o.type,
5706 -- o.cluster_id is always NULL for views, so use the cluster of the index instead
5707 COALESCE(o.cluster_id, i.cluster_id) AS cluster_id,
5708 list_agg(i.id) AS indexes
5709 FROM mz_catalog.mz_objects o
5710 JOIN mz_internal.mz_object_dependencies AS d
5711 ON (o.id = d.referenced_object_id)
5712 JOIN mz_catalog.mz_objects AS i
5713 ON (i.id = d.object_id AND i.type = 'index')
5714 WHERE o.id LIKE 'u%' AND o.type IN ('materialized-view', 'view', 'source')
5715 GROUP BY o.id, o.type, o.cluster_id, i.cluster_id
5716 ),
5717
5718 -- maintained objects that are at the leafs of the dependency graph with respect to a specific cluster
5719 maintained_leafs(id text, justification text) AS (
5720 -- materialized views that are connected to a sink
5721 SELECT
5722 m.id,
5723 s.id AS justification
5724 FROM objects AS m
5725 JOIN mz_internal.mz_object_dependencies AS d
5726 ON (m.id = d.referenced_object_id)
5727 JOIN mz_catalog.mz_objects AS s
5728 ON (s.id = d.object_id AND s.type = 'sink')
5729 WHERE m.type = 'materialized-view'
5730
5731 UNION ALL
5732
5733 -- (materialized) views with an index that are not transitively depend on by maintained objects on the same cluster
5734 SELECT
5735 v.id,
5736 unnest(v.indexes) AS justification
5737 FROM objects AS v
5738 WHERE v.type IN ('view', 'materialized-view', 'source') AND NOT EXISTS (
5739 SELECT FROM mz_internal.mz_object_transitive_dependencies AS d
5740 INNER JOIN mz_catalog.mz_objects AS child
5741 ON (d.object_id = child.id)
5742 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]
5743 )
5744 ),
5745
5746 -- this is just a helper cte to union multiple lists as part of an aggregation, which is not directly possible in SQL
5747 agg_maintained_children(id text, maintained_children text list) AS (
5748 SELECT
5749 parent_id AS id,
5750 list_agg(maintained_child) AS maintained_leafs
5751 FROM (
5752 SELECT DISTINCT
5753 d.referenced_object_id AS parent_id,
5754 -- it's not possible to union lists in an aggregation, so we have to unnest the list first
5755 unnest(child.maintained_children) AS maintained_child
5756 FROM propagate_dependencies AS child
5757 INNER JOIN mz_internal.mz_object_dependencies AS d
5758 ON (child.id = d.object_id)
5759 )
5760 GROUP BY parent_id
5761 ),
5762
5763 -- propagate dependencies of maintained objects from the leafs to the roots of the dependency graph and
5764 -- record a justification when an object should be maintained, e.g. when it is depended on by more than one maintained object
5765 -- 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
5766 propagate_dependencies(id text, maintained_children text list, justification text list) AS (
5767 -- base case: start with the leafs
5768 SELECT DISTINCT
5769 id,
5770 LIST[id] AS maintained_children,
5771 list_agg(justification) AS justification
5772 FROM maintained_leafs
5773 GROUP BY id
5774
5775 UNION
5776
5777 -- recursive case: if there is a child with the same dependencies as the parent,
5778 -- the parent is only reused by a single child
5779 SELECT
5780 parent.id,
5781 child.maintained_children,
5782 NULL::text list AS justification
5783 FROM agg_maintained_children AS parent
5784 INNER JOIN mz_internal.mz_object_dependencies AS d
5785 ON (parent.id = d.referenced_object_id)
5786 INNER JOIN propagate_dependencies AS child
5787 ON (d.object_id = child.id)
5788 WHERE parent.maintained_children = child.maintained_children
5789
5790 UNION
5791
5792 -- recursive case: if there is NO child with the same dependencies as the parent,
5793 -- different children are reusing the parent so maintaining the object is justified by itself
5794 SELECT DISTINCT
5795 parent.id,
5796 LIST[parent.id] AS maintained_children,
5797 parent.maintained_children AS justification
5798 FROM agg_maintained_children AS parent
5799 WHERE NOT EXISTS (
5800 SELECT FROM mz_internal.mz_object_dependencies AS d
5801 INNER JOIN propagate_dependencies AS child
5802 ON (d.object_id = child.id AND d.referenced_object_id = parent.id)
5803 WHERE parent.maintained_children = child.maintained_children
5804 )
5805 ),
5806
5807 objects_with_justification(id text, type text, cluster_id text, maintained_children text list, justification text list, indexes text list) AS (
5808 SELECT
5809 p.id,
5810 o.type,
5811 o.cluster_id,
5812 p.maintained_children,
5813 p.justification,
5814 o.indexes
5815 FROM propagate_dependencies p
5816 JOIN objects AS o
5817 ON (p.id = o.id)
5818 ),
5819
5820 hints(id text, hint text, details text, justification text list) AS (
5821 -- materialized views that are not required
5822 SELECT
5823 id,
5824 'convert to a view' AS hint,
5825 'no dependencies from sinks nor from objects on different clusters' AS details,
5826 justification
5827 FROM objects_with_justification
5828 WHERE type = 'materialized-view' AND justification IS NULL
5829
5830 UNION ALL
5831
5832 -- materialized views that are required because a sink or a maintained object from a different cluster depends on them
5833 SELECT
5834 id,
5835 'keep' AS hint,
5836 'dependencies from sinks or objects on different clusters: ' AS details,
5837 justification
5838 FROM objects_with_justification AS m
5839 WHERE type = 'materialized-view' AND justification IS NOT NULL AND EXISTS (
5840 SELECT FROM unnest(justification) AS dependency
5841 JOIN mz_catalog.mz_objects s ON (s.type = 'sink' AND s.id = dependency)
5842
5843 UNION ALL
5844
5845 SELECT FROM unnest(justification) AS dependency
5846 JOIN mz_catalog.mz_objects AS d ON (d.id = dependency)
5847 WHERE d.cluster_id != m.cluster_id
5848 )
5849
5850 UNION ALL
5851
5852 -- 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
5853 SELECT
5854 id,
5855 'convert to a view with an index' AS hint,
5856 'no dependencies from sinks nor from objects on different clusters, but maintained dependencies on the same cluster: ' AS details,
5857 justification
5858 FROM objects_with_justification AS m
5859 WHERE type = 'materialized-view' AND justification IS NOT NULL AND NOT EXISTS (
5860 SELECT FROM unnest(justification) AS dependency
5861 JOIN mz_catalog.mz_objects s ON (s.type = 'sink' AND s.id = dependency)
5862
5863 UNION ALL
5864
5865 SELECT FROM unnest(justification) AS dependency
5866 JOIN mz_catalog.mz_objects AS d ON (d.id = dependency)
5867 WHERE d.cluster_id != m.cluster_id
5868 )
5869
5870 UNION ALL
5871
5872 -- views that have indexes on different clusters should be a materialized view
5873 SELECT
5874 o.id,
5875 'convert to materialized view' AS hint,
5876 'dependencies on multiple clusters: ' AS details,
5877 o.justification
5878 FROM objects_with_justification o,
5879 LATERAL unnest(o.justification) j
5880 LEFT JOIN mz_catalog.mz_objects AS m
5881 ON (m.id = j AND m.type IN ('index', 'materialized-view'))
5882 WHERE o.type = 'view' AND o.justification IS NOT NULL
5883 GROUP BY o.id, o.justification
5884 HAVING count(DISTINCT m.cluster_id) >= 2
5885
5886 UNION ALL
5887
5888 -- views without an index that should be maintained
5889 SELECT
5890 id,
5891 'add index' AS hint,
5892 'multiple downstream dependencies: ' AS details,
5893 justification
5894 FROM objects_with_justification
5895 WHERE type = 'view' AND justification IS NOT NULL AND indexes = '{}'::text list
5896
5897 UNION ALL
5898
5899 -- index inside the dependency graph (not a leaf)
5900 SELECT
5901 unnest(indexes) AS id,
5902 'drop unless queried directly' AS hint,
5903 'fewer than two downstream dependencies: ' AS details,
5904 maintained_children AS justification
5905 FROM objects_with_justification
5906 WHERE type = 'view' AND NOT indexes = '{}'::text list AND justification IS NULL
5907
5908 UNION ALL
5909
5910 -- index on a leaf of the dependency graph
5911 SELECT
5912 unnest(indexes) AS id,
5913 'drop unless queried directly' AS hint,
5914 'associated object does not have any dependencies (maintained or not maintained)' AS details,
5915 NULL::text list AS justification
5916 FROM objects_with_justification
5917 -- indexes can only be part of justification for leaf nodes
5918 WHERE type IN ('view', 'materialized-view') AND NOT indexes = '{}'::text list AND justification @> indexes
5919
5920 UNION ALL
5921
5922 -- index on a source
5923 SELECT
5924 unnest(indexes) AS id,
5925 'drop unless queried directly' AS hint,
5926 'sources do not transform data and can expose data directly' AS details,
5927 NULL::text list AS justification
5928 FROM objects_with_justification
5929 -- indexes can only be part of justification for leaf nodes
5930 WHERE type = 'source' AND NOT indexes = '{}'::text list
5931
5932 UNION ALL
5933
5934 -- indexes on views inside the dependency graph
5935 SELECT
5936 unnest(indexes) AS id,
5937 'keep' AS hint,
5938 'multiple downstream dependencies: ' AS details,
5939 justification
5940 FROM objects_with_justification
5941 -- indexes can only be part of justification for leaf nodes
5942 WHERE type = 'view' AND justification IS NOT NULL AND NOT indexes = '{}'::text list AND NOT justification @> indexes
5943 ),
5944
5945 hints_resolved_ids(id text, hint text, details text, justification text list) AS (
5946 SELECT
5947 h.id,
5948 h.hint,
5949 h.details || list_agg(o.name)::text AS details,
5950 h.justification
5951 FROM hints AS h,
5952 LATERAL unnest(h.justification) j
5953 JOIN mz_catalog.mz_objects AS o
5954 ON (o.id = j)
5955 GROUP BY h.id, h.hint, h.details, h.justification
5956
5957 UNION ALL
5958
5959 SELECT
5960 id,
5961 hint,
5962 details,
5963 justification
5964 FROM hints
5965 WHERE justification IS NULL
5966 )
5967
5968SELECT
5969 h.id AS object_id,
5970 h.hint AS hint,
5971 h.details,
5972 h.justification AS referenced_object_ids
5973FROM hints_resolved_ids AS h",
5974 access: vec![PUBLIC_SELECT],
5975 ontology: None,
5976 }
5977});
5978
5979pub static PG_AUTHID_CORE: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
5982 name: "pg_authid_core",
5983 schema: MZ_INTERNAL_SCHEMA,
5984 oid: oid::VIEW_PG_AUTHID_CORE_OID,
5985 desc: RelationDesc::builder()
5986 .with_column("oid", SqlScalarType::Oid.nullable(false))
5987 .with_column("rolname", SqlScalarType::String.nullable(false))
5988 .with_column("rolsuper", SqlScalarType::Bool.nullable(true))
5989 .with_column("rolinherit", SqlScalarType::Bool.nullable(false))
5990 .with_column("rolcanlogin", SqlScalarType::Bool.nullable(false))
5991 .with_column("rolreplication", SqlScalarType::Bool.nullable(false))
5992 .with_column("rolbypassrls", SqlScalarType::Bool.nullable(false))
5993 .with_column("rolconnlimit", SqlScalarType::Int32.nullable(false))
5994 .with_column("rolpassword", SqlScalarType::String.nullable(true))
5995 .with_column(
5996 "rolvaliduntil",
5997 SqlScalarType::TimestampTz { precision: None }.nullable(true),
5998 )
5999 .finish(),
6000 column_comments: BTreeMap::new(),
6001 sql: r#"
6002SELECT
6003 r.oid AS oid,
6004 r.name AS rolname,
6005 rolsuper,
6006 inherit AS rolinherit,
6007 COALESCE(r.rolcanlogin, false) AS rolcanlogin,
6008 -- MZ doesn't support replication in the same way Postgres does
6009 false AS rolreplication,
6010 -- MZ doesn't how row level security
6011 false AS rolbypassrls,
6012 -- MZ doesn't have a connection limit
6013 -1 AS rolconnlimit,
6014 a.password_hash AS rolpassword,
6015 NULL::pg_catalog.timestamptz AS rolvaliduntil
6016FROM mz_catalog.mz_roles r
6017LEFT JOIN mz_catalog.mz_role_auth a ON r.oid = a.role_oid"#,
6018 access: vec![rbac::owner_privilege(ObjectType::Table, MZ_SYSTEM_ROLE_ID)],
6019 ontology: None,
6020});
6021
6022pub const PG_AUTHID_CORE_IND: BuiltinIndex = BuiltinIndex {
6023 name: "pg_authid_core_ind",
6024 schema: MZ_INTERNAL_SCHEMA,
6025 oid: oid::INDEX_PG_AUTHID_CORE_IND_OID,
6026 sql: "IN CLUSTER mz_catalog_server
6027ON mz_internal.pg_authid_core (rolname)",
6028 is_retained_metrics_object: false,
6029};
6030
6031pub static MZ_SHOW_ALL_OBJECTS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
6032 name: "mz_show_all_objects",
6033 schema: MZ_INTERNAL_SCHEMA,
6034 oid: oid::VIEW_MZ_SHOW_ALL_OBJECTS_OID,
6035 desc: RelationDesc::builder()
6036 .with_column("schema_id", SqlScalarType::String.nullable(false))
6037 .with_column("name", SqlScalarType::String.nullable(false))
6038 .with_column("type", SqlScalarType::String.nullable(false))
6039 .with_column("comment", SqlScalarType::String.nullable(false))
6040 .finish(),
6041 column_comments: BTreeMap::new(),
6042 sql: "WITH comments AS (
6043 SELECT id, object_type, comment
6044 FROM mz_internal.mz_comments
6045 WHERE object_sub_id IS NULL
6046 )
6047 SELECT schema_id, name, type, COALESCE(comment, '') AS comment
6048 FROM mz_catalog.mz_objects AS objs
6049 LEFT JOIN comments ON objs.id = comments.id AND comments.object_type = objs.type",
6050 access: vec![PUBLIC_SELECT],
6051 ontology: None,
6052});
6053
6054pub static MZ_SHOW_CLUSTERS: LazyLock<BuiltinView> = LazyLock::new(|| {
6055 BuiltinView {
6056 name: "mz_show_clusters",
6057 schema: MZ_INTERNAL_SCHEMA,
6058 oid: oid::VIEW_MZ_SHOW_CLUSTERS_OID,
6059 desc: RelationDesc::builder()
6060 .with_column("name", SqlScalarType::String.nullable(false))
6061 .with_column("replicas", SqlScalarType::String.nullable(true))
6062 .with_column("activity", SqlScalarType::String.nullable(true))
6065 .with_column("comment", SqlScalarType::String.nullable(false))
6066 .finish(),
6067 column_comments: BTreeMap::new(),
6068 sql: "
6078 WITH clusters AS (
6079 SELECT
6080 mc.id,
6081 mc.name,
6082 pg_catalog.string_agg(mcr.name || ' (' || mcr.size || ')', ', ' ORDER BY mcr.name) AS replicas
6083 FROM mz_catalog.mz_clusters mc
6084 LEFT JOIN mz_catalog.mz_cluster_replicas mcr
6085 ON mc.id = mcr.cluster_id
6086 GROUP BY mc.id, mc.name
6087 ),
6088 comments AS (
6089 SELECT id, comment
6090 FROM mz_internal.mz_comments
6091 WHERE object_type = 'cluster' AND object_sub_id IS NULL
6092 ),
6093 reconfigurations AS (
6094 SELECT
6095 cluster_id,
6096 'reconfiguring ' || NULLIF(array_to_string(ARRAY[
6097 'size to ' || (changes->>'size'),
6098 'replication factor to ' || (changes->>'replication_factor'),
6099 CASE WHEN changes->'availability_zones' IS NOT NULL THEN 'availability zones' END,
6100 CASE WHEN changes->'logging' IS NOT NULL THEN 'introspection settings' END,
6101 CASE WHEN changes->'arrangement_compression' IS NOT NULL THEN 'arrangement compression' END
6102 ], ', '), '') AS summary
6103 FROM mz_internal.mz_cluster_reconfigurations
6104 WHERE status = 'in-progress'
6105 )
6106 SELECT
6107 name,
6108 replicas,
6109 CASE
6110 WHEN recon.summary IS NOT NULL AND scaling.state IS NOT NULL
6111 THEN recon.summary
6112 || '; hydration burst at ' || (scaling.state->'burst'->>'burst_size')
6113 WHEN recon.summary IS NOT NULL
6114 THEN recon.summary
6115 WHEN scaling.state IS NOT NULL
6116 THEN 'hydration burst at ' || (scaling.state->'burst'->>'burst_size')
6117 ELSE NULL
6118 END AS activity,
6119 COALESCE(comment, '') as comment
6120 FROM clusters
6121 LEFT JOIN comments ON clusters.id = comments.id
6122 LEFT JOIN reconfigurations recon
6123 ON clusters.id = recon.cluster_id
6124 LEFT JOIN mz_internal.mz_cluster_auto_scaling_strategies scaling ON clusters.id = scaling.cluster_id",
6125 access: vec![PUBLIC_SELECT],
6126 ontology: None,
6127}
6128});
6129
6130pub static MZ_SHOW_SECRETS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
6131 name: "mz_show_secrets",
6132 schema: MZ_INTERNAL_SCHEMA,
6133 oid: oid::VIEW_MZ_SHOW_SECRETS_OID,
6134 desc: RelationDesc::builder()
6135 .with_column("schema_id", SqlScalarType::String.nullable(false))
6136 .with_column("name", SqlScalarType::String.nullable(false))
6137 .with_column("comment", SqlScalarType::String.nullable(false))
6138 .finish(),
6139 column_comments: BTreeMap::new(),
6140 sql: "WITH comments AS (
6141 SELECT id, comment
6142 FROM mz_internal.mz_comments
6143 WHERE object_type = 'secret' AND object_sub_id IS NULL
6144 )
6145 SELECT schema_id, name, COALESCE(comment, '') as comment
6146 FROM mz_catalog.mz_secrets secrets
6147 LEFT JOIN comments ON secrets.id = comments.id",
6148 access: vec![PUBLIC_SELECT],
6149 ontology: None,
6150});
6151
6152pub static MZ_SHOW_COLUMNS: LazyLock<BuiltinView> = LazyLock::new(|| {
6153 BuiltinView {
6154 name: "mz_show_columns",
6155 schema: MZ_INTERNAL_SCHEMA,
6156 oid: oid::VIEW_MZ_SHOW_COLUMNS_OID,
6157 desc: RelationDesc::builder()
6158 .with_column("id", SqlScalarType::String.nullable(false))
6159 .with_column("name", SqlScalarType::String.nullable(false))
6160 .with_column("nullable", SqlScalarType::Bool.nullable(false))
6161 .with_column("type", SqlScalarType::String.nullable(false))
6162 .with_column("position", SqlScalarType::UInt64.nullable(false))
6163 .with_column("comment", SqlScalarType::String.nullable(false))
6164 .finish(),
6165 column_comments: BTreeMap::new(),
6166 sql: "
6172 SELECT columns.id, columns.name, columns.nullable, columns.type, columns.position, COALESCE(comment, '') as comment
6173 FROM mz_catalog.mz_columns columns
6174 LEFT JOIN mz_catalog.mz_objects obj ON obj.id = columns.id
6175 LEFT JOIN mz_internal.mz_comments comments
6176 ON columns.id = comments.id
6177 AND columns.position = comments.object_sub_id
6178 AND comments.object_type = obj.type",
6179 access: vec![PUBLIC_SELECT],
6180 ontology: None,
6181}
6182});
6183
6184pub static MZ_SHOW_DATABASES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
6185 name: "mz_show_databases",
6186 schema: MZ_INTERNAL_SCHEMA,
6187 oid: oid::VIEW_MZ_SHOW_DATABASES_OID,
6188 desc: RelationDesc::builder()
6189 .with_column("name", SqlScalarType::String.nullable(false))
6190 .with_column("comment", SqlScalarType::String.nullable(false))
6191 .finish(),
6192 column_comments: BTreeMap::new(),
6193 sql: "WITH comments AS (
6194 SELECT id, comment
6195 FROM mz_internal.mz_comments
6196 WHERE object_type = 'database' AND object_sub_id IS NULL
6197 )
6198 SELECT name, COALESCE(comment, '') as comment
6199 FROM mz_catalog.mz_databases databases
6200 LEFT JOIN comments ON databases.id = comments.id",
6201 access: vec![PUBLIC_SELECT],
6202 ontology: None,
6203});
6204
6205pub static MZ_SHOW_SCHEMAS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
6206 name: "mz_show_schemas",
6207 schema: MZ_INTERNAL_SCHEMA,
6208 oid: oid::VIEW_MZ_SHOW_SCHEMAS_OID,
6209 desc: RelationDesc::builder()
6210 .with_column("database_id", SqlScalarType::String.nullable(true))
6211 .with_column("name", SqlScalarType::String.nullable(false))
6212 .with_column("comment", SqlScalarType::String.nullable(false))
6213 .finish(),
6214 column_comments: BTreeMap::new(),
6215 sql: "WITH comments AS (
6216 SELECT id, comment
6217 FROM mz_internal.mz_comments
6218 WHERE object_type = 'schema' AND object_sub_id IS NULL
6219 )
6220 SELECT database_id, name, COALESCE(comment, '') as comment
6221 FROM mz_catalog.mz_schemas schemas
6222 LEFT JOIN comments ON schemas.id = comments.id",
6223 access: vec![PUBLIC_SELECT],
6224 ontology: None,
6225});
6226
6227pub static MZ_SHOW_ROLES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
6228 name: "mz_show_roles",
6229 schema: MZ_INTERNAL_SCHEMA,
6230 oid: oid::VIEW_MZ_SHOW_ROLES_OID,
6231 desc: RelationDesc::builder()
6232 .with_column("name", SqlScalarType::String.nullable(false))
6233 .with_column("comment", SqlScalarType::String.nullable(false))
6234 .finish(),
6235 column_comments: BTreeMap::new(),
6236 sql: "WITH comments AS (
6237 SELECT id, comment
6238 FROM mz_internal.mz_comments
6239 WHERE object_type = 'role' AND object_sub_id IS NULL
6240 )
6241 SELECT name, COALESCE(comment, '') as comment
6242 FROM mz_catalog.mz_roles roles
6243 LEFT JOIN comments ON roles.id = comments.id
6244 WHERE roles.id NOT LIKE 's%'
6245 AND roles.id NOT LIKE 'g%'",
6246 access: vec![PUBLIC_SELECT],
6247 ontology: None,
6248});
6249
6250pub static MZ_SHOW_TABLES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
6251 name: "mz_show_tables",
6252 schema: MZ_INTERNAL_SCHEMA,
6253 oid: oid::VIEW_MZ_SHOW_TABLES_OID,
6254 desc: RelationDesc::builder()
6255 .with_column("schema_id", SqlScalarType::String.nullable(false))
6256 .with_column("name", SqlScalarType::String.nullable(false))
6257 .with_column("comment", SqlScalarType::String.nullable(false))
6258 .with_column("source_id", SqlScalarType::String.nullable(true))
6259 .finish(),
6260 column_comments: BTreeMap::new(),
6261 sql: "WITH comments AS (
6262 SELECT id, comment
6263 FROM mz_internal.mz_comments
6264 WHERE object_type = 'table' AND object_sub_id IS NULL
6265 )
6266 SELECT schema_id, name, COALESCE(comment, '') as comment, source_id
6267 FROM mz_catalog.mz_tables tables
6268 LEFT JOIN comments ON tables.id = comments.id",
6269 access: vec![PUBLIC_SELECT],
6270 ontology: None,
6271});
6272
6273pub static MZ_SHOW_VIEWS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
6274 name: "mz_show_views",
6275 schema: MZ_INTERNAL_SCHEMA,
6276 oid: oid::VIEW_MZ_SHOW_VIEWS_OID,
6277 desc: RelationDesc::builder()
6278 .with_column("schema_id", SqlScalarType::String.nullable(false))
6279 .with_column("name", SqlScalarType::String.nullable(false))
6280 .with_column("comment", SqlScalarType::String.nullable(false))
6281 .finish(),
6282 column_comments: BTreeMap::new(),
6283 sql: "WITH comments AS (
6284 SELECT id, comment
6285 FROM mz_internal.mz_comments
6286 WHERE object_type = 'view' AND object_sub_id IS NULL
6287 )
6288 SELECT schema_id, name, COALESCE(comment, '') as comment
6289 FROM mz_catalog.mz_views views
6290 LEFT JOIN comments ON views.id = comments.id",
6291 access: vec![PUBLIC_SELECT],
6292 ontology: None,
6293});
6294
6295pub static MZ_SHOW_TYPES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
6296 name: "mz_show_types",
6297 schema: MZ_INTERNAL_SCHEMA,
6298 oid: oid::VIEW_MZ_SHOW_TYPES_OID,
6299 desc: RelationDesc::builder()
6300 .with_column("schema_id", SqlScalarType::String.nullable(false))
6301 .with_column("name", SqlScalarType::String.nullable(false))
6302 .with_column("comment", SqlScalarType::String.nullable(false))
6303 .finish(),
6304 column_comments: BTreeMap::new(),
6305 sql: "WITH comments AS (
6306 SELECT id, comment
6307 FROM mz_internal.mz_comments
6308 WHERE object_type = 'type' AND object_sub_id IS NULL
6309 )
6310 SELECT schema_id, name, COALESCE(comment, '') as comment
6311 FROM mz_catalog.mz_types types
6312 LEFT JOIN comments ON types.id = comments.id",
6313 access: vec![PUBLIC_SELECT],
6314 ontology: None,
6315});
6316
6317pub static MZ_SHOW_CONNECTIONS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
6318 name: "mz_show_connections",
6319 schema: MZ_INTERNAL_SCHEMA,
6320 oid: oid::VIEW_MZ_SHOW_CONNECTIONS_OID,
6321 desc: RelationDesc::builder()
6322 .with_column("schema_id", SqlScalarType::String.nullable(false))
6323 .with_column("name", SqlScalarType::String.nullable(false))
6324 .with_column("type", SqlScalarType::String.nullable(false))
6325 .with_column("comment", SqlScalarType::String.nullable(false))
6326 .finish(),
6327 column_comments: BTreeMap::new(),
6328 sql: "WITH comments AS (
6329 SELECT id, comment
6330 FROM mz_internal.mz_comments
6331 WHERE object_type = 'connection' AND object_sub_id IS NULL
6332 )
6333 SELECT schema_id, name, type, COALESCE(comment, '') as comment
6334 FROM mz_catalog.mz_connections connections
6335 LEFT JOIN comments ON connections.id = comments.id",
6336 access: vec![PUBLIC_SELECT],
6337 ontology: None,
6338});
6339
6340pub static MZ_SHOW_SOURCES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
6341 name: "mz_show_sources",
6342 schema: MZ_INTERNAL_SCHEMA,
6343 oid: oid::VIEW_MZ_SHOW_SOURCES_OID,
6344 desc: RelationDesc::builder()
6345 .with_column("id", SqlScalarType::String.nullable(false))
6346 .with_column("name", SqlScalarType::String.nullable(false))
6347 .with_column("type", SqlScalarType::String.nullable(false))
6348 .with_column("cluster", SqlScalarType::String.nullable(true))
6349 .with_column("schema_id", SqlScalarType::String.nullable(false))
6350 .with_column("cluster_id", SqlScalarType::String.nullable(true))
6351 .with_column("comment", SqlScalarType::String.nullable(false))
6352 .finish(),
6353 column_comments: BTreeMap::new(),
6354 sql: "
6355WITH comments AS (
6356 SELECT id, comment
6357 FROM mz_internal.mz_comments
6358 WHERE object_type = 'source' AND object_sub_id IS NULL
6359)
6360SELECT
6361 sources.id,
6362 sources.name,
6363 sources.type,
6364 clusters.name AS cluster,
6365 schema_id,
6366 cluster_id,
6367 COALESCE(comments.comment, '') as comment
6368FROM
6369 mz_catalog.mz_sources AS sources
6370 LEFT JOIN
6371 mz_catalog.mz_clusters AS clusters
6372 ON clusters.id = sources.cluster_id
6373 LEFT JOIN comments ON sources.id = comments.id",
6374 access: vec![PUBLIC_SELECT],
6375 ontology: None,
6376});
6377
6378pub static MZ_SHOW_SINKS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
6379 name: "mz_show_sinks",
6380 schema: MZ_INTERNAL_SCHEMA,
6381 oid: oid::VIEW_MZ_SHOW_SINKS_OID,
6382 desc: RelationDesc::builder()
6383 .with_column("id", SqlScalarType::String.nullable(false))
6384 .with_column("name", SqlScalarType::String.nullable(false))
6385 .with_column("type", SqlScalarType::String.nullable(false))
6386 .with_column("cluster", SqlScalarType::String.nullable(false))
6387 .with_column("schema_id", SqlScalarType::String.nullable(false))
6388 .with_column("cluster_id", SqlScalarType::String.nullable(false))
6389 .with_column("comment", SqlScalarType::String.nullable(false))
6390 .finish(),
6391 column_comments: BTreeMap::new(),
6392 sql: "
6393WITH comments AS (
6394 SELECT id, comment
6395 FROM mz_internal.mz_comments
6396 WHERE object_type = 'sink' AND object_sub_id IS NULL
6397)
6398SELECT
6399 sinks.id,
6400 sinks.name,
6401 sinks.type,
6402 clusters.name AS cluster,
6403 schema_id,
6404 cluster_id,
6405 COALESCE(comments.comment, '') as comment
6406FROM
6407 mz_catalog.mz_sinks AS sinks
6408 JOIN
6409 mz_catalog.mz_clusters AS clusters
6410 ON clusters.id = sinks.cluster_id
6411 LEFT JOIN comments ON sinks.id = comments.id",
6412 access: vec![PUBLIC_SELECT],
6413 ontology: None,
6414});
6415
6416pub static MZ_SHOW_MATERIALIZED_VIEWS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
6417 name: "mz_show_materialized_views",
6418 schema: MZ_INTERNAL_SCHEMA,
6419 oid: oid::VIEW_MZ_SHOW_MATERIALIZED_VIEWS_OID,
6420 desc: RelationDesc::builder()
6421 .with_column("id", SqlScalarType::String.nullable(false))
6422 .with_column("name", SqlScalarType::String.nullable(false))
6423 .with_column("cluster", SqlScalarType::String.nullable(false))
6424 .with_column("schema_id", SqlScalarType::String.nullable(false))
6425 .with_column("cluster_id", SqlScalarType::String.nullable(false))
6426 .with_column("comment", SqlScalarType::String.nullable(false))
6427 .finish(),
6428 column_comments: BTreeMap::new(),
6429 sql: "
6430WITH
6431 comments AS (
6432 SELECT id, comment
6433 FROM mz_internal.mz_comments
6434 WHERE object_type = 'materialized-view' AND object_sub_id IS NULL
6435 )
6436SELECT
6437 mviews.id as id,
6438 mviews.name,
6439 clusters.name AS cluster,
6440 schema_id,
6441 cluster_id,
6442 COALESCE(comments.comment, '') as comment
6443FROM
6444 mz_catalog.mz_materialized_views AS mviews
6445 JOIN mz_catalog.mz_clusters AS clusters ON clusters.id = mviews.cluster_id
6446 LEFT JOIN comments ON mviews.id = comments.id",
6447 access: vec![PUBLIC_SELECT],
6448 ontology: None,
6449});
6450
6451pub static MZ_SHOW_INDEXES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
6452 name: "mz_show_indexes",
6453 schema: MZ_INTERNAL_SCHEMA,
6454 oid: oid::VIEW_MZ_SHOW_INDEXES_OID,
6455 desc: RelationDesc::builder()
6456 .with_column("id", SqlScalarType::String.nullable(false))
6457 .with_column("name", SqlScalarType::String.nullable(false))
6458 .with_column("on", SqlScalarType::String.nullable(false))
6459 .with_column("cluster", SqlScalarType::String.nullable(false))
6460 .with_column(
6461 "key",
6462 SqlScalarType::Array(Box::new(SqlScalarType::String)).nullable(false),
6463 )
6464 .with_column("on_id", SqlScalarType::String.nullable(false))
6465 .with_column("schema_id", SqlScalarType::String.nullable(false))
6466 .with_column("cluster_id", SqlScalarType::String.nullable(false))
6467 .with_column("comment", SqlScalarType::String.nullable(false))
6468 .finish(),
6469 column_comments: BTreeMap::new(),
6470 sql: "
6471WITH comments AS (
6472 SELECT id, comment
6473 FROM mz_internal.mz_comments
6474 WHERE object_type = 'index' AND object_sub_id IS NULL
6475)
6476SELECT
6477 idxs.id AS id,
6478 idxs.name AS name,
6479 objs.name AS on,
6480 clusters.name AS cluster,
6481 COALESCE(keys.key, '{}'::_text) AS key,
6482 idxs.on_id AS on_id,
6483 objs.schema_id AS schema_id,
6484 clusters.id AS cluster_id,
6485 COALESCE(comments.comment, '') as comment
6486FROM
6487 mz_catalog.mz_indexes AS idxs
6488 JOIN mz_catalog.mz_objects AS objs ON idxs.on_id = objs.id
6489 JOIN mz_catalog.mz_clusters AS clusters ON clusters.id = idxs.cluster_id
6490 LEFT JOIN
6491 (SELECT
6492 idxs.id,
6493 ARRAY_AGG(
6494 CASE
6495 WHEN idx_cols.on_expression IS NULL THEN obj_cols.name
6496 ELSE idx_cols.on_expression
6497 END
6498 ORDER BY idx_cols.index_position ASC
6499 ) AS key
6500 FROM
6501 mz_catalog.mz_indexes AS idxs
6502 JOIN mz_catalog.mz_index_columns idx_cols ON idxs.id = idx_cols.index_id
6503 LEFT JOIN mz_catalog.mz_columns obj_cols ON
6504 idxs.on_id = obj_cols.id AND idx_cols.on_position = obj_cols.position
6505 GROUP BY idxs.id) AS keys
6506 ON idxs.id = keys.id
6507 LEFT JOIN comments ON idxs.id = comments.id",
6508 access: vec![PUBLIC_SELECT],
6509 ontology: None,
6510});
6511
6512pub static MZ_SHOW_CLUSTER_REPLICAS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
6513 name: "mz_show_cluster_replicas",
6514 schema: MZ_INTERNAL_SCHEMA,
6515 oid: oid::VIEW_MZ_SHOW_CLUSTER_REPLICAS_OID,
6516 desc: RelationDesc::builder()
6517 .with_column("cluster", SqlScalarType::String.nullable(false))
6518 .with_column("replica", SqlScalarType::String.nullable(false))
6519 .with_column("replica_id", SqlScalarType::String.nullable(false))
6520 .with_column("size", SqlScalarType::String.nullable(true))
6521 .with_column("ready", SqlScalarType::Bool.nullable(false))
6522 .with_column("comment", SqlScalarType::String.nullable(false))
6523 .finish(),
6524 column_comments: BTreeMap::new(),
6525 sql: r#"SELECT
6526 mz_catalog.mz_clusters.name AS cluster,
6527 mz_catalog.mz_cluster_replicas.name AS replica,
6528 mz_catalog.mz_cluster_replicas.id as replica_id,
6529 mz_catalog.mz_cluster_replicas.size AS size,
6530 coalesce(statuses.ready, FALSE) AS ready,
6531 coalesce(comments.comment, '') as comment
6532FROM
6533 mz_catalog.mz_cluster_replicas
6534 JOIN mz_catalog.mz_clusters
6535 ON mz_catalog.mz_cluster_replicas.cluster_id = mz_catalog.mz_clusters.id
6536 LEFT JOIN
6537 (
6538 SELECT
6539 replica_id,
6540 bool_and(hydrated) AS ready
6541 FROM mz_internal.mz_hydration_statuses
6542 WHERE replica_id is not null
6543 GROUP BY replica_id
6544 ) AS statuses
6545 ON mz_catalog.mz_cluster_replicas.id = statuses.replica_id
6546 LEFT JOIN mz_internal.mz_comments comments
6547 ON mz_catalog.mz_cluster_replicas.id = comments.id
6548 AND comments.object_type = 'cluster-replica'
6549ORDER BY 1, 2"#,
6550 access: vec![PUBLIC_SELECT],
6551 ontology: None,
6552});
6553
6554pub static MZ_MCP_DATA_PRODUCTS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
6563 name: "mz_mcp_data_products",
6564 schema: MZ_INTERNAL_SCHEMA,
6565 oid: oid::VIEW_MZ_MCP_DATA_PRODUCTS_OID,
6566 desc: RelationDesc::builder()
6567 .with_column("object_name", SqlScalarType::String.nullable(false))
6568 .with_column("cluster", SqlScalarType::String.nullable(true))
6569 .with_column("description", SqlScalarType::String.nullable(true))
6570 .with_key(vec![0, 1, 2])
6571 .finish(),
6572 column_comments: BTreeMap::from_iter([
6573 (
6574 "object_name",
6575 "Fully qualified object name (database.schema.name).",
6576 ),
6577 (
6578 "cluster",
6579 "Cluster hosting the object's index or compute. Reads still work from any cluster you can use, but only reads on this cluster benefit from the index. Shown only when your role has USAGE on it (otherwise null).",
6580 ),
6581 (
6582 "description",
6583 "Index comment if available, otherwise object comment. Used as data product description.",
6584 ),
6585 ]),
6586 sql: r#"
6595SELECT DISTINCT
6596 '"' || op.database || '"."' || op.schema || '"."' || op.name || '"' AS object_name,
6597 CASE WHEN cp.name IS NOT NULL THEN COALESCE(c_idx.name, c_obj.name) END AS cluster,
6598 COALESCE(cts_idx.comment, cts_obj.comment) AS description
6599FROM mz_internal.mz_show_my_object_privileges op
6600JOIN mz_objects o ON op.name = o.name AND op.object_type = o.type
6601JOIN mz_schemas s ON s.name = op.schema AND s.id = o.schema_id
6602JOIN mz_databases d ON d.name = op.database AND d.id = s.database_id
6603LEFT JOIN mz_indexes i ON i.on_id = o.id
6604LEFT JOIN mz_clusters c_idx ON c_idx.id = i.cluster_id
6605LEFT JOIN mz_clusters c_obj ON c_obj.id = o.cluster_id
6606LEFT JOIN mz_internal.mz_show_my_cluster_privileges cp
6607 ON cp.name = COALESCE(c_idx.name, c_obj.name) AND cp.privilege_type = 'USAGE'
6608LEFT JOIN mz_internal.mz_comments cts_idx ON cts_idx.id = i.id AND cts_idx.object_type = 'index' AND cts_idx.object_sub_id IS NULL
6609LEFT JOIN mz_internal.mz_comments cts_obj ON cts_obj.id = o.id AND cts_obj.object_type = o.type AND cts_obj.object_sub_id IS NULL
6610WHERE op.privilege_type = 'SELECT'
6611 AND (o.type = 'materialized-view'
6612 OR (o.type = 'view' AND i.id IS NOT NULL AND cp.name IS NOT NULL))
6613 AND s.name NOT IN ('mz_catalog', 'mz_internal', 'pg_catalog', 'information_schema', 'mz_introspection')
6614"#,
6615 access: vec![PUBLIC_SELECT],
6616 ontology: None,
6617});
6618
6619pub static MZ_MCP_DATA_PRODUCT_DETAILS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
6628 name: "mz_mcp_data_product_details",
6629 schema: MZ_INTERNAL_SCHEMA,
6630 oid: oid::VIEW_MZ_MCP_DATA_PRODUCT_DETAILS_OID,
6631 desc: RelationDesc::builder()
6638 .with_column("object_name", SqlScalarType::String.nullable(false))
6639 .with_column("cluster", SqlScalarType::String.nullable(true))
6640 .with_column("description", SqlScalarType::String.nullable(true))
6641 .with_column("schema", SqlScalarType::Jsonb.nullable(false))
6642 .with_column("hydration", SqlScalarType::Jsonb.nullable(false))
6643 .finish(),
6644 column_comments: BTreeMap::from_iter([
6645 (
6646 "object_name",
6647 "Fully qualified object name (database.schema.name).",
6648 ),
6649 (
6650 "cluster",
6651 "Cluster hosting the object's index or compute. Reads still work from any cluster you can use, but only reads on this cluster benefit from the index. Shown only when your role has USAGE on it (otherwise null).",
6652 ),
6653 (
6654 "description",
6655 "Index comment if available, otherwise object comment. Used as data product description.",
6656 ),
6657 (
6658 "schema",
6659 "JSON Schema describing the object's columns and types.",
6660 ),
6661 (
6662 "hydration",
6663 "Readiness summary as a JSON object with `hydrated` (bool), `replica_count` (int), and `hydrated_replica_count` (int). `hydrated` is true only when the cluster has at least one replica and the dataflow is hydrated on every replica. Reads against a non-hydrated data product block until the dataflow catches up (they never return partial data). Check this before reading: if `hydrated` is false and `replica_count > 0`, wait and retry; if `replica_count` is 0, the cluster has no replicas and that needs operator action, not a retry.",
6664 ),
6665 ]),
6666 sql: r#"
6667WITH details_raw AS (
6668 SELECT
6669 '"' || op.database || '"."' || op.schema || '"."' || op.name || '"' AS object_name,
6670 COALESCE(c_idx.name, c_obj.name) AS cluster,
6671 COALESCE(cts_idx.comment, cts_obj.comment) AS description,
6672 COALESCE(jsonb_build_object(
6673 'type', 'object',
6674 'indexedColumns', jsonb_agg(distinct ccol.name) FILTER (WHERE ccol.position = ic.on_position),
6675 'properties', jsonb_strip_nulls(jsonb_object_agg(
6676 ccol.name,
6677 CASE
6678 WHEN ccol.type IN (
6679 'uint2', 'uint4','uint8', 'int', 'integer', 'smallint',
6680 'double', 'double precision', 'bigint', 'float',
6681 'numeric', 'real'
6682 ) THEN jsonb_build_object(
6683 'type', 'number',
6684 'description', cts_col.comment
6685 )
6686 WHEN ccol.type = 'boolean' THEN jsonb_build_object(
6687 'type', 'boolean',
6688 'description', cts_col.comment
6689 )
6690 WHEN ccol.type = 'bytea' THEN jsonb_build_object(
6691 'type', 'string',
6692 'description', cts_col.comment,
6693 'contentEncoding', 'base64',
6694 'contentMediaType', 'application/octet-stream'
6695 )
6696 WHEN ccol.type = 'date' THEN jsonb_build_object(
6697 'type', 'string',
6698 'format', 'date',
6699 'description', cts_col.comment
6700 )
6701 WHEN ccol.type = 'time' THEN jsonb_build_object(
6702 'type', 'string',
6703 'format', 'time',
6704 'description', cts_col.comment
6705 )
6706 WHEN ccol.type ilike 'timestamp%%' THEN jsonb_build_object(
6707 'type', 'string',
6708 'format', 'date-time',
6709 'description', cts_col.comment
6710 )
6711 WHEN ccol.type = 'jsonb' THEN jsonb_build_object(
6712 'type', 'object',
6713 'description', cts_col.comment
6714 )
6715 WHEN ccol.type = 'uuid' THEN jsonb_build_object(
6716 'type', 'string',
6717 'format', 'uuid',
6718 'description', cts_col.comment
6719 )
6720 ELSE jsonb_build_object(
6721 'type', 'string',
6722 'description', cts_col.comment
6723 )
6724 END
6725 ))
6726 ), '{"type": "object", "properties": {}}'::jsonb) AS schema
6727FROM mz_internal.mz_show_my_object_privileges op
6728JOIN mz_objects o ON op.name = o.name AND op.object_type = o.type
6729JOIN mz_schemas s ON s.name = op.schema AND s.id = o.schema_id
6730JOIN mz_databases d ON d.name = op.database AND d.id = s.database_id
6731JOIN mz_columns ccol ON ccol.id = o.id
6732LEFT JOIN mz_indexes i ON i.on_id = o.id
6733LEFT JOIN mz_index_columns ic ON i.id = ic.index_id
6734LEFT JOIN mz_clusters c_idx ON c_idx.id = i.cluster_id
6735LEFT JOIN mz_clusters c_obj ON c_obj.id = o.cluster_id
6736LEFT JOIN mz_internal.mz_show_my_cluster_privileges cp
6737 ON cp.name = COALESCE(c_idx.name, c_obj.name) AND cp.privilege_type = 'USAGE'
6738LEFT JOIN mz_internal.mz_comments cts_idx ON cts_idx.id = i.id AND cts_idx.object_type = 'index' AND cts_idx.object_sub_id IS NULL
6739LEFT JOIN mz_internal.mz_comments cts_obj ON cts_obj.id = o.id AND cts_obj.object_type = o.type AND cts_obj.object_sub_id IS NULL
6740LEFT JOIN mz_internal.mz_comments cts_col ON cts_col.id = o.id AND cts_col.object_type = o.type AND cts_col.object_sub_id = ccol.position
6741WHERE op.privilege_type = 'SELECT'
6742 AND (o.type = 'materialized-view'
6743 OR (o.type = 'view' AND i.id IS NOT NULL AND cp.name IS NOT NULL))
6744 AND s.name NOT IN ('mz_catalog', 'mz_internal', 'pg_catalog', 'information_schema', 'mz_introspection')
6745GROUP BY 1, 2, 3
6746),
6747-- Pick the right (object_id, cluster_id) for hydration: the index's id +
6748-- cluster when an index exists (its arrangement is what the data product
6749-- reads from), otherwise the materialized view's own id + cluster.
6750hydration_meta AS (
6751 SELECT DISTINCT
6752 '"' || db.name || '"."' || s.name || '"."' || o.name || '"' AS object_name,
6753 COALESCE(c_idx.name, c_obj.name) AS cluster,
6754 COALESCE(i.id, o.id) AS hydration_object_id,
6755 COALESCE(i.cluster_id, o.cluster_id) AS cluster_id
6756 FROM mz_objects o
6757 JOIN mz_schemas s ON s.id = o.schema_id
6758 JOIN mz_databases db ON db.id = s.database_id
6759 LEFT JOIN mz_indexes i ON i.on_id = o.id
6760 LEFT JOIN mz_clusters c_idx ON c_idx.id = i.cluster_id
6761 LEFT JOIN mz_clusters c_obj ON c_obj.id = o.cluster_id
6762 WHERE (o.type = 'materialized-view' OR (o.type = 'view' AND i.id IS NOT NULL))
6763 AND s.name NOT IN ('mz_catalog', 'mz_internal', 'pg_catalog', 'information_schema', 'mz_introspection')
6764),
6765-- Dedupe by replica before counting: an MV with multiple indexes on the
6766-- same cluster has multiple rows in `hydration_meta`, and joining each
6767-- of them against `mz_cluster_replicas` would otherwise inflate the
6768-- counts by the number of indexes. A replica is "hydrated" only when
6769-- every index dataflow for this data product is hydrated on it.
6770hydration_per_replica AS (
6771 SELECT
6772 m.object_name,
6773 m.cluster,
6774 r.id AS replica_id,
6775 bool_and(COALESCE(h.hydrated, false)) AS replica_hydrated
6776 FROM hydration_meta m
6777 LEFT JOIN mz_catalog.mz_cluster_replicas r ON r.cluster_id = m.cluster_id
6778 LEFT JOIN mz_internal.mz_hydration_statuses h
6779 ON h.replica_id = r.id AND h.object_id = m.hydration_object_id
6780 GROUP BY m.object_name, m.cluster, r.id
6781),
6782hydration AS (
6783 SELECT
6784 object_name,
6785 cluster,
6786 COUNT(replica_id)::int AS replica_count,
6787 COUNT(replica_id) FILTER (WHERE replica_hydrated)::int AS hydrated_replica_count
6788 FROM hydration_per_replica
6789 GROUP BY object_name, cluster
6790)
6791SELECT
6792 d.object_name,
6793 -- Null the advertised cluster unless the role has USAGE on it (DEX-66),
6794 -- matching mz_mcp_data_products. Hydration below still joins on the real
6795 -- d.cluster, so readiness is reported accurately even when the name is
6796 -- hidden.
6797 CASE WHEN EXISTS (
6798 SELECT 1 FROM mz_internal.mz_show_my_cluster_privileges cp
6799 WHERE cp.name = d.cluster AND cp.privilege_type = 'USAGE'
6800 ) THEN d.cluster END AS cluster,
6801 d.description,
6802 d.schema,
6803 jsonb_build_object(
6804 'hydrated',
6805 COALESCE(h.replica_count > 0 AND h.hydrated_replica_count = h.replica_count, false),
6806 'replica_count', COALESCE(h.replica_count, 0),
6807 'hydrated_replica_count', COALESCE(h.hydrated_replica_count, 0)
6808 ) AS hydration
6809FROM details_raw d
6810LEFT JOIN hydration h
6811 ON h.object_name = d.object_name
6812 AND h.cluster IS NOT DISTINCT FROM d.cluster
6813"#,
6814 access: vec![PUBLIC_SELECT],
6815 ontology: None,
6816});
6817
6818pub static MZ_SHOW_ROLE_MEMBERS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
6819 name: "mz_show_role_members",
6820 schema: MZ_INTERNAL_SCHEMA,
6821 oid: oid::VIEW_MZ_SHOW_ROLE_MEMBERS_OID,
6822 desc: RelationDesc::builder()
6823 .with_column("role", SqlScalarType::String.nullable(false))
6824 .with_column("member", SqlScalarType::String.nullable(false))
6825 .with_column("grantor", SqlScalarType::String.nullable(false))
6826 .finish(),
6827 column_comments: BTreeMap::from_iter([
6828 ("role", "The role that `member` is a member of."),
6829 ("member", "The role that is a member of `role`."),
6830 (
6831 "grantor",
6832 "The role that granted membership of `member` to `role`.",
6833 ),
6834 ]),
6835 sql: r#"SELECT
6836 r1.name AS role,
6837 r2.name AS member,
6838 r3.name AS grantor
6839FROM mz_catalog.mz_role_members rm
6840JOIN mz_catalog.mz_roles r1 ON r1.id = rm.role_id
6841JOIN mz_catalog.mz_roles r2 ON r2.id = rm.member
6842JOIN mz_catalog.mz_roles r3 ON r3.id = rm.grantor
6843ORDER BY role"#,
6844 access: vec![PUBLIC_SELECT],
6845 ontology: None,
6846});
6847
6848pub static MZ_SHOW_MY_ROLE_MEMBERS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
6849 name: "mz_show_my_role_members",
6850 schema: MZ_INTERNAL_SCHEMA,
6851 oid: oid::VIEW_MZ_SHOW_MY_ROLE_MEMBERS_OID,
6852 desc: RelationDesc::builder()
6853 .with_column("role", SqlScalarType::String.nullable(false))
6854 .with_column("member", SqlScalarType::String.nullable(false))
6855 .with_column("grantor", SqlScalarType::String.nullable(false))
6856 .finish(),
6857 column_comments: BTreeMap::from_iter([
6858 ("role", "The role that `member` is a member of."),
6859 ("member", "The role that is a member of `role`."),
6860 (
6861 "grantor",
6862 "The role that granted membership of `member` to `role`.",
6863 ),
6864 ]),
6865 sql: r#"SELECT role, member, grantor
6866FROM mz_internal.mz_show_role_members
6867WHERE pg_has_role(member, 'USAGE')"#,
6868 access: vec![PUBLIC_SELECT],
6869 ontology: None,
6870});
6871
6872pub static MZ_SHOW_SYSTEM_PRIVILEGES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
6873 name: "mz_show_system_privileges",
6874 schema: MZ_INTERNAL_SCHEMA,
6875 oid: oid::VIEW_MZ_SHOW_SYSTEM_PRIVILEGES_OID,
6876 desc: RelationDesc::builder()
6877 .with_column("grantor", SqlScalarType::String.nullable(true))
6878 .with_column("grantee", SqlScalarType::String.nullable(true))
6879 .with_column("privilege_type", SqlScalarType::String.nullable(false))
6880 .finish(),
6881 column_comments: BTreeMap::from_iter([
6882 ("grantor", "The role that granted the privilege."),
6883 ("grantee", "The role that the privilege was granted to."),
6884 ("privilege_type", "They type of privilege granted."),
6885 ]),
6886 sql: r#"SELECT
6887 grantor.name AS grantor,
6888 CASE privileges.grantee
6889 WHEN 'p' THEN 'PUBLIC'
6890 ELSE grantee.name
6891 END AS grantee,
6892 privileges.privilege_type AS privilege_type
6893FROM
6894 (SELECT mz_internal.mz_aclexplode(ARRAY[privileges]).*
6895 FROM mz_catalog.mz_system_privileges) AS privileges
6896LEFT JOIN mz_catalog.mz_roles grantor ON privileges.grantor = grantor.id
6897LEFT JOIN mz_catalog.mz_roles grantee ON privileges.grantee = grantee.id
6898WHERE privileges.grantee NOT LIKE 's%'"#,
6899 access: vec![PUBLIC_SELECT],
6900 ontology: None,
6901});
6902
6903pub static MZ_SHOW_MY_SYSTEM_PRIVILEGES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
6904 name: "mz_show_my_system_privileges",
6905 schema: MZ_INTERNAL_SCHEMA,
6906 oid: oid::VIEW_MZ_SHOW_MY_SYSTEM_PRIVILEGES_OID,
6907 desc: RelationDesc::builder()
6908 .with_column("grantor", SqlScalarType::String.nullable(true))
6909 .with_column("grantee", SqlScalarType::String.nullable(true))
6910 .with_column("privilege_type", SqlScalarType::String.nullable(false))
6911 .finish(),
6912 column_comments: BTreeMap::from_iter([
6913 ("grantor", "The role that granted the privilege."),
6914 ("grantee", "The role that the privilege was granted to."),
6915 ("privilege_type", "They type of privilege granted."),
6916 ]),
6917 sql: r#"SELECT grantor, grantee, privilege_type
6918FROM mz_internal.mz_show_system_privileges
6919WHERE
6920 CASE
6921 WHEN grantee = 'PUBLIC' THEN true
6922 -- Semantically equivalent to pg_has_role(grantee, 'USAGE'), which checks
6923 -- whether the current user holds role `grantee`. For a nonexistent grantee
6924 -- name, both return false. We use mz_session_role_memberships() instead
6925 -- because pg_has_role internally calls mz_role_oid_memberships(), which
6926 -- loads the full system role graph and is blocked in restricted sessions.
6927 ELSE grantee = ANY(mz_catalog.mz_session_role_memberships())
6928 END"#,
6929 access: vec![PUBLIC_SELECT],
6930 ontology: None,
6931});
6932
6933pub static MZ_SHOW_CLUSTER_PRIVILEGES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
6934 name: "mz_show_cluster_privileges",
6935 schema: MZ_INTERNAL_SCHEMA,
6936 oid: oid::VIEW_MZ_SHOW_CLUSTER_PRIVILEGES_OID,
6937 desc: RelationDesc::builder()
6938 .with_column("grantor", SqlScalarType::String.nullable(true))
6939 .with_column("grantee", SqlScalarType::String.nullable(true))
6940 .with_column("name", SqlScalarType::String.nullable(false))
6941 .with_column("privilege_type", SqlScalarType::String.nullable(false))
6942 .finish(),
6943 column_comments: BTreeMap::from_iter([
6944 ("grantor", "The role that granted the privilege."),
6945 ("grantee", "The role that the privilege was granted to."),
6946 ("name", "The name of the cluster."),
6947 ("privilege_type", "They type of privilege granted."),
6948 ]),
6949 sql: r#"SELECT
6950 grantor.name AS grantor,
6951 CASE privileges.grantee
6952 WHEN 'p' THEN 'PUBLIC'
6953 ELSE grantee.name
6954 END AS grantee,
6955 privileges.name AS name,
6956 privileges.privilege_type AS privilege_type
6957FROM
6958 (SELECT mz_internal.mz_aclexplode(privileges).*, name
6959 FROM mz_catalog.mz_clusters
6960 WHERE id NOT LIKE 's%') AS privileges
6961LEFT JOIN mz_catalog.mz_roles grantor ON privileges.grantor = grantor.id
6962LEFT JOIN mz_catalog.mz_roles grantee ON privileges.grantee = grantee.id
6963WHERE privileges.grantee NOT LIKE 's%'"#,
6964 access: vec![PUBLIC_SELECT],
6965 ontology: None,
6966});
6967
6968pub static MZ_SHOW_MY_CLUSTER_PRIVILEGES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
6969 name: "mz_show_my_cluster_privileges",
6970 schema: MZ_INTERNAL_SCHEMA,
6971 oid: oid::VIEW_MZ_SHOW_MY_CLUSTER_PRIVILEGES_OID,
6972 desc: RelationDesc::builder()
6973 .with_column("grantor", SqlScalarType::String.nullable(true))
6974 .with_column("grantee", SqlScalarType::String.nullable(true))
6975 .with_column("name", SqlScalarType::String.nullable(false))
6976 .with_column("privilege_type", SqlScalarType::String.nullable(false))
6977 .finish(),
6978 column_comments: BTreeMap::from_iter([
6979 ("grantor", "The role that granted the privilege."),
6980 ("grantee", "The role that the privilege was granted to."),
6981 ("name", "The name of the cluster."),
6982 ("privilege_type", "They type of privilege granted."),
6983 ]),
6984 sql: r#"SELECT grantor, grantee, name, privilege_type
6985FROM mz_internal.mz_show_cluster_privileges
6986WHERE
6987 CASE
6988 WHEN grantee = 'PUBLIC' THEN true
6989 -- Semantically equivalent to pg_has_role(grantee, 'USAGE'), which checks
6990 -- whether the current user holds role `grantee`. For a nonexistent grantee
6991 -- name, both return false. We use mz_session_role_memberships() instead
6992 -- because pg_has_role internally calls mz_role_oid_memberships(), which
6993 -- loads the full system role graph and is blocked in restricted sessions.
6994 ELSE grantee = ANY(mz_catalog.mz_session_role_memberships())
6995 END"#,
6996 access: vec![PUBLIC_SELECT],
6997 ontology: None,
6998});
6999
7000pub static MZ_SHOW_DATABASE_PRIVILEGES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
7001 name: "mz_show_database_privileges",
7002 schema: MZ_INTERNAL_SCHEMA,
7003 oid: oid::VIEW_MZ_SHOW_DATABASE_PRIVILEGES_OID,
7004 desc: RelationDesc::builder()
7005 .with_column("grantor", SqlScalarType::String.nullable(true))
7006 .with_column("grantee", SqlScalarType::String.nullable(true))
7007 .with_column("name", SqlScalarType::String.nullable(false))
7008 .with_column("privilege_type", SqlScalarType::String.nullable(false))
7009 .finish(),
7010 column_comments: BTreeMap::from_iter([
7011 ("grantor", "The role that granted the privilege."),
7012 ("grantee", "The role that the privilege was granted to."),
7013 ("name", "The name of the database."),
7014 ("privilege_type", "They type of privilege granted."),
7015 ]),
7016 sql: r#"SELECT
7017 grantor.name AS grantor,
7018 CASE privileges.grantee
7019 WHEN 'p' THEN 'PUBLIC'
7020 ELSE grantee.name
7021 END AS grantee,
7022 privileges.name AS name,
7023 privileges.privilege_type AS privilege_type
7024FROM
7025 (SELECT mz_internal.mz_aclexplode(privileges).*, name
7026 FROM mz_catalog.mz_databases
7027 WHERE id NOT LIKE 's%') AS privileges
7028LEFT JOIN mz_catalog.mz_roles grantor ON privileges.grantor = grantor.id
7029LEFT JOIN mz_catalog.mz_roles grantee ON privileges.grantee = grantee.id
7030WHERE privileges.grantee NOT LIKE 's%'"#,
7031 access: vec![PUBLIC_SELECT],
7032 ontology: None,
7033});
7034
7035pub static MZ_SHOW_MY_DATABASE_PRIVILEGES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
7036 name: "mz_show_my_database_privileges",
7037 schema: MZ_INTERNAL_SCHEMA,
7038 oid: oid::VIEW_MZ_SHOW_MY_DATABASE_PRIVILEGES_OID,
7039 desc: RelationDesc::builder()
7040 .with_column("grantor", SqlScalarType::String.nullable(true))
7041 .with_column("grantee", SqlScalarType::String.nullable(true))
7042 .with_column("name", SqlScalarType::String.nullable(false))
7043 .with_column("privilege_type", SqlScalarType::String.nullable(false))
7044 .finish(),
7045 column_comments: BTreeMap::from_iter([
7046 ("grantor", "The role that granted the privilege."),
7047 ("grantee", "The role that the privilege was granted to."),
7048 ("name", "The name of the cluster."),
7049 ("privilege_type", "They type of privilege granted."),
7050 ]),
7051 sql: r#"SELECT grantor, grantee, name, privilege_type
7052FROM mz_internal.mz_show_database_privileges
7053WHERE
7054 CASE
7055 WHEN grantee = 'PUBLIC' THEN true
7056 -- Semantically equivalent to pg_has_role(grantee, 'USAGE'), which checks
7057 -- whether the current user holds role `grantee`. For a nonexistent grantee
7058 -- name, both return false. We use mz_session_role_memberships() instead
7059 -- because pg_has_role internally calls mz_role_oid_memberships(), which
7060 -- loads the full system role graph and is blocked in restricted sessions.
7061 ELSE grantee = ANY(mz_catalog.mz_session_role_memberships())
7062 END"#,
7063 access: vec![PUBLIC_SELECT],
7064 ontology: None,
7065});
7066
7067pub static MZ_SHOW_SCHEMA_PRIVILEGES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
7068 name: "mz_show_schema_privileges",
7069 schema: MZ_INTERNAL_SCHEMA,
7070 oid: oid::VIEW_MZ_SHOW_SCHEMA_PRIVILEGES_OID,
7071 desc: RelationDesc::builder()
7072 .with_column("grantor", SqlScalarType::String.nullable(true))
7073 .with_column("grantee", SqlScalarType::String.nullable(true))
7074 .with_column("database", SqlScalarType::String.nullable(true))
7075 .with_column("name", SqlScalarType::String.nullable(false))
7076 .with_column("privilege_type", SqlScalarType::String.nullable(false))
7077 .finish(),
7078 column_comments: BTreeMap::from_iter([
7079 ("grantor", "The role that granted the privilege."),
7080 ("grantee", "The role that the privilege was granted to."),
7081 (
7082 "database",
7083 "The name of the database containing the schema.",
7084 ),
7085 ("name", "The name of the schema."),
7086 ("privilege_type", "They type of privilege granted."),
7087 ]),
7088 sql: r#"SELECT
7089 grantor.name AS grantor,
7090 CASE privileges.grantee
7091 WHEN 'p' THEN 'PUBLIC'
7092 ELSE grantee.name
7093 END AS grantee,
7094 databases.name AS database,
7095 privileges.name AS name,
7096 privileges.privilege_type AS privilege_type
7097FROM
7098 (SELECT mz_internal.mz_aclexplode(privileges).*, database_id, name
7099 FROM mz_catalog.mz_schemas
7100 WHERE id NOT LIKE 's%') AS privileges
7101LEFT JOIN mz_catalog.mz_roles grantor ON privileges.grantor = grantor.id
7102LEFT JOIN mz_catalog.mz_roles grantee ON privileges.grantee = grantee.id
7103LEFT JOIN mz_catalog.mz_databases databases ON privileges.database_id = databases.id
7104WHERE privileges.grantee NOT LIKE 's%'"#,
7105 access: vec![PUBLIC_SELECT],
7106 ontology: None,
7107});
7108
7109pub static MZ_SHOW_MY_SCHEMA_PRIVILEGES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
7110 name: "mz_show_my_schema_privileges",
7111 schema: MZ_INTERNAL_SCHEMA,
7112 oid: oid::VIEW_MZ_SHOW_MY_SCHEMA_PRIVILEGES_OID,
7113 desc: RelationDesc::builder()
7114 .with_column("grantor", SqlScalarType::String.nullable(true))
7115 .with_column("grantee", SqlScalarType::String.nullable(true))
7116 .with_column("database", SqlScalarType::String.nullable(true))
7117 .with_column("name", SqlScalarType::String.nullable(false))
7118 .with_column("privilege_type", SqlScalarType::String.nullable(false))
7119 .finish(),
7120 column_comments: BTreeMap::from_iter([
7121 ("grantor", "The role that granted the privilege."),
7122 ("grantee", "The role that the privilege was granted to."),
7123 (
7124 "database",
7125 "The name of the database containing the schema.",
7126 ),
7127 ("name", "The name of the schema."),
7128 ("privilege_type", "They type of privilege granted."),
7129 ]),
7130 sql: r#"SELECT grantor, grantee, database, name, privilege_type
7131FROM mz_internal.mz_show_schema_privileges
7132WHERE
7133 CASE
7134 WHEN grantee = 'PUBLIC' THEN true
7135 -- Semantically equivalent to pg_has_role(grantee, 'USAGE'), which checks
7136 -- whether the current user holds role `grantee`. For a nonexistent grantee
7137 -- name, both return false. We use mz_session_role_memberships() instead
7138 -- because pg_has_role internally calls mz_role_oid_memberships(), which
7139 -- loads the full system role graph and is blocked in restricted sessions.
7140 ELSE grantee = ANY(mz_catalog.mz_session_role_memberships())
7141 END"#,
7142 access: vec![PUBLIC_SELECT],
7143 ontology: None,
7144});
7145
7146pub static MZ_SHOW_OBJECT_PRIVILEGES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
7147 name: "mz_show_object_privileges",
7148 schema: MZ_INTERNAL_SCHEMA,
7149 oid: oid::VIEW_MZ_SHOW_OBJECT_PRIVILEGES_OID,
7150 desc: RelationDesc::builder()
7151 .with_column("grantor", SqlScalarType::String.nullable(true))
7152 .with_column("grantee", SqlScalarType::String.nullable(true))
7153 .with_column("database", SqlScalarType::String.nullable(true))
7154 .with_column("schema", SqlScalarType::String.nullable(true))
7155 .with_column("name", SqlScalarType::String.nullable(false))
7156 .with_column("object_type", SqlScalarType::String.nullable(false))
7157 .with_column("privilege_type", SqlScalarType::String.nullable(false))
7158 .finish(),
7159 column_comments: BTreeMap::from_iter([
7160 ("grantor", "The role that granted the privilege."),
7161 ("grantee", "The role that the privilege was granted to."),
7162 (
7163 "database",
7164 "The name of the database containing the object.",
7165 ),
7166 ("schema", "The name of the schema containing the object."),
7167 ("name", "The name of the object."),
7168 (
7169 "object_type",
7170 "The type of object the privilege is granted on.",
7171 ),
7172 ("privilege_type", "They type of privilege granted."),
7173 ]),
7174 sql: r#"SELECT
7175 grantor.name AS grantor,
7176 CASE privileges.grantee
7177 WHEN 'p' THEN 'PUBLIC'
7178 ELSE grantee.name
7179 END AS grantee,
7180 databases.name AS database,
7181 schemas.name AS schema,
7182 privileges.name AS name,
7183 privileges.type AS object_type,
7184 privileges.privilege_type AS privilege_type
7185FROM
7186 (SELECT mz_internal.mz_aclexplode(privileges).*, schema_id, name, type
7187 FROM mz_catalog.mz_objects
7188 WHERE id NOT LIKE 's%') AS privileges
7189LEFT JOIN mz_catalog.mz_roles grantor ON privileges.grantor = grantor.id
7190LEFT JOIN mz_catalog.mz_roles grantee ON privileges.grantee = grantee.id
7191LEFT JOIN mz_catalog.mz_schemas schemas ON privileges.schema_id = schemas.id
7192LEFT JOIN mz_catalog.mz_databases databases ON schemas.database_id = databases.id
7193WHERE privileges.grantee NOT LIKE 's%'"#,
7194 access: vec![PUBLIC_SELECT],
7195 ontology: None,
7196});
7197
7198pub static MZ_SHOW_MY_OBJECT_PRIVILEGES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
7199 name: "mz_show_my_object_privileges",
7200 schema: MZ_INTERNAL_SCHEMA,
7201 oid: oid::VIEW_MZ_SHOW_MY_OBJECT_PRIVILEGES_OID,
7202 desc: RelationDesc::builder()
7203 .with_column("grantor", SqlScalarType::String.nullable(true))
7204 .with_column("grantee", SqlScalarType::String.nullable(true))
7205 .with_column("database", SqlScalarType::String.nullable(true))
7206 .with_column("schema", SqlScalarType::String.nullable(true))
7207 .with_column("name", SqlScalarType::String.nullable(false))
7208 .with_column("object_type", SqlScalarType::String.nullable(false))
7209 .with_column("privilege_type", SqlScalarType::String.nullable(false))
7210 .finish(),
7211 column_comments: BTreeMap::from_iter([
7212 ("grantor", "The role that granted the privilege."),
7213 ("grantee", "The role that the privilege was granted to."),
7214 (
7215 "database",
7216 "The name of the database containing the object.",
7217 ),
7218 ("schema", "The name of the schema containing the object."),
7219 ("name", "The name of the object."),
7220 (
7221 "object_type",
7222 "The type of object the privilege is granted on.",
7223 ),
7224 ("privilege_type", "They type of privilege granted."),
7225 ]),
7226 sql: r#"SELECT grantor, grantee, database, schema, name, object_type, privilege_type
7227FROM mz_internal.mz_show_object_privileges
7228WHERE
7229 CASE
7230 WHEN grantee = 'PUBLIC' THEN true
7231 -- Semantically equivalent to pg_has_role(grantee, 'USAGE'), which checks
7232 -- whether the current user holds role `grantee`. For a nonexistent grantee
7233 -- name, both return false. We use mz_session_role_memberships() instead
7234 -- because pg_has_role internally calls mz_role_oid_memberships(), which
7235 -- loads the full system role graph and is blocked in restricted sessions.
7236 ELSE grantee = ANY(mz_catalog.mz_session_role_memberships())
7237 END"#,
7238 access: vec![PUBLIC_SELECT],
7239 ontology: None,
7240});
7241
7242pub static MZ_SHOW_ALL_PRIVILEGES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
7243 name: "mz_show_all_privileges",
7244 schema: MZ_INTERNAL_SCHEMA,
7245 oid: oid::VIEW_MZ_SHOW_ALL_PRIVILEGES_OID,
7246 desc: RelationDesc::builder()
7247 .with_column("grantor", SqlScalarType::String.nullable(true))
7248 .with_column("grantee", SqlScalarType::String.nullable(true))
7249 .with_column("database", SqlScalarType::String.nullable(true))
7250 .with_column("schema", SqlScalarType::String.nullable(true))
7251 .with_column("name", SqlScalarType::String.nullable(true))
7252 .with_column("object_type", SqlScalarType::String.nullable(false))
7253 .with_column("privilege_type", SqlScalarType::String.nullable(false))
7254 .finish(),
7255 column_comments: BTreeMap::from_iter([
7256 ("grantor", "The role that granted the privilege."),
7257 ("grantee", "The role that the privilege was granted to."),
7258 (
7259 "database",
7260 "The name of the database containing the object.",
7261 ),
7262 ("schema", "The name of the schema containing the object."),
7263 ("name", "The name of the privilege target."),
7264 (
7265 "object_type",
7266 "The type of object the privilege is granted on.",
7267 ),
7268 ("privilege_type", "They type of privilege granted."),
7269 ]),
7270 sql: r#"SELECT grantor, grantee, NULL AS database, NULL AS schema, NULL AS name, 'system' AS object_type, privilege_type
7271FROM mz_internal.mz_show_system_privileges
7272UNION ALL
7273SELECT grantor, grantee, NULL AS database, NULL AS schema, name, 'cluster' AS object_type, privilege_type
7274FROM mz_internal.mz_show_cluster_privileges
7275UNION ALL
7276SELECT grantor, grantee, NULL AS database, NULL AS schema, name, 'database' AS object_type, privilege_type
7277FROM mz_internal.mz_show_database_privileges
7278UNION ALL
7279SELECT grantor, grantee, database, NULL AS schema, name, 'schema' AS object_type, privilege_type
7280FROM mz_internal.mz_show_schema_privileges
7281UNION ALL
7282SELECT grantor, grantee, database, schema, name, object_type, privilege_type
7283FROM mz_internal.mz_show_object_privileges"#,
7284 access: vec![PUBLIC_SELECT],
7285 ontology: None,
7286});
7287
7288pub static MZ_SHOW_ALL_MY_PRIVILEGES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
7289 name: "mz_show_all_my_privileges",
7290 schema: MZ_INTERNAL_SCHEMA,
7291 oid: oid::VIEW_MZ_SHOW_ALL_MY_PRIVILEGES_OID,
7292 desc: RelationDesc::builder()
7293 .with_column("grantor", SqlScalarType::String.nullable(true))
7294 .with_column("grantee", SqlScalarType::String.nullable(true))
7295 .with_column("database", SqlScalarType::String.nullable(true))
7296 .with_column("schema", SqlScalarType::String.nullable(true))
7297 .with_column("name", SqlScalarType::String.nullable(true))
7298 .with_column("object_type", SqlScalarType::String.nullable(false))
7299 .with_column("privilege_type", SqlScalarType::String.nullable(false))
7300 .finish(),
7301 column_comments: BTreeMap::from_iter([
7302 ("grantor", "The role that granted the privilege."),
7303 ("grantee", "The role that the privilege was granted to."),
7304 (
7305 "database",
7306 "The name of the database containing the object.",
7307 ),
7308 ("schema", "The name of the schema containing the object."),
7309 ("name", "The name of the privilege target."),
7310 (
7311 "object_type",
7312 "The type of object the privilege is granted on.",
7313 ),
7314 ("privilege_type", "They type of privilege granted."),
7315 ]),
7316 sql: r#"SELECT grantor, grantee, database, schema, name, object_type, privilege_type
7317FROM mz_internal.mz_show_all_privileges
7318WHERE
7319 CASE
7320 WHEN grantee = 'PUBLIC' THEN true
7321 -- Semantically equivalent to pg_has_role(grantee, 'USAGE'), which checks
7322 -- whether the current user holds role `grantee`. For a nonexistent grantee
7323 -- name, both return false. We use mz_session_role_memberships() instead
7324 -- because pg_has_role internally calls mz_role_oid_memberships(), which
7325 -- loads the full system role graph and is blocked in restricted sessions.
7326 ELSE grantee = ANY(mz_catalog.mz_session_role_memberships())
7327 END"#,
7328 access: vec![PUBLIC_SELECT],
7329 ontology: None,
7330});
7331
7332pub static MZ_SHOW_DEFAULT_PRIVILEGES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
7333 name: "mz_show_default_privileges",
7334 schema: MZ_INTERNAL_SCHEMA,
7335 oid: oid::VIEW_MZ_SHOW_DEFAULT_PRIVILEGES_OID,
7336 desc: RelationDesc::builder()
7337 .with_column("object_owner", SqlScalarType::String.nullable(true))
7338 .with_column("database", SqlScalarType::String.nullable(true))
7339 .with_column("schema", SqlScalarType::String.nullable(true))
7340 .with_column("object_type", SqlScalarType::String.nullable(false))
7341 .with_column("grantee", SqlScalarType::String.nullable(true))
7342 .with_column("privilege_type", SqlScalarType::String.nullable(true))
7343 .finish(),
7344 column_comments: BTreeMap::from_iter([
7345 (
7346 "object_owner",
7347 "Privileges described in this row will be granted on objects created by `object_owner`.",
7348 ),
7349 (
7350 "database",
7351 "Privileges described in this row will be granted only on objects created in `database` if non-null.",
7352 ),
7353 (
7354 "schema",
7355 "Privileges described in this row will be granted only on objects created in `schema` if non-null.",
7356 ),
7357 (
7358 "object_type",
7359 "Privileges described in this row will be granted only on objects of type `object_type`.",
7360 ),
7361 (
7362 "grantee",
7363 "Privileges described in this row will be granted to `grantee`.",
7364 ),
7365 ("privilege_type", "They type of privilege to be granted."),
7366 ]),
7367 sql: r#"SELECT
7368 CASE defaults.role_id
7369 WHEN 'p' THEN 'PUBLIC'
7370 ELSE object_owner.name
7371 END AS object_owner,
7372 databases.name AS database,
7373 schemas.name AS schema,
7374 object_type,
7375 CASE defaults.grantee
7376 WHEN 'p' THEN 'PUBLIC'
7377 ELSE grantee.name
7378 END AS grantee,
7379 unnest(mz_internal.mz_format_privileges(defaults.privileges)) AS privilege_type
7380FROM mz_catalog.mz_default_privileges defaults
7381LEFT JOIN mz_catalog.mz_roles AS object_owner ON defaults.role_id = object_owner.id
7382LEFT JOIN mz_catalog.mz_roles AS grantee ON defaults.grantee = grantee.id
7383LEFT JOIN mz_catalog.mz_databases AS databases ON defaults.database_id = databases.id
7384LEFT JOIN mz_catalog.mz_schemas AS schemas ON defaults.schema_id = schemas.id
7385WHERE defaults.grantee NOT LIKE 's%'
7386 AND defaults.database_id IS NULL OR defaults.database_id NOT LIKE 's%'
7387 AND defaults.schema_id IS NULL OR defaults.schema_id NOT LIKE 's%'"#,
7388 access: vec![PUBLIC_SELECT],
7389 ontology: None,
7390});
7391
7392pub static MZ_SHOW_MY_DEFAULT_PRIVILEGES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
7393 name: "mz_show_my_default_privileges",
7394 schema: MZ_INTERNAL_SCHEMA,
7395 oid: oid::VIEW_MZ_SHOW_MY_DEFAULT_PRIVILEGES_OID,
7396 desc: RelationDesc::builder()
7397 .with_column("object_owner", SqlScalarType::String.nullable(true))
7398 .with_column("database", SqlScalarType::String.nullable(true))
7399 .with_column("schema", SqlScalarType::String.nullable(true))
7400 .with_column("object_type", SqlScalarType::String.nullable(false))
7401 .with_column("grantee", SqlScalarType::String.nullable(true))
7402 .with_column("privilege_type", SqlScalarType::String.nullable(true))
7403 .finish(),
7404 column_comments: BTreeMap::from_iter([
7405 (
7406 "object_owner",
7407 "Privileges described in this row will be granted on objects created by `object_owner`.",
7408 ),
7409 (
7410 "database",
7411 "Privileges described in this row will be granted only on objects created in `database` if non-null.",
7412 ),
7413 (
7414 "schema",
7415 "Privileges described in this row will be granted only on objects created in `schema` if non-null.",
7416 ),
7417 (
7418 "object_type",
7419 "Privileges described in this row will be granted only on objects of type `object_type`.",
7420 ),
7421 (
7422 "grantee",
7423 "Privileges described in this row will be granted to `grantee`.",
7424 ),
7425 ("privilege_type", "They type of privilege to be granted."),
7426 ]),
7427 sql: r#"SELECT object_owner, database, schema, object_type, grantee, privilege_type
7428FROM mz_internal.mz_show_default_privileges
7429WHERE
7430 CASE
7431 WHEN grantee = 'PUBLIC' THEN true
7432 -- Semantically equivalent to pg_has_role(grantee, 'USAGE'), which checks
7433 -- whether the current user holds role `grantee`. For a nonexistent grantee
7434 -- name, both return false. We use mz_session_role_memberships() instead
7435 -- because pg_has_role internally calls mz_role_oid_memberships(), which
7436 -- loads the full system role graph and is blocked in restricted sessions.
7437 ELSE grantee = ANY(mz_catalog.mz_session_role_memberships())
7438 END"#,
7439 access: vec![PUBLIC_SELECT],
7440 ontology: None,
7441});
7442
7443pub static MZ_SHOW_NETWORK_POLICIES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
7444 name: "mz_show_network_policies",
7445 schema: MZ_INTERNAL_SCHEMA,
7446 oid: oid::VIEW_MZ_SHOW_NETWORK_POLICIES_OID,
7447 desc: RelationDesc::builder()
7448 .with_column("name", SqlScalarType::String.nullable(false))
7449 .with_column("rules", SqlScalarType::String.nullable(true))
7450 .with_column("comment", SqlScalarType::String.nullable(false))
7451 .finish(),
7452 column_comments: BTreeMap::new(),
7453 sql: "
7454WITH comments AS (
7455 SELECT id, comment
7456 FROM mz_internal.mz_comments
7457 WHERE object_type = 'network-policy' AND object_sub_id IS NULL
7458)
7459SELECT
7460 policy.name,
7461 pg_catalog.string_agg(rule.name,',' ORDER BY rule.name) as rules,
7462 COALESCE(comment, '') as comment
7463FROM
7464 mz_internal.mz_network_policies as policy
7465LEFT JOIN
7466 mz_internal.mz_network_policy_rules as rule ON policy.id = rule.policy_id
7467LEFT JOIN
7468 comments ON policy.id = comments.id
7469WHERE
7470 policy.id NOT LIKE 's%'
7471AND
7472 policy.id NOT LIKE 'g%'
7473GROUP BY policy.name, comments.comment;",
7474 access: vec![PUBLIC_SELECT],
7475 ontology: None,
7476});
7477
7478pub static MZ_CLUSTER_REPLICA_HISTORY: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
7479 name: "mz_cluster_replica_history",
7480 schema: MZ_INTERNAL_SCHEMA,
7481 oid: oid::VIEW_MZ_CLUSTER_REPLICA_HISTORY_OID,
7482 desc: RelationDesc::builder()
7483 .with_column("replica_id", SqlScalarType::String.nullable(true))
7484 .with_column("size", SqlScalarType::String.nullable(true))
7485 .with_column("cluster_id", SqlScalarType::String.nullable(true))
7486 .with_column("cluster_name", SqlScalarType::String.nullable(true))
7487 .with_column("replica_name", SqlScalarType::String.nullable(true))
7488 .with_column(
7489 "created_at",
7490 SqlScalarType::TimestampTz { precision: None }.nullable(false),
7491 )
7492 .with_column(
7493 "dropped_at",
7494 SqlScalarType::TimestampTz { precision: None }.nullable(true),
7495 )
7496 .with_column(
7497 "credits_per_hour",
7498 SqlScalarType::Numeric { max_scale: None }.nullable(true),
7499 )
7500 .finish(),
7501 column_comments: BTreeMap::from_iter([
7502 ("replica_id", "The ID of a cluster replica."),
7503 (
7504 "size",
7505 "The size of the cluster replica. Corresponds to `mz_cluster_replica_sizes.size`.",
7506 ),
7507 (
7508 "cluster_id",
7509 "The ID of the cluster associated with the replica.",
7510 ),
7511 (
7512 "cluster_name",
7513 "The name of the cluster associated with the replica.",
7514 ),
7515 ("replica_name", "The name of the replica."),
7516 ("created_at", "The time at which the replica was created."),
7517 (
7518 "dropped_at",
7519 "The time at which the replica was dropped, or `NULL` if it still exists.",
7520 ),
7521 (
7522 "credits_per_hour",
7523 "The number of compute credits consumed per hour. Corresponds to `mz_cluster_replica_sizes.credits_per_hour`.",
7524 ),
7525 ]),
7526 sql: r#"
7527 WITH
7528 creates AS
7529 (
7530 SELECT
7531 details ->> 'logical_size' AS size,
7532 details ->> 'replica_id' AS replica_id,
7533 details ->> 'replica_name' AS replica_name,
7534 details ->> 'cluster_name' AS cluster_name,
7535 details ->> 'cluster_id' AS cluster_id,
7536 occurred_at
7537 FROM mz_catalog.mz_audit_events
7538 WHERE
7539 object_type = 'cluster-replica' AND event_type = 'create'
7540 AND
7541 details ->> 'replica_id' IS NOT NULL
7542 AND
7543 details ->> 'cluster_id' !~~ 's%'
7544 ),
7545 drops AS
7546 (
7547 SELECT details ->> 'replica_id' AS replica_id, occurred_at
7548 FROM mz_catalog.mz_audit_events
7549 WHERE object_type = 'cluster-replica' AND event_type = 'drop'
7550 )
7551 SELECT
7552 creates.replica_id,
7553 creates.size,
7554 creates.cluster_id,
7555 creates.cluster_name,
7556 creates.replica_name,
7557 creates.occurred_at AS created_at,
7558 drops.occurred_at AS dropped_at,
7559 mz_cluster_replica_sizes.credits_per_hour as credits_per_hour
7560 FROM
7561 creates
7562 LEFT JOIN drops ON creates.replica_id = drops.replica_id
7563 LEFT JOIN
7564 mz_catalog.mz_cluster_replica_sizes
7565 ON mz_cluster_replica_sizes.size = creates.size"#,
7566 access: vec![PUBLIC_SELECT],
7567 ontology: Some(Ontology {
7568 entity_name: "replica_history",
7569 description: "Historical record of replica creation/drops",
7570 links: &const { [] },
7571 column_semantic_types: &[],
7572 }),
7573});
7574
7575pub static MZ_CLUSTER_REPLICA_NAME_HISTORY: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
7576 name: "mz_cluster_replica_name_history",
7577 schema: MZ_INTERNAL_SCHEMA,
7578 oid: oid::VIEW_MZ_CLUSTER_REPLICA_NAME_HISTORY_OID,
7579 desc: RelationDesc::builder()
7580 .with_column(
7581 "occurred_at",
7582 SqlScalarType::TimestampTz { precision: None }.nullable(true),
7583 )
7584 .with_column("id", SqlScalarType::String.nullable(true))
7585 .with_column("previous_name", SqlScalarType::String.nullable(true))
7586 .with_column("new_name", SqlScalarType::String.nullable(true))
7587 .finish(),
7588 column_comments: BTreeMap::from_iter([
7589 (
7590 "occurred_at",
7591 "The time at which the cluster replica was created or renamed. `NULL` if it's a built in system cluster replica.",
7592 ),
7593 ("id", "The ID of the cluster replica."),
7594 (
7595 "previous_name",
7596 "The previous name of the cluster replica. `NULL` if there was no previous name.",
7597 ),
7598 ("new_name", "The new name of the cluster replica."),
7599 ]),
7600 sql: r#"WITH user_replica_alter_history AS (
7601 SELECT occurred_at,
7602 audit_events.details->>'replica_id' AS id,
7603 audit_events.details->>'old_name' AS previous_name,
7604 audit_events.details->>'new_name' AS new_name
7605 FROM mz_catalog.mz_audit_events AS audit_events
7606 WHERE object_type = 'cluster-replica'
7607 AND audit_events.event_type = 'alter'
7608 AND audit_events.details->>'replica_id' like 'u%'
7609),
7610user_replica_create_history AS (
7611 SELECT occurred_at,
7612 audit_events.details->>'replica_id' AS id,
7613 NULL AS previous_name,
7614 audit_events.details->>'replica_name' AS new_name
7615 FROM mz_catalog.mz_audit_events AS audit_events
7616 WHERE object_type = 'cluster-replica'
7617 AND audit_events.event_type = 'create'
7618 AND audit_events.details->>'replica_id' like 'u%'
7619),
7620-- Because built in system cluster replicas don't have audit events, we need to manually add them
7621system_replicas AS (
7622 -- We assume that the system cluster replicas were created at the beginning of time
7623 SELECT NULL::timestamptz AS occurred_at,
7624 id,
7625 NULL AS previous_name,
7626 name AS new_name
7627 FROM mz_catalog.mz_cluster_replicas
7628 WHERE id LIKE 's%'
7629)
7630SELECT *
7631FROM user_replica_alter_history
7632UNION ALL
7633SELECT *
7634FROM user_replica_create_history
7635UNION ALL
7636SELECT *
7637FROM system_replicas"#,
7638 access: vec![PUBLIC_SELECT],
7639 ontology: Some(Ontology {
7640 entity_name: "replica_name_history",
7641 description: "Historical replica names",
7642 links: &const { [] },
7643 column_semantic_types: &[("id", SemanticType::CatalogItemId)],
7644 }),
7645});
7646
7647pub static MZ_HYDRATION_STATUSES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
7648 name: "mz_hydration_statuses",
7649 schema: MZ_INTERNAL_SCHEMA,
7650 oid: oid::VIEW_MZ_HYDRATION_STATUSES_OID,
7651 desc: RelationDesc::builder()
7652 .with_column("object_id", SqlScalarType::String.nullable(false))
7653 .with_column("replica_id", SqlScalarType::String.nullable(true))
7654 .with_column("hydrated", SqlScalarType::Bool.nullable(true))
7655 .finish(),
7656 column_comments: BTreeMap::from_iter([
7657 (
7658 "object_id",
7659 "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`.",
7660 ),
7661 ("replica_id", "The ID of a cluster replica."),
7662 ("hydrated", "Whether the object is hydrated on the replica."),
7663 ]),
7664 sql: r#"WITH
7665-- Joining against the linearizable catalog tables ensures that this view
7666-- always contains the set of installed objects, even when it depends
7667-- on introspection relations that may received delayed updates.
7668--
7669-- Note that this view only includes objects that are maintained by dataflows.
7670-- In particular, some source types (webhook, introspection, ...) are not and
7671-- are therefore omitted.
7672indexes AS (
7673 SELECT
7674 i.id AS object_id,
7675 h.replica_id,
7676 COALESCE(h.hydrated, false) AS hydrated
7677 FROM mz_catalog.mz_indexes i
7678 LEFT JOIN mz_internal.mz_compute_hydration_statuses h
7679 ON (h.object_id = i.id)
7680),
7681materialized_views AS (
7682 SELECT
7683 i.id AS object_id,
7684 h.replica_id,
7685 COALESCE(h.hydrated, false) AS hydrated
7686 FROM mz_catalog.mz_materialized_views i
7687 LEFT JOIN mz_internal.mz_compute_hydration_statuses h
7688 ON (h.object_id = i.id)
7689),
7690-- Hydration is a dataflow concept and not all sources are maintained by
7691-- dataflows, so we need to find the ones that are. Generally, sources that
7692-- have a cluster ID are maintained by a dataflow running on that cluster.
7693-- Webhook sources are an exception to this rule.
7694sources_with_clusters AS (
7695 SELECT id, cluster_id
7696 FROM mz_catalog.mz_sources
7697 WHERE cluster_id IS NOT NULL AND type != 'webhook'
7698),
7699sources AS (
7700 SELECT
7701 s.id AS object_id,
7702 ss.replica_id AS replica_id,
7703 ss.rehydration_latency IS NOT NULL AS hydrated
7704 FROM sources_with_clusters s
7705 LEFT JOIN mz_internal.mz_source_statistics ss USING (id)
7706),
7707-- We don't yet report sink hydration status (database-issues#8331), so we do a best effort attempt here and
7708-- define a sink as hydrated when it's both "running" and has a frontier greater than the minimum.
7709-- There is likely still a possibility of FPs.
7710sinks AS (
7711 SELECT
7712 s.id AS object_id,
7713 r.id AS replica_id,
7714 ss.status = 'running' AND COALESCE(f.write_frontier, 0) > 0 AS hydrated
7715 FROM mz_catalog.mz_sinks s
7716 LEFT JOIN mz_internal.mz_sink_statuses ss USING (id)
7717 JOIN mz_catalog.mz_cluster_replicas r
7718 ON (r.cluster_id = s.cluster_id)
7719 LEFT JOIN mz_catalog.mz_cluster_replica_frontiers f
7720 ON (f.object_id = s.id AND f.replica_id = r.id)
7721)
7722SELECT * FROM indexes
7723UNION ALL
7724SELECT * FROM materialized_views
7725UNION ALL
7726SELECT * FROM sources
7727UNION ALL
7728SELECT * FROM sinks"#,
7729 access: vec![PUBLIC_SELECT],
7730 ontology: Some(Ontology {
7731 entity_name: "hydration_status",
7732 description: "Overall hydration status per object",
7733 links: &const {
7734 [
7735 OntologyLink {
7736 name: "hydration_of",
7737 target: "object",
7738 properties: LinkProperties::fk_typed(
7739 "object_id",
7740 "id",
7741 Cardinality::OneToOne,
7742 mz_repr::SemanticType::CatalogItemId,
7743 ),
7744 },
7745 OntologyLink {
7746 name: "hydration_on_replica",
7747 target: "replica",
7748 properties: LinkProperties::fk("replica_id", "id", Cardinality::ManyToOne),
7749 },
7750 ]
7751 },
7752 column_semantic_types: &const {
7753 [
7754 ("object_id", SemanticType::CatalogItemId),
7755 ("replica_id", SemanticType::ReplicaId),
7756 ]
7757 },
7758 }),
7759});
7760
7761pub const MZ_HYDRATION_STATUSES_IND: BuiltinIndex = BuiltinIndex {
7762 name: "mz_hydration_statuses_ind",
7763 schema: MZ_INTERNAL_SCHEMA,
7764 oid: oid::INDEX_MZ_HYDRATION_STATUSES_IND_OID,
7765 sql: "IN CLUSTER mz_catalog_server
7766ON mz_internal.mz_hydration_statuses (object_id, replica_id)",
7767 is_retained_metrics_object: false,
7768};
7769
7770pub static MZ_MATERIALIZATION_DEPENDENCIES: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
7771 name: "mz_materialization_dependencies",
7772 schema: MZ_INTERNAL_SCHEMA,
7773 oid: oid::VIEW_MZ_MATERIALIZATION_DEPENDENCIES_OID,
7774 desc: RelationDesc::builder()
7775 .with_column("object_id", SqlScalarType::String.nullable(false))
7776 .with_column("dependency_id", SqlScalarType::String.nullable(false))
7777 .finish(),
7778 column_comments: BTreeMap::from_iter([
7779 (
7780 "object_id",
7781 "The ID of a materialization. Corresponds to `mz_catalog.mz_indexes.id`, `mz_catalog.mz_materialized_views.id`, or `mz_catalog.mz_sinks.id`.",
7782 ),
7783 (
7784 "dependency_id",
7785 "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`.",
7786 ),
7787 ]),
7788 sql: "
7789SELECT object_id, dependency_id
7790FROM mz_internal.mz_compute_dependencies
7791UNION ALL
7792SELECT s.id, d.referenced_object_id AS dependency_id
7793FROM mz_internal.mz_object_dependencies d
7794JOIN mz_catalog.mz_sinks s ON (s.id = d.object_id)
7795JOIN mz_catalog.mz_relations r ON (r.id = d.referenced_object_id)",
7796 access: vec![PUBLIC_SELECT],
7797 ontology: Some(Ontology {
7798 entity_name: "materialization_dep",
7799 description: "Dependencies between materializations",
7800 links: &const {
7801 [
7802 OntologyLink {
7803 name: "depends_on",
7804 target: "object",
7805 properties: LinkProperties::DependsOn {
7806 source_column: "object_id",
7807 target_column: "id",
7808 source_id_type: Some(mz_repr::SemanticType::CatalogItemId),
7809 requires_mapping: None,
7810 },
7811 },
7812 OntologyLink {
7813 name: "dependency_is",
7814 target: "object",
7815 properties: LinkProperties::fk("dependency_id", "id", Cardinality::ManyToOne),
7816 },
7817 ]
7818 },
7819 column_semantic_types: &const {
7820 [
7821 ("object_id", SemanticType::CatalogItemId),
7822 ("dependency_id", SemanticType::CatalogItemId),
7823 ]
7824 },
7825 }),
7826});
7827
7828pub static MZ_MATERIALIZATION_LAG: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
7829 name: "mz_materialization_lag",
7830 schema: MZ_INTERNAL_SCHEMA,
7831 oid: oid::VIEW_MZ_MATERIALIZATION_LAG_OID,
7832 desc: RelationDesc::builder()
7833 .with_column("object_id", SqlScalarType::String.nullable(false))
7834 .with_column("local_lag", SqlScalarType::Interval.nullable(true))
7835 .with_column("global_lag", SqlScalarType::Interval.nullable(true))
7836 .with_column(
7837 "slowest_local_input_id",
7838 SqlScalarType::String.nullable(false),
7839 )
7840 .with_column(
7841 "slowest_global_input_id",
7842 SqlScalarType::String.nullable(false),
7843 )
7844 .finish(),
7845 column_comments: BTreeMap::from_iter([
7846 (
7847 "object_id",
7848 "The ID of the materialized view, index, or sink.",
7849 ),
7850 (
7851 "local_lag",
7852 "The amount of time the materialization lags behind its direct inputs.",
7853 ),
7854 (
7855 "global_lag",
7856 "The amount of time the materialization lags behind its root inputs (sources and tables).",
7857 ),
7858 (
7859 "slowest_local_input_id",
7860 "The ID of the slowest direct input.",
7861 ),
7862 (
7863 "slowest_global_input_id",
7864 "The ID of the slowest root input.",
7865 ),
7866 ]),
7867 sql: "
7868WITH MUTUALLY RECURSIVE
7869 -- IDs of objects for which we want to know the lag.
7870 materializations (id text) AS (
7871 SELECT id FROM mz_catalog.mz_indexes
7872 UNION ALL
7873 SELECT id FROM mz_catalog.mz_materialized_views
7874 UNION ALL
7875 SELECT id FROM mz_catalog.mz_sinks
7876 ),
7877 -- Direct dependencies of materializations.
7878 direct_dependencies (id text, dep_id text) AS (
7879 SELECT m.id, d.dependency_id
7880 FROM materializations m
7881 JOIN mz_internal.mz_materialization_dependencies d ON (m.id = d.object_id)
7882 ),
7883 -- All transitive dependencies of materializations.
7884 transitive_dependencies (id text, dep_id text) AS (
7885 SELECT id, dep_id FROM direct_dependencies
7886 UNION
7887 SELECT td.id, dd.dep_id
7888 FROM transitive_dependencies td
7889 JOIN direct_dependencies dd ON (dd.id = td.dep_id)
7890 ),
7891 -- Root dependencies of materializations (sources and tables).
7892 root_dependencies (id text, dep_id text) AS (
7893 SELECT *
7894 FROM transitive_dependencies td
7895 WHERE NOT EXISTS (
7896 SELECT 1
7897 FROM direct_dependencies dd
7898 WHERE dd.id = td.dep_id
7899 )
7900 ),
7901 -- Write progress times of materializations.
7902 materialization_times (id text, time timestamptz) AS (
7903 SELECT m.id, to_timestamp(f.write_frontier::text::double / 1000)
7904 FROM materializations m
7905 JOIN mz_internal.mz_frontiers f ON (m.id = f.object_id)
7906 ),
7907 -- Write progress times of direct dependencies of materializations.
7908 input_times (id text, slowest_dep text, time timestamptz) AS (
7909 SELECT DISTINCT ON (d.id)
7910 d.id,
7911 d.dep_id,
7912 to_timestamp(f.write_frontier::text::double / 1000)
7913 FROM direct_dependencies d
7914 JOIN mz_internal.mz_frontiers f ON (d.dep_id = f.object_id)
7915 ORDER BY d.id, f.write_frontier ASC
7916 ),
7917 -- Write progress times of root dependencies of materializations.
7918 root_times (id text, slowest_dep text, time timestamptz) AS (
7919 SELECT DISTINCT ON (d.id)
7920 d.id,
7921 d.dep_id,
7922 to_timestamp(f.write_frontier::text::double / 1000)
7923 FROM root_dependencies d
7924 JOIN mz_internal.mz_frontiers f ON (d.dep_id = f.object_id)
7925 ORDER BY d.id, f.write_frontier ASC
7926 )
7927SELECT
7928 id AS object_id,
7929 -- Ensure that lag values are always NULL for materializations that have reached the empty
7930 -- frontier, as those have processed all their input data.
7931 -- Also make sure that lag values are never negative, even when input frontiers are before
7932 -- output frontiers (as can happen during hydration).
7933 CASE
7934 WHEN m.time IS NULL THEN INTERVAL '0'
7935 WHEN i.time IS NULL THEN NULL
7936 ELSE greatest(i.time - m.time, INTERVAL '0')
7937 END AS local_lag,
7938 CASE
7939 WHEN m.time IS NULL THEN INTERVAL '0'
7940 WHEN r.time IS NULL THEN NULL
7941 ELSE greatest(r.time - m.time, INTERVAL '0')
7942 END AS global_lag,
7943 i.slowest_dep AS slowest_local_input_id,
7944 r.slowest_dep AS slowest_global_input_id
7945FROM materialization_times m
7946JOIN input_times i USING (id)
7947JOIN root_times r USING (id)",
7948 access: vec![PUBLIC_SELECT],
7949 ontology: Some(Ontology {
7950 entity_name: "materialization_lag",
7951 description: "Lag between a materialization and its inputs",
7952 links: &const {
7953 [
7954 OntologyLink {
7955 name: "measures_materialization_lag",
7956 target: "object",
7957 properties: LinkProperties::measures("object_id", "id", "materialization_lag"),
7958 },
7959 OntologyLink {
7960 name: "slowest_local_input",
7961 target: "object",
7962 properties: LinkProperties::fk(
7963 "slowest_local_input_id",
7964 "id",
7965 Cardinality::ManyToOne,
7966 ),
7967 },
7968 OntologyLink {
7969 name: "slowest_global_input",
7970 target: "object",
7971 properties: LinkProperties::fk(
7972 "slowest_global_input_id",
7973 "id",
7974 Cardinality::ManyToOne,
7975 ),
7976 },
7977 ]
7978 },
7979 column_semantic_types: &const {
7980 [
7981 ("object_id", SemanticType::CatalogItemId),
7982 ("slowest_local_input_id", SemanticType::CatalogItemId),
7983 ("slowest_global_input_id", SemanticType::CatalogItemId),
7984 ]
7985 },
7986 }),
7987});
7988const CONSOLE_MEMORY_SHARES_SQL: &str = "\
8013 MAX(m.memory_bytes::float8) / NULLIF(s.memory_bytes, 0) AS ram_percent,
8014 MAX(m.swap_bytes::float8) / NULLIF(s.memory_bytes, 0) AS swap_of_ram_percent,
8015 MAX(m.heap_limit::float8) / NULLIF(s.memory_bytes, 0) AS heap_limit_percent";
8016
8017fn console_cluster_utilization_overview_desc() -> RelationDesc {
8021 RelationDesc::builder()
8022 .with_column(
8023 "bucket_start",
8024 SqlScalarType::TimestampTz { precision: None }.nullable(false),
8025 )
8026 .with_column("replica_id", SqlScalarType::String.nullable(false))
8027 .with_column("memory_percent", SqlScalarType::Float64.nullable(true))
8028 .with_column(
8029 "max_memory_at",
8030 SqlScalarType::TimestampTz { precision: None }.nullable(false),
8031 )
8032 .with_column("disk_percent", SqlScalarType::Float64.nullable(true))
8033 .with_column(
8034 "max_disk_at",
8035 SqlScalarType::TimestampTz { precision: None }.nullable(false),
8036 )
8037 .with_column(
8038 "memory_and_disk_percent",
8039 SqlScalarType::Float64.nullable(true),
8040 )
8041 .with_column(
8042 "max_memory_and_disk_memory_percent",
8043 SqlScalarType::Float64.nullable(true),
8044 )
8045 .with_column(
8046 "max_memory_and_disk_disk_percent",
8047 SqlScalarType::Float64.nullable(true),
8048 )
8049 .with_column(
8050 "max_memory_and_disk_at",
8051 SqlScalarType::TimestampTz { precision: None }.nullable(false),
8052 )
8053 .with_column("heap_percent", SqlScalarType::Float64.nullable(true))
8054 .with_column(
8055 "max_heap_at",
8056 SqlScalarType::TimestampTz { precision: None }.nullable(false),
8057 )
8058 .with_column("ram_percent", SqlScalarType::Float64.nullable(true))
8059 .with_column("swap_of_ram_percent", SqlScalarType::Float64.nullable(true))
8060 .with_column("heap_limit_percent", SqlScalarType::Float64.nullable(true))
8061 .with_column("max_cpu_percent", SqlScalarType::Float64.nullable(true))
8062 .with_column(
8063 "max_cpu_at",
8064 SqlScalarType::TimestampTz { precision: None }.nullable(false),
8065 )
8066 .with_column("offline_events", SqlScalarType::Jsonb.nullable(true))
8067 .with_column(
8068 "bucket_end",
8069 SqlScalarType::TimestampTz { precision: None }.nullable(false),
8070 )
8071 .with_column("name", SqlScalarType::String.nullable(true))
8072 .with_column("cluster_id", SqlScalarType::String.nullable(true))
8073 .with_column("size", SqlScalarType::String.nullable(true))
8074 .finish()
8075}
8076
8077fn console_cluster_utilization_overview_sql(bin: &str, retention: &str, group_size: u32) -> String {
8094 format!(
8095 r#"WITH replica_history AS (
8096 SELECT replica_id, size, cluster_id
8097 FROM mz_internal.mz_cluster_replica_history
8098 UNION
8099 -- We union the current set of cluster replicas since mz_cluster_replica_history doesn't include system clusters.
8100 SELECT id AS replica_id, size, cluster_id
8101 FROM mz_catalog.mz_cluster_replicas
8102),
8103replica_metrics_history AS (
8104 SELECT
8105 m.occurred_at,
8106 m.replica_id,
8107 r.size,
8108 (SUM(m.cpu_nano_cores::float8) / NULLIF(s.cpu_nano_cores, 0) / NULLIF(s.processes, 0)) AS cpu_percent,
8109 (SUM(m.memory_bytes::float8) / NULLIF(s.memory_bytes, 0) / NULLIF(s.processes, 0)) AS memory_percent,
8110 (SUM(m.disk_bytes::float8) / NULLIF(s.disk_bytes, 0) / NULLIF(s.processes, 0)) AS disk_percent,
8111 SUM(m.disk_bytes::float8) AS disk_bytes,
8112 SUM(m.memory_bytes::float8) AS memory_bytes,
8113 s.disk_bytes::float8 * s.processes AS total_disk_bytes,
8114 s.memory_bytes::float8 * s.processes AS total_memory_bytes,
8115 MAX(m.heap_bytes::float8) AS heap_bytes,
8116 MAX(m.heap_limit) AS heap_limit,
8117 -- heap_limit is NULL when clusterd isn't launched with --heap-limit (e.g.
8118 -- the emulator's process orchestrator). Fall back to the size-based memory
8119 -- percent so the chart still renders.
8120 COALESCE(
8121 MAX(m.heap_bytes::float8 / NULLIF(m.heap_limit, 0)),
8122 SUM(m.memory_bytes::float8) / NULLIF(s.memory_bytes, 0) / NULLIF(s.processes, 0)
8123 ) AS heap_percent,
8124{shares}
8125 FROM
8126 replica_history AS r
8127 INNER JOIN mz_catalog.mz_cluster_replica_sizes AS s ON r.size = s.size
8128 INNER JOIN mz_internal.mz_cluster_replica_metrics_history AS m ON m.replica_id = r.replica_id
8129 GROUP BY
8130 m.occurred_at,
8131 m.replica_id,
8132 r.size,
8133 s.cpu_nano_cores,
8134 s.memory_bytes,
8135 s.disk_bytes,
8136 s.processes
8137),
8138replica_utilization_history_binned AS (
8139 -- NOTE: we read directly from replica_metrics_history rather than re-joining
8140 -- replica_history; every replica_id here already came from replica_history,
8141 -- so the join was redundant (and could fan out a replica that changed size).
8142 SELECT
8143 m.occurred_at,
8144 m.replica_id,
8145 m.cpu_percent,
8146 m.memory_percent,
8147 m.memory_bytes,
8148 m.disk_percent,
8149 m.disk_bytes,
8150 m.total_disk_bytes,
8151 m.total_memory_bytes,
8152 m.heap_bytes,
8153 m.heap_percent,
8154 m.ram_percent,
8155 m.swap_of_ram_percent,
8156 m.heap_limit_percent,
8157 m.size,
8158 date_bin('{bin}', m.occurred_at, '1970-01-01'::timestamp) AS bucket_start
8159 FROM replica_metrics_history AS m
8160 WHERE mz_now() <= date_bin('{bin}', m.occurred_at, '1970-01-01'::timestamp) + INTERVAL '{retention}'
8161),
8162-- For each (replica, bucket), take the sample with the highest memory.
8163max_memory AS (
8164 SELECT DISTINCT ON (bucket_start, replica_id) bucket_start, replica_id, memory_percent, occurred_at
8165 FROM replica_utilization_history_binned
8166 OPTIONS (DISTINCT ON INPUT GROUP SIZE = {group_size})
8167 ORDER BY bucket_start, replica_id, COALESCE(memory_bytes, 0) DESC
8168),
8169-- For each (replica, bucket), take the sample with the highest disk.
8170max_disk AS (
8171 SELECT DISTINCT ON (bucket_start, replica_id) bucket_start, replica_id, disk_percent, occurred_at
8172 FROM replica_utilization_history_binned
8173 OPTIONS (DISTINCT ON INPUT GROUP SIZE = {group_size})
8174 ORDER BY bucket_start, replica_id, COALESCE(disk_bytes, 0) DESC
8175),
8176-- For each (replica, bucket), take the sample with the highest cpu.
8177max_cpu AS (
8178 SELECT DISTINCT ON (bucket_start, replica_id) bucket_start, replica_id, cpu_percent, occurred_at
8179 FROM replica_utilization_history_binned
8180 OPTIONS (DISTINCT ON INPUT GROUP SIZE = {group_size})
8181 ORDER BY bucket_start, replica_id, COALESCE(cpu_percent, 0) DESC
8182),
8183/*
8184 For each (replica, bucket), take the sample with the highest combined memory
8185 and disk. This is different from adding max_memory and max_disk per bucket
8186 because both values may not occur at the same time if the bucket interval is
8187 large.
8188*/
8189max_memory_and_disk AS (
8190 SELECT DISTINCT ON (bucket_start, replica_id) bucket_start, replica_id, memory_percent, disk_percent, memory_and_disk_percent, occurred_at
8191 FROM (
8192 SELECT *,
8193 CASE
8194 WHEN disk_bytes IS NULL AND memory_bytes IS NULL THEN NULL
8195 ELSE (COALESCE(memory_bytes, 0) + COALESCE(disk_bytes, 0)) / NULLIF((total_memory_bytes + total_disk_bytes), 0)
8196 END AS memory_and_disk_percent
8197 FROM replica_utilization_history_binned
8198 ) AS max_memory_and_disk_inner
8199 OPTIONS (DISTINCT ON INPUT GROUP SIZE = {group_size})
8200 ORDER BY bucket_start, replica_id, COALESCE(memory_and_disk_percent, 0) DESC
8201),
8202-- For each (replica, bucket), take the sample with the highest heap. The RAM
8203-- and swap shares ride along, so they describe that sample rather than the
8204-- bucket's peak RAM, which is what max_memory reports.
8205max_heap AS (
8206 SELECT DISTINCT ON (bucket_start, replica_id) bucket_start, replica_id, heap_percent, ram_percent, swap_of_ram_percent, heap_limit_percent, occurred_at
8207 FROM replica_utilization_history_binned
8208 OPTIONS (DISTINCT ON INPUT GROUP SIZE = {group_size})
8209 ORDER BY bucket_start, replica_id, COALESCE(heap_bytes, 0) DESC
8210),
8211-- For each (replica, bucket), collect its offline events at that time.
8212replica_offline_event_history AS (
8213 SELECT
8214 date_bin('{bin}', occurred_at, '1970-01-01'::timestamp) AS bucket_start,
8215 replica_id,
8216 jsonb_agg(
8217 jsonb_build_object(
8218 'replicaId', rsh.replica_id,
8219 'occurredAt', rsh.occurred_at,
8220 'status', rsh.status,
8221 'reason', rsh.reason
8222 )
8223 ) AS offline_events
8224 FROM mz_internal.mz_cluster_replica_status_history AS rsh
8225 -- We assume the statuses for process 0 are the same as all processes.
8226 WHERE process_id = '0'
8227 AND status = 'offline'
8228 AND mz_now() <= date_bin('{bin}', occurred_at, '1970-01-01'::timestamp) + INTERVAL '{retention}'
8229 GROUP BY bucket_start, replica_id
8230)
8231SELECT
8232 bucket_start,
8233 replica_id,
8234 max_memory.memory_percent,
8235 max_memory.occurred_at AS max_memory_at,
8236 max_disk.disk_percent,
8237 max_disk.occurred_at AS max_disk_at,
8238 max_memory_and_disk.memory_and_disk_percent AS memory_and_disk_percent,
8239 max_memory_and_disk.memory_percent AS max_memory_and_disk_memory_percent,
8240 max_memory_and_disk.disk_percent AS max_memory_and_disk_disk_percent,
8241 max_memory_and_disk.occurred_at AS max_memory_and_disk_at,
8242 max_heap.heap_percent,
8243 max_heap.occurred_at AS max_heap_at,
8244 max_heap.ram_percent,
8245 max_heap.swap_of_ram_percent,
8246 max_heap.heap_limit_percent,
8247 max_cpu.cpu_percent AS max_cpu_percent,
8248 max_cpu.occurred_at AS max_cpu_at,
8249 replica_offline_event_history.offline_events,
8250 bucket_start + INTERVAL '{bin}' AS bucket_end,
8251 replica_name_history.new_name AS name,
8252 replica_history.cluster_id,
8253 replica_history.size
8254FROM max_memory
8255JOIN max_disk USING (bucket_start, replica_id)
8256JOIN max_cpu USING (bucket_start, replica_id)
8257JOIN max_memory_and_disk USING (bucket_start, replica_id)
8258JOIN max_heap USING (bucket_start, replica_id)
8259JOIN replica_history USING (replica_id)
8260/*
8261 TOP k=1 over the name history via a LATERAL subquery + LIMIT: for each bucket,
8262 get the most recent replica name as of the end of the bucket.
8263*/
8264CROSS JOIN LATERAL (
8265 SELECT new_name
8266 FROM mz_internal.mz_cluster_replica_name_history AS replica_name_history
8267 WHERE replica_id = replica_name_history.id
8268 -- We treat NULLs as the beginning of time.
8269 AND bucket_start + INTERVAL '{bin}' >= COALESCE(replica_name_history.occurred_at, '1970-01-01'::timestamp)
8270 ORDER BY replica_name_history.occurred_at DESC
8271 LIMIT 1
8272) AS replica_name_history
8273LEFT JOIN replica_offline_event_history USING (bucket_start, replica_id)"#,
8274 bin = bin,
8275 retention = retention,
8276 group_size = group_size,
8277 shares = CONSOLE_MEMORY_SHARES_SQL,
8278 )
8279}
8280
8281fn console_cluster_utilization_unbinned_3h_desc() -> RelationDesc {
8285 RelationDesc::builder()
8286 .with_column("replica_id", SqlScalarType::String.nullable(false))
8287 .with_column("cluster_id", SqlScalarType::String.nullable(true))
8288 .with_column("size", SqlScalarType::String.nullable(false))
8289 .with_column("name", SqlScalarType::String.nullable(true))
8290 .with_column(
8291 "occurred_at",
8292 SqlScalarType::TimestampTz { precision: None }.nullable(false),
8293 )
8294 .with_column("cpu_percent", SqlScalarType::Float64.nullable(true))
8295 .with_column("memory_percent", SqlScalarType::Float64.nullable(true))
8296 .with_column("disk_percent", SqlScalarType::Float64.nullable(true))
8297 .with_column("heap_percent", SqlScalarType::Float64.nullable(true))
8298 .with_column("ram_percent", SqlScalarType::Float64.nullable(true))
8299 .with_column("swap_of_ram_percent", SqlScalarType::Float64.nullable(true))
8300 .with_column("heap_limit_percent", SqlScalarType::Float64.nullable(true))
8301 .with_column(
8302 "memory_and_disk_percent",
8303 SqlScalarType::Float64.nullable(true),
8304 )
8305 .finish()
8306}
8307
8308fn console_cluster_utilization_unbinned_3h_sql(retention: &str) -> String {
8316 format!(
8317 r#"WITH replica_history AS (
8318 -- Dedup to one row per replica (prefer the current size). Size is fixed per
8319 -- replica so this is normally a no-op, but a stray duplicate size in history
8320 -- would fan out the metrics join; with no Top-1 dedup here that would emit two
8321 -- rows per (replica_id, occurred_at) and break the Console SUBSCRIBE upsert key.
8322 SELECT DISTINCT ON (replica_id) replica_id, size, cluster_id
8323 FROM (
8324 -- We union the current set of cluster replicas since mz_cluster_replica_history doesn't include system clusters.
8325 SELECT id AS replica_id, size, cluster_id, 0 AS source_rank
8326 FROM mz_catalog.mz_cluster_replicas
8327 UNION ALL
8328 SELECT replica_id, size, cluster_id, 1 AS source_rank
8329 FROM mz_internal.mz_cluster_replica_history
8330 ) all_replicas
8331 ORDER BY replica_id, source_rank
8332),
8333replica_metrics AS (
8334 SELECT
8335 m.occurred_at,
8336 m.replica_id,
8337 r.cluster_id,
8338 r.size,
8339 (SUM(m.cpu_nano_cores::float8) / NULLIF(s.cpu_nano_cores, 0) / NULLIF(s.processes, 0)) AS cpu_percent,
8340 (SUM(m.memory_bytes::float8) / NULLIF(s.memory_bytes, 0) / NULLIF(s.processes, 0)) AS memory_percent,
8341 (SUM(m.disk_bytes::float8) / NULLIF(s.disk_bytes, 0) / NULLIF(s.processes, 0)) AS disk_percent,
8342 COALESCE(
8343 MAX(m.heap_bytes::float8 / NULLIF(m.heap_limit, 0)),
8344 SUM(m.memory_bytes::float8) / NULLIF(s.memory_bytes, 0) / NULLIF(s.processes, 0)
8345 ) AS heap_percent,
8346{shares},
8347 CASE
8348 WHEN SUM(m.disk_bytes::float8) IS NULL AND SUM(m.memory_bytes::float8) IS NULL THEN NULL
8349 ELSE (COALESCE(SUM(m.memory_bytes::float8), 0) + COALESCE(SUM(m.disk_bytes::float8), 0))
8350 / NULLIF((s.memory_bytes::float8 + s.disk_bytes::float8) * s.processes, 0)
8351 END AS memory_and_disk_percent
8352 FROM replica_history AS r
8353 INNER JOIN mz_catalog.mz_cluster_replica_sizes AS s ON r.size = s.size
8354 INNER JOIN mz_internal.mz_cluster_replica_metrics_history AS m ON m.replica_id = r.replica_id
8355 -- No aggregation over time: one row per (replica, sample) so the Console bins
8356 -- client-side. The temporal mz_now() filter keeps the maintained arrangement
8357 -- bounded to the retention window.
8358 WHERE mz_now() <= m.occurred_at + INTERVAL '{retention}'
8359 GROUP BY
8360 m.occurred_at,
8361 m.replica_id,
8362 r.cluster_id,
8363 r.size,
8364 s.cpu_nano_cores,
8365 s.memory_bytes,
8366 s.disk_bytes,
8367 s.processes
8368)
8369SELECT
8370 m.replica_id,
8371 m.cluster_id,
8372 m.size,
8373 replica_name_history.new_name AS name,
8374 m.occurred_at,
8375 m.cpu_percent,
8376 m.memory_percent,
8377 m.disk_percent,
8378 m.heap_percent,
8379 m.ram_percent,
8380 m.swap_of_ram_percent,
8381 m.heap_limit_percent,
8382 m.memory_and_disk_percent
8383FROM replica_metrics AS m
8384/* Most recent replica name as of the sample time. */
8385CROSS JOIN LATERAL (
8386 SELECT new_name
8387 FROM mz_internal.mz_cluster_replica_name_history AS replica_name_history
8388 WHERE m.replica_id = replica_name_history.id
8389 -- We treat NULLs as the beginning of time.
8390 AND m.occurred_at >= COALESCE(replica_name_history.occurred_at, '1970-01-01'::timestamp)
8391 ORDER BY replica_name_history.occurred_at DESC
8392 LIMIT 1
8393) AS replica_name_history"#,
8394 retention = retention,
8395 shares = CONSOLE_MEMORY_SHARES_SQL,
8396 )
8397}
8398
8399pub static MZ_CONSOLE_CLUSTER_UTILIZATION_OVERVIEW: LazyLock<BuiltinView> =
8406 LazyLock::new(|| BuiltinView {
8407 name: "mz_console_cluster_utilization_overview",
8408 schema: MZ_INTERNAL_SCHEMA,
8409 oid: oid::VIEW_MZ_CONSOLE_CLUSTER_UTILIZATION_OVERVIEW_OID,
8410 desc: console_cluster_utilization_overview_desc(),
8411 column_comments: BTreeMap::new(),
8412 sql: Box::leak(
8413 console_cluster_utilization_overview_sql("1 HOUR", "14 DAYS", 60).into_boxed_str(),
8414 ),
8415 access: vec![PUBLIC_SELECT],
8416 ontology: None,
8417 });
8418
8419pub static MZ_CONSOLE_CLUSTER_UTILIZATION_OVERVIEW_3H: LazyLock<BuiltinView> =
8426 LazyLock::new(|| BuiltinView {
8427 name: "mz_console_cluster_utilization_overview_3h",
8428 schema: MZ_INTERNAL_SCHEMA,
8429 oid: oid::VIEW_MZ_CONSOLE_CLUSTER_UTILIZATION_OVERVIEW_3H_OID,
8430 desc: console_cluster_utilization_unbinned_3h_desc(),
8431 column_comments: BTreeMap::new(),
8432 sql: Box::leak(console_cluster_utilization_unbinned_3h_sql("3 HOURS").into_boxed_str()),
8433 access: vec![PUBLIC_SELECT],
8434 ontology: None,
8435 });
8436
8437pub static MZ_CONSOLE_CLUSTER_UTILIZATION_OVERVIEW_24H: LazyLock<BuiltinView> =
8443 LazyLock::new(|| BuiltinView {
8444 name: "mz_console_cluster_utilization_overview_24h",
8445 schema: MZ_INTERNAL_SCHEMA,
8446 oid: oid::VIEW_MZ_CONSOLE_CLUSTER_UTILIZATION_OVERVIEW_24H_OID,
8447 desc: console_cluster_utilization_overview_desc(),
8448 column_comments: BTreeMap::new(),
8449 sql: Box::leak(
8450 console_cluster_utilization_overview_sql("5 MINUTES", "24 HOURS", 5).into_boxed_str(),
8451 ),
8452 access: vec![PUBLIC_SELECT],
8453 ontology: None,
8454 });
8455pub static MZ_CLUSTER_DEPLOYMENT_LINEAGE: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
8477 name: "mz_cluster_deployment_lineage",
8478 schema: MZ_INTERNAL_SCHEMA,
8479 oid: oid::VIEW_MZ_CLUSTER_DEPLOYMENT_LINEAGE_OID,
8480 desc: RelationDesc::builder()
8481 .with_column("cluster_id", SqlScalarType::String.nullable(true))
8482 .with_column(
8483 "current_deployment_cluster_id",
8484 SqlScalarType::String.nullable(false),
8485 )
8486 .with_column("cluster_name", SqlScalarType::String.nullable(false))
8487 .with_key(vec![0, 1, 2])
8488 .finish(),
8489 column_comments: BTreeMap::from_iter([
8490 (
8491 "cluster_id",
8492 "The ID of the cluster. Corresponds to `mz_clusters.id` (though the cluster may no longer exist).",
8493 ),
8494 (
8495 "current_deployment_cluster_id",
8496 "The cluster ID of the last cluster in `cluster_id`'s blue/green lineage (the cluster is guaranteed to exist).",
8497 ),
8498 ("cluster_name", "The name of the cluster"),
8499 ]),
8500 sql: r#"WITH MUTUALLY RECURSIVE cluster_events (
8501 cluster_id text,
8502 cluster_name text,
8503 event_type text,
8504 occurred_at timestamptz
8505) AS (
8506 SELECT coalesce(details->>'id', details->>'cluster_id') AS cluster_id,
8507 coalesce(details->>'name', details->>'new_name') AS cluster_name,
8508 event_type,
8509 occurred_at
8510 FROM mz_audit_events
8511 WHERE (
8512 event_type IN ('create', 'drop')
8513 OR (
8514 event_type = 'alter'
8515 AND details ? 'new_name'
8516 )
8517 )
8518 AND object_type = 'cluster'
8519 AND mz_now() < occurred_at + INTERVAL '30 days'
8520),
8521mz_cluster_deployment_lineage (
8522 cluster_id text,
8523 current_deployment_cluster_id text,
8524 cluster_name text
8525) AS (
8526 SELECT c.id,
8527 c.id,
8528 c.name
8529 FROM mz_clusters c
8530 WHERE c.id LIKE 'u%'
8531 UNION
8532 SELECT *
8533 FROM dropped_clusters
8534),
8535-- Closest create or rename event based on the current clusters in the result set
8536most_recent_create_or_rename (
8537 cluster_id text,
8538 current_deployment_cluster_id text,
8539 cluster_name text,
8540 occurred_at timestamptz
8541) AS (
8542 SELECT DISTINCT ON (e.cluster_id) e.cluster_id,
8543 c.current_deployment_cluster_id,
8544 e.cluster_name,
8545 e.occurred_at
8546 FROM mz_cluster_deployment_lineage c
8547 JOIN cluster_events e ON c.cluster_id = e.cluster_id
8548 AND c.cluster_name = e.cluster_name
8549 WHERE e.event_type <> 'drop'
8550 ORDER BY e.cluster_id,
8551 e.occurred_at DESC
8552),
8553-- Clusters that were dropped most recently within 1 minute of most_recent_create_or_rename
8554dropped_clusters (
8555 cluster_id text,
8556 current_deployment_cluster_id text,
8557 cluster_name text
8558) AS (
8559 SELECT DISTINCT ON (cr.cluster_id) e.cluster_id,
8560 cr.current_deployment_cluster_id,
8561 cr.cluster_name
8562 FROM most_recent_create_or_rename cr
8563 JOIN cluster_events e ON e.occurred_at BETWEEN cr.occurred_at - interval '1 minute'
8564 AND cr.occurred_at + interval '1 minute'
8565 AND (
8566 e.cluster_name = cr.cluster_name
8567 OR e.cluster_name = cr.cluster_name || '_dbt_deploy'
8568 )
8569 WHERE e.event_type = 'drop'
8570 ORDER BY cr.cluster_id,
8571 abs(
8572 extract(
8573 epoch
8574 FROM cr.occurred_at - e.occurred_at
8575 )
8576 )
8577)
8578SELECT *
8579FROM mz_cluster_deployment_lineage"#,
8580 access: vec![PUBLIC_SELECT],
8581 ontology: Some(Ontology {
8582 entity_name: "cluster_deployment",
8583 description: "Cluster deployment lineage information",
8584 links: &const {
8585 [
8586 OntologyLink {
8587 name: "deployment_of",
8588 target: "cluster",
8589 properties: LinkProperties::fk("cluster_id", "id", Cardinality::ManyToOne),
8590 },
8591 OntologyLink {
8592 name: "current_deployment",
8593 target: "cluster",
8594 properties: LinkProperties::fk(
8595 "current_deployment_cluster_id",
8596 "id",
8597 Cardinality::ManyToOne,
8598 ),
8599 },
8600 ]
8601 },
8602 column_semantic_types: &[],
8603 }),
8604});
8605
8606pub const MZ_SHOW_DATABASES_IND: BuiltinIndex = BuiltinIndex {
8607 name: "mz_show_databases_ind",
8608 schema: MZ_INTERNAL_SCHEMA,
8609 oid: oid::INDEX_MZ_SHOW_DATABASES_IND_OID,
8610 sql: "IN CLUSTER mz_catalog_server
8611ON mz_internal.mz_show_databases (name)",
8612 is_retained_metrics_object: false,
8613};
8614
8615pub const MZ_SHOW_SCHEMAS_IND: BuiltinIndex = BuiltinIndex {
8616 name: "mz_show_schemas_ind",
8617 schema: MZ_INTERNAL_SCHEMA,
8618 oid: oid::INDEX_MZ_SHOW_SCHEMAS_IND_OID,
8619 sql: "IN CLUSTER mz_catalog_server
8620ON mz_internal.mz_show_schemas (database_id)",
8621 is_retained_metrics_object: false,
8622};
8623
8624pub const MZ_SHOW_CONNECTIONS_IND: BuiltinIndex = BuiltinIndex {
8625 name: "mz_show_connections_ind",
8626 schema: MZ_INTERNAL_SCHEMA,
8627 oid: oid::INDEX_MZ_SHOW_CONNECTIONS_IND_OID,
8628 sql: "IN CLUSTER mz_catalog_server
8629ON mz_internal.mz_show_connections (schema_id)",
8630 is_retained_metrics_object: false,
8631};
8632
8633pub const MZ_SHOW_TABLES_IND: BuiltinIndex = BuiltinIndex {
8634 name: "mz_show_tables_ind",
8635 schema: MZ_INTERNAL_SCHEMA,
8636 oid: oid::INDEX_MZ_SHOW_TABLES_IND_OID,
8637 sql: "IN CLUSTER mz_catalog_server
8638ON mz_internal.mz_show_tables (schema_id)",
8639 is_retained_metrics_object: false,
8640};
8641
8642pub const MZ_SHOW_SOURCES_IND: BuiltinIndex = BuiltinIndex {
8643 name: "mz_show_sources_ind",
8644 schema: MZ_INTERNAL_SCHEMA,
8645 oid: oid::INDEX_MZ_SHOW_SOURCES_IND_OID,
8646 sql: "IN CLUSTER mz_catalog_server
8647ON mz_internal.mz_show_sources (schema_id)",
8648 is_retained_metrics_object: false,
8649};
8650
8651pub const MZ_SHOW_VIEWS_IND: BuiltinIndex = BuiltinIndex {
8652 name: "mz_show_views_ind",
8653 schema: MZ_INTERNAL_SCHEMA,
8654 oid: oid::INDEX_MZ_SHOW_VIEWS_IND_OID,
8655 sql: "IN CLUSTER mz_catalog_server
8656ON mz_internal.mz_show_views (schema_id)",
8657 is_retained_metrics_object: false,
8658};
8659
8660pub const MZ_SHOW_MATERIALIZED_VIEWS_IND: BuiltinIndex = BuiltinIndex {
8661 name: "mz_show_materialized_views_ind",
8662 schema: MZ_INTERNAL_SCHEMA,
8663 oid: oid::INDEX_MZ_SHOW_MATERIALIZED_VIEWS_IND_OID,
8664 sql: "IN CLUSTER mz_catalog_server
8665ON mz_internal.mz_show_materialized_views (schema_id)",
8666 is_retained_metrics_object: false,
8667};
8668
8669pub const MZ_SHOW_SINKS_IND: BuiltinIndex = BuiltinIndex {
8670 name: "mz_show_sinks_ind",
8671 schema: MZ_INTERNAL_SCHEMA,
8672 oid: oid::INDEX_MZ_SHOW_SINKS_IND_OID,
8673 sql: "IN CLUSTER mz_catalog_server
8674ON mz_internal.mz_show_sinks (schema_id)",
8675 is_retained_metrics_object: false,
8676};
8677
8678pub const MZ_SHOW_TYPES_IND: BuiltinIndex = BuiltinIndex {
8679 name: "mz_show_types_ind",
8680 schema: MZ_INTERNAL_SCHEMA,
8681 oid: oid::INDEX_MZ_SHOW_TYPES_IND_OID,
8682 sql: "IN CLUSTER mz_catalog_server
8683ON mz_internal.mz_show_types (schema_id)",
8684 is_retained_metrics_object: false,
8685};
8686
8687pub const MZ_SHOW_ROLES_IND: BuiltinIndex = BuiltinIndex {
8688 name: "mz_show_roles_ind",
8689 schema: MZ_INTERNAL_SCHEMA,
8690 oid: oid::INDEX_MZ_SHOW_ROLES_IND_OID,
8691 sql: "IN CLUSTER mz_catalog_server
8692ON mz_internal.mz_show_roles (name)",
8693 is_retained_metrics_object: false,
8694};
8695
8696pub const MZ_SHOW_ALL_OBJECTS_IND: BuiltinIndex = BuiltinIndex {
8697 name: "mz_show_all_objects_ind",
8698 schema: MZ_INTERNAL_SCHEMA,
8699 oid: oid::INDEX_MZ_SHOW_ALL_OBJECTS_IND_OID,
8700 sql: "IN CLUSTER mz_catalog_server
8701ON mz_internal.mz_show_all_objects (schema_id)",
8702 is_retained_metrics_object: false,
8703};
8704
8705pub const MZ_SHOW_INDEXES_IND: BuiltinIndex = BuiltinIndex {
8706 name: "mz_show_indexes_ind",
8707 schema: MZ_INTERNAL_SCHEMA,
8708 oid: oid::INDEX_MZ_SHOW_INDEXES_IND_OID,
8709 sql: "IN CLUSTER mz_catalog_server
8710ON mz_internal.mz_show_indexes (schema_id)",
8711 is_retained_metrics_object: false,
8712};
8713
8714pub const MZ_SHOW_COLUMNS_IND: BuiltinIndex = BuiltinIndex {
8715 name: "mz_show_columns_ind",
8716 schema: MZ_INTERNAL_SCHEMA,
8717 oid: oid::INDEX_MZ_SHOW_COLUMNS_IND_OID,
8718 sql: "IN CLUSTER mz_catalog_server
8719ON mz_internal.mz_show_columns (id)",
8720 is_retained_metrics_object: false,
8721};
8722
8723pub const MZ_SHOW_CLUSTERS_IND: BuiltinIndex = BuiltinIndex {
8724 name: "mz_show_clusters_ind",
8725 schema: MZ_INTERNAL_SCHEMA,
8726 oid: oid::INDEX_MZ_SHOW_CLUSTERS_IND_OID,
8727 sql: "IN CLUSTER mz_catalog_server
8728ON mz_internal.mz_show_clusters (name)",
8729 is_retained_metrics_object: false,
8730};
8731
8732pub const MZ_SHOW_CLUSTER_REPLICAS_IND: BuiltinIndex = BuiltinIndex {
8733 name: "mz_show_cluster_replicas_ind",
8734 schema: MZ_INTERNAL_SCHEMA,
8735 oid: oid::INDEX_MZ_SHOW_CLUSTER_REPLICAS_IND_OID,
8736 sql: "IN CLUSTER mz_catalog_server
8737ON mz_internal.mz_show_cluster_replicas (cluster)",
8738 is_retained_metrics_object: false,
8739};
8740
8741pub const MZ_SHOW_SECRETS_IND: BuiltinIndex = BuiltinIndex {
8742 name: "mz_show_secrets_ind",
8743 schema: MZ_INTERNAL_SCHEMA,
8744 oid: oid::INDEX_MZ_SHOW_SECRETS_IND_OID,
8745 sql: "IN CLUSTER mz_catalog_server
8746ON mz_internal.mz_show_secrets (schema_id)",
8747 is_retained_metrics_object: false,
8748};
8749
8750pub const MZ_CONSOLE_CLUSTER_UTILIZATION_OVERVIEW_IND: BuiltinIndex = BuiltinIndex {
8751 name: "mz_console_cluster_utilization_overview_ind",
8752 schema: MZ_INTERNAL_SCHEMA,
8753 oid: oid::INDEX_MZ_CONSOLE_CLUSTER_UTILIZATION_OVERVIEW_IND_OID,
8754 sql: "IN CLUSTER mz_catalog_server
8755ON mz_internal.mz_console_cluster_utilization_overview (cluster_id)",
8756 is_retained_metrics_object: false,
8757};
8758
8759pub const MZ_CONSOLE_CLUSTER_UTILIZATION_OVERVIEW_3H_IND: BuiltinIndex = BuiltinIndex {
8760 name: "mz_console_cluster_utilization_overview_3h_ind",
8761 schema: MZ_INTERNAL_SCHEMA,
8762 oid: oid::INDEX_MZ_CONSOLE_CLUSTER_UTILIZATION_OVERVIEW_3H_IND_OID,
8763 sql: "IN CLUSTER mz_catalog_server
8764ON mz_internal.mz_console_cluster_utilization_overview_3h (cluster_id)",
8765 is_retained_metrics_object: false,
8766};
8767
8768pub const MZ_CONSOLE_CLUSTER_UTILIZATION_OVERVIEW_24H_IND: BuiltinIndex = BuiltinIndex {
8769 name: "mz_console_cluster_utilization_overview_24h_ind",
8770 schema: MZ_INTERNAL_SCHEMA,
8771 oid: oid::INDEX_MZ_CONSOLE_CLUSTER_UTILIZATION_OVERVIEW_24H_IND_OID,
8772 sql: "IN CLUSTER mz_catalog_server
8773ON mz_internal.mz_console_cluster_utilization_overview_24h (cluster_id)",
8774 is_retained_metrics_object: false,
8775};
8776
8777pub const MZ_CLUSTER_DEPLOYMENT_LINEAGE_IND: BuiltinIndex = BuiltinIndex {
8778 name: "mz_cluster_deployment_lineage_ind",
8779 schema: MZ_INTERNAL_SCHEMA,
8780 oid: oid::INDEX_MZ_CLUSTER_DEPLOYMENT_LINEAGE_IND_OID,
8781 sql: "IN CLUSTER mz_catalog_server
8782ON mz_internal.mz_cluster_deployment_lineage (cluster_id)",
8783 is_retained_metrics_object: false,
8784};
8785
8786pub const MZ_SOURCE_STATUSES_IND: BuiltinIndex = BuiltinIndex {
8787 name: "mz_source_statuses_ind",
8788 schema: MZ_INTERNAL_SCHEMA,
8789 oid: oid::INDEX_MZ_SOURCE_STATUSES_IND_OID,
8790 sql: "IN CLUSTER mz_catalog_server
8791ON mz_internal.mz_source_statuses (id)",
8792 is_retained_metrics_object: false,
8793};
8794
8795pub const MZ_SINK_STATUSES_IND: BuiltinIndex = BuiltinIndex {
8796 name: "mz_sink_statuses_ind",
8797 schema: MZ_INTERNAL_SCHEMA,
8798 oid: oid::INDEX_MZ_SINK_STATUSES_IND_OID,
8799 sql: "IN CLUSTER mz_catalog_server
8800ON mz_internal.mz_sink_statuses (id)",
8801 is_retained_metrics_object: false,
8802};
8803
8804pub const MZ_SOURCE_STATUS_HISTORY_IND: BuiltinIndex = BuiltinIndex {
8805 name: "mz_source_status_history_ind",
8806 schema: MZ_INTERNAL_SCHEMA,
8807 oid: oid::INDEX_MZ_SOURCE_STATUS_HISTORY_IND_OID,
8808 sql: "IN CLUSTER mz_catalog_server
8809ON mz_internal.mz_source_status_history (source_id)",
8810 is_retained_metrics_object: false,
8811};
8812
8813pub const MZ_SINK_STATUS_HISTORY_IND: BuiltinIndex = BuiltinIndex {
8814 name: "mz_sink_status_history_ind",
8815 schema: MZ_INTERNAL_SCHEMA,
8816 oid: oid::INDEX_MZ_SINK_STATUS_HISTORY_IND_OID,
8817 sql: "IN CLUSTER mz_catalog_server
8818ON mz_internal.mz_sink_status_history (sink_id)",
8819 is_retained_metrics_object: false,
8820};
8821
8822pub static MZ_SOURCE_STATISTICS_WITH_HISTORY: LazyLock<BuiltinView> =
8836 LazyLock::new(|| BuiltinView {
8837 name: "mz_source_statistics_with_history",
8838 schema: MZ_INTERNAL_SCHEMA,
8839 oid: oid::VIEW_MZ_SOURCE_STATISTICS_WITH_HISTORY_OID,
8840 desc: RelationDesc::builder()
8841 .with_column("id", SqlScalarType::String.nullable(false))
8842 .with_column("replica_id", SqlScalarType::String.nullable(true))
8843 .with_column("messages_received", SqlScalarType::UInt64.nullable(false))
8844 .with_column("bytes_received", SqlScalarType::UInt64.nullable(false))
8845 .with_column("updates_staged", SqlScalarType::UInt64.nullable(false))
8846 .with_column("updates_committed", SqlScalarType::UInt64.nullable(false))
8847 .with_column("records_indexed", SqlScalarType::UInt64.nullable(false))
8848 .with_column("bytes_indexed", SqlScalarType::UInt64.nullable(false))
8849 .with_column(
8850 "rehydration_latency",
8851 SqlScalarType::Interval.nullable(true),
8852 )
8853 .with_column(
8854 "snapshot_records_known",
8855 SqlScalarType::UInt64.nullable(true),
8856 )
8857 .with_column(
8858 "snapshot_records_staged",
8859 SqlScalarType::UInt64.nullable(true),
8860 )
8861 .with_column("snapshot_committed", SqlScalarType::Bool.nullable(false))
8862 .with_column("offset_known", SqlScalarType::UInt64.nullable(true))
8863 .with_column("offset_committed", SqlScalarType::UInt64.nullable(true))
8864 .with_key(vec![0, 1])
8865 .finish(),
8866 column_comments: BTreeMap::new(),
8867 sql: "
8868WITH
8869 -- For each subsource, statistics are reported as its parent source
8870 subsource_to_parent AS
8871 (
8872 SELECT subsource.id AS id, parent.id AS report_id
8873 FROM mz_catalog.mz_sources AS subsource
8874 JOIN mz_internal.mz_object_dependencies AS dep ON subsource.id = dep.object_id
8875 JOIN mz_catalog.mz_sources AS parent ON parent.id = dep.referenced_object_id
8876 WHERE subsource.type = 'subsource'
8877 ),
8878 -- For each table from source, statistics are reported as its parent source
8879 table_to_parent AS
8880 (
8881 SELECT id, source_id AS report_id
8882 FROM mz_catalog.mz_tables
8883 WHERE source_id IS NOT NULL
8884 ),
8885 -- For each source and subsource, statistics are reported as itself
8886 source_refl AS
8887 (
8888 SELECT id, id AS report_id
8889 FROM mz_catalog.mz_sources
8890 WHERE type NOT IN ('progress', 'log')
8891 ),
8892 -- For each table from source, statistics are reported as itself
8893 table_refl AS
8894 (
8895 SELECT id, id AS report_id
8896 FROM mz_catalog.mz_tables
8897 WHERE source_id IS NOT NULL
8898 ),
8899 report_paths AS
8900 (
8901 SELECT id, report_id FROM subsource_to_parent
8902 UNION ALL SELECT id, report_id FROM table_to_parent
8903 UNION ALL SELECT id, report_id FROM source_refl
8904 UNION ALL SELECT id, report_id FROM table_refl
8905 )
8906SELECT
8907 report_paths.report_id AS id,
8908 replica_id,
8909 -- Counters
8910 SUM(messages_received)::uint8 AS messages_received,
8911 SUM(bytes_received)::uint8 AS bytes_received,
8912 SUM(updates_staged)::uint8 AS updates_staged,
8913 SUM(updates_committed)::uint8 AS updates_committed,
8914 -- Resetting Gauges
8915 SUM(records_indexed)::uint8 AS records_indexed,
8916 SUM(bytes_indexed)::uint8 AS bytes_indexed,
8917 -- Ensure we aggregate to NULL when not all workers are done rehydrating.
8918 CASE
8919 WHEN bool_or(rehydration_latency IS NULL) THEN NULL
8920 ELSE MAX(rehydration_latency)::interval
8921 END AS rehydration_latency,
8922 SUM(snapshot_records_known)::uint8 AS snapshot_records_known,
8923 SUM(snapshot_records_staged)::uint8 AS snapshot_records_staged,
8924 bool_and(snapshot_committed) as snapshot_committed,
8925 -- Gauges
8926 MAX(offset_known)::uint8 AS offset_known,
8927 MIN(offset_committed)::uint8 AS offset_committed
8928FROM mz_internal.mz_source_statistics_raw
8929 JOIN report_paths USING (id)
8930GROUP BY report_paths.report_id, replica_id",
8931 access: vec![PUBLIC_SELECT],
8932 ontology: None,
8933 });
8934
8935pub const MZ_SOURCE_STATISTICS_WITH_HISTORY_IND: BuiltinIndex = BuiltinIndex {
8936 name: "mz_source_statistics_with_history_ind",
8937 schema: MZ_INTERNAL_SCHEMA,
8938 oid: oid::INDEX_MZ_SOURCE_STATISTICS_WITH_HISTORY_IND_OID,
8939 sql: "IN CLUSTER mz_catalog_server
8940ON mz_internal.mz_source_statistics_with_history (id, replica_id)",
8941 is_retained_metrics_object: true,
8942};
8943
8944pub static MZ_SOURCE_STATISTICS: LazyLock<BuiltinView> = LazyLock::new(|| {
8947 BuiltinView {
8948 name: "mz_source_statistics",
8949 schema: MZ_INTERNAL_SCHEMA,
8950 oid: oid::VIEW_MZ_SOURCE_STATISTICS_OID,
8951 desc: RelationDesc::builder()
8953 .with_column("id", SqlScalarType::String.nullable(false))
8954 .with_column("replica_id", SqlScalarType::String.nullable(true))
8955 .with_column("messages_received", SqlScalarType::UInt64.nullable(false))
8956 .with_column("bytes_received", SqlScalarType::UInt64.nullable(false))
8957 .with_column("updates_staged", SqlScalarType::UInt64.nullable(false))
8958 .with_column("updates_committed", SqlScalarType::UInt64.nullable(false))
8959 .with_column("records_indexed", SqlScalarType::UInt64.nullable(false))
8960 .with_column("bytes_indexed", SqlScalarType::UInt64.nullable(false))
8961 .with_column(
8962 "rehydration_latency",
8963 SqlScalarType::Interval.nullable(true),
8964 )
8965 .with_column(
8966 "snapshot_records_known",
8967 SqlScalarType::UInt64.nullable(true),
8968 )
8969 .with_column(
8970 "snapshot_records_staged",
8971 SqlScalarType::UInt64.nullable(true),
8972 )
8973 .with_column("snapshot_committed", SqlScalarType::Bool.nullable(false))
8974 .with_column("offset_known", SqlScalarType::UInt64.nullable(true))
8975 .with_column("offset_committed", SqlScalarType::UInt64.nullable(true))
8976 .with_key(vec![0, 1])
8977 .finish(),
8978 column_comments: BTreeMap::from_iter([
8979 (
8980 "id",
8981 "The ID of the source. Corresponds to `mz_catalog.mz_sources.id`.",
8982 ),
8983 (
8984 "replica_id",
8985 "The ID of a replica running the source. Corresponds to `mz_catalog.mz_cluster_replicas.id`.",
8986 ),
8987 (
8988 "messages_received",
8989 "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.",
8990 ),
8991 (
8992 "bytes_received",
8993 "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.",
8994 ),
8995 (
8996 "updates_staged",
8997 "The number of updates (insertions plus deletions) the source has written but not yet committed to the storage layer.",
8998 ),
8999 (
9000 "updates_committed",
9001 "The number of updates (insertions plus deletions) the source has committed to the storage layer.",
9002 ),
9003 (
9004 "records_indexed",
9005 "The number of individual records indexed in the source envelope state.",
9006 ),
9007 (
9008 "bytes_indexed",
9009 "The number of bytes stored in the source's internal index, if any.",
9010 ),
9011 (
9012 "rehydration_latency",
9013 "The amount of time it took for the source to rehydrate its internal index, if any, after the source last restarted.",
9014 ),
9015 (
9016 "snapshot_records_known",
9017 "The size of the source's snapshot, measured in number of records. See below to learn what constitutes a record.",
9018 ),
9019 (
9020 "snapshot_records_staged",
9021 "The number of records in the source's snapshot that Materialize has read. See below to learn what constitutes a record.",
9022 ),
9023 (
9024 "snapshot_committed",
9025 "Whether the source has committed the initial snapshot for a source.",
9026 ),
9027 (
9028 "offset_known",
9029 "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.",
9030 ),
9031 (
9032 "offset_committed",
9033 "The offset of the the data that Materialize has durably ingested. See below to learn what constitutes an offset.",
9034 ),
9035 ]),
9036 sql: "SELECT * FROM mz_internal.mz_source_statistics_with_history WHERE length(id) > 0",
9037 access: vec![PUBLIC_SELECT],
9038 ontology: Some(Ontology {
9039 entity_name: "source_statistics",
9040 description: "Aggregated source ingestion statistics",
9041 links: &const {
9042 [OntologyLink {
9043 name: "statistics_of_source",
9044 target: "source",
9045 properties: LinkProperties::measures("id", "id", "ingestion_statistics"),
9046 }]
9047 },
9048 column_semantic_types: &const {
9049 [
9050 ("id", SemanticType::CatalogItemId),
9051 ("replica_id", SemanticType::ReplicaId),
9052 ("messages_received", SemanticType::RecordCount),
9053 ("bytes_received", SemanticType::ByteCount),
9054 ("updates_staged", SemanticType::RecordCount),
9055 ("updates_committed", SemanticType::RecordCount),
9056 ("records_indexed", SemanticType::RecordCount),
9057 ("bytes_indexed", SemanticType::ByteCount),
9058 ("snapshot_records_known", SemanticType::RecordCount),
9059 ("snapshot_records_staged", SemanticType::RecordCount),
9060 ]
9061 },
9062 }),
9063 }
9064});
9065
9066pub const MZ_SOURCE_STATISTICS_IND: BuiltinIndex = BuiltinIndex {
9067 name: "mz_source_statistics_ind",
9068 schema: MZ_INTERNAL_SCHEMA,
9069 oid: oid::INDEX_MZ_SOURCE_STATISTICS_IND_OID,
9070 sql: "IN CLUSTER mz_catalog_server
9071ON mz_internal.mz_source_statistics (id, replica_id)",
9072 is_retained_metrics_object: false,
9073};
9074
9075pub static MZ_SINK_STATISTICS: LazyLock<BuiltinView> = LazyLock::new(|| BuiltinView {
9076 name: "mz_sink_statistics",
9077 schema: MZ_INTERNAL_SCHEMA,
9078 oid: oid::VIEW_MZ_SINK_STATISTICS_OID,
9079 desc: RelationDesc::builder()
9080 .with_column("id", SqlScalarType::String.nullable(false))
9081 .with_column("replica_id", SqlScalarType::String.nullable(true))
9082 .with_column("messages_staged", SqlScalarType::UInt64.nullable(false))
9083 .with_column("messages_committed", SqlScalarType::UInt64.nullable(false))
9084 .with_column("bytes_staged", SqlScalarType::UInt64.nullable(false))
9085 .with_column("bytes_committed", SqlScalarType::UInt64.nullable(false))
9086 .with_key(vec![0, 1])
9087 .finish(),
9088 column_comments: BTreeMap::from_iter([
9089 (
9090 "id",
9091 "The ID of the sink. Corresponds to `mz_catalog.mz_sinks.id`.",
9092 ),
9093 (
9094 "replica_id",
9095 "The ID of a replica running the sink. Corresponds to `mz_catalog.mz_cluster_replicas.id`.",
9096 ),
9097 (
9098 "messages_staged",
9099 "The number of messages staged but possibly not committed to the sink.",
9100 ),
9101 (
9102 "messages_committed",
9103 "The number of messages committed to the sink.",
9104 ),
9105 (
9106 "bytes_staged",
9107 "The number of bytes staged but possibly not committed to the sink. This counts both keys and values, if applicable.",
9108 ),
9109 (
9110 "bytes_committed",
9111 "The number of bytes committed to the sink. This counts both keys and values, if applicable.",
9112 ),
9113 ]),
9114 sql: "
9115SELECT
9116 id,
9117 replica_id,
9118 SUM(messages_staged)::uint8 AS messages_staged,
9119 SUM(messages_committed)::uint8 AS messages_committed,
9120 SUM(bytes_staged)::uint8 AS bytes_staged,
9121 SUM(bytes_committed)::uint8 AS bytes_committed
9122FROM mz_internal.mz_sink_statistics_raw
9123GROUP BY id, replica_id",
9124 access: vec![PUBLIC_SELECT],
9125 ontology: Some(Ontology {
9126 entity_name: "sink_statistics",
9127 description: "Aggregated sink export statistics",
9128 links: &const {
9129 [OntologyLink {
9130 name: "statistics_of_sink",
9131 target: "sink",
9132 properties: LinkProperties::measures("id", "id", "export_statistics"),
9133 }]
9134 },
9135 column_semantic_types: &const {
9136 [
9137 ("id", SemanticType::CatalogItemId),
9138 ("replica_id", SemanticType::ReplicaId),
9139 ("messages_staged", SemanticType::RecordCount),
9140 ("messages_committed", SemanticType::RecordCount),
9141 ("bytes_staged", SemanticType::ByteCount),
9142 ("bytes_committed", SemanticType::ByteCount),
9143 ]
9144 },
9145 }),
9146});
9147
9148pub const MZ_SINK_STATISTICS_IND: BuiltinIndex = BuiltinIndex {
9149 name: "mz_sink_statistics_ind",
9150 schema: MZ_INTERNAL_SCHEMA,
9151 oid: oid::INDEX_MZ_SINK_STATISTICS_IND_OID,
9152 sql: "IN CLUSTER mz_catalog_server
9153ON mz_internal.mz_sink_statistics (id, replica_id)",
9154 is_retained_metrics_object: true,
9155};
9156
9157pub const MZ_CLUSTER_REPLICA_STATUSES_IND: BuiltinIndex = BuiltinIndex {
9158 name: "mz_cluster_replica_statuses_ind",
9159 schema: MZ_INTERNAL_SCHEMA,
9160 oid: oid::INDEX_MZ_CLUSTER_REPLICA_STATUSES_IND_OID,
9161 sql: "IN CLUSTER mz_catalog_server
9162ON mz_internal.mz_cluster_replica_statuses (replica_id)",
9163 is_retained_metrics_object: false,
9164};
9165
9166pub const MZ_CLUSTER_REPLICA_STATUS_HISTORY_IND: BuiltinIndex = BuiltinIndex {
9167 name: "mz_cluster_replica_status_history_ind",
9168 schema: MZ_INTERNAL_SCHEMA,
9169 oid: oid::INDEX_MZ_CLUSTER_REPLICA_STATUS_HISTORY_IND_OID,
9170 sql: "IN CLUSTER mz_catalog_server
9171ON mz_internal.mz_cluster_replica_status_history (replica_id)",
9172 is_retained_metrics_object: false,
9173};
9174
9175pub const MZ_CLUSTER_REPLICA_METRICS_IND: BuiltinIndex = BuiltinIndex {
9176 name: "mz_cluster_replica_metrics_ind",
9177 schema: MZ_INTERNAL_SCHEMA,
9178 oid: oid::INDEX_MZ_CLUSTER_REPLICA_METRICS_IND_OID,
9179 sql: "IN CLUSTER mz_catalog_server
9180ON mz_internal.mz_cluster_replica_metrics (replica_id)",
9181 is_retained_metrics_object: false,
9182};
9183
9184pub const MZ_CLUSTER_REPLICA_METRICS_HISTORY_IND: BuiltinIndex = BuiltinIndex {
9185 name: "mz_cluster_replica_metrics_history_ind",
9186 schema: MZ_INTERNAL_SCHEMA,
9187 oid: oid::INDEX_MZ_CLUSTER_REPLICA_METRICS_HISTORY_IND_OID,
9188 sql: "IN CLUSTER mz_catalog_server
9189ON mz_internal.mz_cluster_replica_metrics_history (replica_id)",
9190 is_retained_metrics_object: false,
9191};
9192
9193pub const MZ_CLUSTER_REPLICA_HISTORY_IND: BuiltinIndex = BuiltinIndex {
9194 name: "mz_cluster_replica_history_ind",
9195 schema: MZ_INTERNAL_SCHEMA,
9196 oid: oid::INDEX_MZ_CLUSTER_REPLICA_HISTORY_IND_OID,
9197 sql: "IN CLUSTER mz_catalog_server
9198ON mz_internal.mz_cluster_replica_history (dropped_at)",
9199 is_retained_metrics_object: true,
9200};
9201
9202pub const MZ_CLUSTER_REPLICA_NAME_HISTORY_IND: BuiltinIndex = BuiltinIndex {
9203 name: "mz_cluster_replica_name_history_ind",
9204 schema: MZ_INTERNAL_SCHEMA,
9205 oid: oid::INDEX_MZ_CLUSTER_REPLICA_NAME_HISTORY_IND_OID,
9206 sql: "IN CLUSTER mz_catalog_server
9207ON mz_internal.mz_cluster_replica_name_history (id)",
9208 is_retained_metrics_object: false,
9209};
9210
9211pub const MZ_OBJECT_LIFETIMES_IND: BuiltinIndex = BuiltinIndex {
9212 name: "mz_object_lifetimes_ind",
9213 schema: MZ_INTERNAL_SCHEMA,
9214 oid: oid::INDEX_MZ_OBJECT_LIFETIMES_IND_OID,
9215 sql: "IN CLUSTER mz_catalog_server
9216ON mz_internal.mz_object_lifetimes (id)",
9217 is_retained_metrics_object: false,
9218};
9219
9220pub const MZ_OBJECT_HISTORY_IND: BuiltinIndex = BuiltinIndex {
9221 name: "mz_object_history_ind",
9222 schema: MZ_INTERNAL_SCHEMA,
9223 oid: oid::INDEX_MZ_OBJECT_HISTORY_IND_OID,
9224 sql: "IN CLUSTER mz_catalog_server
9225ON mz_internal.mz_object_history (id)",
9226 is_retained_metrics_object: false,
9227};
9228
9229pub const MZ_OBJECT_DEPENDENCIES_IND: BuiltinIndex = BuiltinIndex {
9230 name: "mz_object_dependencies_ind",
9231 schema: MZ_INTERNAL_SCHEMA,
9232 oid: oid::INDEX_MZ_OBJECT_DEPENDENCIES_IND_OID,
9233 sql: "IN CLUSTER mz_catalog_server
9234ON mz_internal.mz_object_dependencies (object_id)",
9235 is_retained_metrics_object: true,
9236};
9237
9238pub const MZ_COMPUTE_DEPENDENCIES_IND: BuiltinIndex = BuiltinIndex {
9239 name: "mz_compute_dependencies_ind",
9240 schema: MZ_INTERNAL_SCHEMA,
9241 oid: oid::INDEX_MZ_COMPUTE_DEPENDENCIES_IND_OID,
9242 sql: "IN CLUSTER mz_catalog_server
9243ON mz_internal.mz_compute_dependencies (dependency_id)",
9244 is_retained_metrics_object: false,
9245};
9246
9247pub const MZ_OBJECT_TRANSITIVE_DEPENDENCIES_IND: BuiltinIndex = BuiltinIndex {
9248 name: "mz_object_transitive_dependencies_ind",
9249 schema: MZ_INTERNAL_SCHEMA,
9250 oid: oid::INDEX_MZ_OBJECT_TRANSITIVE_DEPENDENCIES_IND_OID,
9251 sql: "IN CLUSTER mz_catalog_server
9252ON mz_internal.mz_object_transitive_dependencies (object_id)",
9253 is_retained_metrics_object: false,
9254};
9255
9256pub const MZ_OBJECT_GRAPH_EDGES_IND: BuiltinIndex = BuiltinIndex {
9257 name: "mz_object_graph_edges_ind",
9258 schema: MZ_INTERNAL_SCHEMA,
9259 oid: oid::INDEX_MZ_OBJECT_GRAPH_EDGES_IND_OID,
9260 sql: "IN CLUSTER mz_catalog_server
9261ON mz_internal.mz_object_graph_edges (object_id)",
9262 is_retained_metrics_object: false,
9263};
9264
9265pub const MZ_FRONTIERS_IND: BuiltinIndex = BuiltinIndex {
9266 name: "mz_frontiers_ind",
9267 schema: MZ_INTERNAL_SCHEMA,
9268 oid: oid::INDEX_MZ_FRONTIERS_IND_OID,
9269 sql: "IN CLUSTER mz_catalog_server
9270ON mz_internal.mz_frontiers (object_id)",
9271 is_retained_metrics_object: false,
9272};
9273
9274pub const MZ_WALLCLOCK_GLOBAL_LAG_RECENT_HISTORY_IND: BuiltinIndex = BuiltinIndex {
9275 name: "mz_wallclock_global_lag_recent_history_ind",
9276 schema: MZ_INTERNAL_SCHEMA,
9277 oid: oid::INDEX_MZ_WALLCLOCK_GLOBAL_LAG_RECENT_HISTORY_IND_OID,
9278 sql: "IN CLUSTER mz_catalog_server
9279ON mz_internal.mz_wallclock_global_lag_recent_history (object_id)",
9280 is_retained_metrics_object: false,
9281};
9282
9283pub const MZ_RECENT_ACTIVITY_LOG_THINNED_IND: BuiltinIndex = BuiltinIndex {
9284 name: "mz_recent_activity_log_thinned_ind",
9285 schema: MZ_INTERNAL_SCHEMA,
9286 oid: oid::INDEX_MZ_RECENT_ACTIVITY_LOG_THINNED_IND_OID,
9287 sql: "IN CLUSTER mz_catalog_server
9288-- sql_hash because we plan to join
9289-- this against mz_internal.mz_sql_text
9290ON mz_internal.mz_recent_activity_log_thinned (sql_hash)",
9291 is_retained_metrics_object: false,
9292};
9293
9294pub const MZ_WEBHOOK_SOURCES_IND: BuiltinIndex = BuiltinIndex {
9295 name: "mz_webhook_sources_ind",
9296 schema: MZ_INTERNAL_SCHEMA,
9297 oid: oid::INDEX_MZ_WEBHOOK_SOURCES_IND_OID,
9298 sql: "IN CLUSTER mz_catalog_server
9299ON mz_internal.mz_webhook_sources (id)",
9300 is_retained_metrics_object: true,
9301};
9302
9303pub const MZ_COMMENTS_IND: BuiltinIndex = BuiltinIndex {
9304 name: "mz_comments_ind",
9305 schema: MZ_INTERNAL_SCHEMA,
9306 oid: oid::INDEX_MZ_COMMENTS_IND_OID,
9307 sql: "IN CLUSTER mz_catalog_server
9308ON mz_internal.mz_comments (id)",
9309 is_retained_metrics_object: true,
9310};
9311
9312pub static MZ_ANALYTICS: BuiltinConnection = BuiltinConnection {
9313 name: "mz_analytics",
9314 schema: MZ_INTERNAL_SCHEMA,
9315 oid: oid::CONNECTION_MZ_ANALYTICS_OID,
9316 sql: "CREATE CONNECTION mz_internal.mz_analytics TO AWS (ASSUME ROLE ARN = '')",
9317 access: &[MzAclItem {
9318 grantee: MZ_SYSTEM_ROLE_ID,
9319 grantor: MZ_ANALYTICS_ROLE_ID,
9320 acl_mode: rbac::all_object_privileges(SystemObjectType::Object(ObjectType::Connection)),
9321 }],
9322 owner_id: &MZ_ANALYTICS_ROLE_ID,
9323 runtime_alterable: true,
9324};