mz_catalog/memory/
error.rs
1use std::fmt;
11
12use mz_ore::str::StrExt;
13use mz_proto::TryFromProtoError;
14use mz_sql::catalog::CatalogError as SqlCatalogError;
15use mz_sql::session::vars::VarError;
16
17#[derive(Debug, thiserror::Error)]
18#[error(transparent)]
19pub struct Error {
20 #[from]
21 pub kind: ErrorKind,
22}
23
24#[derive(Debug, thiserror::Error)]
25pub enum ErrorKind {
26 #[error("corrupt catalog: {detail}")]
27 Corruption { detail: String },
28 #[error("oid counter overflows i64")]
29 OidExhaustion,
30 #[error(transparent)]
31 Sql(#[from] SqlCatalogError),
32 #[error("unacceptable schema name '{0}'")]
33 ReservedSchemaName(String),
34 #[error("role name {} is reserved", .0.quoted())]
35 ReservedRoleName(String),
36 #[error("role name {} is reserved", .0.quoted())]
37 ReservedSystemRoleName(String),
38 #[error("role name {} cannot be granted", .0.quoted())]
39 UngrantableRoleName(String),
40 #[error("cluster name {} is reserved", .0.quoted())]
41 ReservedClusterName(String),
42 #[error("network policy name {} is reserved", .0.quoted())]
43 ReservedNetworkPolicyName(String),
44 #[error("system network policy '{0}' cannot be modified")]
45 ReadOnlyNetworkPolicy(String),
46 #[error("replica name {} is reserved", .0.quoted())]
47 ReservedReplicaName(String),
48 #[error("system cluster '{0}' cannot be modified")]
49 ReadOnlyCluster(String),
50 #[error("system cluster replica '{0}' cannot be modified")]
51 ReadOnlyClusterReplica(String),
52 #[error("system database '{0}' cannot be modified")]
53 ReadOnlyDatabase(String),
54 #[error("system schema '{0}' cannot be modified")]
55 ReadOnlySystemSchema(String),
56 #[error("system item '{0}' cannot be modified")]
57 ReadOnlyItem(String),
58 #[error("cannot drop non-empty schema '{0}'")]
59 SchemaNotEmpty(String),
60 #[error("non-temporary items cannot depend on temporary item '{0}'")]
61 InvalidTemporaryDependency(String),
62 #[error("cannot create temporary item in non-temporary schema")]
63 InvalidTemporarySchema,
64 #[error("catalog item '{depender_name}' depends on system logging, but logging is disabled")]
65 UnsatisfiableLoggingDependency { depender_name: String },
66 #[error("cannot create {object_type} with unstable dependencies")]
68 UnstableDependency {
69 object_type: String,
70 unstable_dependencies: Vec<String>,
71 },
72 #[error(transparent)]
73 AmbiguousRename(#[from] AmbiguousRename),
74 #[error("cannot rename type: {0}")]
75 TypeRename(String),
76 #[error("cannot rename schemas in the ambient database: {}", .0.quoted())]
77 AmbientSchemaRename(String),
78 #[error(
79 "cannot migrate from catalog version {last_seen_version} to version {this_version} (earlier versions might still work): {cause}"
80 )]
81 FailedMigration {
82 last_seen_version: String,
83 this_version: &'static str,
84 cause: String,
85 },
86 #[error("failpoint {0} reached)")]
87 FailpointReached(String),
88 #[error("{0}")]
89 Unstructured(String),
90 #[error(transparent)]
91 Durable(#[from] crate::durable::DurableCatalogError),
92 #[error(transparent)]
93 Uuid(#[from] uuid::Error),
94 #[error("role \"{role_name}\" is a member of role \"{member_name}\"")]
95 CircularRoleMembership {
96 role_name: String,
97 member_name: String,
98 },
99 #[error("cluster '{0}' is managed and cannot be directly modified")]
100 ManagedCluster(String),
101 #[error(transparent)]
102 VarError(#[from] VarError),
103 #[error("unknown cluster replica size {size}")]
104 InvalidClusterReplicaSize { size: String, expected: Vec<String> },
105 #[error("internal error: {0}")]
106 Internal(String),
107}
108
109impl Error {
110 pub fn new(kind: ErrorKind) -> Error {
111 Error { kind }
112 }
113
114 pub fn detail(&self) -> Option<String> {
116 match &self.kind {
117 ErrorKind::ReservedSchemaName(_) => {
118 Some("The prefixes \"mz_\" and \"pg_\" are reserved for system schemas.".into())
119 }
120 ErrorKind::ReservedRoleName(_) => {
121 Some("The role \"public\" and the prefixes \"mz_\" and \"pg_\" are reserved for system roles.".into())
122 }
123 ErrorKind::ReservedSystemRoleName(_) => {
124 Some("The role prefixes \"mz_\" and \"pg_\" are reserved for system roles.".into())
125 }
126 ErrorKind::ReservedClusterName(_) => {
127 Some("The prefixes \"mz_\" and \"pg_\" are reserved for system clusters.".into())
128 }
129 ErrorKind::UnstableDependency {unstable_dependencies, ..} => Some(
130 format!(
131 "The object depends on the following unstable objects:\n {}",
132 unstable_dependencies.join("\n "),
133 )
134 ),
135 ErrorKind::VarError(e) => e.detail(),
136 _ => None,
137 }
138 }
139
140 pub fn hint(&self) -> Option<String> {
142 match &self.kind {
143 ErrorKind::VarError(e) => e.hint(),
144 ErrorKind::InvalidClusterReplicaSize { expected, .. } => Some(format!(
145 "Valid cluster replica sizes are: {}",
146 expected.join(", ")
147 )),
148 _ => None,
149 }
150 }
151}
152
153impl From<SqlCatalogError> for Error {
154 fn from(e: SqlCatalogError) -> Error {
155 Error::new(ErrorKind::from(e))
156 }
157}
158
159impl From<TryFromProtoError> for Error {
160 fn from(e: TryFromProtoError) -> Error {
161 Error::from(crate::durable::CatalogError::from(e))
162 }
163}
164
165impl From<uuid::Error> for Error {
166 fn from(e: uuid::Error) -> Error {
167 Error::new(ErrorKind::from(e))
168 }
169}
170
171impl From<crate::durable::CatalogError> for Error {
172 fn from(e: crate::durable::CatalogError) -> Self {
173 match e {
174 crate::durable::CatalogError::Catalog(e) => Error::new(ErrorKind::from(e)),
175 crate::durable::CatalogError::Durable(e) => Error::new(ErrorKind::from(e)),
176 }
177 }
178}
179
180impl From<VarError> for Error {
181 fn from(e: VarError) -> Self {
182 let kind: ErrorKind = e.into();
183 kind.into()
184 }
185}
186
187#[derive(Debug)]
188pub struct AmbiguousRename {
189 pub depender: String,
190 pub dependee: String,
191 pub message: String,
192}
193
194impl fmt::Display for AmbiguousRename {
196 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
197 if self.depender == self.dependee {
198 write!(
199 f,
200 "renaming conflict: in {}, {}",
201 self.dependee, self.message
202 )
203 } else {
204 write!(
205 f,
206 "renaming conflict: in {}, which uses {}, {}",
207 self.depender, self.dependee, self.message
208 )
209 }
210 }
211}
212
213impl std::error::Error for AmbiguousRename {
214 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
216 None
217 }
218}