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