mz_repr/
global_id.rs
1use std::fmt;
11use std::str::FromStr;
12
13use anyhow::{Error, anyhow};
14use columnar::Columnar;
15use columnation::{Columnation, CopyRegion};
16use mz_lowertest::MzReflect;
17use mz_ore::id_gen::AtomicIdGen;
18use mz_proto::{RustType, TryFromProtoError};
19use proptest_derive::Arbitrary;
20use serde::{Deserialize, Serialize};
21
22use crate::CatalogItemId;
23
24include!(concat!(env!("OUT_DIR"), "/mz_repr.global_id.rs"));
25
26#[derive(
32 Arbitrary,
33 Clone,
34 Copy,
35 Debug,
36 Eq,
37 PartialEq,
38 Ord,
39 PartialOrd,
40 Hash,
41 Serialize,
42 Deserialize,
43 MzReflect,
44 Columnar,
45)]
46pub enum GlobalId {
47 System(u64),
49 IntrospectionSourceIndex(u64),
51 User(u64),
53 Transient(u64),
55 Explain,
57}
58
59static_assertions::assert_eq_size!(GlobalId, [u8; 16]);
62
63impl GlobalId {
64 pub fn is_system(&self) -> bool {
66 matches!(
67 self,
68 GlobalId::System(_) | GlobalId::IntrospectionSourceIndex(_)
69 )
70 }
71
72 pub fn is_user(&self) -> bool {
74 matches!(self, GlobalId::User(_))
75 }
76
77 pub fn is_transient(&self) -> bool {
79 matches!(self, GlobalId::Transient(_))
80 }
81}
82
83impl FromStr for GlobalId {
84 type Err = Error;
85
86 fn from_str(mut s: &str) -> Result<Self, Self::Err> {
87 if s.len() < 2 {
88 return Err(anyhow!("couldn't parse id {}", s));
89 }
90 if s == "Explained Query" {
91 return Ok(GlobalId::Explain);
92 }
93 let tag = s.chars().next().unwrap();
94 s = &s[1..];
95 let variant = match tag {
96 's' => {
97 if Some('i') == s.chars().next() {
98 s = &s[1..];
99 GlobalId::IntrospectionSourceIndex
100 } else {
101 GlobalId::System
102 }
103 }
104 'u' => GlobalId::User,
105 't' => GlobalId::Transient,
106 _ => return Err(anyhow!("couldn't parse id {}", s)),
107 };
108 let val: u64 = s.parse()?;
109 Ok(variant(val))
110 }
111}
112
113impl fmt::Display for GlobalId {
114 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
115 match self {
116 GlobalId::System(id) => write!(f, "s{}", id),
117 GlobalId::IntrospectionSourceIndex(id) => write!(f, "si{}", id),
118 GlobalId::User(id) => write!(f, "u{}", id),
119 GlobalId::Transient(id) => write!(f, "t{}", id),
120 GlobalId::Explain => write!(f, "Explained Query"),
121 }
122 }
123}
124
125impl RustType<ProtoGlobalId> for GlobalId {
126 fn into_proto(&self) -> ProtoGlobalId {
127 use proto_global_id::Kind::*;
128 ProtoGlobalId {
129 kind: Some(match self {
130 GlobalId::System(x) => System(*x),
131 GlobalId::IntrospectionSourceIndex(x) => IntrospectionSourceIndex(*x),
132 GlobalId::User(x) => User(*x),
133 GlobalId::Transient(x) => Transient(*x),
134 GlobalId::Explain => Explain(()),
135 }),
136 }
137 }
138
139 fn from_proto(proto: ProtoGlobalId) -> Result<Self, TryFromProtoError> {
140 use proto_global_id::Kind::*;
141 match proto.kind {
142 Some(System(x)) => Ok(GlobalId::System(x)),
143 Some(IntrospectionSourceIndex(x)) => Ok(GlobalId::IntrospectionSourceIndex(x)),
144 Some(User(x)) => Ok(GlobalId::User(x)),
145 Some(Transient(x)) => Ok(GlobalId::Transient(x)),
146 Some(Explain(_)) => Ok(GlobalId::Explain),
147 None => Err(TryFromProtoError::missing_field("ProtoGlobalId::kind")),
148 }
149 }
150}
151
152impl Columnation for GlobalId {
153 type InnerRegion = CopyRegion<GlobalId>;
154}
155
156#[derive(Debug)]
157pub struct TransientIdGen(AtomicIdGen);
158
159impl TransientIdGen {
160 pub fn new() -> Self {
161 let inner = AtomicIdGen::default();
162 let _ = inner.allocate_id();
164 Self(inner)
165 }
166
167 pub fn allocate_id(&self) -> (CatalogItemId, GlobalId) {
168 let inner = self.0.allocate_id();
169 (CatalogItemId::Transient(inner), GlobalId::Transient(inner))
170 }
171}