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