Skip to main content

mz_catalog/durable/
objects.rs

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