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