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