Skip to main content

mz_catalog/durable/
objects.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10//! The current types used to represent catalog data stored on disk. These objects generally fall
11//! into two categories.
12//!
13//! The key-value objects are a one-to-one mapping of the protobuf objects used to save catalog
14//! data durably. They can be converted to and from protobuf via the [`mz_proto::RustType`] trait.
15//! These objects should not be exposed anywhere outside the [`crate::durable`] module.
16//!
17//! The other type of objects combine the information from keys and values into a single struct,
18//! but are still a direct representation of the data stored on disk. They can be converted to and
19//! from the key-value objects via the [`DurableType`] trait. These objects are used to pass
20//! information to other modules in this crate and other catalog related code.
21//!
22//! All non-catalog code should interact with the objects in [`crate::memory::objects`] and never
23//! directly interact with the objects in this module.
24//!
25//! As an example, [`DatabaseKey`] and [`DatabaseValue`] are key-value objects, while [`Database`]
26//! is the non-key-value counterpart.
27
28pub mod serialization;
29pub(crate) mod state_update;
30
31use std::cmp::Ordering;
32use std::collections::BTreeMap;
33use std::time::Duration;
34
35use mz_audit_log::VersionedEvent;
36use mz_controller::clusters::ReplicaLogging;
37use mz_controller_types::{ClusterId, ReplicaId};
38use mz_persist_types::ShardId;
39use mz_repr::adt::mz_acl_item::{AclMode, MzAclItem};
40use mz_repr::network_policy_id::NetworkPolicyId;
41use mz_repr::role_id::RoleId;
42use mz_repr::{CatalogItemId, GlobalId, RelationVersion};
43use mz_sql::catalog::{
44    CatalogItemType, DefaultPrivilegeAclItem, DefaultPrivilegeObject, ObjectType, RoleAttributes,
45    RoleMembership, RoleVars,
46};
47use mz_sql::names::{CommentObjectId, DatabaseId, SchemaId};
48use mz_sql::plan::{AutoScalingStrategy, ClusterSchedule, NetworkPolicyRule, OnTimeoutAction};
49#[cfg(test)]
50use proptest_derive::Arbitrary;
51
52use crate::builtin::RUNTIME_ALTERABLE_FINGERPRINT_SENTINEL;
53use crate::durable::Epoch;
54use crate::durable::objects::serialization::proto;
55
56// Structs used to pass information to outside modules.
57
58/// A trait for representing `Self` as a key-value pair of type
59/// `(Key, Value)` for the purpose of storing this value durably.
60///
61/// To encode a key-value pair, use [`DurableType::into_key_value`].
62///
63/// To decode a key-value pair, use [`DurableType::from_key_value`].
64///
65/// This trait is based on [`RustType`], however it is meant to
66/// convert the types used in [`RustType`] to a more consumable and
67/// condensed type.
68///
69/// [`RustType`]: mz_proto::RustType
70pub trait DurableType: Sized {
71    type Key;
72    type Value;
73
74    /// Consume and convert `Self` into a `(Key, Value)` key-value pair.
75    fn into_key_value(self) -> (Self::Key, Self::Value);
76
77    /// Consume and convert a `(Key, Value)` key-value pair back into a
78    /// `Self` value.
79    fn from_key_value(key: Self::Key, value: Self::Value) -> Self;
80
81    // TODO(jkosh44) Would be great to not clone, since this is always used for lookups which only
82    // needs a reference. In practice, we currently almost always use this method to clone a single
83    // 64-bit integer, so it's not a huge deal.
84    /// Produce a `Key` from self. This may involve cloning/copying required fields.
85    fn key(&self) -> Self::Key;
86}
87
88#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq)]
89pub struct Database {
90    pub id: DatabaseId,
91    pub oid: u32,
92    pub name: String,
93    pub owner_id: RoleId,
94    pub privileges: Vec<MzAclItem>,
95}
96
97impl DurableType for Database {
98    type Key = DatabaseKey;
99    type Value = DatabaseValue;
100
101    fn into_key_value(self) -> (Self::Key, Self::Value) {
102        (
103            DatabaseKey { id: self.id },
104            DatabaseValue {
105                oid: self.oid,
106                name: self.name,
107                owner_id: self.owner_id,
108                privileges: self.privileges,
109            },
110        )
111    }
112
113    fn from_key_value(key: Self::Key, value: Self::Value) -> Self {
114        Self {
115            id: key.id,
116            oid: value.oid,
117            name: value.name,
118            owner_id: value.owner_id,
119            privileges: value.privileges,
120        }
121    }
122
123    fn key(&self) -> Self::Key {
124        DatabaseKey { id: self.id }
125    }
126}
127
128#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq)]
129pub struct Schema {
130    pub id: SchemaId,
131    pub oid: u32,
132    pub name: String,
133    pub database_id: Option<DatabaseId>,
134    pub owner_id: RoleId,
135    pub privileges: Vec<MzAclItem>,
136}
137
138impl DurableType for Schema {
139    type Key = SchemaKey;
140    type Value = SchemaValue;
141
142    fn into_key_value(self) -> (Self::Key, Self::Value) {
143        (
144            SchemaKey { id: self.id },
145            SchemaValue {
146                oid: self.oid,
147                database_id: self.database_id,
148                name: self.name,
149                owner_id: self.owner_id,
150                privileges: self.privileges,
151            },
152        )
153    }
154
155    fn from_key_value(key: Self::Key, value: Self::Value) -> Self {
156        Self {
157            id: key.id,
158            oid: value.oid,
159            name: value.name,
160            database_id: value.database_id,
161            owner_id: value.owner_id,
162            privileges: value.privileges,
163        }
164    }
165
166    fn key(&self) -> Self::Key {
167        SchemaKey { id: self.id }
168    }
169}
170
171#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq)]
172pub struct Role {
173    pub id: RoleId,
174    pub oid: u32,
175    pub name: String,
176    pub attributes: RoleAttributes,
177    pub membership: RoleMembership,
178    pub vars: RoleVars,
179}
180
181impl DurableType for Role {
182    type Key = RoleKey;
183    type Value = RoleValue;
184
185    fn into_key_value(self) -> (Self::Key, Self::Value) {
186        (
187            RoleKey { id: self.id },
188            RoleValue {
189                oid: self.oid,
190                name: self.name,
191                attributes: self.attributes,
192                membership: self.membership,
193                vars: self.vars,
194            },
195        )
196    }
197
198    fn from_key_value(key: Self::Key, value: Self::Value) -> Self {
199        Self {
200            id: key.id,
201            oid: value.oid,
202            name: value.name,
203            attributes: value.attributes,
204            membership: value.membership,
205            vars: value.vars,
206        }
207    }
208
209    fn key(&self) -> Self::Key {
210        RoleKey { id: self.id }
211    }
212}
213
214#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq)]
215pub struct RoleAuth {
216    pub role_id: RoleId,
217    pub password_hash: Option<String>,
218    pub updated_at: u64,
219}
220
221impl DurableType for RoleAuth {
222    type Key = RoleAuthKey;
223    type Value = RoleAuthValue;
224
225    fn into_key_value(self) -> (Self::Key, Self::Value) {
226        (
227            RoleAuthKey {
228                role_id: self.role_id,
229            },
230            RoleAuthValue {
231                password_hash: self.password_hash,
232                updated_at: self.updated_at,
233            },
234        )
235    }
236
237    fn from_key_value(key: Self::Key, value: Self::Value) -> Self {
238        Self {
239            role_id: key.role_id,
240            password_hash: value.password_hash,
241            updated_at: value.updated_at,
242        }
243    }
244
245    fn key(&self) -> Self::Key {
246        RoleAuthKey {
247            role_id: self.role_id,
248        }
249    }
250}
251
252#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq)]
253pub struct NetworkPolicy {
254    pub name: String,
255    pub id: NetworkPolicyId,
256    pub oid: u32,
257    pub rules: Vec<NetworkPolicyRule>,
258    pub owner_id: RoleId,
259    pub(crate) privileges: Vec<MzAclItem>,
260}
261
262impl DurableType for NetworkPolicy {
263    type Key = NetworkPolicyKey;
264    type Value = NetworkPolicyValue;
265
266    fn into_key_value(self) -> (Self::Key, Self::Value) {
267        (
268            NetworkPolicyKey { id: self.id },
269            NetworkPolicyValue {
270                oid: self.oid,
271                name: self.name,
272                rules: self.rules,
273                owner_id: self.owner_id,
274                privileges: self.privileges,
275            },
276        )
277    }
278
279    fn from_key_value(key: Self::Key, value: Self::Value) -> Self {
280        Self {
281            id: key.id,
282            oid: value.oid,
283            name: value.name,
284            rules: value.rules,
285            owner_id: value.owner_id,
286            privileges: value.privileges,
287        }
288    }
289
290    fn key(&self) -> Self::Key {
291        NetworkPolicyKey { id: self.id }
292    }
293}
294
295#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq)]
296pub struct Cluster {
297    pub id: ClusterId,
298    pub name: String,
299    pub owner_id: RoleId,
300    pub privileges: Vec<MzAclItem>,
301    pub config: ClusterConfig,
302}
303
304impl DurableType for Cluster {
305    type Key = ClusterKey;
306    type Value = ClusterValue;
307
308    fn into_key_value(self) -> (Self::Key, Self::Value) {
309        (
310            ClusterKey { id: self.id },
311            ClusterValue {
312                name: self.name,
313                owner_id: self.owner_id,
314                privileges: self.privileges,
315                config: self.config,
316            },
317        )
318    }
319
320    fn from_key_value(key: Self::Key, value: Self::Value) -> Self {
321        Self {
322            id: key.id,
323            name: value.name,
324            owner_id: value.owner_id,
325            privileges: value.privileges,
326            config: value.config,
327        }
328    }
329
330    fn key(&self) -> Self::Key {
331        ClusterKey { id: self.id }
332    }
333}
334
335#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord)]
336pub struct ClusterConfig {
337    pub variant: ClusterVariant,
338    pub workload_class: Option<String>,
339}
340
341#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord)]
342pub enum ClusterVariant {
343    Managed(ClusterVariantManaged),
344    Unmanaged,
345}
346
347#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord)]
348pub struct ClusterVariantManaged {
349    pub size: String,
350    pub availability_zones: Vec<String>,
351    pub logging: ReplicaLogging,
352    pub replication_factor: u32,
353    pub optimizer_feature_overrides: BTreeMap<String, String>,
354    pub schedule: ClusterSchedule,
355    /// User-configured autoscaling policy, distinct from the in-flight runtime
356    /// records below.
357    pub auto_scaling_strategy: Option<AutoScalingStrategy>,
358    /// In-flight graceful reconfiguration the controller is converging on.
359    pub reconfiguration: Option<ReconfigurationState>,
360    /// In-flight hydration burst the controller is running.
361    pub burst: Option<BurstState>,
362}
363
364/// An in-flight graceful reconfiguration: the config shape the cluster is
365/// moving to plus the deadline by which it must complete.
366///
367/// `ALTER` writes this record and returns; the realized config (`cluster.size`,
368/// ...) is advanced by the controller only at cut-over. A past `deadline` with
369/// the record still present is a timeout tombstone.
370#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord)]
371pub struct ReconfigurationState {
372    pub target: ReconfigurationTarget,
373    pub deadline: mz_repr::Timestamp,
374    /// The action the controller applies if `deadline` passes before the
375    /// target hydrates. Success takes precedence: a hydrated target cuts over
376    /// regardless of this field.
377    pub on_timeout: OnTimeoutAction,
378}
379
380/// The full config shape a reconfiguration is moving the cluster to, so a
381/// combined size + replication-factor + availability-zone change is one record.
382#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord)]
383pub struct ReconfigurationTarget {
384    pub size: String,
385    pub replication_factor: u32,
386    pub availability_zones: Vec<String>,
387    pub logging: ReplicaLogging,
388}
389
390/// An active hydration burst the controller is running.
391#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord)]
392pub struct BurstState {
393    pub burst_size: String,
394    pub linger_duration: Duration,
395    /// When the steady-state replicas were first observed hydrated. Absent
396    /// until that observation; the linger countdown runs from this point.
397    pub steady_hydrated_at: Option<mz_repr::Timestamp>,
398}
399
400#[derive(Clone, Debug, Ord, PartialOrd, PartialEq, Eq)]
401pub struct IntrospectionSourceIndex {
402    pub cluster_id: ClusterId,
403    pub name: String,
404    pub item_id: CatalogItemId,
405    pub index_id: GlobalId,
406    pub oid: u32,
407}
408
409impl DurableType for IntrospectionSourceIndex {
410    type Key = ClusterIntrospectionSourceIndexKey;
411    type Value = ClusterIntrospectionSourceIndexValue;
412
413    fn into_key_value(self) -> (Self::Key, Self::Value) {
414        (
415            ClusterIntrospectionSourceIndexKey {
416                cluster_id: self.cluster_id,
417                name: self.name,
418            },
419            ClusterIntrospectionSourceIndexValue {
420                catalog_id: self
421                    .item_id
422                    .try_into()
423                    .expect("cluster introspection source index mapping must be an Introspection Source Index ID"),
424                global_id: self
425                    .index_id
426                    .try_into()
427                    .expect("cluster introspection source index mapping must be a Introspection Source Index ID"),
428                oid: self.oid,
429            },
430        )
431    }
432
433    fn from_key_value(key: Self::Key, value: Self::Value) -> Self {
434        Self {
435            cluster_id: key.cluster_id,
436            name: key.name,
437            item_id: value.catalog_id.into(),
438            index_id: value.global_id.into(),
439            oid: value.oid,
440        }
441    }
442
443    fn key(&self) -> Self::Key {
444        ClusterIntrospectionSourceIndexKey {
445            cluster_id: self.cluster_id,
446            name: self.name.clone(),
447        }
448    }
449}
450
451#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq)]
452pub struct ClusterReplica {
453    pub cluster_id: ClusterId,
454    pub replica_id: ReplicaId,
455    pub name: String,
456    pub config: ReplicaConfig,
457    pub owner_id: RoleId,
458}
459
460impl DurableType for ClusterReplica {
461    type Key = ClusterReplicaKey;
462    type Value = ClusterReplicaValue;
463
464    fn into_key_value(self) -> (Self::Key, Self::Value) {
465        (
466            ClusterReplicaKey {
467                id: self.replica_id,
468            },
469            ClusterReplicaValue {
470                cluster_id: self.cluster_id,
471                name: self.name,
472                config: self.config,
473                owner_id: self.owner_id,
474            },
475        )
476    }
477
478    fn from_key_value(key: Self::Key, value: Self::Value) -> Self {
479        Self {
480            cluster_id: value.cluster_id,
481            replica_id: key.id,
482            name: value.name,
483            config: value.config,
484            owner_id: value.owner_id,
485        }
486    }
487
488    fn key(&self) -> Self::Key {
489        ClusterReplicaKey {
490            id: self.replica_id,
491        }
492    }
493}
494
495// The on-disk replica configuration does not match the in-memory replica configuration, so we need
496// separate structs. As of writing this comment, it is mainly due to the fact that we don't persist
497// the replica allocation.
498#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord)]
499pub struct ReplicaConfig {
500    pub location: ReplicaLocation,
501    pub logging: ReplicaLogging,
502}
503
504impl From<mz_controller::clusters::ReplicaConfig> for ReplicaConfig {
505    fn from(config: mz_controller::clusters::ReplicaConfig) -> Self {
506        Self {
507            location: config.location.into(),
508            logging: config.compute.logging,
509        }
510    }
511}
512
513#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord)]
514pub enum ReplicaLocation {
515    Unmanaged {
516        storagectl_addrs: Vec<String>,
517        computectl_addrs: Vec<String>,
518    },
519    Managed {
520        size: String,
521        /// The availability zones the replica was provisioned under.
522        ///
523        /// For a replica of a managed cluster this is the cluster's
524        /// `AVAILABILITY ZONES` pool at provision time; the cluster controller
525        /// compares it against a cluster's target `availability_zones` to tell
526        /// realized- from target-shape replicas (including an
527        /// `AVAILABILITY ZONES` divergence). For a replica of an unmanaged
528        /// cluster it is the user-pinned `AVAILABILITY ZONE`, as a zero- or
529        /// one-element list. Empty when no zones constrain placement.
530        availability_zones: Vec<String>,
531        internal: bool,
532        billed_as: Option<String>,
533        pending: bool,
534    },
535}
536
537impl From<mz_controller::clusters::ReplicaLocation> for ReplicaLocation {
538    fn from(loc: mz_controller::clusters::ReplicaLocation) -> Self {
539        match loc {
540            mz_controller::clusters::ReplicaLocation::Unmanaged(
541                mz_controller::clusters::UnmanagedReplicaLocation {
542                    storagectl_addrs,
543                    computectl_addrs,
544                },
545            ) => Self::Unmanaged {
546                storagectl_addrs,
547                computectl_addrs,
548            },
549            mz_controller::clusters::ReplicaLocation::Managed(
550                mz_controller::clusters::ManagedReplicaLocation {
551                    allocation: _,
552                    size,
553                    availability_zones,
554                    billed_as,
555                    internal,
556                    pending,
557                },
558            ) => ReplicaLocation::Managed {
559                size,
560                availability_zones,
561                internal,
562                billed_as,
563                pending,
564            },
565        }
566    }
567}
568
569#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq)]
570pub struct Item {
571    pub id: CatalogItemId,
572    pub oid: u32,
573    pub global_id: GlobalId,
574    pub schema_id: SchemaId,
575    pub name: String,
576    pub create_sql: String,
577    pub owner_id: RoleId,
578    pub privileges: Vec<MzAclItem>,
579    pub extra_versions: BTreeMap<RelationVersion, GlobalId>,
580}
581
582impl Item {
583    pub fn item_type(&self) -> CatalogItemType {
584        item_type(&self.create_sql)
585    }
586}
587
588impl DurableType for Item {
589    type Key = ItemKey;
590    type Value = ItemValue;
591
592    fn into_key_value(self) -> (Self::Key, Self::Value) {
593        (
594            ItemKey { id: self.id },
595            ItemValue {
596                oid: self.oid,
597                global_id: self.global_id,
598                schema_id: self.schema_id,
599                name: self.name,
600                create_sql: self.create_sql,
601                owner_id: self.owner_id,
602                privileges: self.privileges,
603                extra_versions: self.extra_versions,
604            },
605        )
606    }
607
608    fn from_key_value(key: Self::Key, value: Self::Value) -> Self {
609        Self {
610            id: key.id,
611            oid: value.oid,
612            global_id: value.global_id,
613            schema_id: value.schema_id,
614            name: value.name,
615            create_sql: value.create_sql,
616            owner_id: value.owner_id,
617            privileges: value.privileges,
618            extra_versions: value.extra_versions,
619        }
620    }
621
622    fn key(&self) -> Self::Key {
623        ItemKey { id: self.id }
624    }
625}
626
627#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq)]
628pub struct SourceReferences {
629    pub source_id: CatalogItemId,
630    pub updated_at: u64,
631    pub references: Vec<SourceReference>,
632}
633
634#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq)]
635#[cfg_attr(test, derive(Arbitrary))]
636pub struct SourceReference {
637    pub name: String,
638    pub namespace: Option<String>,
639    pub columns: Vec<String>,
640}
641
642impl DurableType for SourceReferences {
643    type Key = SourceReferencesKey;
644    type Value = SourceReferencesValue;
645
646    fn into_key_value(self) -> (Self::Key, Self::Value) {
647        (
648            SourceReferencesKey {
649                source_id: self.source_id,
650            },
651            SourceReferencesValue {
652                updated_at: self.updated_at,
653                references: self.references,
654            },
655        )
656    }
657
658    fn from_key_value(key: Self::Key, value: Self::Value) -> Self {
659        Self {
660            source_id: key.source_id,
661            updated_at: value.updated_at,
662            references: value.references,
663        }
664    }
665
666    fn key(&self) -> Self::Key {
667        SourceReferencesKey {
668            source_id: self.source_id,
669        }
670    }
671}
672
673/// A newtype wrapper for [`CatalogItemId`] that is only for the "system" namespace.
674#[derive(Debug, Copy, Clone, Ord, PartialOrd, PartialEq, Eq)]
675pub struct SystemCatalogItemId(u64);
676
677impl TryFrom<CatalogItemId> for SystemCatalogItemId {
678    type Error = &'static str;
679
680    fn try_from(val: CatalogItemId) -> Result<Self, Self::Error> {
681        match val {
682            CatalogItemId::System(x) => Ok(SystemCatalogItemId(x)),
683            CatalogItemId::IntrospectionSourceIndex(_) => Err("introspection_source_index"),
684            CatalogItemId::User(_) => Err("user"),
685            CatalogItemId::Transient(_) => Err("transient"),
686        }
687    }
688}
689
690impl From<SystemCatalogItemId> for CatalogItemId {
691    fn from(val: SystemCatalogItemId) -> Self {
692        CatalogItemId::System(val.0)
693    }
694}
695
696/// A newtype wrapper for [`CatalogItemId`] that is only for the "introspection source index" namespace.
697#[derive(Debug, Copy, Clone, Ord, PartialOrd, PartialEq, Eq)]
698pub struct IntrospectionSourceIndexCatalogItemId(u64);
699
700impl TryFrom<CatalogItemId> for IntrospectionSourceIndexCatalogItemId {
701    type Error = &'static str;
702
703    fn try_from(val: CatalogItemId) -> Result<Self, Self::Error> {
704        match val {
705            CatalogItemId::System(_) => Err("system"),
706            CatalogItemId::IntrospectionSourceIndex(x) => {
707                Ok(IntrospectionSourceIndexCatalogItemId(x))
708            }
709            CatalogItemId::User(_) => Err("user"),
710            CatalogItemId::Transient(_) => Err("transient"),
711        }
712    }
713}
714
715impl From<IntrospectionSourceIndexCatalogItemId> for CatalogItemId {
716    fn from(val: IntrospectionSourceIndexCatalogItemId) -> Self {
717        CatalogItemId::IntrospectionSourceIndex(val.0)
718    }
719}
720
721/// A newtype wrapper for [`GlobalId`] that is only for the "system" namespace.
722#[derive(Debug, Copy, Clone, Ord, PartialOrd, PartialEq, Eq)]
723pub struct SystemGlobalId(u64);
724
725impl TryFrom<GlobalId> for SystemGlobalId {
726    type Error = &'static str;
727
728    fn try_from(val: GlobalId) -> Result<Self, Self::Error> {
729        match val {
730            GlobalId::System(x) => Ok(SystemGlobalId(x)),
731            GlobalId::IntrospectionSourceIndex(_) => Err("introspection_source_index"),
732            GlobalId::User(_) => Err("user"),
733            GlobalId::Transient(_) => Err("transient"),
734            GlobalId::Explain => Err("explain"),
735        }
736    }
737}
738
739impl From<SystemGlobalId> for GlobalId {
740    fn from(val: SystemGlobalId) -> Self {
741        GlobalId::System(val.0)
742    }
743}
744
745/// A newtype wrapper for [`GlobalId`] that is only for the "introspection source index" namespace.
746#[derive(Debug, Copy, Clone, Ord, PartialOrd, PartialEq, Eq)]
747pub struct IntrospectionSourceIndexGlobalId(u64);
748
749impl TryFrom<GlobalId> for IntrospectionSourceIndexGlobalId {
750    type Error = &'static str;
751
752    fn try_from(val: GlobalId) -> Result<Self, Self::Error> {
753        match val {
754            GlobalId::System(_) => Err("system"),
755            GlobalId::IntrospectionSourceIndex(x) => Ok(IntrospectionSourceIndexGlobalId(x)),
756            GlobalId::User(_) => Err("user"),
757            GlobalId::Transient(_) => Err("transient"),
758            GlobalId::Explain => Err("explain"),
759        }
760    }
761}
762
763impl From<IntrospectionSourceIndexGlobalId> for GlobalId {
764    fn from(val: IntrospectionSourceIndexGlobalId) -> Self {
765        GlobalId::IntrospectionSourceIndex(val.0)
766    }
767}
768
769#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
770pub struct SystemObjectDescription {
771    pub schema_name: String,
772    pub object_type: CatalogItemType,
773    pub object_name: String,
774}
775
776#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq)]
777pub struct SystemObjectUniqueIdentifier {
778    pub catalog_id: CatalogItemId,
779    pub global_id: GlobalId,
780    pub fingerprint: String,
781}
782
783impl SystemObjectUniqueIdentifier {
784    pub fn runtime_alterable(&self) -> bool {
785        self.fingerprint == RUNTIME_ALTERABLE_FINGERPRINT_SENTINEL
786    }
787}
788
789/// Functions can share the same name as any other catalog item type
790/// within a given schema.
791/// For example, a function can have the same name as a type, e.g.
792/// 'date'.
793/// As such, system objects are keyed in the catalog storage by the
794/// tuple (schema_name, object_type, object_name), which is guaranteed
795/// to be unique.
796#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq)]
797pub struct SystemObjectMapping {
798    pub description: SystemObjectDescription,
799    pub unique_identifier: SystemObjectUniqueIdentifier,
800}
801
802impl DurableType for SystemObjectMapping {
803    type Key = GidMappingKey;
804    type Value = GidMappingValue;
805
806    fn into_key_value(self) -> (Self::Key, Self::Value) {
807        (
808            GidMappingKey {
809                schema_name: self.description.schema_name,
810                object_type: self.description.object_type,
811                object_name: self.description.object_name,
812            },
813            GidMappingValue {
814                catalog_id: self
815                    .unique_identifier
816                    .catalog_id
817                    .try_into()
818                    .expect("catalog_id to be in the system namespace"),
819                global_id: self
820                    .unique_identifier
821                    .global_id
822                    .try_into()
823                    .expect("collection_id to be in the system namespace"),
824                fingerprint: self.unique_identifier.fingerprint,
825            },
826        )
827    }
828
829    fn from_key_value(key: Self::Key, value: Self::Value) -> Self {
830        Self {
831            description: SystemObjectDescription {
832                schema_name: key.schema_name,
833                object_type: key.object_type,
834                object_name: key.object_name,
835            },
836            unique_identifier: SystemObjectUniqueIdentifier {
837                catalog_id: value.catalog_id.into(),
838                global_id: value.global_id.into(),
839                fingerprint: value.fingerprint,
840            },
841        }
842    }
843
844    fn key(&self) -> Self::Key {
845        GidMappingKey {
846            schema_name: self.description.schema_name.clone(),
847            object_type: self.description.object_type.clone(),
848            object_name: self.description.object_name.clone(),
849        }
850    }
851}
852
853#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq)]
854pub struct DefaultPrivilege {
855    pub object: DefaultPrivilegeObject,
856    pub acl_item: DefaultPrivilegeAclItem,
857}
858
859impl DurableType for DefaultPrivilege {
860    type Key = DefaultPrivilegesKey;
861    type Value = DefaultPrivilegesValue;
862
863    fn into_key_value(self) -> (Self::Key, Self::Value) {
864        (
865            DefaultPrivilegesKey {
866                role_id: self.object.role_id,
867                database_id: self.object.database_id,
868                schema_id: self.object.schema_id,
869                object_type: self.object.object_type,
870                grantee: self.acl_item.grantee,
871            },
872            DefaultPrivilegesValue {
873                privileges: self.acl_item.acl_mode,
874            },
875        )
876    }
877
878    fn from_key_value(key: Self::Key, value: Self::Value) -> Self {
879        Self {
880            object: DefaultPrivilegeObject {
881                role_id: key.role_id,
882                database_id: key.database_id,
883                schema_id: key.schema_id,
884                object_type: key.object_type,
885            },
886            acl_item: DefaultPrivilegeAclItem {
887                grantee: key.grantee,
888                acl_mode: value.privileges,
889            },
890        }
891    }
892
893    fn key(&self) -> Self::Key {
894        DefaultPrivilegesKey {
895            role_id: self.object.role_id,
896            database_id: self.object.database_id,
897            schema_id: self.object.schema_id,
898            object_type: self.object.object_type,
899            grantee: self.acl_item.grantee,
900        }
901    }
902}
903
904#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq)]
905pub struct Comment {
906    pub object_id: CommentObjectId,
907    pub sub_component: Option<usize>,
908    pub comment: String,
909}
910
911impl DurableType for Comment {
912    type Key = CommentKey;
913    type Value = CommentValue;
914
915    fn into_key_value(self) -> (Self::Key, Self::Value) {
916        (
917            CommentKey {
918                object_id: self.object_id,
919                sub_component: self.sub_component,
920            },
921            CommentValue {
922                comment: self.comment,
923            },
924        )
925    }
926
927    fn from_key_value(key: Self::Key, value: Self::Value) -> Self {
928        Self {
929            object_id: key.object_id,
930            sub_component: key.sub_component,
931            comment: value.comment,
932        }
933    }
934
935    fn key(&self) -> Self::Key {
936        CommentKey {
937            object_id: self.object_id,
938            sub_component: self.sub_component,
939        }
940    }
941}
942
943#[derive(Debug, Clone, PartialEq, Eq)]
944pub struct IdAlloc {
945    pub name: String,
946    pub next_id: u64,
947}
948
949impl DurableType for IdAlloc {
950    type Key = IdAllocKey;
951    type Value = IdAllocValue;
952
953    fn into_key_value(self) -> (Self::Key, Self::Value) {
954        (
955            IdAllocKey { name: self.name },
956            IdAllocValue {
957                next_id: self.next_id,
958            },
959        )
960    }
961
962    fn from_key_value(key: Self::Key, value: Self::Value) -> Self {
963        Self {
964            name: key.name,
965            next_id: value.next_id,
966        }
967    }
968
969    fn key(&self) -> Self::Key {
970        IdAllocKey {
971            name: self.name.clone(),
972        }
973    }
974}
975
976#[derive(Debug, Clone, PartialEq, Eq)]
977pub struct Config {
978    pub key: String,
979    pub value: u64,
980}
981
982impl DurableType for Config {
983    type Key = ConfigKey;
984    type Value = ConfigValue;
985
986    fn into_key_value(self) -> (Self::Key, Self::Value) {
987        (
988            ConfigKey { key: self.key },
989            ConfigValue { value: self.value },
990        )
991    }
992
993    fn from_key_value(key: Self::Key, value: Self::Value) -> Self {
994        Self {
995            key: key.key,
996            value: value.value,
997        }
998    }
999
1000    fn key(&self) -> Self::Key {
1001        ConfigKey {
1002            key: self.key.clone(),
1003        }
1004    }
1005}
1006
1007#[derive(Debug, Clone)]
1008pub struct Setting {
1009    pub name: String,
1010    pub value: String,
1011}
1012
1013impl DurableType for Setting {
1014    type Key = SettingKey;
1015    type Value = SettingValue;
1016
1017    fn into_key_value(self) -> (Self::Key, Self::Value) {
1018        (
1019            SettingKey { name: self.name },
1020            SettingValue { value: self.value },
1021        )
1022    }
1023
1024    fn from_key_value(key: Self::Key, value: Self::Value) -> Self {
1025        Self {
1026            name: key.name,
1027            value: value.value,
1028        }
1029    }
1030
1031    fn key(&self) -> Self::Key {
1032        SettingKey {
1033            name: self.name.clone(),
1034        }
1035    }
1036}
1037
1038#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq)]
1039pub struct SystemConfiguration {
1040    pub name: String,
1041    pub value: String,
1042}
1043
1044impl DurableType for SystemConfiguration {
1045    type Key = ServerConfigurationKey;
1046    type Value = ServerConfigurationValue;
1047
1048    fn into_key_value(self) -> (Self::Key, Self::Value) {
1049        (
1050            ServerConfigurationKey { name: self.name },
1051            ServerConfigurationValue { value: self.value },
1052        )
1053    }
1054
1055    fn from_key_value(key: Self::Key, value: Self::Value) -> Self {
1056        Self {
1057            name: key.name,
1058            value: value.value,
1059        }
1060    }
1061
1062    fn key(&self) -> Self::Key {
1063        ServerConfigurationKey {
1064            name: self.name.clone(),
1065        }
1066    }
1067}
1068
1069/// A single cluster-coherent scoped system-parameter override: parameter `name`
1070/// has value `value` on the cluster `cluster_id`.
1071///
1072/// This is the in-memory shape of the durable `cluster_system_configurations`
1073/// collection that backs cluster-coherent scoped feature flags. The collection
1074/// — keyed by `(ClusterId, name)` — is the analog of `system_configurations`
1075/// (`ALTER SYSTEM`), but for per-cluster values; it is written solely by the
1076/// system-parameter sync loop, and the coordinator's in-memory working copy is
1077/// maintained from it on every catalog update.
1078#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq)]
1079pub struct ClusterSystemConfiguration {
1080    pub cluster_id: ClusterId,
1081    pub name: String,
1082    pub value: String,
1083}
1084
1085impl DurableType for ClusterSystemConfiguration {
1086    type Key = ClusterSystemConfigurationKey;
1087    type Value = ClusterSystemConfigurationValue;
1088
1089    fn into_key_value(self) -> (Self::Key, Self::Value) {
1090        (
1091            ClusterSystemConfigurationKey {
1092                cluster_id: self.cluster_id,
1093                name: self.name,
1094            },
1095            ClusterSystemConfigurationValue { value: self.value },
1096        )
1097    }
1098
1099    fn from_key_value(key: Self::Key, value: Self::Value) -> Self {
1100        Self {
1101            cluster_id: key.cluster_id,
1102            name: key.name,
1103            value: value.value,
1104        }
1105    }
1106
1107    fn key(&self) -> Self::Key {
1108        ClusterSystemConfigurationKey {
1109            cluster_id: self.cluster_id,
1110            name: self.name.clone(),
1111        }
1112    }
1113}
1114
1115/// A single replica-local scoped system-parameter override: parameter `name`
1116/// has value `value` on the replica `replica_id`.
1117///
1118/// This is the in-memory shape of the durable `replica_system_configurations`
1119/// collection that backs replica-local scoped feature flags. The collection —
1120/// keyed by `(ReplicaId, name)` — is the analog of `system_configurations`
1121/// (`ALTER SYSTEM`), but for per-replica values; it is written solely by the
1122/// system-parameter sync loop, and the coordinator's in-memory working copy is
1123/// maintained from it on every catalog update.
1124#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq)]
1125pub struct ReplicaSystemConfiguration {
1126    pub replica_id: ReplicaId,
1127    pub name: String,
1128    pub value: String,
1129}
1130
1131impl DurableType for ReplicaSystemConfiguration {
1132    type Key = ReplicaSystemConfigurationKey;
1133    type Value = ReplicaSystemConfigurationValue;
1134
1135    fn into_key_value(self) -> (Self::Key, Self::Value) {
1136        (
1137            ReplicaSystemConfigurationKey {
1138                replica_id: self.replica_id,
1139                name: self.name,
1140            },
1141            ReplicaSystemConfigurationValue { value: self.value },
1142        )
1143    }
1144
1145    fn from_key_value(key: Self::Key, value: Self::Value) -> Self {
1146        Self {
1147            replica_id: key.replica_id,
1148            name: key.name,
1149            value: value.value,
1150        }
1151    }
1152
1153    fn key(&self) -> Self::Key {
1154        ReplicaSystemConfigurationKey {
1155            replica_id: self.replica_id,
1156            name: self.name.clone(),
1157        }
1158    }
1159}
1160
1161impl DurableType for MzAclItem {
1162    type Key = SystemPrivilegesKey;
1163    type Value = SystemPrivilegesValue;
1164
1165    fn into_key_value(self) -> (Self::Key, Self::Value) {
1166        (
1167            SystemPrivilegesKey {
1168                grantee: self.grantee,
1169                grantor: self.grantor,
1170            },
1171            SystemPrivilegesValue {
1172                acl_mode: self.acl_mode,
1173            },
1174        )
1175    }
1176
1177    fn from_key_value(key: Self::Key, value: Self::Value) -> Self {
1178        Self {
1179            grantee: key.grantee,
1180            grantor: key.grantor,
1181            acl_mode: value.acl_mode,
1182        }
1183    }
1184
1185    fn key(&self) -> Self::Key {
1186        SystemPrivilegesKey {
1187            grantee: self.grantee,
1188            grantor: self.grantor,
1189        }
1190    }
1191}
1192
1193#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq)]
1194pub struct AuditLog {
1195    pub event: VersionedEvent,
1196}
1197
1198impl DurableType for AuditLog {
1199    type Key = AuditLogKey;
1200    type Value = ();
1201
1202    fn into_key_value(self) -> (Self::Key, Self::Value) {
1203        (AuditLogKey { event: self.event }, ())
1204    }
1205
1206    fn from_key_value(key: Self::Key, _value: Self::Value) -> Self {
1207        Self { event: key.event }
1208    }
1209
1210    fn key(&self) -> Self::Key {
1211        AuditLogKey {
1212            event: self.event.clone(),
1213        }
1214    }
1215}
1216
1217#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq)]
1218pub struct StorageCollectionMetadata {
1219    pub id: GlobalId,
1220    pub shard: ShardId,
1221}
1222
1223impl DurableType for StorageCollectionMetadata {
1224    type Key = StorageCollectionMetadataKey;
1225    type Value = StorageCollectionMetadataValue;
1226
1227    fn into_key_value(self) -> (Self::Key, Self::Value) {
1228        (
1229            StorageCollectionMetadataKey { id: self.id },
1230            StorageCollectionMetadataValue { shard: self.shard },
1231        )
1232    }
1233
1234    fn from_key_value(key: Self::Key, value: Self::Value) -> Self {
1235        Self {
1236            id: key.id,
1237            shard: value.shard,
1238        }
1239    }
1240
1241    fn key(&self) -> Self::Key {
1242        StorageCollectionMetadataKey { id: self.id }
1243    }
1244}
1245
1246#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq)]
1247pub struct UnfinalizedShard {
1248    pub shard: ShardId,
1249}
1250
1251impl DurableType for UnfinalizedShard {
1252    type Key = UnfinalizedShardKey;
1253    type Value = ();
1254
1255    fn into_key_value(self) -> (Self::Key, Self::Value) {
1256        (UnfinalizedShardKey { shard: self.shard }, ())
1257    }
1258
1259    fn from_key_value(key: Self::Key, _value: Self::Value) -> Self {
1260        Self { shard: key.shard }
1261    }
1262
1263    fn key(&self) -> Self::Key {
1264        UnfinalizedShardKey {
1265            shard: self.shard.clone(),
1266        }
1267    }
1268}
1269
1270// Structs used internally to represent on-disk state.
1271
1272/// A snapshot of the current on-disk state.
1273#[derive(Debug, Clone, PartialEq, Eq, Default)]
1274pub struct Snapshot {
1275    pub databases: BTreeMap<proto::DatabaseKey, proto::DatabaseValue>,
1276    pub schemas: BTreeMap<proto::SchemaKey, proto::SchemaValue>,
1277    pub roles: BTreeMap<proto::RoleKey, proto::RoleValue>,
1278    pub role_auth: BTreeMap<proto::RoleAuthKey, proto::RoleAuthValue>,
1279    pub items: BTreeMap<proto::ItemKey, proto::ItemValue>,
1280    pub comments: BTreeMap<proto::CommentKey, proto::CommentValue>,
1281    pub clusters: BTreeMap<proto::ClusterKey, proto::ClusterValue>,
1282    pub network_policies: BTreeMap<proto::NetworkPolicyKey, proto::NetworkPolicyValue>,
1283    pub cluster_replicas: BTreeMap<proto::ClusterReplicaKey, proto::ClusterReplicaValue>,
1284    pub introspection_sources: BTreeMap<
1285        proto::ClusterIntrospectionSourceIndexKey,
1286        proto::ClusterIntrospectionSourceIndexValue,
1287    >,
1288    pub id_allocator: BTreeMap<proto::IdAllocKey, proto::IdAllocValue>,
1289    pub configs: BTreeMap<proto::ConfigKey, proto::ConfigValue>,
1290    pub settings: BTreeMap<proto::SettingKey, proto::SettingValue>,
1291    pub system_object_mappings: BTreeMap<proto::GidMappingKey, proto::GidMappingValue>,
1292    pub system_configurations:
1293        BTreeMap<proto::ServerConfigurationKey, proto::ServerConfigurationValue>,
1294    pub cluster_system_configurations:
1295        BTreeMap<proto::ClusterSystemConfigurationKey, proto::ClusterSystemConfigurationValue>,
1296    pub replica_system_configurations:
1297        BTreeMap<proto::ReplicaSystemConfigurationKey, proto::ReplicaSystemConfigurationValue>,
1298    pub default_privileges: BTreeMap<proto::DefaultPrivilegesKey, proto::DefaultPrivilegesValue>,
1299    pub source_references: BTreeMap<proto::SourceReferencesKey, proto::SourceReferencesValue>,
1300    pub system_privileges: BTreeMap<proto::SystemPrivilegesKey, proto::SystemPrivilegesValue>,
1301    pub storage_collection_metadata:
1302        BTreeMap<proto::StorageCollectionMetadataKey, proto::StorageCollectionMetadataValue>,
1303    pub unfinalized_shards: BTreeMap<proto::UnfinalizedShardKey, ()>,
1304    pub txn_wal_shard: BTreeMap<(), proto::TxnWalShardValue>,
1305}
1306
1307impl Snapshot {
1308    pub fn empty() -> Snapshot {
1309        Snapshot::default()
1310    }
1311}
1312
1313/// Token used to fence out other processes.
1314///
1315/// Every time a new process takes over, the `epoch` should be incremented.
1316/// Every time a new version is deployed, the `deploy` generation should be incremented.
1317#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1318#[cfg_attr(test, derive(Arbitrary))]
1319pub struct FenceToken {
1320    pub(crate) deploy_generation: u64,
1321    pub(crate) epoch: Epoch,
1322}
1323
1324impl PartialOrd for FenceToken {
1325    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1326        Some(self.cmp(other))
1327    }
1328}
1329
1330impl Ord for FenceToken {
1331    fn cmp(&self, other: &Self) -> Ordering {
1332        self.deploy_generation
1333            .cmp(&other.deploy_generation)
1334            .then(self.epoch.cmp(&other.epoch))
1335    }
1336}
1337
1338#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord, Hash)]
1339pub struct SettingKey {
1340    pub(crate) name: String,
1341}
1342
1343#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord)]
1344pub struct SettingValue {
1345    pub(crate) value: String,
1346}
1347
1348#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord, Hash)]
1349pub struct IdAllocKey {
1350    pub(crate) name: String,
1351}
1352
1353#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord)]
1354pub struct IdAllocValue {
1355    pub(crate) next_id: u64,
1356}
1357
1358#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord, Hash)]
1359pub struct GidMappingKey {
1360    pub(crate) schema_name: String,
1361    pub(crate) object_type: CatalogItemType,
1362    pub(crate) object_name: String,
1363}
1364
1365#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord)]
1366pub struct GidMappingValue {
1367    pub(crate) catalog_id: SystemCatalogItemId,
1368    pub(crate) global_id: SystemGlobalId,
1369    pub(crate) fingerprint: String,
1370}
1371
1372#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord, Hash)]
1373pub struct ClusterKey {
1374    pub(crate) id: ClusterId,
1375}
1376
1377#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord)]
1378pub struct ClusterValue {
1379    pub(crate) name: String,
1380    pub(crate) owner_id: RoleId,
1381    pub(crate) privileges: Vec<MzAclItem>,
1382    pub(crate) config: ClusterConfig,
1383}
1384
1385#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord, Hash)]
1386pub struct ClusterIntrospectionSourceIndexKey {
1387    pub(crate) cluster_id: ClusterId,
1388    pub(crate) name: String,
1389}
1390
1391#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord)]
1392pub struct ClusterIntrospectionSourceIndexValue {
1393    pub(crate) catalog_id: IntrospectionSourceIndexCatalogItemId,
1394    pub(crate) global_id: IntrospectionSourceIndexGlobalId,
1395    pub(crate) oid: u32,
1396}
1397
1398#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord, Hash)]
1399pub struct ClusterReplicaKey {
1400    pub(crate) id: ReplicaId,
1401}
1402
1403#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord)]
1404pub struct ClusterReplicaValue {
1405    pub(crate) cluster_id: ClusterId,
1406    pub(crate) name: String,
1407    pub(crate) config: ReplicaConfig,
1408    pub(crate) owner_id: RoleId,
1409}
1410
1411#[derive(Clone, Copy, Debug, PartialOrd, PartialEq, Eq, Ord, Hash)]
1412#[cfg_attr(test, derive(Arbitrary))]
1413pub struct DatabaseKey {
1414    pub(crate) id: DatabaseId,
1415}
1416
1417#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord)]
1418#[cfg_attr(test, derive(Arbitrary))]
1419pub struct DatabaseValue {
1420    pub(crate) name: String,
1421    pub(crate) owner_id: RoleId,
1422    pub(crate) privileges: Vec<MzAclItem>,
1423    pub(crate) oid: u32,
1424}
1425
1426#[derive(Clone, Copy, Debug, PartialOrd, PartialEq, Eq, Ord, Hash)]
1427#[cfg_attr(test, derive(Arbitrary))]
1428pub struct SourceReferencesKey {
1429    pub(crate) source_id: CatalogItemId,
1430}
1431
1432#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord)]
1433#[cfg_attr(test, derive(Arbitrary))]
1434pub struct SourceReferencesValue {
1435    pub(crate) references: Vec<SourceReference>,
1436    pub(crate) updated_at: u64,
1437}
1438
1439#[derive(Clone, Copy, Debug, PartialOrd, PartialEq, Eq, Ord, Hash)]
1440#[cfg_attr(test, derive(Arbitrary))]
1441pub struct SchemaKey {
1442    pub(crate) id: SchemaId,
1443}
1444
1445#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord)]
1446#[cfg_attr(test, derive(Arbitrary))]
1447pub struct SchemaValue {
1448    pub(crate) database_id: Option<DatabaseId>,
1449    pub(crate) name: String,
1450    pub(crate) owner_id: RoleId,
1451    pub(crate) privileges: Vec<MzAclItem>,
1452    pub(crate) oid: u32,
1453}
1454
1455#[derive(Clone, PartialOrd, PartialEq, Eq, Ord, Hash, Debug)]
1456#[cfg_attr(test, derive(Arbitrary))]
1457pub struct ItemKey {
1458    pub(crate) id: CatalogItemId,
1459}
1460
1461#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord)]
1462#[cfg_attr(test, derive(Arbitrary))]
1463pub struct ItemValue {
1464    pub(crate) schema_id: SchemaId,
1465    pub(crate) name: String,
1466    pub(crate) create_sql: String,
1467    pub(crate) owner_id: RoleId,
1468    pub(crate) privileges: Vec<MzAclItem>,
1469    pub(crate) oid: u32,
1470    pub(crate) global_id: GlobalId,
1471    pub(crate) extra_versions: BTreeMap<RelationVersion, GlobalId>,
1472}
1473
1474impl ItemValue {
1475    pub fn item_type(&self) -> CatalogItemType {
1476        item_type(&self.create_sql)
1477    }
1478}
1479
1480pub fn item_type(create_sql: &str) -> CatalogItemType {
1481    // NOTE(benesch): the implementation of this method is hideous, but is
1482    // there a better alternative? Storing the object type alongside the
1483    // `create_sql` would introduce the possibility of skew.
1484    let mut tokens = create_sql.split_whitespace();
1485    assert_eq!(tokens.next(), Some("CREATE"));
1486
1487    // Read away item type modifiers, if any.
1488    let next_token = match tokens.next() {
1489        Some("TEMPORARY") | Some("REPLACEMENT") => tokens.next(),
1490        token => token,
1491    };
1492
1493    match next_token {
1494        Some("TABLE") => CatalogItemType::Table,
1495        Some("SOURCE") | Some("SUBSOURCE") => CatalogItemType::Source,
1496        Some("SINK") => CatalogItemType::Sink,
1497        Some("VIEW") => CatalogItemType::View,
1498        Some("MATERIALIZED") => {
1499            assert_eq!(tokens.next(), Some("VIEW"));
1500            CatalogItemType::MaterializedView
1501        }
1502        Some("INDEX") => CatalogItemType::Index,
1503        Some("TYPE") => CatalogItemType::Type,
1504        Some("FUNCTION") => CatalogItemType::Func,
1505        Some("SECRET") => CatalogItemType::Secret,
1506        Some("CONNECTION") => CatalogItemType::Connection,
1507        _ => panic!("unexpected create sql: {}", create_sql),
1508    }
1509}
1510
1511#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord)]
1512pub struct CommentKey {
1513    pub(crate) object_id: CommentObjectId,
1514    pub(crate) sub_component: Option<usize>,
1515}
1516
1517#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord)]
1518#[cfg_attr(test, derive(Arbitrary))]
1519pub struct CommentValue {
1520    pub(crate) comment: String,
1521}
1522
1523#[derive(Clone, PartialOrd, PartialEq, Eq, Ord, Hash, Debug)]
1524pub struct RoleKey {
1525    pub(crate) id: RoleId,
1526}
1527
1528#[derive(Clone, PartialOrd, PartialEq, Eq, Ord, Debug)]
1529pub struct RoleValue {
1530    pub(crate) name: String,
1531    pub(crate) attributes: RoleAttributes,
1532    pub(crate) membership: RoleMembership,
1533    pub(crate) vars: RoleVars,
1534    pub(crate) oid: u32,
1535}
1536
1537#[derive(Clone, PartialOrd, PartialEq, Eq, Ord, Hash, Debug)]
1538pub struct NetworkPolicyKey {
1539    pub(crate) id: NetworkPolicyId,
1540}
1541
1542#[derive(Clone, PartialOrd, PartialEq, Eq, Ord, Debug)]
1543pub struct NetworkPolicyValue {
1544    pub(crate) name: String,
1545    pub(crate) rules: Vec<NetworkPolicyRule>,
1546    pub(crate) owner_id: RoleId,
1547    pub(crate) privileges: Vec<MzAclItem>,
1548    pub(crate) oid: u32,
1549}
1550
1551#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord)]
1552pub struct ConfigKey {
1553    pub(crate) key: String,
1554}
1555
1556#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord, Hash)]
1557pub struct ConfigValue {
1558    pub(crate) value: u64,
1559}
1560
1561#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord, Hash)]
1562pub struct AuditLogKey {
1563    pub(crate) event: VersionedEvent,
1564}
1565
1566#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord, Hash)]
1567pub struct StorageCollectionMetadataKey {
1568    pub(crate) id: GlobalId,
1569}
1570
1571/// This value is stored transparently, however, it should only ever be
1572/// manipulated by the storage controller.
1573#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord)]
1574pub struct StorageCollectionMetadataValue {
1575    pub(crate) shard: ShardId,
1576}
1577
1578/// This value is stored transparently, however, it should only ever be
1579/// manipulated by the storage controller.
1580#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord)]
1581pub struct UnfinalizedShardKey {
1582    pub(crate) shard: ShardId,
1583}
1584
1585/// This value is stored transparently, however, it should only ever be
1586/// manipulated by the storage controller.
1587#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord)]
1588pub struct TxnWalShardValue {
1589    pub(crate) shard: ShardId,
1590}
1591
1592#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord, Hash)]
1593pub struct ServerConfigurationKey {
1594    pub(crate) name: String,
1595}
1596
1597#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord)]
1598pub struct ServerConfigurationValue {
1599    pub(crate) value: String,
1600}
1601
1602#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord, Hash)]
1603pub struct ClusterSystemConfigurationKey {
1604    pub(crate) cluster_id: ClusterId,
1605    pub(crate) name: String,
1606}
1607
1608#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord)]
1609pub struct ClusterSystemConfigurationValue {
1610    pub(crate) value: String,
1611}
1612
1613#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord, Hash)]
1614pub struct ReplicaSystemConfigurationKey {
1615    pub(crate) replica_id: ReplicaId,
1616    pub(crate) name: String,
1617}
1618
1619#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord)]
1620pub struct ReplicaSystemConfigurationValue {
1621    pub(crate) value: String,
1622}
1623
1624#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord, Hash)]
1625pub struct DefaultPrivilegesKey {
1626    pub(crate) role_id: RoleId,
1627    pub(crate) database_id: Option<DatabaseId>,
1628    pub(crate) schema_id: Option<SchemaId>,
1629    pub(crate) object_type: ObjectType,
1630    pub(crate) grantee: RoleId,
1631}
1632
1633#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord, Hash)]
1634pub struct DefaultPrivilegesValue {
1635    pub(crate) privileges: AclMode,
1636}
1637
1638#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord, Hash)]
1639pub struct SystemPrivilegesKey {
1640    pub(crate) grantee: RoleId,
1641    pub(crate) grantor: RoleId,
1642}
1643
1644#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord, Hash)]
1645pub struct SystemPrivilegesValue {
1646    pub(crate) acl_mode: AclMode,
1647}
1648
1649#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord, Hash)]
1650pub struct RoleAuthKey {
1651    // TODO(auth): Depending on what the future holds, here is where
1652    // we might also want to key by a `version` field.
1653    // That way we can store password versions or what have you.
1654    pub(crate) role_id: RoleId,
1655}
1656
1657#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord, Hash)]
1658pub struct RoleAuthValue {
1659    pub(crate) password_hash: Option<String>,
1660    pub(crate) updated_at: u64,
1661}
1662
1663#[cfg(test)]
1664mod test {
1665    use mz_proto::{ProtoType, RustType};
1666    use proptest::prelude::*;
1667
1668    use super::{
1669        DatabaseKey, DatabaseValue, FenceToken, ItemKey, ItemValue, SchemaKey, SchemaValue,
1670    };
1671    use crate::durable::Epoch;
1672
1673    proptest! {
1674        #[mz_ore::test]
1675        #[cfg_attr(miri, ignore)] // slow
1676        fn proptest_database_key_roundtrip(key: DatabaseKey) {
1677            let proto = key.into_proto();
1678            let round = proto.into_rust().expect("to roundtrip");
1679
1680            prop_assert_eq!(key, round);
1681        }
1682
1683        #[mz_ore::test]
1684        #[cfg_attr(miri, ignore)] // slow
1685        fn proptest_database_value_roundtrip(value: DatabaseValue) {
1686            let proto = value.into_proto();
1687            let round = proto.into_rust().expect("to roundtrip");
1688
1689            prop_assert_eq!(value, round);
1690        }
1691
1692        #[mz_ore::test]
1693        #[cfg_attr(miri, ignore)] // slow
1694        fn proptest_schema_key_roundtrip(key: SchemaKey) {
1695            let proto = key.into_proto();
1696            let round = proto.into_rust().expect("to roundtrip");
1697
1698            prop_assert_eq!(key, round);
1699        }
1700
1701        #[mz_ore::test]
1702        #[cfg_attr(miri, ignore)] // slow
1703        fn proptest_schema_value_roundtrip(value: SchemaValue) {
1704            let proto = value.into_proto();
1705            let round = proto.into_rust().expect("to roundtrip");
1706
1707            prop_assert_eq!(value, round);
1708        }
1709
1710        #[mz_ore::test]
1711        #[cfg_attr(miri, ignore)] // slow
1712        fn proptest_item_key_roundtrip(key: ItemKey) {
1713            let proto = key.into_proto();
1714            let round = proto.into_rust().expect("to roundtrip");
1715
1716            prop_assert_eq!(key, round);
1717        }
1718
1719        #[mz_ore::test]
1720        #[cfg_attr(miri, ignore)] // slow
1721        fn proptest_item_value_roundtrip(value: ItemValue) {
1722            let proto = value.into_proto();
1723            let round = proto.into_rust().expect("to roundtrip");
1724
1725            prop_assert_eq!(value, round);
1726        }
1727    }
1728
1729    #[mz_ore::test]
1730    fn test_fence_token_order() {
1731        let ft1 = FenceToken {
1732            deploy_generation: 10,
1733            epoch: Epoch::new(20).expect("non-zero"),
1734        };
1735        let ft2 = FenceToken {
1736            deploy_generation: 10,
1737            epoch: Epoch::new(19).expect("non-zero"),
1738        };
1739
1740        assert!(ft1 > ft2);
1741
1742        let ft3 = FenceToken {
1743            deploy_generation: 11,
1744            epoch: Epoch::new(10).expect("non-zero"),
1745        };
1746
1747        assert!(ft3 > ft1);
1748
1749        let ft4 = FenceToken {
1750            deploy_generation: 11,
1751            epoch: Epoch::new(30).expect("non-zero"),
1752        };
1753
1754        assert!(ft4 > ft1);
1755    }
1756}