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