Skip to main content

nodedb_types/error/
sqlstate.rs

1// SPDX-License-Identifier: Apache-2.0
2
3//! Standard PostgreSQL SQLSTATE code constants.
4//!
5//! A single source of truth for every five-character SQLSTATE string used
6//! across the codebase. Grouping follows the PostgreSQL documentation
7//! appendix (Class 00–XX).  All constants are `&'static str` so they compose
8//! directly with `pgwire::error::ErrorInfo` without any allocation.
9//!
10//! Add new codes here when a new error path needs one; never inline a literal
11//! elsewhere — a typo in a SQLSTATE string is undetectable at compile time.
12
13/// A SQLSTATE string shared by more than one [`crate::error::ErrorCode`]
14/// meaning at the `DdlError` construction sites that actually use it.
15///
16/// Deliberately not `&str`: passing one to `DdlError::new`, which derives
17/// the code from the SQLSTATE string, does not compile. Construct through
18/// the paired `DdlError::<name>` constructor instead, which supplies the
19/// code explicitly rather than guessing it from the wire string.
20#[derive(Debug, Clone, Copy)]
21pub struct AmbiguousSqlstate(pub &'static str);
22
23// ── Class 00 — Successful Completion ────────────────────────────────────────
24
25/// `00000` — `successful_completion`
26pub const SUCCESS: &str = "00000";
27
28// ── Class 01 — Warning ───────────────────────────────────────────────────────
29
30/// `01000` — `warning` (generic warning)
31pub const WARNING: &str = "01000";
32
33// ── Class 02 — No Data ───────────────────────────────────────────────────────
34
35/// `02000` — `no_data` (document / row not found)
36pub const NO_DATA: &str = "02000";
37
38// ── Class 0A — Feature Not Supported ────────────────────────────────────────
39
40/// `0A000` — `feature_not_supported`
41pub const FEATURE_NOT_SUPPORTED: &str = "0A000";
42
43/// `0A000` — Cannot drop the built-in `default` database, which is immutable.
44/// Aliased to `feature_not_supported` per the PostgreSQL convention for
45/// unsupported DDL operations on reserved objects. Ambiguous with
46/// `FEATURE_NOT_SUPPORTED` and `CANNOT_CLONE_MIRROR` — see
47/// [`AmbiguousSqlstate`].
48pub const CANNOT_DROP_DEFAULT_DATABASE: AmbiguousSqlstate = AmbiguousSqlstate("0A000");
49
50// ── Class 22 — Data Exception ────────────────────────────────────────────────
51
52/// `22000` — `data_exception` (a function received a value it cannot compute
53/// on: a vector of the wrong dimension, an argument of the wrong shape, a
54/// malformed JSONPath)
55pub const DATA_EXCEPTION: &str = "22000";
56
57/// `22003` — `numeric_value_out_of_range`
58pub const NUMERIC_VALUE_OUT_OF_RANGE: &str = "22003";
59
60/// `22007` — `invalid_datetime_format` (text that does not parse as a
61/// `timestamp` or `timestamptz`)
62pub const INVALID_DATETIME_FORMAT: &str = "22007";
63
64/// `22008` — `datetime_field_overflow` (an instant outside the range a
65/// `timestamp` or `timestamptz` holds)
66pub const DATETIME_FIELD_OVERFLOW: &str = "22008";
67
68/// `22012` — `division_by_zero` (`/` or `%` with a zero divisor —
69/// raised at runtime instead of evaluating to `NULL`)
70pub const DIVISION_BY_ZERO: &str = "22012";
71
72/// `2201W` — `invalid_limit_value` (a LIMIT/OFFSET/FETCH bound that is
73/// negative, fractional, non-numeric, or wider than `usize`)
74pub const INVALID_LIMIT_VALUE: &str = "2201W";
75
76/// `22P02` — `invalid_text_representation` (stored text that does not
77/// parse as the number an operation reads, e.g. `INCR` on `"abc"`)
78pub const INVALID_TEXT_REPRESENTATION: &str = "22P02";
79
80/// `22023` — `invalid_parameter_value` (a `SET` value the parameter's own
81/// grammar refuses, e.g. `SET statement_timeout = 'later'`)
82pub const INVALID_PARAMETER_VALUE: &str = "22023";
83
84// ── Class 23 — Integrity Constraint Violation ────────────────────────────────
85
86/// `23000` — `integrity_constraint_violation` (generic)
87pub const INTEGRITY_CONSTRAINT_VIOLATION: &str = "23000";
88
89/// `428C9` — `generated_always` (a write names a generated column; its
90/// value is computed from other columns)
91pub const GENERATED_ALWAYS: &str = "428C9";
92
93/// `23502` — `not_null_violation`
94pub const NOT_NULL_VIOLATION: &str = "23502";
95
96/// `23503` — `foreign_key_violation` (dangling-edge rejection)
97pub const FOREIGN_KEY_VIOLATION: &str = "23503";
98
99/// `23505` — `unique_violation`
100pub const UNIQUE_VIOLATION: &str = "23505";
101
102/// `23514` — `check_violation`
103pub const CHECK_VIOLATION: &str = "23514";
104
105/// `23601` — NodeDB extension: append-only write rejected.
106pub const APPEND_ONLY_VIOLATION: &str = "23601";
107
108/// `23602` — NodeDB extension: balance constraint violated.
109pub const BALANCE_VIOLATION: &str = "23602";
110
111/// `23603` — NodeDB extension: period lock; writes rejected.
112pub const PERIOD_LOCKED: &str = "23603";
113
114/// `23604` — NodeDB extension: state-transition constraint violated.
115pub const STATE_TRANSITION_VIOLATION: &str = "23604";
116
117/// `23605` — NodeDB extension: transition-check constraint violated.
118pub const TRANSITION_CHECK_VIOLATION: &str = "23605";
119
120/// `23606` — NodeDB extension: retention policy blocks deletion.
121pub const RETENTION_VIOLATION: &str = "23606";
122
123/// `23607` — NodeDB extension: legal hold blocks deletion.
124pub const LEGAL_HOLD_ACTIVE: &str = "23607";
125
126/// `23608` — NodeDB extension: type-guard constraint violated.
127pub const TYPE_GUARD_VIOLATION: &str = "23608";
128
129/// `23609` — NodeDB extension: period-lock reference row has no configured
130/// status column; a misconfigured column name, not a locked period.
131pub const PERIOD_LOCK_MISCONFIGURED: &str = "23609";
132
133// ── Class 28 — Invalid Authorization Specification ───────────────────────────
134
135/// `28000` — `invalid_authorization_specification`: no valid credentials.
136/// The default meaning, a credential failure. Its code is
137/// `AUTHENTICATION_FAILED`, the code `INVALID_PASSWORD` has too, so a client
138/// cannot tell a wrong password from an unknown user.
139pub const INVALID_AUTHORIZATION: &str = "28000";
140
141/// `28P01` — `invalid_password`: a credential failure. Same code as
142/// `INVALID_AUTHORIZATION`.
143pub const INVALID_PASSWORD: &str = "28P01";
144
145/// `28000` — the session's bearer token expired, and the client must
146/// re-authenticate. Its code is `AUTH_EXPIRED`. Ambiguous with the
147/// credential-failure meaning of `28000` — see [`AmbiguousSqlstate`].
148pub const AUTH_TOKEN_EXPIRED: AmbiguousSqlstate = AmbiguousSqlstate("28000");
149
150/// `active_sql_transaction`: the statement cannot run inside a transaction
151/// block.
152pub const ACTIVE_SQL_TRANSACTION: &str = "25001";
153
154/// `25006` — `read_only_sql_transaction`: a write targeted a read-only
155/// database, such as an unpromoted mirror.
156pub const READ_ONLY_SQL_TRANSACTION: &str = "25006";
157
158// ── Class 2B — Dependent Privilege Descriptors Still Exist ───────────────────
159
160/// `2BP01` — `dependent_objects_still_exist`: a DROP names an object that
161/// other objects depend on.
162pub const DEPENDENT_OBJECTS_STILL_EXIST: &str = "2BP01";
163
164// ── Class 3D — Invalid Catalog Name ──────────────────────────────────────────
165
166/// `3D000` — `invalid_catalog_name` (the selected database does not exist)
167pub const INVALID_CATALOG_NAME: &str = "3D000";
168
169// ── Class 40 — Transaction Rollback ──────────────────────────────────────────
170
171/// `40000` — `transaction_rollback` (rolled back for a reason other than a
172/// serialization conflict; class 40 tells the client to retry)
173pub const TRANSACTION_ROLLBACK: &str = "40000";
174
175/// `40001` — `serialization_failure` (write conflict; client should retry)
176pub const SERIALIZATION_FAILURE: &str = "40001";
177
178// ── Class 42 — Syntax Error or Access Rule Violation ─────────────────────────
179
180/// `42501` — `insufficient_privilege`
181pub const INSUFFICIENT_PRIVILEGE: &str = "42501";
182
183/// `42601` — `syntax_error`
184pub const SYNTAX_ERROR: &str = "42601";
185
186/// `42704` — `undefined_object` (a runtime parameter the server does not
187/// carry, e.g. `SET nonsense = 1` or `SHOW nonsense`)
188pub const UNDEFINED_OBJECT: &str = "42704";
189
190/// `42710` — `duplicate_object`: a named catalog object already exists.
191pub const DUPLICATE_OBJECT: &str = "42710";
192
193/// `42703` — `undefined_column` (a column reference that resolves against no
194/// relation in scope)
195pub const UNDEFINED_COLUMN: &str = "42703";
196
197/// `42702` — `ambiguous_column`: a bare column name that resolves against
198/// more than one relation in scope.
199pub const AMBIGUOUS_COLUMN: &str = "42702";
200
201/// `42804` — `datatype_mismatch` (a literal the declared column type cannot
202/// represent, such as a column `DEFAULT` refused at `CREATE`)
203pub const DATATYPE_MISMATCH: &str = "42804";
204
205/// `42809` — `wrong_object_type` (a statement the named object's kind does
206/// not take, such as a write to a continuous aggregate)
207pub const WRONG_OBJECT_TYPE: &str = "42809";
208
209/// `42846` — `cannot_coerce`
210pub const CANNOT_COERCE: &str = "42846";
211
212/// `42P01` — `undefined_table` (collection not found)
213pub const UNDEFINED_TABLE: &str = "42P01";
214
215/// `42883` — `undefined_function` (no scalar/aggregate/window function
216/// registered under the called name)
217pub const UNDEFINED_FUNCTION: &str = "42883";
218
219// ── Class 53 — Insufficient Resources ────────────────────────────────────────
220
221/// `53200` — `out_of_memory`
222pub const OUT_OF_MEMORY: &str = "53200";
223
224/// `53300` — `too_many_connections` (closest match for rate-limit denial)
225pub const TOO_MANY_CONNECTIONS: &str = "53300";
226
227/// `53400` — `configuration_limit_exceeded` (quota exceeded)
228pub const CONFIGURATION_LIMIT_EXCEEDED: &str = "53400";
229
230// ── Class 54 — Program Limit Exceeded ────────────────────────────────────────
231
232/// `54000` — `program_limit_exceeded` (generic over-cap)
233pub const PROGRAM_LIMIT_EXCEEDED: &str = "54000";
234
235/// `54001` — `statement_too_complex`
236pub const STATEMENT_TOO_COMPLEX: &str = "54001";
237
238// ── Class 55 — Object Not In Prerequisite State ──────────────────────────────
239
240/// `55000` — `object_not_in_prerequisite_state` (the object exists but the
241/// step this statement needs has not run, e.g. `currval` before `nextval`)
242pub const OBJECT_NOT_IN_PREREQUISITE_STATE: &str = "55000";
243
244/// `55P03` — `lock_not_available` (no cluster leader)
245pub const LOCK_NOT_AVAILABLE: &str = "55P03";
246
247// ── Class 57 — Operator Intervention ─────────────────────────────────────────
248
249/// `57014` — `query_canceled`: a deadline passed, or a user or statement
250/// cancelled the query. No meaning is the default, so a bare `57014` never
251/// classifies as the retriable deadline code — see [`AmbiguousSqlstate`].
252pub const QUERY_CANCELED: AmbiguousSqlstate = AmbiguousSqlstate("57014");
253
254/// `57P03` — `cannot_connect_now` (collection is draining)
255pub const CANNOT_CONNECT_NOW: &str = "57P03";
256
257/// `57P04` — `database_dropped` (not-leader redirect; client should retry elsewhere)
258pub const DATABASE_DROPPED: &str = "57P04";
259
260// ── Quota-specific aliases (Class 53 / 57) ───────────────────────────────────
261//
262// PostgreSQL class 53 "Insufficient Resources" is the closest match for quota
263// exhaustion conditions.  Class 57P03 "cannot_connect_now" covers transient
264// overload situations where the server is running but cannot accept the request.
265
266/// `53400` — `configuration_limit_exceeded`: sum of tenant/database quotas would
267/// exceed the configured global or parent ceiling (`QUOTA_OVERCOMMIT`).
268/// Alias for [`CONFIGURATION_LIMIT_EXCEEDED`].
269pub const QUOTA_OVERCOMMIT: &str = "53400";
270
271/// `53400` — `configuration_limit_exceeded`: tenant or database has exhausted its
272/// configured resource budget (`TENANT_QUOTA_EXCEEDED`, `DATABASE_QUOTA_EXCEEDED`).
273/// Class 53 is preferred over 54 because the limit is a runtime configuration
274/// setting, not a hard-coded program limit.
275pub const QUOTA_EXCEEDED: &str = "53400";
276
277/// `57P03` — `cannot_connect_now`: server is under global resource pressure and
278/// cannot accept new requests (`SERVER_OVERLOAD`). Using `57P03` rather than
279/// `53300` (too_many_connections) because the condition is transient and the
280/// server may accept requests again shortly — clients should retry after backoff.
281pub const SERVER_OVERLOAD: &str = "57P03";
282
283// ── Clone DDL (Class 54 / 55 / 0A) ──────────────────────────────────────────
284
285/// `54011` — NodeDB extension: clone chain depth exceeds `MAX_CLONE_DEPTH`.
286///
287/// Uses Class 54 "Program Limit Exceeded" because the limit is a hard-coded
288/// structural cap (depth 8), not a runtime quota setting.
289pub const CLONE_DEPTH_EXCEEDED: &str = "54011";
290
291/// `0A000` — NodeDB extension: a mirror database cannot be cloned.
292///
293/// Aliased to `feature_not_supported` — cloning a mirror creates ambiguous
294/// lineage; the operator must promote the mirror to a writable database
295/// first. Ambiguous with `FEATURE_NOT_SUPPORTED` and
296/// `CANNOT_DROP_DEFAULT_DATABASE` — see [`AmbiguousSqlstate`].
297pub const CANNOT_CLONE_MIRROR: AmbiguousSqlstate = AmbiguousSqlstate("0A000");
298
299/// `55006` — NodeDB extension: source database has active clone dependents.
300///
301/// Uses Class 55 "Object Not In Prerequisite State" because the source is in
302/// the correct state for normal use but cannot be dropped until dependents
303/// are resolved. Ambiguous with the generic "object busy" use of `55006` —
304/// see [`AmbiguousSqlstate`].
305pub const CLONE_DEPENDENCY: AmbiguousSqlstate = AmbiguousSqlstate("55006");
306
307/// `22023` — NodeDB extension: `AS OF` timestamp predates the clone's
308/// creation point; the database did not exist at that time.
309///
310/// Uses Class 22 "Data Exception" / `22023` (invalid parameter value) because
311/// the user-supplied timestamp is valid in general but out of range for this
312/// specific clone.
313pub const CLONE_PREDATES_QUERY_TIME: &str = "22023";
314
315/// `55P03` — NodeDB extension: this node cannot satisfy the requested
316/// consistency level, because it is not the Raft leader for the data and
317/// cannot prove that it is.
318///
319/// Uses Class 55 "Object Not In Prerequisite State": the target is valid but
320/// is not in the state (Raft leader) the requested consistency needs. Raised
321/// for a mirror database, which should be redirected to the source cluster,
322/// and for a linearizable read whose leadership no quorum confirms. Retriable
323/// in both cases.
324pub const STALE_READ_NOT_LEADER: &str = "55P03";
325
326/// `55006` — NodeDB extension: a write targeted a `Shadowed`/`Materializing`
327/// clone collection whose engine has no copy-on-write support.
328///
329/// Uses Class 55 "Object Not In Prerequisite State", same as
330/// [`CLONE_DEPENDENCY`] — the collection is valid but not yet in the state
331/// (materialized) the write needs. Ambiguous — see [`AmbiguousSqlstate`].
332pub const CLONE_WRITE_REQUIRES_MATERIALIZE: AmbiguousSqlstate = AmbiguousSqlstate("55006");
333
334// ── Backup / Restore (Class 22 / 28) ────────────────────────────────────────
335
336/// `22023` — NodeDB extension: RESTORE's target tenant does not match the
337/// tenant the envelope belongs to. Uses Class 22 "Data Exception" because the
338/// envelope is well-formed, just not for the requested tenant.
339pub const BACKUP_TENANT_MISMATCH: &str = "22023";
340
341/// `28000` — NodeDB extension: the backup envelope did not decrypt under this
342/// server's configured `backup_encryption` key. Aliased to
343/// `invalid_authorization_specification`, the same class used for any other
344/// presented-key mismatch. Ambiguous with the credential-failure meaning of
345/// `28000` — see [`AmbiguousSqlstate`].
346pub const BACKUP_KEY_MISMATCH: AmbiguousSqlstate = AmbiguousSqlstate("28000");
347
348// ── Move Tenant DDL (Class 55 / 57) ─────────────────────────────────────────
349
350/// `57014` — `query_canceled`: drain phase timed out; client should re-try after
351/// ensuring the tenant has no active connections on the source database.
352/// Ambiguous with the other meanings of `QUERY_CANCELED` — see
353/// [`AmbiguousSqlstate`].
354pub const MOVE_TENANT_DRAIN_TIMEOUT: AmbiguousSqlstate = AmbiguousSqlstate("57014");
355
356/// `55P02` — `lock_not_available`: pre-flight check found schema incompatibility
357/// between the source and target databases; no state was mutated.
358pub const MOVE_TENANT_PREFLIGHT_FAILED: &str = "55P02";
359
360/// `XX000` — internal error during snapshot phase; source left unchanged.
361/// Ambiguous with the generic internal-error use of `XX000` — see
362/// [`AmbiguousSqlstate`].
363pub const MOVE_TENANT_SNAPSHOT_FAILED: AmbiguousSqlstate = AmbiguousSqlstate("XX000");
364
365/// `XX000` — internal error during cutover phase; source still holds data.
366/// Ambiguous with the generic internal-error use of `XX000` — see
367/// [`AmbiguousSqlstate`].
368pub const MOVE_TENANT_CUTOVER_FAILED: AmbiguousSqlstate = AmbiguousSqlstate("XX000");
369
370/// `02000` — `no_data`: tenant is already present in the target database;
371/// the `MOVE TENANT` is a no-op (idempotent retry of a completed move).
372/// Ambiguous with the generic "no data found" use of `02000` — see
373/// [`AmbiguousSqlstate`].
374pub const MOVE_TENANT_ALREADY_AT_TARGET: AmbiguousSqlstate = AmbiguousSqlstate("02000");
375
376// ── Class 08 — Connection Exception ──────────────────────────────────────────
377
378/// `08006` — `connection_failure`: a Control-to-Data-Plane dispatch could not
379/// reach the target core (bridge closed, core panic, timeout).
380pub const CONNECTION_FAILURE: &str = "08006";
381
382/// `08004` — `sqlserver_rejected_establishment_of_sqlconnection`: the server
383/// refused to establish a sync shape subscription.
384pub const SERVER_REJECTED_ESTABLISHMENT: &str = "08004";
385
386/// `08P01` — `protocol_violation`: the protocol handshake failed.
387pub const PROTOCOL_VIOLATION: &str = "08P01";
388
389// ── Class 58 — System Error ──────────────────────────────────────────────────
390
391/// `58030` — `io_error`: a WAL append or filesystem operation failed.
392pub const IO_ERROR: &str = "58030";
393
394// ── Class XX — Internal Error ────────────────────────────────────────────────
395
396/// `XX000` — `internal_error`
397pub const INTERNAL_ERROR: &str = "XX000";
398
399#[cfg(test)]
400mod tests {
401    use super::*;
402
403    #[test]
404    fn all_codes_are_five_chars() {
405        let codes = [
406            SUCCESS,
407            WARNING,
408            NO_DATA,
409            FEATURE_NOT_SUPPORTED,
410            DATA_EXCEPTION,
411            NUMERIC_VALUE_OUT_OF_RANGE,
412            INVALID_DATETIME_FORMAT,
413            DATETIME_FIELD_OVERFLOW,
414            DIVISION_BY_ZERO,
415            INVALID_LIMIT_VALUE,
416            INVALID_TEXT_REPRESENTATION,
417            INTEGRITY_CONSTRAINT_VIOLATION,
418            GENERATED_ALWAYS,
419            NOT_NULL_VIOLATION,
420            FOREIGN_KEY_VIOLATION,
421            UNIQUE_VIOLATION,
422            CHECK_VIOLATION,
423            APPEND_ONLY_VIOLATION,
424            BALANCE_VIOLATION,
425            PERIOD_LOCKED,
426            PERIOD_LOCK_MISCONFIGURED,
427            STATE_TRANSITION_VIOLATION,
428            TRANSITION_CHECK_VIOLATION,
429            RETENTION_VIOLATION,
430            LEGAL_HOLD_ACTIVE,
431            TYPE_GUARD_VIOLATION,
432            INVALID_AUTHORIZATION,
433            INVALID_PASSWORD,
434            ACTIVE_SQL_TRANSACTION,
435            READ_ONLY_SQL_TRANSACTION,
436            DEPENDENT_OBJECTS_STILL_EXIST,
437            SERIALIZATION_FAILURE,
438            INSUFFICIENT_PRIVILEGE,
439            SYNTAX_ERROR,
440            UNDEFINED_COLUMN,
441            AMBIGUOUS_COLUMN,
442            UNDEFINED_OBJECT,
443            DATATYPE_MISMATCH,
444            WRONG_OBJECT_TYPE,
445            CANNOT_COERCE,
446            UNDEFINED_TABLE,
447            UNDEFINED_FUNCTION,
448            OUT_OF_MEMORY,
449            TOO_MANY_CONNECTIONS,
450            CONFIGURATION_LIMIT_EXCEEDED,
451            PROGRAM_LIMIT_EXCEEDED,
452            STATEMENT_TOO_COMPLEX,
453            OBJECT_NOT_IN_PREREQUISITE_STATE,
454            LOCK_NOT_AVAILABLE,
455            CANNOT_CONNECT_NOW,
456            DATABASE_DROPPED,
457            INTERNAL_ERROR,
458            QUOTA_OVERCOMMIT,
459            QUOTA_EXCEEDED,
460            SERVER_OVERLOAD,
461            CLONE_DEPTH_EXCEEDED,
462            CLONE_PREDATES_QUERY_TIME,
463            STALE_READ_NOT_LEADER,
464            CONNECTION_FAILURE,
465            SERVER_REJECTED_ESTABLISHMENT,
466            PROTOCOL_VIOLATION,
467            DUPLICATE_OBJECT,
468            IO_ERROR,
469        ];
470        for code in &codes {
471            assert_eq!(
472                code.len(),
473                5,
474                "SQLSTATE '{code}' must be exactly 5 characters"
475            );
476        }
477
478        let ambiguous = [
479            QUERY_CANCELED,
480            AUTH_TOKEN_EXPIRED,
481            BACKUP_KEY_MISMATCH,
482            CANNOT_DROP_DEFAULT_DATABASE,
483            CANNOT_CLONE_MIRROR,
484            CLONE_DEPENDENCY,
485            CLONE_WRITE_REQUIRES_MATERIALIZE,
486            MOVE_TENANT_DRAIN_TIMEOUT,
487            MOVE_TENANT_SNAPSHOT_FAILED,
488            MOVE_TENANT_CUTOVER_FAILED,
489            MOVE_TENANT_ALREADY_AT_TARGET,
490        ];
491        for code in &ambiguous {
492            assert_eq!(
493                code.0.len(),
494                5,
495                "SQLSTATE '{}' must be exactly 5 characters",
496                code.0
497            );
498        }
499    }
500
501    #[test]
502    fn spot_check_well_known_codes() {
503        assert_eq!(UNIQUE_VIOLATION, "23505");
504        assert_eq!(UNDEFINED_COLUMN, "42703");
505        assert_eq!(AMBIGUOUS_COLUMN, "42702");
506        assert_eq!(UNDEFINED_TABLE, "42P01");
507        assert_eq!(INSUFFICIENT_PRIVILEGE, "42501");
508        assert_eq!(QUERY_CANCELED.0, "57014");
509        assert_eq!(INTERNAL_ERROR, "XX000");
510        assert_eq!(FEATURE_NOT_SUPPORTED, "0A000");
511    }
512
513    #[test]
514    fn ambiguous_sqlstates_alias_their_documented_string() {
515        assert_eq!(CANNOT_DROP_DEFAULT_DATABASE.0, "0A000");
516        assert_eq!(CANNOT_CLONE_MIRROR.0, "0A000");
517        assert_eq!(CLONE_DEPENDENCY.0, "55006");
518        assert_eq!(CLONE_WRITE_REQUIRES_MATERIALIZE.0, "55006");
519        assert_eq!(MOVE_TENANT_DRAIN_TIMEOUT.0, "57014");
520        assert_eq!(MOVE_TENANT_SNAPSHOT_FAILED.0, "XX000");
521        assert_eq!(MOVE_TENANT_CUTOVER_FAILED.0, "XX000");
522        assert_eq!(MOVE_TENANT_ALREADY_AT_TARGET.0, "02000");
523    }
524}