mz_catalog/memory/
error.rs1use 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("failed to get catalog setting: {0}")]
106 SettingError(String),
107 #[error("internal error: {0}")]
108 Internal(String),
109}
110
111impl Error {
112 pub fn new(kind: ErrorKind) -> Error {
113 Error { kind }
114 }
115
116 pub fn detail(&self) -> Option<String> {
118 match &self.kind {
119 ErrorKind::ReservedSchemaName(_) => {
120 Some("The prefixes \"mz_\" and \"pg_\" are reserved for system schemas.".into())
121 }
122 ErrorKind::ReservedRoleName(_) => {
123 Some("The role \"public\" and the prefixes \"mz_\" and \"pg_\" are reserved for system roles.".into())
124 }
125 ErrorKind::ReservedSystemRoleName(_) => {
126 Some("The role prefixes \"mz_\" and \"pg_\" are reserved for system roles.".into())
127 }
128 ErrorKind::ReservedClusterName(_) => {
129 Some("The prefixes \"mz_\" and \"pg_\" are reserved for system clusters.".into())
130 }
131 ErrorKind::UnstableDependency {unstable_dependencies, ..} => Some(
132 format!(
133 "The object depends on the following unstable objects:\n {}",
134 unstable_dependencies.join("\n "),
135 )
136 ),
137 ErrorKind::VarError(e) => e.detail(),
138 _ => None,
139 }
140 }
141
142 pub fn hint(&self) -> Option<String> {
144 match &self.kind {
145 ErrorKind::VarError(e) => e.hint(),
146 ErrorKind::InvalidClusterReplicaSize { expected, .. } => Some(format!(
147 "Valid cluster replica sizes are: {}",
148 expected.join(", ")
149 )),
150 _ => None,
151 }
152 }
153}
154
155impl From<SqlCatalogError> for Error {
156 fn from(e: SqlCatalogError) -> Error {
157 Error::new(ErrorKind::from(e))
158 }
159}
160
161impl From<TryFromProtoError> for Error {
162 fn from(e: TryFromProtoError) -> Error {
163 Error::from(crate::durable::CatalogError::from(e))
164 }
165}
166
167impl From<uuid::Error> for Error {
168 fn from(e: uuid::Error) -> Error {
169 Error::new(ErrorKind::from(e))
170 }
171}
172
173impl From<crate::durable::CatalogError> for Error {
174 fn from(e: crate::durable::CatalogError) -> Self {
175 match e {
176 crate::durable::CatalogError::Catalog(e) => Error::new(ErrorKind::from(e)),
177 crate::durable::CatalogError::Durable(e) => Error::new(ErrorKind::from(e)),
178 }
179 }
180}
181
182impl From<VarError> for Error {
183 fn from(e: VarError) -> Self {
184 let kind: ErrorKind = e.into();
185 kind.into()
186 }
187}
188
189#[derive(Debug)]
190pub struct AmbiguousRename {
191 pub depender: String,
192 pub dependee: String,
193 pub message: String,
194}
195
196impl fmt::Display for AmbiguousRename {
198 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
199 if self.depender == self.dependee {
200 write!(
201 f,
202 "renaming conflict: in {}, {}",
203 self.dependee, self.message
204 )
205 } else {
206 write!(
207 f,
208 "renaming conflict: in {}, which uses {}, {}",
209 self.depender, self.dependee, self.message
210 )
211 }
212 }
213}
214
215impl std::error::Error for AmbiguousRename {
216 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
218 None
219 }
220}