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