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