Skip to main content

icydb_diagnostic_code/
lib.rs

1//! Compact diagnostic identity for IcyDB.
2//!
3//! This crate intentionally contains no rich diagnostic prose or Candid wire
4//! types. Production canister builds collapse diagnostics to numeric wire
5//! codes before they cross the public canister boundary.
6
7///
8/// DiagnosticCode
9///
10/// Stable machine-readable diagnostic reason.
11///
12
13#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
14pub enum DiagnosticCode {
15    QueryValidate,
16    QueryIntent,
17    QueryPlan,
18    QueryAccessRequirement,
19    QueryUnorderedPagination,
20    QueryInvalidContinuationCursor,
21    QueryNotFound,
22    QueryNotUnique,
23    QueryNumericOverflow,
24    QueryNumericNotRepresentable,
25    QueryUnsupportedSqlFeature,
26    QuerySqlSurfaceMismatch,
27    QuerySqlWriteBoundary,
28    SchemaDdlAdmission,
29    StoreNotFound,
30    StoreCorruption,
31    StoreInvariantViolation,
32    RuntimeCorruption,
33    RuntimeIncompatiblePersistedFormat,
34    RuntimeInvariantViolation,
35    RuntimeConflict,
36    RuntimeNotFound,
37    RuntimeUnsupported,
38    RuntimeInternal,
39}
40
41impl DiagnosticCode {
42    /// Return the broad diagnostic class for this code.
43    #[must_use]
44    pub const fn class(self) -> ErrorClass {
45        match self {
46            Self::StoreCorruption | Self::RuntimeCorruption => ErrorClass::Corruption,
47            Self::RuntimeIncompatiblePersistedFormat => ErrorClass::IncompatiblePersistedFormat,
48            Self::QueryNotFound | Self::StoreNotFound | Self::RuntimeNotFound => {
49                ErrorClass::NotFound
50            }
51            Self::RuntimeConflict => ErrorClass::Conflict,
52            Self::QueryUnsupportedSqlFeature
53            | Self::QuerySqlSurfaceMismatch
54            | Self::QuerySqlWriteBoundary
55            | Self::RuntimeUnsupported => ErrorClass::Unsupported,
56            Self::StoreInvariantViolation | Self::RuntimeInvariantViolation => {
57                ErrorClass::InvariantViolation
58            }
59            Self::RuntimeInternal => ErrorClass::Internal,
60            Self::QueryValidate
61            | Self::QueryIntent
62            | Self::QueryPlan
63            | Self::QueryAccessRequirement
64            | Self::QueryUnorderedPagination
65            | Self::QueryInvalidContinuationCursor
66            | Self::QueryNotUnique
67            | Self::QueryNumericOverflow
68            | Self::QueryNumericNotRepresentable
69            | Self::SchemaDdlAdmission => ErrorClass::Query,
70        }
71    }
72
73    /// Return the default diagnostic origin for this code.
74    #[must_use]
75    pub const fn origin(self) -> ErrorOrigin {
76        match self {
77            Self::StoreNotFound | Self::StoreCorruption | Self::StoreInvariantViolation => {
78                ErrorOrigin::Store
79            }
80            Self::RuntimeCorruption
81            | Self::RuntimeIncompatiblePersistedFormat
82            | Self::RuntimeInvariantViolation
83            | Self::RuntimeConflict
84            | Self::RuntimeNotFound
85            | Self::RuntimeUnsupported
86            | Self::RuntimeInternal => ErrorOrigin::Runtime,
87            Self::QueryValidate
88            | Self::QueryIntent
89            | Self::QueryPlan
90            | Self::QueryAccessRequirement
91            | Self::QueryUnorderedPagination
92            | Self::QueryInvalidContinuationCursor
93            | Self::QueryNotFound
94            | Self::QueryNotUnique
95            | Self::QueryNumericOverflow
96            | Self::QueryNumericNotRepresentable
97            | Self::QueryUnsupportedSqlFeature
98            | Self::QuerySqlSurfaceMismatch
99            | Self::QuerySqlWriteBoundary
100            | Self::SchemaDdlAdmission => ErrorOrigin::Query,
101        }
102    }
103
104    /// Return the compact public wire code for this broad diagnostic reason.
105    #[must_use]
106    pub const fn error_code(self) -> ErrorCode {
107        match self {
108            Self::QueryValidate => ErrorCode::QUERY_VALIDATE,
109            Self::QueryIntent => ErrorCode::QUERY_INTENT,
110            Self::QueryPlan => ErrorCode::QUERY_PLAN,
111            Self::QueryAccessRequirement => ErrorCode::QUERY_ACCESS_REQUIREMENT,
112            Self::QueryUnorderedPagination => ErrorCode::QUERY_UNORDERED_PAGINATION,
113            Self::QueryInvalidContinuationCursor => ErrorCode::QUERY_INVALID_CONTINUATION_CURSOR,
114            Self::QueryNotFound => ErrorCode::QUERY_NOT_FOUND,
115            Self::QueryNotUnique => ErrorCode::QUERY_NOT_UNIQUE,
116            Self::QueryNumericOverflow => ErrorCode::QUERY_NUMERIC_OVERFLOW,
117            Self::QueryNumericNotRepresentable => ErrorCode::QUERY_NUMERIC_NOT_REPRESENTABLE,
118            Self::QueryUnsupportedSqlFeature => ErrorCode::QUERY_UNSUPPORTED_SQL_FEATURE,
119            Self::QuerySqlSurfaceMismatch => ErrorCode::QUERY_SQL_SURFACE_MISMATCH,
120            Self::QuerySqlWriteBoundary => ErrorCode::QUERY_SQL_WRITE_BOUNDARY,
121            Self::SchemaDdlAdmission => ErrorCode::SCHEMA_DDL_ADMISSION,
122            Self::StoreNotFound => ErrorCode::STORE_NOT_FOUND,
123            Self::StoreCorruption => ErrorCode::STORE_CORRUPTION,
124            Self::StoreInvariantViolation => ErrorCode::STORE_INVARIANT_VIOLATION,
125            Self::RuntimeCorruption => ErrorCode::RUNTIME_CORRUPTION,
126            Self::RuntimeIncompatiblePersistedFormat => {
127                ErrorCode::RUNTIME_INCOMPATIBLE_PERSISTED_FORMAT
128            }
129            Self::RuntimeInvariantViolation => ErrorCode::RUNTIME_INVARIANT_VIOLATION,
130            Self::RuntimeConflict => ErrorCode::RUNTIME_CONFLICT,
131            Self::RuntimeNotFound => ErrorCode::RUNTIME_NOT_FOUND,
132            Self::RuntimeUnsupported => ErrorCode::RUNTIME_UNSUPPORTED,
133            Self::RuntimeInternal => ErrorCode::RUNTIME_INTERNAL,
134        }
135    }
136}
137
138///
139/// ErrorCode
140///
141/// Stable numeric public error identity.
142///
143/// The public Candid `icydb::Error` stores this value as `nat16` so canister
144/// interfaces do not retain rich diagnostic enum labels. Rich diagnostics can
145/// still be reconstructed by host-side tooling from this leaf code. Before
146/// 1.0.0, the code space is hard-cut to a single compact sequential range.
147///
148
149#[derive(Clone, Copy, Eq, Hash, PartialEq)]
150pub struct ErrorCode(u16);
151
152impl ErrorCode {
153    pub const QUERY_VALIDATE: Self = Self(1);
154    pub const QUERY_INTENT: Self = Self(2);
155    pub const QUERY_PLAN: Self = Self(3);
156    pub const QUERY_ACCESS_REQUIREMENT: Self = Self(4);
157    pub const QUERY_UNORDERED_PAGINATION: Self = Self(5);
158    pub const QUERY_INVALID_CONTINUATION_CURSOR: Self = Self(6);
159    pub const QUERY_NOT_FOUND: Self = Self(7);
160    pub const QUERY_NOT_UNIQUE: Self = Self(8);
161    pub const QUERY_NUMERIC_OVERFLOW: Self = Self(9);
162    pub const QUERY_NUMERIC_NOT_REPRESENTABLE: Self = Self(10);
163    pub const QUERY_UNSUPPORTED_SQL_FEATURE: Self = Self(11);
164    pub const QUERY_SQL_SURFACE_MISMATCH: Self = Self(12);
165    pub const SCHEMA_DDL_ADMISSION: Self = Self(13);
166    pub const STORE_NOT_FOUND: Self = Self(14);
167    pub const STORE_CORRUPTION: Self = Self(15);
168    pub const STORE_INVARIANT_VIOLATION: Self = Self(16);
169    pub const RUNTIME_CORRUPTION: Self = Self(17);
170    pub const RUNTIME_INCOMPATIBLE_PERSISTED_FORMAT: Self = Self(18);
171    pub const RUNTIME_INVARIANT_VIOLATION: Self = Self(19);
172    pub const RUNTIME_CONFLICT: Self = Self(20);
173    pub const RUNTIME_NOT_FOUND: Self = Self(21);
174    pub const RUNTIME_UNSUPPORTED: Self = Self(22);
175    pub const RUNTIME_INTERNAL: Self = Self(23);
176
177    pub const RUNTIME_BOUNDARY_SQL_SURFACE_CONTROLLER_REQUIRED: Self = Self(24);
178    pub const RUNTIME_BOUNDARY_SCHEMA_SURFACE_CONTROLLER_REQUIRED: Self = Self(25);
179    pub const RUNTIME_BOUNDARY_SQL_QUERY_NO_CONFIGURED_ENTITIES: Self = Self(26);
180    pub const RUNTIME_BOUNDARY_SQL_QUERY_ENTITY_NOT_CONFIGURED: Self = Self(27);
181    pub const RUNTIME_BOUNDARY_SQL_DDL_TARGET_REQUIRED: Self = Self(28);
182    pub const RUNTIME_BOUNDARY_SQL_DDL_ENTITY_NOT_CONFIGURED: Self = Self(29);
183    pub const RUNTIME_BOUNDARY_QUERY_RESPONSE_ROWS_REQUIRED: Self = Self(30);
184    pub const RUNTIME_BOUNDARY_QUERY_RESPONSE_GROUPED_ROWS_REQUIRED: Self = Self(31);
185    pub const RUNTIME_BOUNDARY_MUTATION_RESULT_ENTITY_REQUIRED: Self = Self(32);
186    pub const RUNTIME_BOUNDARY_MUTATION_RESULT_ENTITIES_REQUIRED: Self = Self(33);
187    pub const RUNTIME_BOUNDARY_MUTATION_RESULT_ID_REQUIRED: Self = Self(34);
188    pub const RUNTIME_BOUNDARY_MUTATION_RESULT_IDS_REQUIRED: Self = Self(35);
189    pub const RUNTIME_BOUNDARY_ROW_PROJECTION_FIELD_NOT_CONFIGURED: Self = Self(36);
190
191    pub const SQL_FEATURE_AGGREGATE_FILTER_CLAUSE: Self = Self(37);
192    pub const SQL_FEATURE_ALTER_STATEMENT_BEYOND_ALTER_TABLE: Self = Self(38);
193    pub const SQL_FEATURE_ALTER_TABLE_ADD_COLUMN_DUPLICATE_DEFAULT: Self = Self(39);
194    pub const SQL_FEATURE_ALTER_TABLE_ADD_COLUMN_MODIFIERS: Self = Self(40);
195    pub const SQL_FEATURE_ALTER_TABLE_ADD_STATEMENT_BEYOND_ADD_COLUMN: Self = Self(41);
196    pub const SQL_FEATURE_ALTER_TABLE_ALTER_COLUMN_DROP_UNSUPPORTED_ACTION: Self = Self(42);
197    pub const SQL_FEATURE_ALTER_TABLE_ALTER_COLUMN_MODIFIERS: Self = Self(43);
198    pub const SQL_FEATURE_ALTER_TABLE_ALTER_COLUMN_SET_UNSUPPORTED_ACTION: Self = Self(44);
199    pub const SQL_FEATURE_ALTER_TABLE_ALTER_COLUMN_UNSUPPORTED_ACTION: Self = Self(45);
200    pub const SQL_FEATURE_ALTER_TABLE_ALTER_STATEMENT_BEYOND_ALTER_COLUMN: Self = Self(46);
201    pub const SQL_FEATURE_ALTER_TABLE_DROP_COLUMN_IF_EXISTS_SYNTAX: Self = Self(47);
202    pub const SQL_FEATURE_ALTER_TABLE_DROP_COLUMN_MODIFIERS: Self = Self(48);
203    pub const SQL_FEATURE_ALTER_TABLE_DROP_STATEMENT_BEYOND_DROP_COLUMN: Self = Self(49);
204    pub const SQL_FEATURE_ALTER_TABLE_RENAME_COLUMN_MISSING_TO: Self = Self(50);
205    pub const SQL_FEATURE_ALTER_TABLE_RENAME_COLUMN_MODIFIERS: Self = Self(51);
206    pub const SQL_FEATURE_ALTER_TABLE_RENAME_STATEMENT_BEYOND_RENAME_COLUMN: Self = Self(52);
207    pub const SQL_FEATURE_ALTER_TABLE_UNSUPPORTED_OPERATION: Self = Self(53);
208    pub const SQL_FEATURE_COLUMN_ALIAS: Self = Self(54);
209    pub const SQL_FEATURE_CREATE_INDEX_IF_NOT_EXISTS_SYNTAX: Self = Self(55);
210    pub const SQL_FEATURE_CREATE_INDEX_KEY_ORDERING_MODIFIERS: Self = Self(56);
211    pub const SQL_FEATURE_CREATE_INDEX_MODIFIERS: Self = Self(57);
212    pub const SQL_FEATURE_CREATE_STATEMENT_BEYOND_CREATE_INDEX: Self = Self(58);
213    pub const SQL_FEATURE_DESCRIBE_MODIFIER: Self = Self(59);
214    pub const SQL_FEATURE_DDL_SCHEMA_VERSION_DUPLICATE_EXPECTED_CLAUSE: Self = Self(60);
215    pub const SQL_FEATURE_DDL_SCHEMA_VERSION_DUPLICATE_SET_CLAUSE: Self = Self(61);
216    pub const SQL_FEATURE_DROP_INDEX_MODIFIERS: Self = Self(62);
217    pub const SQL_FEATURE_DROP_INDEX_IF_EXISTS_SYNTAX: Self = Self(63);
218    pub const SQL_FEATURE_DROP_STATEMENT_BEYOND_DROP_INDEX: Self = Self(64);
219    pub const SQL_FEATURE_EXPRESSION_INDEX_UNSUPPORTED_FUNCTION: Self = Self(65);
220    pub const SQL_FEATURE_HAVING: Self = Self(66);
221    pub const SQL_FEATURE_INSERT: Self = Self(67);
222    pub const SQL_FEATURE_JOIN: Self = Self(68);
223    pub const SQL_FEATURE_LIKE_PATTERN_BEYOND_TRAILING_PREFIX: Self = Self(69);
224    pub const SQL_FEATURE_LOWER_FIELD_PREDICATE_UNSUPPORTED: Self = Self(70);
225    pub const SQL_FEATURE_MULTI_STATEMENT_SQL: Self = Self(71);
226    pub const SQL_FEATURE_NESTED_AGGREGATE_INPUT: Self = Self(72);
227    pub const SQL_FEATURE_NESTED_PROJECTION_FUNCTION_IN_ARITHMETIC: Self = Self(73);
228    pub const SQL_FEATURE_ORDER_BY_UNSUPPORTED_FORM: Self = Self(74);
229    pub const SQL_FEATURE_OTHER: Self = Self(75);
230    pub const SQL_FEATURE_PARAMETER_BINDING: Self = Self(76);
231    pub const SQL_FEATURE_PARAMETERIZED_SCHEMA_VERSION: Self = Self(77);
232    pub const SQL_FEATURE_PREDICATE_STARTS_WITH_FIRST_ARGUMENT: Self = Self(78);
233    pub const SQL_FEATURE_QUOTED_IDENTIFIERS: Self = Self(79);
234    pub const SQL_FEATURE_RETURNING_UNSUPPORTED_SHAPE: Self = Self(80);
235    pub const SQL_FEATURE_SCALAR_FUNCTION_EXPRESSION_POSITION: Self = Self(81);
236    pub const SQL_FEATURE_SCALE_TAKING_NUMERIC_FUNCTION_EXPRESSION_POSITION: Self = Self(82);
237    pub const SQL_FEATURE_SEARCHED_CASE_GROUPED_ORDER_BY: Self = Self(83);
238    pub const SQL_FEATURE_SHOW_COLUMNS_MODIFIERS: Self = Self(84);
239    pub const SQL_FEATURE_SHOW_ENTITIES_MODIFIERS: Self = Self(85);
240    pub const SQL_FEATURE_SHOW_INDEXES_MODIFIERS: Self = Self(86);
241    pub const SQL_FEATURE_SHOW_MEMORY_MODIFIERS: Self = Self(87);
242    pub const SQL_FEATURE_SHOW_STORES_MODIFIERS: Self = Self(88);
243    pub const SQL_FEATURE_SHOW_UNSUPPORTED_COMMAND: Self = Self(89);
244    pub const SQL_FEATURE_SIMPLE_CASE_EXPRESSION: Self = Self(90);
245    pub const SQL_FEATURE_STANDALONE_LITERAL_PROJECTION_ITEM: Self = Self(91);
246    pub const SQL_FEATURE_SUPPORTED_GROUPED_ORDER_BY_EXPRESSION_FAMILY: Self = Self(92);
247    pub const SQL_FEATURE_SUPPORTED_ORDER_BY_EXPRESSION_FAMILY: Self = Self(93);
248    pub const SQL_FEATURE_UNION_INTERSECT_EXCEPT: Self = Self(94);
249    pub const SQL_FEATURE_UNSUPPORTED_FUNCTION_NAMESPACE: Self = Self(95);
250    pub const SQL_FEATURE_UPDATE: Self = Self(96);
251    pub const SQL_FEATURE_UPPER_FIELD_PREDICATE_UNSUPPORTED: Self = Self(97);
252    pub const SQL_FEATURE_WINDOW_FUNCTION: Self = Self(98);
253    pub const SQL_FEATURE_WITH: Self = Self(99);
254
255    const SQL_FEATURE_DETAILS: [SqlFeatureCode; 63] = [
256        SqlFeatureCode::AggregateFilterClause,
257        SqlFeatureCode::AlterStatementBeyondAlterTable,
258        SqlFeatureCode::AlterTableAddColumnDuplicateDefault,
259        SqlFeatureCode::AlterTableAddColumnModifiers,
260        SqlFeatureCode::AlterTableAddStatementBeyondAddColumn,
261        SqlFeatureCode::AlterTableAlterColumnDropUnsupportedAction,
262        SqlFeatureCode::AlterTableAlterColumnModifiers,
263        SqlFeatureCode::AlterTableAlterColumnSetUnsupportedAction,
264        SqlFeatureCode::AlterTableAlterColumnUnsupportedAction,
265        SqlFeatureCode::AlterTableAlterStatementBeyondAlterColumn,
266        SqlFeatureCode::AlterTableDropColumnIfExistsSyntax,
267        SqlFeatureCode::AlterTableDropColumnModifiers,
268        SqlFeatureCode::AlterTableDropStatementBeyondDropColumn,
269        SqlFeatureCode::AlterTableRenameColumnMissingTo,
270        SqlFeatureCode::AlterTableRenameColumnModifiers,
271        SqlFeatureCode::AlterTableRenameStatementBeyondRenameColumn,
272        SqlFeatureCode::AlterTableUnsupportedOperation,
273        SqlFeatureCode::ColumnAlias,
274        SqlFeatureCode::CreateIndexIfNotExistsSyntax,
275        SqlFeatureCode::CreateIndexKeyOrderingModifiers,
276        SqlFeatureCode::CreateIndexModifiers,
277        SqlFeatureCode::CreateStatementBeyondCreateIndex,
278        SqlFeatureCode::DescribeModifier,
279        SqlFeatureCode::DdlSchemaVersionDuplicateExpectedClause,
280        SqlFeatureCode::DdlSchemaVersionDuplicateSetClause,
281        SqlFeatureCode::DropIndexModifiers,
282        SqlFeatureCode::DropIndexIfExistsSyntax,
283        SqlFeatureCode::DropStatementBeyondDropIndex,
284        SqlFeatureCode::ExpressionIndexUnsupportedFunction,
285        SqlFeatureCode::Having,
286        SqlFeatureCode::Insert,
287        SqlFeatureCode::Join,
288        SqlFeatureCode::LikePatternBeyondTrailingPrefix,
289        SqlFeatureCode::LowerFieldPredicateUnsupported,
290        SqlFeatureCode::MultiStatementSql,
291        SqlFeatureCode::NestedAggregateInput,
292        SqlFeatureCode::NestedProjectionFunctionInArithmetic,
293        SqlFeatureCode::OrderByUnsupportedForm,
294        SqlFeatureCode::Other,
295        SqlFeatureCode::ParameterBinding,
296        SqlFeatureCode::ParameterizedSchemaVersion,
297        SqlFeatureCode::PredicateStartsWithFirstArgument,
298        SqlFeatureCode::QuotedIdentifiers,
299        SqlFeatureCode::ReturningUnsupportedShape,
300        SqlFeatureCode::ScalarFunctionExpressionPosition,
301        SqlFeatureCode::ScaleTakingNumericFunctionExpressionPosition,
302        SqlFeatureCode::SearchedCaseGroupedOrderBy,
303        SqlFeatureCode::ShowColumnsModifiers,
304        SqlFeatureCode::ShowEntitiesModifiers,
305        SqlFeatureCode::ShowIndexesModifiers,
306        SqlFeatureCode::ShowMemoryModifiers,
307        SqlFeatureCode::ShowStoresModifiers,
308        SqlFeatureCode::ShowUnsupportedCommand,
309        SqlFeatureCode::SimpleCaseExpression,
310        SqlFeatureCode::StandaloneLiteralProjectionItem,
311        SqlFeatureCode::SupportedGroupedOrderByExpressionFamily,
312        SqlFeatureCode::SupportedOrderByExpressionFamily,
313        SqlFeatureCode::UnionIntersectExcept,
314        SqlFeatureCode::UnsupportedFunctionNamespace,
315        SqlFeatureCode::Update,
316        SqlFeatureCode::UpperFieldPredicateUnsupported,
317        SqlFeatureCode::WindowFunction,
318        SqlFeatureCode::With,
319    ];
320
321    pub const SQL_SURFACE_QUERY_REJECTS_INSERT: Self = Self(100);
322    pub const SQL_SURFACE_QUERY_REJECTS_UPDATE: Self = Self(101);
323    pub const SQL_SURFACE_QUERY_REJECTS_DELETE: Self = Self(102);
324    pub const SQL_SURFACE_UPDATE_REJECTS_SELECT: Self = Self(103);
325    pub const SQL_SURFACE_UPDATE_REJECTS_EXPLAIN: Self = Self(104);
326    pub const SQL_SURFACE_UPDATE_REJECTS_DESCRIBE: Self = Self(105);
327    pub const SQL_SURFACE_UPDATE_REJECTS_SHOW_INDEXES: Self = Self(106);
328    pub const SQL_SURFACE_UPDATE_REJECTS_SHOW_COLUMNS: Self = Self(107);
329    pub const SQL_SURFACE_UPDATE_REJECTS_SHOW_ENTITIES: Self = Self(108);
330    pub const SQL_SURFACE_UPDATE_REJECTS_SHOW_STORES: Self = Self(109);
331    pub const SQL_SURFACE_UPDATE_REJECTS_SHOW_MEMORY: Self = Self(110);
332
333    pub const SCHEMA_DDL_MISSING_EXPECTED_SCHEMA_VERSION: Self = Self(111);
334    pub const SCHEMA_DDL_MISSING_NEXT_SCHEMA_VERSION: Self = Self(112);
335    pub const SCHEMA_DDL_STALE_EXPECTED_SCHEMA_VERSION: Self = Self(113);
336    pub const SCHEMA_DDL_INVALID_EXPECTED_SCHEMA_VERSION: Self = Self(114);
337    pub const SCHEMA_DDL_INVALID_NEXT_SCHEMA_VERSION: Self = Self(115);
338    pub const SCHEMA_DDL_ACCEPTED_SCHEMA_CHANGE_WITHOUT_VERSION_BUMP: Self = Self(116);
339    pub const SCHEMA_DDL_EMPTY_VERSION_BUMP: Self = Self(117);
340    pub const SCHEMA_DDL_VERSION_GAP: Self = Self(118);
341    pub const SCHEMA_DDL_VERSION_ROLLBACK: Self = Self(119);
342    pub const SCHEMA_DDL_FINGERPRINT_METHOD_MISMATCH: Self = Self(120);
343    pub const SCHEMA_DDL_UNSUPPORTED_TRANSITION_CLASS: Self = Self(121);
344    pub const SCHEMA_DDL_PHYSICAL_RUNNER_MISSING: Self = Self(122);
345    pub const SCHEMA_DDL_VALIDATION_FAILED: Self = Self(123);
346    pub const SCHEMA_DDL_PUBLICATION_RACE_LOST: Self = Self(124);
347    pub const SCHEMA_DDL_INVALID_ADD_COLUMN_DEFAULT: Self = Self(125);
348    pub const SCHEMA_DDL_INVALID_ALTER_COLUMN_DEFAULT: Self = Self(126);
349    pub const SCHEMA_DDL_GENERATED_INDEX_DROP_REJECTED: Self = Self(127);
350    pub const SCHEMA_DDL_REQUIRED_DROP_DEFAULT_UNSUPPORTED: Self = Self(128);
351    pub const SCHEMA_DDL_GENERATED_FIELD_DEFAULT_CHANGE_REJECTED: Self = Self(129);
352    pub const SCHEMA_DDL_GENERATED_FIELD_NULLABILITY_CHANGE_REJECTED: Self = Self(130);
353    pub const SCHEMA_DDL_SET_NOT_NULL_VALIDATION_FAILED: Self = Self(131);
354    pub const QUERY_SQL_WRITE_BOUNDARY: Self = Self(132);
355    pub const SQL_WRITE_PRIMARY_KEY_LITERAL_SHAPE: Self = Self(133);
356    pub const SQL_WRITE_PRIMARY_KEY_LITERAL_INCOMPATIBLE: Self = Self(134);
357    pub const SQL_WRITE_MISSING_PRIMARY_KEY: Self = Self(135);
358    pub const SQL_WRITE_MISSING_REQUIRED_FIELDS: Self = Self(136);
359    pub const SQL_WRITE_EXPLICIT_MANAGED_FIELD: Self = Self(137);
360    pub const SQL_WRITE_EXPLICIT_GENERATED_FIELD: Self = Self(138);
361    pub const SQL_WRITE_INSERT_SELECT_REQUIRES_SCALAR: Self = Self(139);
362    pub const SQL_WRITE_INSERT_SELECT_AGGREGATE_PROJECTION: Self = Self(140);
363    pub const SQL_WRITE_INSERT_SELECT_WIDTH_MISMATCH: Self = Self(141);
364    pub const SQL_WRITE_UPDATE_PRIMARY_KEY_MUTATION: Self = Self(142);
365    pub const SQL_WRITE_INVALID_FIELD_LITERAL: Self = Self(143);
366    pub const SQL_WRITE_UNKNOWN_RETURNING_FIELD: Self = Self(144);
367    pub const SQL_WRITE_DUPLICATE_RETURNING_FIELD: Self = Self(145);
368    pub const SQL_WRITE_UPDATE_MISSING_WHERE_PREDICATE: Self = Self(146);
369    pub const SQL_WRITE_ORDER_BY_UNSUPPORTED_SHAPE: Self = Self(147);
370
371    /// Build an error code from its raw public wire value.
372    #[must_use]
373    pub const fn from_raw(raw: u16) -> Self {
374        Self(raw)
375    }
376
377    /// Return the raw public wire value.
378    #[must_use]
379    pub const fn raw(self) -> u16 {
380        self.0
381    }
382
383    /// Collapse a rich diagnostic into one public leaf code.
384    #[must_use]
385    pub const fn from_parts(code: DiagnosticCode, detail: Option<DiagnosticDetail>) -> Self {
386        match detail {
387            Some(DiagnosticDetail::QueryKind { kind }) => Self::from_query_kind(kind),
388            Some(DiagnosticDetail::RuntimeKind { kind }) => Self::from_runtime_kind(kind),
389            Some(DiagnosticDetail::RuntimeBoundary { boundary }) => {
390                Self::from_runtime_boundary(boundary)
391            }
392            Some(DiagnosticDetail::SchemaDdlAdmission { reason }) => Self::from_schema_ddl(reason),
393            Some(DiagnosticDetail::UnsupportedSqlFeature { feature }) => {
394                Self::from_sql_feature(feature)
395            }
396            Some(DiagnosticDetail::SqlSurfaceMismatch { mismatch }) => {
397                Self::from_sql_surface_mismatch(mismatch)
398            }
399            Some(DiagnosticDetail::SqlWriteBoundary { boundary }) => {
400                Self::from_sql_write_boundary(boundary)
401            }
402            None => code.error_code(),
403        }
404    }
405
406    /// Return the broad diagnostic reason represented by this public code.
407    #[must_use]
408    pub const fn diagnostic_code(self) -> DiagnosticCode {
409        match self.raw() {
410            1 => DiagnosticCode::QueryValidate,
411            2 => DiagnosticCode::QueryIntent,
412            3 => DiagnosticCode::QueryPlan,
413            4 => DiagnosticCode::QueryAccessRequirement,
414            5 => DiagnosticCode::QueryUnorderedPagination,
415            6 => DiagnosticCode::QueryInvalidContinuationCursor,
416            7 => DiagnosticCode::QueryNotFound,
417            8 => DiagnosticCode::QueryNotUnique,
418            9 => DiagnosticCode::QueryNumericOverflow,
419            10 => DiagnosticCode::QueryNumericNotRepresentable,
420            11 | 37..=99 => DiagnosticCode::QueryUnsupportedSqlFeature,
421            12 | 100..=110 => DiagnosticCode::QuerySqlSurfaceMismatch,
422            13 | 111..=131 => DiagnosticCode::SchemaDdlAdmission,
423            132..=147 => DiagnosticCode::QuerySqlWriteBoundary,
424            14 => DiagnosticCode::StoreNotFound,
425            15 => DiagnosticCode::StoreCorruption,
426            16 => DiagnosticCode::StoreInvariantViolation,
427            17 => DiagnosticCode::RuntimeCorruption,
428            18 => DiagnosticCode::RuntimeIncompatiblePersistedFormat,
429            19 => DiagnosticCode::RuntimeInvariantViolation,
430            20 => DiagnosticCode::RuntimeConflict,
431            21 => DiagnosticCode::RuntimeNotFound,
432            22 | 24..=36 => DiagnosticCode::RuntimeUnsupported,
433            _ => DiagnosticCode::RuntimeInternal,
434        }
435    }
436
437    /// Return the diagnostic class represented by this public code.
438    #[must_use]
439    pub const fn class(self) -> ErrorClass {
440        self.diagnostic_code().class()
441    }
442
443    /// Reconstruct rich diagnostic detail for host-side rendering, when known.
444    #[must_use]
445    pub const fn diagnostic_detail(self) -> Option<DiagnosticDetail> {
446        match self.raw() {
447            1..=8 => Self::query_kind_detail(self.raw()),
448            17..=23 => Self::runtime_kind_detail(self.raw()),
449            24..=36 => Self::runtime_boundary_detail(self.raw()),
450            37..=99 => Self::sql_feature_detail(self.raw()),
451            100..=110 => Self::sql_surface_detail(self.raw()),
452            111..=131 => Self::schema_ddl_detail(self.raw()),
453            132..=147 => Self::sql_write_boundary_detail(self.raw()),
454            _ => None,
455        }
456    }
457
458    /// Reconstruct a rich diagnostic payload for host-side rendering.
459    #[must_use]
460    pub const fn diagnostic(self, origin: ErrorOrigin) -> Diagnostic {
461        Diagnostic::new(self.diagnostic_code(), origin, self.diagnostic_detail())
462    }
463
464    const fn from_query_kind(kind: QueryErrorKind) -> Self {
465        match kind {
466            QueryErrorKind::Validate => Self::QUERY_VALIDATE,
467            QueryErrorKind::Intent => Self::QUERY_INTENT,
468            QueryErrorKind::Plan => Self::QUERY_PLAN,
469            QueryErrorKind::AccessRequirement => Self::QUERY_ACCESS_REQUIREMENT,
470            QueryErrorKind::UnorderedPagination => Self::QUERY_UNORDERED_PAGINATION,
471            QueryErrorKind::InvalidContinuationCursor => Self::QUERY_INVALID_CONTINUATION_CURSOR,
472            QueryErrorKind::NotFound => Self::QUERY_NOT_FOUND,
473            QueryErrorKind::NotUnique => Self::QUERY_NOT_UNIQUE,
474        }
475    }
476
477    const fn from_runtime_kind(kind: RuntimeErrorKind) -> Self {
478        match kind {
479            RuntimeErrorKind::Corruption => Self::RUNTIME_CORRUPTION,
480            RuntimeErrorKind::IncompatiblePersistedFormat => {
481                Self::RUNTIME_INCOMPATIBLE_PERSISTED_FORMAT
482            }
483            RuntimeErrorKind::InvariantViolation => Self::RUNTIME_INVARIANT_VIOLATION,
484            RuntimeErrorKind::Conflict => Self::RUNTIME_CONFLICT,
485            RuntimeErrorKind::NotFound => Self::RUNTIME_NOT_FOUND,
486            RuntimeErrorKind::Unsupported => Self::RUNTIME_UNSUPPORTED,
487            RuntimeErrorKind::Internal => Self::RUNTIME_INTERNAL,
488        }
489    }
490
491    const fn from_runtime_boundary(boundary: RuntimeBoundaryCode) -> Self {
492        Self(Self::RUNTIME_BOUNDARY_SQL_SURFACE_CONTROLLER_REQUIRED.raw() + boundary as u16)
493    }
494
495    const fn from_sql_feature(feature: SqlFeatureCode) -> Self {
496        Self(Self::SQL_FEATURE_AGGREGATE_FILTER_CLAUSE.raw() + feature as u16)
497    }
498
499    const fn from_sql_surface_mismatch(mismatch: SqlSurfaceMismatchCode) -> Self {
500        Self(Self::SQL_SURFACE_QUERY_REJECTS_INSERT.raw() + mismatch as u16)
501    }
502
503    const fn from_schema_ddl(reason: SchemaDdlAdmissionCode) -> Self {
504        Self(Self::SCHEMA_DDL_MISSING_EXPECTED_SCHEMA_VERSION.raw() + reason as u16)
505    }
506
507    const fn from_sql_write_boundary(boundary: SqlWriteBoundaryCode) -> Self {
508        Self(Self::SQL_WRITE_PRIMARY_KEY_LITERAL_SHAPE.raw() + boundary as u16)
509    }
510
511    const fn query_kind_detail(raw: u16) -> Option<DiagnosticDetail> {
512        match raw {
513            1 => Some(DiagnosticDetail::QueryKind {
514                kind: QueryErrorKind::Validate,
515            }),
516            2 => Some(DiagnosticDetail::QueryKind {
517                kind: QueryErrorKind::Intent,
518            }),
519            3 => Some(DiagnosticDetail::QueryKind {
520                kind: QueryErrorKind::Plan,
521            }),
522            4 => Some(DiagnosticDetail::QueryKind {
523                kind: QueryErrorKind::AccessRequirement,
524            }),
525            5 => Some(DiagnosticDetail::QueryKind {
526                kind: QueryErrorKind::UnorderedPagination,
527            }),
528            6 => Some(DiagnosticDetail::QueryKind {
529                kind: QueryErrorKind::InvalidContinuationCursor,
530            }),
531            7 => Some(DiagnosticDetail::QueryKind {
532                kind: QueryErrorKind::NotFound,
533            }),
534            8 => Some(DiagnosticDetail::QueryKind {
535                kind: QueryErrorKind::NotUnique,
536            }),
537            _ => None,
538        }
539    }
540
541    const fn runtime_kind_detail(raw: u16) -> Option<DiagnosticDetail> {
542        match raw {
543            17 => Some(DiagnosticDetail::RuntimeKind {
544                kind: RuntimeErrorKind::Corruption,
545            }),
546            18 => Some(DiagnosticDetail::RuntimeKind {
547                kind: RuntimeErrorKind::IncompatiblePersistedFormat,
548            }),
549            19 => Some(DiagnosticDetail::RuntimeKind {
550                kind: RuntimeErrorKind::InvariantViolation,
551            }),
552            20 => Some(DiagnosticDetail::RuntimeKind {
553                kind: RuntimeErrorKind::Conflict,
554            }),
555            21 => Some(DiagnosticDetail::RuntimeKind {
556                kind: RuntimeErrorKind::NotFound,
557            }),
558            22 => Some(DiagnosticDetail::RuntimeKind {
559                kind: RuntimeErrorKind::Unsupported,
560            }),
561            23 => Some(DiagnosticDetail::RuntimeKind {
562                kind: RuntimeErrorKind::Internal,
563            }),
564            _ => None,
565        }
566    }
567
568    const fn runtime_boundary_detail(raw: u16) -> Option<DiagnosticDetail> {
569        match raw {
570            24 => Some(DiagnosticDetail::RuntimeBoundary {
571                boundary: RuntimeBoundaryCode::SqlSurfaceControllerRequired,
572            }),
573            25 => Some(DiagnosticDetail::RuntimeBoundary {
574                boundary: RuntimeBoundaryCode::SchemaSurfaceControllerRequired,
575            }),
576            26 => Some(DiagnosticDetail::RuntimeBoundary {
577                boundary: RuntimeBoundaryCode::SqlQueryNoConfiguredEntities,
578            }),
579            27 => Some(DiagnosticDetail::RuntimeBoundary {
580                boundary: RuntimeBoundaryCode::SqlQueryEntityNotConfigured,
581            }),
582            28 => Some(DiagnosticDetail::RuntimeBoundary {
583                boundary: RuntimeBoundaryCode::SqlDdlTargetRequired,
584            }),
585            29 => Some(DiagnosticDetail::RuntimeBoundary {
586                boundary: RuntimeBoundaryCode::SqlDdlEntityNotConfigured,
587            }),
588            30 => Some(DiagnosticDetail::RuntimeBoundary {
589                boundary: RuntimeBoundaryCode::QueryResponseRowsRequired,
590            }),
591            31 => Some(DiagnosticDetail::RuntimeBoundary {
592                boundary: RuntimeBoundaryCode::QueryResponseGroupedRowsRequired,
593            }),
594            32 => Some(DiagnosticDetail::RuntimeBoundary {
595                boundary: RuntimeBoundaryCode::MutationResultEntityRequired,
596            }),
597            33 => Some(DiagnosticDetail::RuntimeBoundary {
598                boundary: RuntimeBoundaryCode::MutationResultEntitiesRequired,
599            }),
600            34 => Some(DiagnosticDetail::RuntimeBoundary {
601                boundary: RuntimeBoundaryCode::MutationResultIdRequired,
602            }),
603            35 => Some(DiagnosticDetail::RuntimeBoundary {
604                boundary: RuntimeBoundaryCode::MutationResultIdsRequired,
605            }),
606            36 => Some(DiagnosticDetail::RuntimeBoundary {
607                boundary: RuntimeBoundaryCode::RowProjectionFieldNotConfigured,
608            }),
609            _ => None,
610        }
611    }
612
613    const fn sql_feature_detail(raw: u16) -> Option<DiagnosticDetail> {
614        let base = Self::SQL_FEATURE_AGGREGATE_FILTER_CLAUSE.raw();
615        if raw < base {
616            return None;
617        }
618
619        let offset = (raw - base) as usize;
620        if offset < Self::SQL_FEATURE_DETAILS.len() {
621            Some(DiagnosticDetail::UnsupportedSqlFeature {
622                feature: Self::SQL_FEATURE_DETAILS[offset],
623            })
624        } else {
625            None
626        }
627    }
628
629    const fn sql_surface_detail(raw: u16) -> Option<DiagnosticDetail> {
630        match raw {
631            100 => Some(DiagnosticDetail::SqlSurfaceMismatch {
632                mismatch: SqlSurfaceMismatchCode::QueryRejectsInsert,
633            }),
634            101 => Some(DiagnosticDetail::SqlSurfaceMismatch {
635                mismatch: SqlSurfaceMismatchCode::QueryRejectsUpdate,
636            }),
637            102 => Some(DiagnosticDetail::SqlSurfaceMismatch {
638                mismatch: SqlSurfaceMismatchCode::QueryRejectsDelete,
639            }),
640            103 => Some(DiagnosticDetail::SqlSurfaceMismatch {
641                mismatch: SqlSurfaceMismatchCode::UpdateRejectsSelect,
642            }),
643            104 => Some(DiagnosticDetail::SqlSurfaceMismatch {
644                mismatch: SqlSurfaceMismatchCode::UpdateRejectsExplain,
645            }),
646            105 => Some(DiagnosticDetail::SqlSurfaceMismatch {
647                mismatch: SqlSurfaceMismatchCode::UpdateRejectsDescribe,
648            }),
649            106 => Some(DiagnosticDetail::SqlSurfaceMismatch {
650                mismatch: SqlSurfaceMismatchCode::UpdateRejectsShowIndexes,
651            }),
652            107 => Some(DiagnosticDetail::SqlSurfaceMismatch {
653                mismatch: SqlSurfaceMismatchCode::UpdateRejectsShowColumns,
654            }),
655            108 => Some(DiagnosticDetail::SqlSurfaceMismatch {
656                mismatch: SqlSurfaceMismatchCode::UpdateRejectsShowEntities,
657            }),
658            109 => Some(DiagnosticDetail::SqlSurfaceMismatch {
659                mismatch: SqlSurfaceMismatchCode::UpdateRejectsShowStores,
660            }),
661            110 => Some(DiagnosticDetail::SqlSurfaceMismatch {
662                mismatch: SqlSurfaceMismatchCode::UpdateRejectsShowMemory,
663            }),
664            _ => None,
665        }
666    }
667
668    const fn schema_ddl_detail(raw: u16) -> Option<DiagnosticDetail> {
669        match raw {
670            111 => Some(DiagnosticDetail::SchemaDdlAdmission {
671                reason: SchemaDdlAdmissionCode::MissingExpectedSchemaVersion,
672            }),
673            112 => Some(DiagnosticDetail::SchemaDdlAdmission {
674                reason: SchemaDdlAdmissionCode::MissingNextSchemaVersion,
675            }),
676            113 => Some(DiagnosticDetail::SchemaDdlAdmission {
677                reason: SchemaDdlAdmissionCode::StaleExpectedSchemaVersion,
678            }),
679            114 => Some(DiagnosticDetail::SchemaDdlAdmission {
680                reason: SchemaDdlAdmissionCode::InvalidExpectedSchemaVersion,
681            }),
682            115 => Some(DiagnosticDetail::SchemaDdlAdmission {
683                reason: SchemaDdlAdmissionCode::InvalidNextSchemaVersion,
684            }),
685            116 => Some(DiagnosticDetail::SchemaDdlAdmission {
686                reason: SchemaDdlAdmissionCode::AcceptedSchemaChangeWithoutVersionBump,
687            }),
688            117 => Some(DiagnosticDetail::SchemaDdlAdmission {
689                reason: SchemaDdlAdmissionCode::EmptyVersionBump,
690            }),
691            118 => Some(DiagnosticDetail::SchemaDdlAdmission {
692                reason: SchemaDdlAdmissionCode::VersionGap,
693            }),
694            119 => Some(DiagnosticDetail::SchemaDdlAdmission {
695                reason: SchemaDdlAdmissionCode::VersionRollback,
696            }),
697            120 => Some(DiagnosticDetail::SchemaDdlAdmission {
698                reason: SchemaDdlAdmissionCode::FingerprintMethodMismatch,
699            }),
700            121 => Some(DiagnosticDetail::SchemaDdlAdmission {
701                reason: SchemaDdlAdmissionCode::UnsupportedTransitionClass,
702            }),
703            122 => Some(DiagnosticDetail::SchemaDdlAdmission {
704                reason: SchemaDdlAdmissionCode::PhysicalRunnerMissing,
705            }),
706            123 => Some(DiagnosticDetail::SchemaDdlAdmission {
707                reason: SchemaDdlAdmissionCode::ValidationFailed,
708            }),
709            124 => Some(DiagnosticDetail::SchemaDdlAdmission {
710                reason: SchemaDdlAdmissionCode::PublicationRaceLost,
711            }),
712            125 => Some(DiagnosticDetail::SchemaDdlAdmission {
713                reason: SchemaDdlAdmissionCode::InvalidAddColumnDefault,
714            }),
715            126 => Some(DiagnosticDetail::SchemaDdlAdmission {
716                reason: SchemaDdlAdmissionCode::InvalidAlterColumnDefault,
717            }),
718            127 => Some(DiagnosticDetail::SchemaDdlAdmission {
719                reason: SchemaDdlAdmissionCode::GeneratedIndexDropRejected,
720            }),
721            128 => Some(DiagnosticDetail::SchemaDdlAdmission {
722                reason: SchemaDdlAdmissionCode::RequiredDropDefaultUnsupported,
723            }),
724            129 => Some(DiagnosticDetail::SchemaDdlAdmission {
725                reason: SchemaDdlAdmissionCode::GeneratedFieldDefaultChangeRejected,
726            }),
727            130 => Some(DiagnosticDetail::SchemaDdlAdmission {
728                reason: SchemaDdlAdmissionCode::GeneratedFieldNullabilityChangeRejected,
729            }),
730            131 => Some(DiagnosticDetail::SchemaDdlAdmission {
731                reason: SchemaDdlAdmissionCode::SetNotNullValidationFailed,
732            }),
733            _ => None,
734        }
735    }
736
737    const fn sql_write_boundary_detail(raw: u16) -> Option<DiagnosticDetail> {
738        match raw {
739            133 => Some(DiagnosticDetail::SqlWriteBoundary {
740                boundary: SqlWriteBoundaryCode::PrimaryKeyLiteralShape,
741            }),
742            134 => Some(DiagnosticDetail::SqlWriteBoundary {
743                boundary: SqlWriteBoundaryCode::PrimaryKeyLiteralIncompatible,
744            }),
745            135 => Some(DiagnosticDetail::SqlWriteBoundary {
746                boundary: SqlWriteBoundaryCode::MissingPrimaryKey,
747            }),
748            136 => Some(DiagnosticDetail::SqlWriteBoundary {
749                boundary: SqlWriteBoundaryCode::MissingRequiredFields,
750            }),
751            137 => Some(DiagnosticDetail::SqlWriteBoundary {
752                boundary: SqlWriteBoundaryCode::ExplicitManagedField,
753            }),
754            138 => Some(DiagnosticDetail::SqlWriteBoundary {
755                boundary: SqlWriteBoundaryCode::ExplicitGeneratedField,
756            }),
757            139 => Some(DiagnosticDetail::SqlWriteBoundary {
758                boundary: SqlWriteBoundaryCode::InsertSelectRequiresScalar,
759            }),
760            140 => Some(DiagnosticDetail::SqlWriteBoundary {
761                boundary: SqlWriteBoundaryCode::InsertSelectAggregateProjection,
762            }),
763            141 => Some(DiagnosticDetail::SqlWriteBoundary {
764                boundary: SqlWriteBoundaryCode::InsertSelectWidthMismatch,
765            }),
766            142 => Some(DiagnosticDetail::SqlWriteBoundary {
767                boundary: SqlWriteBoundaryCode::UpdatePrimaryKeyMutation,
768            }),
769            143 => Some(DiagnosticDetail::SqlWriteBoundary {
770                boundary: SqlWriteBoundaryCode::InvalidFieldLiteral,
771            }),
772            144 => Some(DiagnosticDetail::SqlWriteBoundary {
773                boundary: SqlWriteBoundaryCode::UnknownReturningField,
774            }),
775            145 => Some(DiagnosticDetail::SqlWriteBoundary {
776                boundary: SqlWriteBoundaryCode::DuplicateReturningField,
777            }),
778            146 => Some(DiagnosticDetail::SqlWriteBoundary {
779                boundary: SqlWriteBoundaryCode::UpdateMissingWherePredicate,
780            }),
781            147 => Some(DiagnosticDetail::SqlWriteBoundary {
782                boundary: SqlWriteBoundaryCode::WriteOrderByUnsupportedShape,
783            }),
784            _ => None,
785        }
786    }
787}
788
789impl std::fmt::Debug for ErrorCode {
790    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
791        f.debug_tuple("ErrorCode").field(&self.0).finish()
792    }
793}
794
795///
796/// ErrorClass
797///
798/// Broad diagnostic class used for recovery decisions.
799///
800
801#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
802pub enum ErrorClass {
803    Query,
804    Corruption,
805    IncompatiblePersistedFormat,
806    NotFound,
807    Internal,
808    Conflict,
809    Unsupported,
810    InvariantViolation,
811}
812
813///
814/// ErrorOrigin
815///
816/// Subsystem that owns the diagnostic.
817///
818
819#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
820pub enum ErrorOrigin {
821    Cursor,
822    Executor,
823    Identity,
824    Index,
825    Interface,
826    Planner,
827    Query,
828    Recovery,
829    Response,
830    Runtime,
831    Serialize,
832    Store,
833}
834
835///
836/// QueryErrorKind
837///
838/// Public query error category.
839///
840
841#[repr(u16)]
842#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
843pub enum QueryErrorKind {
844    Validate,
845    Intent,
846    Plan,
847    AccessRequirement,
848    UnorderedPagination,
849    InvalidContinuationCursor,
850    NotFound,
851    NotUnique,
852}
853
854///
855/// RuntimeErrorKind
856///
857/// Public runtime error category.
858///
859
860#[repr(u16)]
861#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
862pub enum RuntimeErrorKind {
863    Corruption,
864    IncompatiblePersistedFormat,
865    InvariantViolation,
866    Conflict,
867    NotFound,
868    Unsupported,
869    Internal,
870}
871
872///
873/// RuntimeBoundaryCode
874///
875/// Compact public-runtime boundary identifier.
876///
877
878#[repr(u16)]
879#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
880pub enum RuntimeBoundaryCode {
881    SqlSurfaceControllerRequired,
882    SchemaSurfaceControllerRequired,
883    SqlQueryNoConfiguredEntities,
884    SqlQueryEntityNotConfigured,
885    SqlDdlTargetRequired,
886    SqlDdlEntityNotConfigured,
887    QueryResponseRowsRequired,
888    QueryResponseGroupedRowsRequired,
889    MutationResultEntityRequired,
890    MutationResultEntitiesRequired,
891    MutationResultIdRequired,
892    MutationResultIdsRequired,
893    RowProjectionFieldNotConfigured,
894}
895
896///
897/// SqlFeatureCode
898///
899/// Compact SQL feature identifier used by unsupported-feature diagnostics.
900///
901
902#[repr(u16)]
903#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
904pub enum SqlFeatureCode {
905    AggregateFilterClause,
906    AlterStatementBeyondAlterTable,
907    AlterTableAddColumnDuplicateDefault,
908    AlterTableAddColumnModifiers,
909    AlterTableAddStatementBeyondAddColumn,
910    AlterTableAlterColumnDropUnsupportedAction,
911    AlterTableAlterColumnModifiers,
912    AlterTableAlterColumnSetUnsupportedAction,
913    AlterTableAlterColumnUnsupportedAction,
914    AlterTableAlterStatementBeyondAlterColumn,
915    AlterTableDropColumnIfExistsSyntax,
916    AlterTableDropColumnModifiers,
917    AlterTableDropStatementBeyondDropColumn,
918    AlterTableRenameColumnMissingTo,
919    AlterTableRenameColumnModifiers,
920    AlterTableRenameStatementBeyondRenameColumn,
921    AlterTableUnsupportedOperation,
922    ColumnAlias,
923    CreateIndexIfNotExistsSyntax,
924    CreateIndexKeyOrderingModifiers,
925    CreateIndexModifiers,
926    CreateStatementBeyondCreateIndex,
927    DescribeModifier,
928    DdlSchemaVersionDuplicateExpectedClause,
929    DdlSchemaVersionDuplicateSetClause,
930    DropIndexModifiers,
931    DropIndexIfExistsSyntax,
932    DropStatementBeyondDropIndex,
933    ExpressionIndexUnsupportedFunction,
934    Having,
935    Insert,
936    Join,
937    LikePatternBeyondTrailingPrefix,
938    LowerFieldPredicateUnsupported,
939    MultiStatementSql,
940    NestedAggregateInput,
941    NestedProjectionFunctionInArithmetic,
942    OrderByUnsupportedForm,
943    Other,
944    ParameterBinding,
945    ParameterizedSchemaVersion,
946    PredicateStartsWithFirstArgument,
947    QuotedIdentifiers,
948    ReturningUnsupportedShape,
949    ScalarFunctionExpressionPosition,
950    ScaleTakingNumericFunctionExpressionPosition,
951    SearchedCaseGroupedOrderBy,
952    ShowColumnsModifiers,
953    ShowEntitiesModifiers,
954    ShowIndexesModifiers,
955    ShowMemoryModifiers,
956    ShowStoresModifiers,
957    ShowUnsupportedCommand,
958    SimpleCaseExpression,
959    StandaloneLiteralProjectionItem,
960    SupportedGroupedOrderByExpressionFamily,
961    SupportedOrderByExpressionFamily,
962    UnionIntersectExcept,
963    UnsupportedFunctionNamespace,
964    Update,
965    UpperFieldPredicateUnsupported,
966    WindowFunction,
967    With,
968}
969
970///
971/// SqlSurfaceMismatchCode
972///
973/// Compact SQL endpoint surface mismatch identifier.
974///
975
976#[repr(u16)]
977#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
978pub enum SqlSurfaceMismatchCode {
979    QueryRejectsInsert,
980    QueryRejectsUpdate,
981    QueryRejectsDelete,
982    UpdateRejectsSelect,
983    UpdateRejectsExplain,
984    UpdateRejectsDescribe,
985    UpdateRejectsShowIndexes,
986    UpdateRejectsShowColumns,
987    UpdateRejectsShowEntities,
988    UpdateRejectsShowStores,
989    UpdateRejectsShowMemory,
990}
991
992///
993/// SqlWriteBoundaryCode
994///
995/// Compact SQL write fail-closed boundary identifier.
996///
997
998#[repr(u16)]
999#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1000pub enum SqlWriteBoundaryCode {
1001    PrimaryKeyLiteralShape,
1002    PrimaryKeyLiteralIncompatible,
1003    MissingPrimaryKey,
1004    MissingRequiredFields,
1005    ExplicitManagedField,
1006    ExplicitGeneratedField,
1007    InsertSelectRequiresScalar,
1008    InsertSelectAggregateProjection,
1009    InsertSelectWidthMismatch,
1010    UpdatePrimaryKeyMutation,
1011    InvalidFieldLiteral,
1012    UnknownReturningField,
1013    DuplicateReturningField,
1014    UpdateMissingWherePredicate,
1015    WriteOrderByUnsupportedShape,
1016}
1017
1018///
1019/// SchemaDdlAdmissionCode
1020///
1021/// Compact SQL DDL admission rejection reason.
1022///
1023
1024#[repr(u16)]
1025#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1026pub enum SchemaDdlAdmissionCode {
1027    MissingExpectedSchemaVersion,
1028    MissingNextSchemaVersion,
1029    StaleExpectedSchemaVersion,
1030    InvalidExpectedSchemaVersion,
1031    InvalidNextSchemaVersion,
1032    AcceptedSchemaChangeWithoutVersionBump,
1033    EmptyVersionBump,
1034    VersionGap,
1035    VersionRollback,
1036    FingerprintMethodMismatch,
1037    UnsupportedTransitionClass,
1038    PhysicalRunnerMissing,
1039    ValidationFailed,
1040    PublicationRaceLost,
1041    InvalidAddColumnDefault,
1042    InvalidAlterColumnDefault,
1043    GeneratedIndexDropRejected,
1044    RequiredDropDefaultUnsupported,
1045    GeneratedFieldDefaultChangeRejected,
1046    GeneratedFieldNullabilityChangeRejected,
1047    SetNotNullValidationFailed,
1048}
1049
1050///
1051/// DiagnosticDetail
1052///
1053/// Small structured diagnostic payload for callers and CLI rendering.
1054///
1055
1056#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1057pub enum DiagnosticDetail {
1058    QueryKind { kind: QueryErrorKind },
1059    RuntimeKind { kind: RuntimeErrorKind },
1060    RuntimeBoundary { boundary: RuntimeBoundaryCode },
1061    SchemaDdlAdmission { reason: SchemaDdlAdmissionCode },
1062    UnsupportedSqlFeature { feature: SqlFeatureCode },
1063    SqlSurfaceMismatch { mismatch: SqlSurfaceMismatchCode },
1064    SqlWriteBoundary { boundary: SqlWriteBoundaryCode },
1065}
1066
1067///
1068/// Diagnostic
1069///
1070/// Compact public diagnostic payload.
1071///
1072
1073#[derive(Clone, Debug, Eq, PartialEq)]
1074pub struct Diagnostic {
1075    code: DiagnosticCode,
1076    origin: ErrorOrigin,
1077    detail: Option<DiagnosticDetail>,
1078}
1079
1080impl Diagnostic {
1081    /// Build a compact diagnostic from a code and optional structured detail.
1082    #[must_use]
1083    pub const fn new(
1084        code: DiagnosticCode,
1085        origin: ErrorOrigin,
1086        detail: Option<DiagnosticDetail>,
1087    ) -> Self {
1088        Self {
1089            code,
1090            origin,
1091            detail,
1092        }
1093    }
1094
1095    /// Build a compact diagnostic using the code's default origin.
1096    #[must_use]
1097    pub const fn from_code(code: DiagnosticCode) -> Self {
1098        Self::new(code, code.origin(), None)
1099    }
1100
1101    /// Return the stable diagnostic code.
1102    #[must_use]
1103    pub const fn code(&self) -> DiagnosticCode {
1104        self.code
1105    }
1106
1107    /// Return the diagnostic class.
1108    #[must_use]
1109    pub const fn class(&self) -> ErrorClass {
1110        self.code.class()
1111    }
1112
1113    /// Return the subsystem origin.
1114    #[must_use]
1115    pub const fn origin(&self) -> ErrorOrigin {
1116        self.origin
1117    }
1118
1119    /// Return structured diagnostic detail, when available.
1120    #[must_use]
1121    pub const fn detail(&self) -> Option<&DiagnosticDetail> {
1122        self.detail.as_ref()
1123    }
1124
1125    /// Return the numeric public wire code for this diagnostic.
1126    #[must_use]
1127    pub const fn error_code(&self) -> ErrorCode {
1128        ErrorCode::from_parts(self.code, self.detail)
1129    }
1130}
1131
1132#[cfg(test)]
1133mod tests {
1134    use super::{Diagnostic, DiagnosticCode, ErrorClass, ErrorCode, ErrorOrigin};
1135
1136    const ORDERED_ERROR_CODES: [ErrorCode; 147] = [
1137        ErrorCode::QUERY_VALIDATE,
1138        ErrorCode::QUERY_INTENT,
1139        ErrorCode::QUERY_PLAN,
1140        ErrorCode::QUERY_ACCESS_REQUIREMENT,
1141        ErrorCode::QUERY_UNORDERED_PAGINATION,
1142        ErrorCode::QUERY_INVALID_CONTINUATION_CURSOR,
1143        ErrorCode::QUERY_NOT_FOUND,
1144        ErrorCode::QUERY_NOT_UNIQUE,
1145        ErrorCode::QUERY_NUMERIC_OVERFLOW,
1146        ErrorCode::QUERY_NUMERIC_NOT_REPRESENTABLE,
1147        ErrorCode::QUERY_UNSUPPORTED_SQL_FEATURE,
1148        ErrorCode::QUERY_SQL_SURFACE_MISMATCH,
1149        ErrorCode::SCHEMA_DDL_ADMISSION,
1150        ErrorCode::STORE_NOT_FOUND,
1151        ErrorCode::STORE_CORRUPTION,
1152        ErrorCode::STORE_INVARIANT_VIOLATION,
1153        ErrorCode::RUNTIME_CORRUPTION,
1154        ErrorCode::RUNTIME_INCOMPATIBLE_PERSISTED_FORMAT,
1155        ErrorCode::RUNTIME_INVARIANT_VIOLATION,
1156        ErrorCode::RUNTIME_CONFLICT,
1157        ErrorCode::RUNTIME_NOT_FOUND,
1158        ErrorCode::RUNTIME_UNSUPPORTED,
1159        ErrorCode::RUNTIME_INTERNAL,
1160        ErrorCode::RUNTIME_BOUNDARY_SQL_SURFACE_CONTROLLER_REQUIRED,
1161        ErrorCode::RUNTIME_BOUNDARY_SCHEMA_SURFACE_CONTROLLER_REQUIRED,
1162        ErrorCode::RUNTIME_BOUNDARY_SQL_QUERY_NO_CONFIGURED_ENTITIES,
1163        ErrorCode::RUNTIME_BOUNDARY_SQL_QUERY_ENTITY_NOT_CONFIGURED,
1164        ErrorCode::RUNTIME_BOUNDARY_SQL_DDL_TARGET_REQUIRED,
1165        ErrorCode::RUNTIME_BOUNDARY_SQL_DDL_ENTITY_NOT_CONFIGURED,
1166        ErrorCode::RUNTIME_BOUNDARY_QUERY_RESPONSE_ROWS_REQUIRED,
1167        ErrorCode::RUNTIME_BOUNDARY_QUERY_RESPONSE_GROUPED_ROWS_REQUIRED,
1168        ErrorCode::RUNTIME_BOUNDARY_MUTATION_RESULT_ENTITY_REQUIRED,
1169        ErrorCode::RUNTIME_BOUNDARY_MUTATION_RESULT_ENTITIES_REQUIRED,
1170        ErrorCode::RUNTIME_BOUNDARY_MUTATION_RESULT_ID_REQUIRED,
1171        ErrorCode::RUNTIME_BOUNDARY_MUTATION_RESULT_IDS_REQUIRED,
1172        ErrorCode::RUNTIME_BOUNDARY_ROW_PROJECTION_FIELD_NOT_CONFIGURED,
1173        ErrorCode::SQL_FEATURE_AGGREGATE_FILTER_CLAUSE,
1174        ErrorCode::SQL_FEATURE_ALTER_STATEMENT_BEYOND_ALTER_TABLE,
1175        ErrorCode::SQL_FEATURE_ALTER_TABLE_ADD_COLUMN_DUPLICATE_DEFAULT,
1176        ErrorCode::SQL_FEATURE_ALTER_TABLE_ADD_COLUMN_MODIFIERS,
1177        ErrorCode::SQL_FEATURE_ALTER_TABLE_ADD_STATEMENT_BEYOND_ADD_COLUMN,
1178        ErrorCode::SQL_FEATURE_ALTER_TABLE_ALTER_COLUMN_DROP_UNSUPPORTED_ACTION,
1179        ErrorCode::SQL_FEATURE_ALTER_TABLE_ALTER_COLUMN_MODIFIERS,
1180        ErrorCode::SQL_FEATURE_ALTER_TABLE_ALTER_COLUMN_SET_UNSUPPORTED_ACTION,
1181        ErrorCode::SQL_FEATURE_ALTER_TABLE_ALTER_COLUMN_UNSUPPORTED_ACTION,
1182        ErrorCode::SQL_FEATURE_ALTER_TABLE_ALTER_STATEMENT_BEYOND_ALTER_COLUMN,
1183        ErrorCode::SQL_FEATURE_ALTER_TABLE_DROP_COLUMN_IF_EXISTS_SYNTAX,
1184        ErrorCode::SQL_FEATURE_ALTER_TABLE_DROP_COLUMN_MODIFIERS,
1185        ErrorCode::SQL_FEATURE_ALTER_TABLE_DROP_STATEMENT_BEYOND_DROP_COLUMN,
1186        ErrorCode::SQL_FEATURE_ALTER_TABLE_RENAME_COLUMN_MISSING_TO,
1187        ErrorCode::SQL_FEATURE_ALTER_TABLE_RENAME_COLUMN_MODIFIERS,
1188        ErrorCode::SQL_FEATURE_ALTER_TABLE_RENAME_STATEMENT_BEYOND_RENAME_COLUMN,
1189        ErrorCode::SQL_FEATURE_ALTER_TABLE_UNSUPPORTED_OPERATION,
1190        ErrorCode::SQL_FEATURE_COLUMN_ALIAS,
1191        ErrorCode::SQL_FEATURE_CREATE_INDEX_IF_NOT_EXISTS_SYNTAX,
1192        ErrorCode::SQL_FEATURE_CREATE_INDEX_KEY_ORDERING_MODIFIERS,
1193        ErrorCode::SQL_FEATURE_CREATE_INDEX_MODIFIERS,
1194        ErrorCode::SQL_FEATURE_CREATE_STATEMENT_BEYOND_CREATE_INDEX,
1195        ErrorCode::SQL_FEATURE_DESCRIBE_MODIFIER,
1196        ErrorCode::SQL_FEATURE_DDL_SCHEMA_VERSION_DUPLICATE_EXPECTED_CLAUSE,
1197        ErrorCode::SQL_FEATURE_DDL_SCHEMA_VERSION_DUPLICATE_SET_CLAUSE,
1198        ErrorCode::SQL_FEATURE_DROP_INDEX_MODIFIERS,
1199        ErrorCode::SQL_FEATURE_DROP_INDEX_IF_EXISTS_SYNTAX,
1200        ErrorCode::SQL_FEATURE_DROP_STATEMENT_BEYOND_DROP_INDEX,
1201        ErrorCode::SQL_FEATURE_EXPRESSION_INDEX_UNSUPPORTED_FUNCTION,
1202        ErrorCode::SQL_FEATURE_HAVING,
1203        ErrorCode::SQL_FEATURE_INSERT,
1204        ErrorCode::SQL_FEATURE_JOIN,
1205        ErrorCode::SQL_FEATURE_LIKE_PATTERN_BEYOND_TRAILING_PREFIX,
1206        ErrorCode::SQL_FEATURE_LOWER_FIELD_PREDICATE_UNSUPPORTED,
1207        ErrorCode::SQL_FEATURE_MULTI_STATEMENT_SQL,
1208        ErrorCode::SQL_FEATURE_NESTED_AGGREGATE_INPUT,
1209        ErrorCode::SQL_FEATURE_NESTED_PROJECTION_FUNCTION_IN_ARITHMETIC,
1210        ErrorCode::SQL_FEATURE_ORDER_BY_UNSUPPORTED_FORM,
1211        ErrorCode::SQL_FEATURE_OTHER,
1212        ErrorCode::SQL_FEATURE_PARAMETER_BINDING,
1213        ErrorCode::SQL_FEATURE_PARAMETERIZED_SCHEMA_VERSION,
1214        ErrorCode::SQL_FEATURE_PREDICATE_STARTS_WITH_FIRST_ARGUMENT,
1215        ErrorCode::SQL_FEATURE_QUOTED_IDENTIFIERS,
1216        ErrorCode::SQL_FEATURE_RETURNING_UNSUPPORTED_SHAPE,
1217        ErrorCode::SQL_FEATURE_SCALAR_FUNCTION_EXPRESSION_POSITION,
1218        ErrorCode::SQL_FEATURE_SCALE_TAKING_NUMERIC_FUNCTION_EXPRESSION_POSITION,
1219        ErrorCode::SQL_FEATURE_SEARCHED_CASE_GROUPED_ORDER_BY,
1220        ErrorCode::SQL_FEATURE_SHOW_COLUMNS_MODIFIERS,
1221        ErrorCode::SQL_FEATURE_SHOW_ENTITIES_MODIFIERS,
1222        ErrorCode::SQL_FEATURE_SHOW_INDEXES_MODIFIERS,
1223        ErrorCode::SQL_FEATURE_SHOW_MEMORY_MODIFIERS,
1224        ErrorCode::SQL_FEATURE_SHOW_STORES_MODIFIERS,
1225        ErrorCode::SQL_FEATURE_SHOW_UNSUPPORTED_COMMAND,
1226        ErrorCode::SQL_FEATURE_SIMPLE_CASE_EXPRESSION,
1227        ErrorCode::SQL_FEATURE_STANDALONE_LITERAL_PROJECTION_ITEM,
1228        ErrorCode::SQL_FEATURE_SUPPORTED_GROUPED_ORDER_BY_EXPRESSION_FAMILY,
1229        ErrorCode::SQL_FEATURE_SUPPORTED_ORDER_BY_EXPRESSION_FAMILY,
1230        ErrorCode::SQL_FEATURE_UNION_INTERSECT_EXCEPT,
1231        ErrorCode::SQL_FEATURE_UNSUPPORTED_FUNCTION_NAMESPACE,
1232        ErrorCode::SQL_FEATURE_UPDATE,
1233        ErrorCode::SQL_FEATURE_UPPER_FIELD_PREDICATE_UNSUPPORTED,
1234        ErrorCode::SQL_FEATURE_WINDOW_FUNCTION,
1235        ErrorCode::SQL_FEATURE_WITH,
1236        ErrorCode::SQL_SURFACE_QUERY_REJECTS_INSERT,
1237        ErrorCode::SQL_SURFACE_QUERY_REJECTS_UPDATE,
1238        ErrorCode::SQL_SURFACE_QUERY_REJECTS_DELETE,
1239        ErrorCode::SQL_SURFACE_UPDATE_REJECTS_SELECT,
1240        ErrorCode::SQL_SURFACE_UPDATE_REJECTS_EXPLAIN,
1241        ErrorCode::SQL_SURFACE_UPDATE_REJECTS_DESCRIBE,
1242        ErrorCode::SQL_SURFACE_UPDATE_REJECTS_SHOW_INDEXES,
1243        ErrorCode::SQL_SURFACE_UPDATE_REJECTS_SHOW_COLUMNS,
1244        ErrorCode::SQL_SURFACE_UPDATE_REJECTS_SHOW_ENTITIES,
1245        ErrorCode::SQL_SURFACE_UPDATE_REJECTS_SHOW_STORES,
1246        ErrorCode::SQL_SURFACE_UPDATE_REJECTS_SHOW_MEMORY,
1247        ErrorCode::SCHEMA_DDL_MISSING_EXPECTED_SCHEMA_VERSION,
1248        ErrorCode::SCHEMA_DDL_MISSING_NEXT_SCHEMA_VERSION,
1249        ErrorCode::SCHEMA_DDL_STALE_EXPECTED_SCHEMA_VERSION,
1250        ErrorCode::SCHEMA_DDL_INVALID_EXPECTED_SCHEMA_VERSION,
1251        ErrorCode::SCHEMA_DDL_INVALID_NEXT_SCHEMA_VERSION,
1252        ErrorCode::SCHEMA_DDL_ACCEPTED_SCHEMA_CHANGE_WITHOUT_VERSION_BUMP,
1253        ErrorCode::SCHEMA_DDL_EMPTY_VERSION_BUMP,
1254        ErrorCode::SCHEMA_DDL_VERSION_GAP,
1255        ErrorCode::SCHEMA_DDL_VERSION_ROLLBACK,
1256        ErrorCode::SCHEMA_DDL_FINGERPRINT_METHOD_MISMATCH,
1257        ErrorCode::SCHEMA_DDL_UNSUPPORTED_TRANSITION_CLASS,
1258        ErrorCode::SCHEMA_DDL_PHYSICAL_RUNNER_MISSING,
1259        ErrorCode::SCHEMA_DDL_VALIDATION_FAILED,
1260        ErrorCode::SCHEMA_DDL_PUBLICATION_RACE_LOST,
1261        ErrorCode::SCHEMA_DDL_INVALID_ADD_COLUMN_DEFAULT,
1262        ErrorCode::SCHEMA_DDL_INVALID_ALTER_COLUMN_DEFAULT,
1263        ErrorCode::SCHEMA_DDL_GENERATED_INDEX_DROP_REJECTED,
1264        ErrorCode::SCHEMA_DDL_REQUIRED_DROP_DEFAULT_UNSUPPORTED,
1265        ErrorCode::SCHEMA_DDL_GENERATED_FIELD_DEFAULT_CHANGE_REJECTED,
1266        ErrorCode::SCHEMA_DDL_GENERATED_FIELD_NULLABILITY_CHANGE_REJECTED,
1267        ErrorCode::SCHEMA_DDL_SET_NOT_NULL_VALIDATION_FAILED,
1268        ErrorCode::QUERY_SQL_WRITE_BOUNDARY,
1269        ErrorCode::SQL_WRITE_PRIMARY_KEY_LITERAL_SHAPE,
1270        ErrorCode::SQL_WRITE_PRIMARY_KEY_LITERAL_INCOMPATIBLE,
1271        ErrorCode::SQL_WRITE_MISSING_PRIMARY_KEY,
1272        ErrorCode::SQL_WRITE_MISSING_REQUIRED_FIELDS,
1273        ErrorCode::SQL_WRITE_EXPLICIT_MANAGED_FIELD,
1274        ErrorCode::SQL_WRITE_EXPLICIT_GENERATED_FIELD,
1275        ErrorCode::SQL_WRITE_INSERT_SELECT_REQUIRES_SCALAR,
1276        ErrorCode::SQL_WRITE_INSERT_SELECT_AGGREGATE_PROJECTION,
1277        ErrorCode::SQL_WRITE_INSERT_SELECT_WIDTH_MISMATCH,
1278        ErrorCode::SQL_WRITE_UPDATE_PRIMARY_KEY_MUTATION,
1279        ErrorCode::SQL_WRITE_INVALID_FIELD_LITERAL,
1280        ErrorCode::SQL_WRITE_UNKNOWN_RETURNING_FIELD,
1281        ErrorCode::SQL_WRITE_DUPLICATE_RETURNING_FIELD,
1282        ErrorCode::SQL_WRITE_UPDATE_MISSING_WHERE_PREDICATE,
1283        ErrorCode::SQL_WRITE_ORDER_BY_UNSUPPORTED_SHAPE,
1284    ];
1285
1286    #[test]
1287    fn diagnostic_from_code_uses_default_origin() {
1288        let diagnostic = Diagnostic::from_code(DiagnosticCode::QueryPlan);
1289
1290        assert_eq!(diagnostic.code(), DiagnosticCode::QueryPlan);
1291        assert_eq!(diagnostic.origin(), ErrorOrigin::Query);
1292    }
1293
1294    #[test]
1295    fn diagnostic_code_reports_broad_class() {
1296        assert_eq!(
1297            DiagnosticCode::QueryUnsupportedSqlFeature.class(),
1298            ErrorClass::Unsupported
1299        );
1300        assert_eq!(
1301            DiagnosticCode::QuerySqlSurfaceMismatch.class(),
1302            ErrorClass::Unsupported
1303        );
1304        assert_eq!(DiagnosticCode::QueryPlan.class(), ErrorClass::Query);
1305        assert_eq!(
1306            DiagnosticCode::StoreCorruption.class(),
1307            ErrorClass::Corruption
1308        );
1309    }
1310
1311    #[test]
1312    fn public_error_codes_are_sequential() {
1313        for (index, code) in ORDERED_ERROR_CODES.iter().enumerate() {
1314            let expected = u16::try_from(index + 1).expect("test error-code index fits u16");
1315            assert_eq!(code.raw(), expected);
1316        }
1317    }
1318}