1#[cfg(test)]
9mod tests;
10
11use icydb_diagnostic_code as diagnostic_code;
12use std::fmt;
13
14pub(crate) const COMPACT_QUERY_DIAGNOSTIC_MESSAGE: &str = "query diagnostic";
15const COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE: &str = "runtime diagnostic";
16const COMPACT_STORE_DIAGNOSTIC_MESSAGE: &str = "store diagnostic";
17const COMPACT_INDEX_DIAGNOSTIC_MESSAGE: &str = "index diagnostic";
18const COMPACT_SERIALIZE_DIAGNOSTIC_MESSAGE: &str = "serialize diagnostic";
19const COMPACT_IDENTITY_DIAGNOSTIC_MESSAGE: &str = "identity diagnostic";
20
21const fn compact_message_for(_class: ErrorClass, origin: ErrorOrigin) -> &'static str {
22 match origin {
23 ErrorOrigin::Serialize => COMPACT_SERIALIZE_DIAGNOSTIC_MESSAGE,
24 ErrorOrigin::Store => COMPACT_STORE_DIAGNOSTIC_MESSAGE,
25 ErrorOrigin::Index => COMPACT_INDEX_DIAGNOSTIC_MESSAGE,
26 ErrorOrigin::Identity => COMPACT_IDENTITY_DIAGNOSTIC_MESSAGE,
27 ErrorOrigin::Query | ErrorOrigin::Planner | ErrorOrigin::Response => {
28 COMPACT_QUERY_DIAGNOSTIC_MESSAGE
29 }
30 ErrorOrigin::Cursor
31 | ErrorOrigin::Recovery
32 | ErrorOrigin::Executor
33 | ErrorOrigin::Interface => COMPACT_RUNTIME_DIAGNOSTIC_MESSAGE,
34 }
35}
36
37pub struct InternalError {
138 pub(crate) class: ErrorClass,
139 pub(crate) origin: ErrorOrigin,
140
141 pub(crate) detail: Option<ErrorDetail>,
144}
145
146#[expect(
147 clippy::missing_const_for_fn,
148 reason = "internal error constructors stay non-const so compact diagnostic construction does not force const churn across subsystem helper seams"
149)]
150impl InternalError {
151 #[must_use]
155 #[cold]
156 #[inline(never)]
157 pub fn new(class: ErrorClass, origin: ErrorOrigin) -> Self {
158 let detail = match (class, origin) {
159 (ErrorClass::Corruption, ErrorOrigin::Store) => {
160 Some(ErrorDetail::Store(StoreError::Corrupt))
161 }
162 (ErrorClass::InvariantViolation, ErrorOrigin::Store) => {
163 Some(ErrorDetail::Store(StoreError::InvariantViolation))
164 }
165 _ => None,
166 };
167
168 Self {
169 class,
170 origin,
171 detail,
172 }
173 }
174
175 #[must_use]
177 pub const fn class(&self) -> ErrorClass {
178 self.class
179 }
180
181 #[must_use]
183 pub const fn origin(&self) -> ErrorOrigin {
184 self.origin
185 }
186
187 #[must_use]
189 pub const fn message(&self) -> &'static str {
190 compact_message_for(self.class, self.origin)
191 }
192
193 #[must_use]
195 pub const fn detail(&self) -> Option<&ErrorDetail> {
196 self.detail.as_ref()
197 }
198
199 #[must_use]
201 pub fn diagnostic(&self) -> diagnostic_code::Diagnostic {
202 diagnostic_code::Diagnostic::new(
203 self.diagnostic_code(),
204 self.origin.diagnostic_origin(),
205 self.detail
206 .as_ref()
207 .and_then(ErrorDetail::diagnostic_detail),
208 )
209 }
210
211 #[must_use]
213 pub fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
214 self.detail.as_ref().map_or_else(
215 || self.class.diagnostic_code(self.origin),
216 ErrorDetail::diagnostic_code,
217 )
218 }
219
220 #[must_use]
222 pub fn into_message(self) -> String {
223 self.message().to_string()
224 }
225
226 #[cold]
228 #[inline(never)]
229 pub(crate) fn classified(class: ErrorClass, origin: ErrorOrigin) -> Self {
230 Self::new(class, origin)
231 }
232
233 #[cold]
237 #[inline(never)]
238 pub(crate) fn with_origin(self, origin: ErrorOrigin) -> Self {
239 Self::classified(self.class, origin)
240 }
241
242 #[cold]
244 #[inline(never)]
245 pub(crate) fn index_invariant() -> Self {
246 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Index)
247 }
248
249 pub(crate) fn index_key_field_count_exceeds_max(
251 _index_name: &str,
252 _field_count: usize,
253 _max_fields: usize,
254 ) -> Self {
255 Self::index_invariant()
256 }
257
258 pub(crate) fn index_key_item_field_missing_on_entity_model(_field: &str) -> Self {
260 Self::index_invariant()
261 }
262
263 pub(crate) fn index_key_item_field_missing_on_lookup_row(_field: &str) -> Self {
265 Self::index_invariant()
266 }
267
268 pub(crate) fn index_expression_source_type_mismatch(
270 _index_name: &str,
271 _expression: impl Sized,
272 _expected: impl Sized,
273 _source_label: &str,
274 ) -> Self {
275 Self::index_invariant()
276 }
277
278 #[cold]
281 #[inline(never)]
282 pub(crate) fn planner_executor_invariant() -> Self {
283 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Planner)
284 }
285
286 #[cold]
289 #[inline(never)]
290 pub(crate) fn query_executor_invariant() -> Self {
291 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Query)
292 }
293
294 #[cold]
297 #[inline(never)]
298 pub(crate) fn cursor_executor_invariant() -> Self {
299 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Cursor)
300 }
301
302 #[cold]
304 #[inline(never)]
305 pub(crate) fn executor_invariant() -> Self {
306 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Executor)
307 }
308
309 #[cold]
311 #[inline(never)]
312 pub(crate) fn executor_internal() -> Self {
313 Self::new(ErrorClass::Internal, ErrorOrigin::Executor)
314 }
315
316 #[cold]
318 #[inline(never)]
319 pub(crate) fn executor_unsupported() -> Self {
320 Self::new(ErrorClass::Unsupported, ErrorOrigin::Executor)
321 }
322
323 pub(crate) fn mutation_entity_primary_key_missing(
325 _entity_path: &str,
326 _field_name: &str,
327 ) -> Self {
328 Self::executor_invariant()
329 }
330
331 pub(crate) fn mutation_entity_primary_key_invalid_value(
333 _entity_path: &str,
334 _field_name: &str,
335 _value: &crate::value::Value,
336 ) -> Self {
337 Self::executor_invariant()
338 }
339
340 pub(crate) fn mutation_entity_primary_key_type_mismatch(
342 _entity_path: &str,
343 _field_name: &str,
344 _value: &crate::value::Value,
345 ) -> Self {
346 Self::executor_invariant()
347 }
348
349 pub(crate) fn mutation_entity_primary_key_mismatch(
351 _entity_path: &str,
352 _field_name: &str,
353 _field_value: &crate::value::Value,
354 _identity_key: &crate::value::Value,
355 ) -> Self {
356 Self::executor_invariant()
357 }
358
359 pub(crate) fn mutation_entity_field_missing(
361 _entity_path: &str,
362 _field_name: &str,
363 _indexed: bool,
364 ) -> Self {
365 Self::executor_invariant()
366 }
367
368 pub(crate) fn mutation_structural_patch_required_field_missing(
370 _entity_path: &str,
371 _field_name: &str,
372 ) -> Self {
373 Self::executor_invariant()
374 }
375
376 pub(crate) fn mutation_entity_field_type_mismatch(
378 _entity_path: &str,
379 _field_name: &str,
380 _value: &crate::value::Value,
381 ) -> Self {
382 Self::executor_invariant()
383 }
384
385 pub(crate) fn mutation_generated_field_explicit(_entity_path: &str, _field_name: &str) -> Self {
387 Self::executor_unsupported()
388 }
389
390 #[must_use]
392 pub fn mutation_create_missing_authored_fields(_entity_path: &str, _field_names: &str) -> Self {
393 Self::executor_unsupported()
394 }
395
396 pub(crate) fn mutation_structural_after_image_invalid(
401 _entity_path: &str,
402 _data_key: impl Sized,
403 _detail: impl Sized,
404 ) -> Self {
405 Self::executor_invariant()
406 }
407
408 pub(crate) fn mutation_structural_field_unknown(_entity_path: &str, _field_name: &str) -> Self {
410 Self::executor_invariant()
411 }
412
413 pub(crate) fn mutation_decimal_scale_mismatch(
415 _entity_path: &str,
416 _field_name: &str,
417 _expected_scale: impl Sized,
418 _actual_scale: impl Sized,
419 ) -> Self {
420 Self::executor_unsupported()
421 }
422
423 pub(crate) fn mutation_text_max_len_exceeded(
425 _entity_path: &str,
426 _field_name: &str,
427 _max_len: impl Sized,
428 _actual_len: impl Sized,
429 ) -> Self {
430 Self::executor_unsupported()
431 }
432
433 pub(crate) fn mutation_set_field_list_required(_entity_path: &str, _field_name: &str) -> Self {
435 Self::executor_invariant()
436 }
437
438 pub(crate) fn mutation_set_field_not_canonical(_entity_path: &str, _field_name: &str) -> Self {
440 Self::executor_invariant()
441 }
442
443 pub(crate) fn mutation_map_field_map_required(_entity_path: &str, _field_name: &str) -> Self {
445 Self::executor_invariant()
446 }
447
448 pub(crate) fn mutation_map_field_entries_invalid(
450 _entity_path: &str,
451 _field_name: &str,
452 _detail: impl Sized,
453 ) -> Self {
454 Self::executor_invariant()
455 }
456
457 pub(crate) fn mutation_map_field_entries_not_canonical(
459 _entity_path: &str,
460 _field_name: &str,
461 ) -> Self {
462 Self::executor_invariant()
463 }
464
465 pub(crate) fn scalar_page_ordering_after_filtering_required() -> Self {
467 Self::query_executor_invariant()
468 }
469
470 pub(crate) fn scalar_page_cursor_boundary_order_required() -> Self {
472 Self::query_executor_invariant()
473 }
474
475 pub(crate) fn scalar_page_cursor_boundary_after_ordering_required() -> Self {
477 Self::query_executor_invariant()
478 }
479
480 pub(crate) fn scalar_page_pagination_after_ordering_required() -> Self {
482 Self::query_executor_invariant()
483 }
484
485 pub(crate) fn scalar_page_delete_limit_after_ordering_required() -> Self {
487 Self::query_executor_invariant()
488 }
489
490 pub(crate) fn load_runtime_scalar_payload_required() -> Self {
492 Self::query_executor_invariant()
493 }
494
495 pub(crate) fn load_runtime_grouped_payload_required() -> Self {
497 Self::query_executor_invariant()
498 }
499
500 pub(crate) fn load_runtime_scalar_surface_payload_required() -> Self {
502 Self::query_executor_invariant()
503 }
504
505 pub(crate) fn load_runtime_grouped_surface_payload_required() -> Self {
507 Self::query_executor_invariant()
508 }
509
510 pub(crate) fn load_executor_load_plan_required() -> Self {
512 Self::query_executor_invariant()
513 }
514
515 pub(crate) fn delete_executor_grouped_unsupported() -> Self {
517 Self::executor_unsupported()
518 }
519
520 pub(crate) fn delete_executor_delete_plan_required() -> Self {
522 Self::query_executor_invariant()
523 }
524
525 pub(crate) fn aggregate_fold_mode_terminal_contract_required() -> Self {
527 Self::query_executor_invariant()
528 }
529
530 pub(crate) fn fast_stream_route_kind_request_match_required() -> Self {
532 Self::query_executor_invariant()
533 }
534
535 pub(crate) fn secondary_index_prefix_spec_required() -> Self {
537 Self::query_executor_invariant()
538 }
539
540 pub(crate) fn index_range_limit_spec_required() -> Self {
542 Self::query_executor_invariant()
543 }
544
545 pub(crate) fn mutation_atomic_save_duplicate_key(_entity_path: &str, _key: impl Sized) -> Self {
547 Self::executor_unsupported()
548 }
549
550 pub(crate) fn mutation_index_store_generation_changed(
552 _expected_generation: u64,
553 _observed_generation: u64,
554 ) -> Self {
555 Self::executor_invariant()
556 }
557
558 #[cold]
560 #[inline(never)]
561 pub(crate) fn planner_invariant() -> Self {
562 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Planner)
563 }
564
565 pub(crate) fn query_invalid_logical_plan() -> Self {
567 Self::planner_invariant()
568 }
569
570 pub(crate) fn store_invariant() -> Self {
572 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Store)
573 }
574
575 pub(crate) fn duplicate_runtime_hooks_for_entity_tag(
577 _entity_tag: crate::types::EntityTag,
578 ) -> Self {
579 Self::store_invariant()
580 }
581
582 pub(crate) fn duplicate_runtime_hooks_for_entity_path(_entity_path: &str) -> Self {
584 Self::store_invariant()
585 }
586
587 #[cold]
589 #[inline(never)]
590 pub(crate) fn store_internal() -> Self {
591 Self::new(ErrorClass::Internal, ErrorOrigin::Store)
592 }
593
594 pub(crate) fn commit_memory_id_unconfigured() -> Self {
596 Self::store_internal()
597 }
598
599 pub(crate) fn commit_memory_id_mismatch(_cached_id: u8, _configured_id: u8) -> Self {
601 Self::store_internal()
602 }
603
604 pub(crate) fn commit_memory_stable_key_mismatch(
606 _cached_key: &str,
607 _configured_key: &str,
608 ) -> Self {
609 Self::store_internal()
610 }
611
612 pub(crate) fn recovery_unsupported_database_format(found: Option<u16>, required: u16) -> Self {
614 Self {
615 class: ErrorClass::IncompatiblePersistedFormat,
616 origin: ErrorOrigin::Recovery,
617 detail: Some(ErrorDetail::Recovery(
618 RecoveryErrorDetail::UnsupportedFormatVersion { found, required },
619 )),
620 }
621 }
622
623 pub(crate) fn recovery_malformed_database_format_marker(
625 reason: RecoveryFormatMarkerError,
626 ) -> Self {
627 Self {
628 class: ErrorClass::Corruption,
629 origin: ErrorOrigin::Recovery,
630 detail: Some(ErrorDetail::Recovery(
631 RecoveryErrorDetail::MalformedFormatMarker { reason },
632 )),
633 }
634 }
635
636 pub(crate) fn recovery_database_format_control_unavailable() -> Self {
638 Self::new(ErrorClass::Internal, ErrorOrigin::Recovery)
639 }
640
641 pub(crate) fn commit_control_memory_growth_failed() -> Self {
643 Self::store_internal()
644 }
645
646 #[cfg(not(test))]
648 pub(crate) fn database_format_memory_registration_failed(_err: impl Sized) -> Self {
649 Self::store_internal()
650 }
651
652 pub(crate) fn delete_rollback_row_required() -> Self {
654 Self::store_internal()
655 }
656
657 pub(crate) fn recovery_integrity_validation_failed(
659 _missing_index_entries: u64,
660 _divergent_index_entries: u64,
661 _orphan_index_references: u64,
662 ) -> Self {
663 Self::store_corruption()
664 }
665
666 #[cold]
668 #[inline(never)]
669 pub(crate) fn index_internal() -> Self {
670 Self::new(ErrorClass::Internal, ErrorOrigin::Index)
671 }
672
673 pub(crate) fn structural_index_removal_entity_key_required() -> Self {
675 Self::index_internal()
676 }
677
678 pub(crate) fn structural_index_insertion_entity_key_required() -> Self {
680 Self::index_internal()
681 }
682
683 pub(crate) fn index_commit_op_old_entity_key_required() -> Self {
685 Self::index_internal()
686 }
687
688 pub(crate) fn index_commit_op_new_entity_key_required() -> Self {
690 Self::index_internal()
691 }
692
693 #[cfg(test)]
695 pub(crate) fn query_internal() -> Self {
696 Self::new(ErrorClass::Internal, ErrorOrigin::Query)
697 }
698
699 #[cold]
701 #[inline(never)]
702 pub(crate) fn query_unsupported() -> Self {
703 Self::new(ErrorClass::Unsupported, ErrorOrigin::Query)
704 }
705
706 #[cold]
709 #[inline(never)]
710 pub(crate) fn query_stale_accepted_schema_revision(
711 _expected_revision: u64,
712 _current_revision: Option<u64>,
713 ) -> Self {
714 Self {
715 class: ErrorClass::Conflict,
716 origin: ErrorOrigin::Query,
717 detail: Some(ErrorDetail::Query(QueryErrorDetail::StaleSchemaRevision)),
718 }
719 }
720
721 #[cold]
723 #[inline(never)]
724 #[cfg(feature = "sql")]
725 pub(crate) fn query_schema_ddl_admission(error: SchemaDdlAdmissionError) -> Self {
726 Self {
727 class: ErrorClass::Unsupported,
728 origin: ErrorOrigin::Query,
729 detail: Some(ErrorDetail::Query(QueryErrorDetail::SchemaDdlAdmission {
730 error,
731 })),
732 }
733 }
734
735 #[cold]
737 #[inline(never)]
738 pub(crate) fn query_numeric_overflow() -> Self {
739 Self {
740 class: ErrorClass::Unsupported,
741 origin: ErrorOrigin::Query,
742 detail: Some(ErrorDetail::Query(QueryErrorDetail::NumericOverflow)),
743 }
744 }
745
746 #[cold]
749 #[inline(never)]
750 pub(crate) fn query_numeric_not_representable() -> Self {
751 Self {
752 class: ErrorClass::Unsupported,
753 origin: ErrorOrigin::Query,
754 detail: Some(ErrorDetail::Query(
755 QueryErrorDetail::NumericNotRepresentable,
756 )),
757 }
758 }
759
760 #[cold]
762 #[inline(never)]
763 pub(crate) fn serialize_internal() -> Self {
764 Self::new(ErrorClass::Internal, ErrorOrigin::Serialize)
765 }
766
767 pub(crate) fn persisted_row_encode_failed(_detail: impl Sized) -> Self {
769 Self::persisted_row_encode_internal()
770 }
771
772 pub(crate) fn persisted_row_encode_internal() -> Self {
774 Self::serialize_internal()
775 }
776
777 pub(crate) fn persisted_row_field_encode_failed(field_name: &str, _detail: impl Sized) -> Self {
779 Self::persisted_row_field_encode_internal(field_name)
780 }
781
782 pub(crate) fn persisted_row_field_encode_internal(_field_name: &str) -> Self {
784 Self::persisted_row_encode_internal()
785 }
786
787 pub(crate) fn bytes_field_value_encode_failed(_detail: impl Sized) -> Self {
789 Self::serialize_internal()
790 }
791
792 #[cold]
794 #[inline(never)]
795 pub(crate) fn store_corruption() -> Self {
796 Self::new(ErrorClass::Corruption, ErrorOrigin::Store)
797 }
798
799 pub(crate) fn commit_corruption() -> Self {
801 Self::store_corruption()
802 }
803
804 pub(crate) fn commit_component_corruption() -> Self {
806 Self::commit_corruption()
807 }
808
809 pub(crate) fn commit_id_generation_failed() -> Self {
811 Self::store_internal()
812 }
813
814 pub(crate) fn commit_marker_payload_exceeds_u32_length_limit() -> Self {
816 Self::store_unsupported()
817 }
818
819 pub(crate) fn commit_component_length_invalid() -> Self {
821 Self::commit_corruption()
822 }
823
824 pub(crate) fn commit_marker_exceeds_max_size() -> Self {
826 Self::commit_corruption()
827 }
828
829 pub(crate) fn commit_control_slot_exceeds_max_size() -> Self {
831 Self::store_unsupported()
832 }
833
834 pub(crate) fn commit_control_slot_marker_bytes_exceed_u32_length_limit() -> Self {
836 Self::store_unsupported()
837 }
838
839 pub(crate) fn startup_index_rebuild_invalid_data_key() -> Self {
841 Self::store_corruption()
842 }
843
844 #[cold]
846 #[inline(never)]
847 pub(crate) fn index_corruption() -> Self {
848 Self::new(ErrorClass::Corruption, ErrorOrigin::Index)
849 }
850
851 pub(crate) fn index_unique_validation_corruption() -> Self {
853 Self::index_plan_index_corruption()
854 }
855
856 pub(crate) fn structural_index_entry_corruption() -> Self {
858 Self::index_plan_index_corruption()
859 }
860
861 pub(crate) fn index_unique_validation_entity_key_required() -> Self {
863 Self::index_invariant()
864 }
865
866 pub(crate) fn index_unique_validation_row_deserialize_failed() -> Self {
868 Self::index_plan_serialize_corruption()
869 }
870
871 pub(crate) fn index_unique_validation_primary_key_decode_failed() -> Self {
873 Self::index_plan_serialize_corruption()
874 }
875
876 pub(crate) fn index_unique_validation_key_rebuild_failed() -> Self {
878 Self::index_plan_serialize_corruption()
879 }
880
881 pub(crate) fn index_unique_validation_row_required() -> Self {
883 Self::index_plan_store_corruption()
884 }
885
886 pub(crate) fn index_only_predicate_component_required() -> Self {
888 Self::index_invariant()
889 }
890
891 pub(crate) fn index_scan_continuation_anchor_within_envelope_required() -> Self {
893 Self::index_invariant()
894 }
895
896 pub(crate) fn index_scan_continuation_advancement_required() -> Self {
898 Self::index_invariant()
899 }
900
901 pub(crate) fn index_scan_key_corrupted_during(
903 _context: &'static str,
904 _err: impl Sized,
905 ) -> Self {
906 Self::index_corruption()
907 }
908
909 pub(crate) fn index_projection_component_required(
911 _index_name: &str,
912 _component_index: usize,
913 ) -> Self {
914 Self::index_invariant()
915 }
916
917 pub(crate) fn index_entry_decode_failed() -> Self {
919 Self::index_corruption()
920 }
921
922 pub(crate) fn serialize_corruption() -> Self {
924 Self::new(ErrorClass::Corruption, ErrorOrigin::Serialize)
925 }
926
927 pub(crate) fn persisted_row_decode_failed(_detail: impl Sized) -> Self {
929 Self::persisted_row_decode_corruption()
930 }
931
932 pub(crate) fn persisted_row_decode_corruption() -> Self {
934 Self::serialize_corruption()
935 }
936
937 pub(crate) fn persisted_row_field_decode_failed(field_name: &str, _detail: impl Sized) -> Self {
939 Self::persisted_row_field_decode_corruption(field_name)
940 }
941
942 pub(crate) fn persisted_row_field_decode_corruption(_field_name: &str) -> Self {
944 Self::persisted_row_decode_corruption()
945 }
946
947 pub(crate) fn persisted_row_field_kind_decode_failed(
949 field_name: &str,
950 _field_kind: impl fmt::Debug,
951 _detail: impl Sized,
952 ) -> Self {
953 Self::persisted_row_field_decode_corruption(field_name)
954 }
955
956 pub(crate) fn persisted_row_field_payload_exact_len_required(field_name: &str) -> Self {
958 Self::persisted_row_field_decode_corruption(field_name)
959 }
960
961 pub(crate) fn persisted_row_field_payload_must_be_empty(field_name: &str) -> Self {
963 Self::persisted_row_field_decode_corruption(field_name)
964 }
965
966 pub(crate) fn persisted_row_field_payload_invalid_byte(field_name: &str) -> Self {
968 Self::persisted_row_field_decode_corruption(field_name)
969 }
970
971 pub(crate) fn persisted_row_field_payload_non_finite(field_name: &str) -> Self {
973 Self::persisted_row_field_decode_corruption(field_name)
974 }
975
976 pub(crate) fn persisted_row_field_payload_out_of_range(field_name: &str) -> Self {
978 Self::persisted_row_field_decode_corruption(field_name)
979 }
980
981 pub(crate) fn persisted_row_field_text_payload_invalid_utf8(field_name: &str) -> Self {
983 Self::persisted_row_field_decode_corruption(field_name)
984 }
985
986 pub(crate) fn persisted_row_slot_lookup_out_of_bounds(_model_path: &str, _slot: usize) -> Self {
988 Self::index_invariant()
989 }
990
991 pub(crate) fn persisted_row_slot_cache_lookup_out_of_bounds(
993 _model_path: &str,
994 _slot: usize,
995 ) -> Self {
996 Self::index_invariant()
997 }
998
999 pub(crate) fn persisted_row_primary_key_not_primary_key_encodable(
1001 _data_key: impl fmt::Debug,
1002 _detail: impl Sized,
1003 ) -> Self {
1004 Self::persisted_row_decode_corruption()
1005 }
1006
1007 pub(crate) fn persisted_row_primary_key_slot_missing(_data_key: impl fmt::Debug) -> Self {
1009 Self::persisted_row_decode_corruption()
1010 }
1011
1012 pub(crate) fn persisted_row_key_mismatch() -> Self {
1014 Self::store_corruption()
1015 }
1016
1017 pub(crate) fn persisted_row_declared_field_missing(field_name: &str) -> Self {
1019 Self::persisted_row_field_decode_corruption(field_name)
1020 }
1021
1022 pub(crate) fn data_key_entity_mismatch() -> Self {
1024 Self::store_corruption()
1025 }
1026
1027 pub(crate) fn reverse_index_ordinal_overflow(
1029 _source_path: &str,
1030 _field_name: &str,
1031 _target_path: &str,
1032 _detail: impl Sized,
1033 ) -> Self {
1034 Self::index_internal()
1035 }
1036
1037 pub(crate) fn reverse_index_entry_corrupted(
1039 _source_path: &str,
1040 _field_name: &str,
1041 _target_path: &str,
1042 _index_key: impl fmt::Debug,
1043 _detail: impl Sized,
1044 ) -> Self {
1045 Self::index_corruption()
1046 }
1047
1048 pub(crate) fn relation_target_store_missing(
1050 _source_path: &str,
1051 _field_name: &str,
1052 _target_path: &str,
1053 _store_path: &str,
1054 _detail: impl Sized,
1055 ) -> Self {
1056 Self::executor_internal()
1057 }
1058
1059 pub(crate) fn relation_target_key_decode_failed(
1061 _context_label: &str,
1062 _source_path: &str,
1063 _field_name: &str,
1064 _target_path: &str,
1065 _detail: impl Sized,
1066 ) -> Self {
1067 Self::identity_corruption()
1068 }
1069
1070 pub(crate) fn relation_target_entity_mismatch(
1072 _context_label: &str,
1073 _source_path: &str,
1074 _field_name: &str,
1075 _target_path: &str,
1076 _target_entity_name: &str,
1077 _expected_tag: impl Sized,
1078 _actual_tag: impl Sized,
1079 ) -> Self {
1080 Self::store_corruption()
1081 }
1082
1083 pub(crate) fn relation_source_row_decode_failed(
1085 _source_path: &str,
1086 _field_name: &str,
1087 _target_path: &str,
1088 _detail: impl Sized,
1089 ) -> Self {
1090 Self::persisted_row_decode_corruption()
1091 }
1092
1093 pub(crate) fn relation_source_row_unsupported_scalar_relation_key(
1095 _source_path: &str,
1096 _field_name: &str,
1097 _target_path: &str,
1098 ) -> Self {
1099 Self::persisted_row_decode_corruption()
1100 }
1101
1102 pub(crate) fn relation_source_row_unsupported_key_kind(_field_kind: impl fmt::Debug) -> Self {
1104 Self::persisted_row_decode_corruption()
1105 }
1106
1107 pub(crate) fn reverse_index_relation_target_decode_invariant_violated(
1109 _source_path: &str,
1110 _field_name: &str,
1111 _target_path: &str,
1112 ) -> Self {
1113 Self::executor_internal()
1114 }
1115
1116 pub(crate) fn bytes_covering_component_payload_empty() -> Self {
1118 Self::index_corruption()
1119 }
1120
1121 pub(crate) fn bytes_covering_bool_payload_truncated() -> Self {
1123 Self::index_corruption()
1124 }
1125
1126 pub(crate) fn bytes_covering_component_payload_invalid_length() -> Self {
1128 Self::index_corruption()
1129 }
1130
1131 pub(crate) fn bytes_covering_bool_payload_invalid_value() -> Self {
1133 Self::index_corruption()
1134 }
1135
1136 pub(crate) fn bytes_covering_text_payload_invalid_terminator() -> Self {
1138 Self::index_corruption()
1139 }
1140
1141 pub(crate) fn bytes_covering_text_payload_trailing_bytes() -> Self {
1143 Self::index_corruption()
1144 }
1145
1146 pub(crate) fn bytes_covering_text_payload_invalid_utf8() -> Self {
1148 Self::index_corruption()
1149 }
1150
1151 pub(crate) fn bytes_covering_text_payload_invalid_escape_byte() -> Self {
1153 Self::index_corruption()
1154 }
1155
1156 pub(crate) fn bytes_covering_text_payload_missing_terminator() -> Self {
1158 Self::index_corruption()
1159 }
1160
1161 #[must_use]
1163 pub fn missing_persisted_slot(field_name: &'static str) -> Self {
1164 Self::persisted_row_field_decode_corruption(field_name)
1165 }
1166
1167 pub(crate) fn identity_corruption() -> Self {
1169 Self::new(ErrorClass::Corruption, ErrorOrigin::Identity)
1170 }
1171
1172 #[cold]
1174 #[inline(never)]
1175 pub(crate) fn store_unsupported() -> Self {
1176 Self::new(ErrorClass::Unsupported, ErrorOrigin::Store)
1177 }
1178
1179 #[cfg(any(test, feature = "sql"))]
1181 pub(crate) fn schema_ddl_publication_race_lost(_entity_path: &'static str) -> Self {
1182 Self {
1183 class: ErrorClass::Unsupported,
1184 origin: ErrorOrigin::Store,
1185 detail: Some(ErrorDetail::Store(StoreError::SchemaDdlPublicationRaceLost)),
1186 }
1187 }
1188
1189 #[cfg(feature = "sql")]
1191 pub(crate) fn schema_ddl_set_not_null_validation_failed(
1192 _entity_path: &'static str,
1193 _column_name: &str,
1194 ) -> Self {
1195 Self {
1196 class: ErrorClass::Unsupported,
1197 origin: ErrorOrigin::Store,
1198 detail: Some(ErrorDetail::Store(
1199 StoreError::SchemaDdlSetNotNullValidationFailed,
1200 )),
1201 }
1202 }
1203
1204 pub(crate) fn unsupported_entity_tag_in_data_store(
1206 _entity_tag: crate::types::EntityTag,
1207 ) -> Self {
1208 Self::store_unsupported()
1209 }
1210
1211 #[cfg(not(test))]
1213 pub(crate) fn commit_memory_id_registration_failed(_err: impl Sized) -> Self {
1214 Self::store_internal()
1215 }
1216
1217 pub(crate) fn index_unsupported() -> Self {
1219 Self::new(ErrorClass::Unsupported, ErrorOrigin::Index)
1220 }
1221
1222 pub(crate) fn index_component_exceeds_max_size() -> Self {
1224 Self::index_unsupported()
1225 }
1226
1227 pub(crate) fn serialize_unsupported() -> Self {
1229 Self::new(ErrorClass::Unsupported, ErrorOrigin::Serialize)
1230 }
1231
1232 pub(crate) fn cursor_invalid_continuation() -> Self {
1234 Self::new(ErrorClass::Unsupported, ErrorOrigin::Cursor)
1235 }
1236
1237 pub(crate) fn serialize_incompatible_persisted_format() -> Self {
1239 Self::new(
1240 ErrorClass::IncompatiblePersistedFormat,
1241 ErrorOrigin::Serialize,
1242 )
1243 }
1244
1245 #[cfg(feature = "sql")]
1248 pub(crate) fn query_unsupported_sql_feature(feature: diagnostic_code::SqlFeatureCode) -> Self {
1249 Self {
1250 class: ErrorClass::Unsupported,
1251 origin: ErrorOrigin::Query,
1252 detail: Some(ErrorDetail::Query(
1253 QueryErrorDetail::UnsupportedSqlFeature { feature },
1254 )),
1255 }
1256 }
1257
1258 #[cfg(feature = "sql")]
1261 pub(crate) fn query_sql_lowering(reason: diagnostic_code::SqlLoweringCode) -> Self {
1262 Self {
1263 class: ErrorClass::Unsupported,
1264 origin: ErrorOrigin::Query,
1265 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlLowering { reason })),
1266 }
1267 }
1268
1269 pub(crate) fn query_unsupported_projection(
1272 reason: diagnostic_code::QueryProjectionCode,
1273 ) -> Self {
1274 Self {
1275 class: ErrorClass::Unsupported,
1276 origin: ErrorOrigin::Query,
1277 detail: Some(ErrorDetail::Query(
1278 QueryErrorDetail::UnsupportedProjection { reason },
1279 )),
1280 }
1281 }
1282
1283 pub(crate) fn query_unknown_aggregate_target_field() -> Self {
1285 Self {
1286 class: ErrorClass::Unsupported,
1287 origin: ErrorOrigin::Query,
1288 detail: Some(ErrorDetail::Query(
1289 QueryErrorDetail::UnknownAggregateTargetField,
1290 )),
1291 }
1292 }
1293
1294 pub(crate) fn query_result_shape_mismatch(
1297 reason: diagnostic_code::QueryResultShapeCode,
1298 ) -> Self {
1299 Self {
1300 class: ErrorClass::Unsupported,
1301 origin: ErrorOrigin::Query,
1302 detail: Some(ErrorDetail::Query(QueryErrorDetail::ResultShapeMismatch {
1303 reason,
1304 })),
1305 }
1306 }
1307
1308 #[cfg(feature = "sql")]
1311 pub(crate) fn query_sql_surface_mismatch(
1312 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1313 ) -> Self {
1314 Self {
1315 class: ErrorClass::Unsupported,
1316 origin: ErrorOrigin::Query,
1317 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlSurfaceMismatch {
1318 mismatch,
1319 })),
1320 }
1321 }
1322
1323 #[cfg(feature = "sql")]
1325 pub(crate) fn query_sql_write_boundary(
1326 boundary: diagnostic_code::SqlWriteBoundaryCode,
1327 ) -> Self {
1328 Self {
1329 class: ErrorClass::Unsupported,
1330 origin: ErrorOrigin::Query,
1331 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlWriteBoundary {
1332 boundary,
1333 })),
1334 }
1335 }
1336
1337 pub fn store_not_found(_key: impl Sized) -> Self {
1338 Self {
1339 class: ErrorClass::NotFound,
1340 origin: ErrorOrigin::Store,
1341 detail: Some(ErrorDetail::Store(StoreError::NotFound)),
1342 }
1343 }
1344
1345 pub fn unsupported_entity_path(_path: impl Sized) -> Self {
1347 Self::store_unsupported()
1348 }
1349
1350 #[must_use]
1351 pub const fn is_not_found(&self) -> bool {
1352 matches!(self.detail, Some(ErrorDetail::Store(StoreError::NotFound)))
1353 }
1354
1355 #[cold]
1357 #[inline(never)]
1358 pub(crate) fn index_plan_corruption(origin: ErrorOrigin) -> Self {
1359 Self::new(ErrorClass::Corruption, origin)
1360 }
1361
1362 #[cold]
1364 #[inline(never)]
1365 pub(crate) fn index_plan_index_corruption() -> Self {
1366 Self::index_plan_corruption(ErrorOrigin::Index)
1367 }
1368
1369 #[cold]
1371 #[inline(never)]
1372 pub(crate) fn index_plan_store_corruption() -> Self {
1373 Self::index_plan_corruption(ErrorOrigin::Store)
1374 }
1375
1376 #[cold]
1378 #[inline(never)]
1379 pub(crate) fn index_plan_serialize_corruption() -> Self {
1380 Self::index_plan_corruption(ErrorOrigin::Serialize)
1381 }
1382
1383 #[cfg(test)]
1385 pub(crate) fn index_plan_invariant(origin: ErrorOrigin) -> Self {
1386 Self::new(ErrorClass::InvariantViolation, origin)
1387 }
1388
1389 #[cfg(test)]
1391 pub(crate) fn index_plan_store_invariant() -> Self {
1392 Self::index_plan_invariant(ErrorOrigin::Store)
1393 }
1394
1395 pub(crate) fn index_violation(_path: &str, _index_fields: &[&str]) -> Self {
1397 Self::new(ErrorClass::Conflict, ErrorOrigin::Index)
1398 }
1399}
1400
1401impl From<diagnostic_code::QueryReadAdmissionCode> for InternalError {
1402 fn from(reason: diagnostic_code::QueryReadAdmissionCode) -> Self {
1403 Self {
1404 class: ErrorClass::Unsupported,
1405 origin: ErrorOrigin::Query,
1406 detail: Some(ErrorDetail::Query(QueryErrorDetail::QueryReadAdmission {
1407 reason,
1408 })),
1409 }
1410 }
1411}
1412
1413impl fmt::Debug for InternalError {
1414 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1415 fmt_compact_diagnostic(
1416 f,
1417 self.diagnostic_code(),
1418 self.detail
1419 .as_ref()
1420 .and_then(ErrorDetail::diagnostic_detail),
1421 )
1422 }
1423}
1424
1425impl fmt::Display for InternalError {
1426 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1427 f.write_str(self.message())
1428 }
1429}
1430
1431impl std::error::Error for InternalError {}
1432
1433pub enum ErrorDetail {
1441 Store(StoreError),
1442 Query(QueryErrorDetail),
1443 Recovery(RecoveryErrorDetail),
1444 }
1449
1450pub enum RecoveryErrorDetail {
1457 UnsupportedFormatVersion { found: Option<u16>, required: u16 },
1458
1459 MalformedFormatMarker { reason: RecoveryFormatMarkerError },
1460}
1461
1462#[derive(Clone, Copy, Eq, PartialEq)]
1464pub enum RecoveryFormatMarkerError {
1465 Magic,
1466 Checksum,
1467 State,
1468}
1469
1470pub enum StoreError {
1478 NotFound,
1479
1480 Corrupt,
1481
1482 InvariantViolation,
1483
1484 SchemaDdlPublicationRaceLost,
1485
1486 SchemaDdlSetNotNullValidationFailed,
1487}
1488
1489pub enum QueryErrorDetail {
1496 NumericOverflow,
1497
1498 NumericNotRepresentable,
1499
1500 UnsupportedSqlFeature {
1501 feature: diagnostic_code::SqlFeatureCode,
1502 },
1503
1504 SqlLowering {
1505 reason: diagnostic_code::SqlLoweringCode,
1506 },
1507
1508 UnsupportedProjection {
1509 reason: diagnostic_code::QueryProjectionCode,
1510 },
1511
1512 UnknownAggregateTargetField,
1513
1514 ResultShapeMismatch {
1515 reason: diagnostic_code::QueryResultShapeCode,
1516 },
1517
1518 QueryReadAdmission {
1519 reason: diagnostic_code::QueryReadAdmissionCode,
1520 },
1521
1522 SqlSurfaceMismatch {
1523 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1524 },
1525
1526 SqlWriteBoundary {
1527 boundary: diagnostic_code::SqlWriteBoundaryCode,
1528 },
1529
1530 SchemaDdlAdmission {
1531 error: SchemaDdlAdmissionError,
1532 },
1533
1534 StaleSchemaRevision,
1535}
1536
1537impl fmt::Display for QueryErrorDetail {
1538 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1539 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
1540 }
1541}
1542
1543impl std::error::Error for QueryErrorDetail {}
1544
1545#[derive(Clone, Copy, Eq, PartialEq)]
1554pub enum SchemaDdlAdmissionError {
1555 MissingExpectedSchemaVersion,
1556
1557 MissingNextSchemaVersion,
1558
1559 StaleExpectedSchemaVersion,
1560
1561 InvalidExpectedSchemaVersion,
1562
1563 InvalidNextSchemaVersion,
1564
1565 AcceptedSchemaChangeWithoutVersionBump,
1566
1567 EmptyVersionBump,
1568
1569 VersionGap,
1570
1571 VersionRollback,
1572
1573 FingerprintMethodMismatch,
1574
1575 UnsupportedTransitionClass,
1576
1577 PhysicalRunnerMissing,
1578
1579 ValidationFailed,
1580
1581 PublicationRaceLost,
1582
1583 InvalidAddColumnDefault,
1584
1585 InvalidAlterColumnDefault,
1586
1587 GeneratedIndexDropRejected,
1588
1589 RequiredDropDefaultUnsupported,
1590
1591 GeneratedFieldDefaultChangeRejected,
1592
1593 GeneratedFieldNullabilityChangeRejected,
1594
1595 SetNotNullValidationFailed,
1596}
1597
1598impl fmt::Display for SchemaDdlAdmissionError {
1599 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1600 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
1601 }
1602}
1603
1604impl std::error::Error for SchemaDdlAdmissionError {}
1605
1606impl fmt::Debug for ErrorDetail {
1607 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1608 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1609 }
1610}
1611
1612impl fmt::Debug for StoreError {
1613 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1614 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1615 }
1616}
1617
1618impl fmt::Debug for QueryErrorDetail {
1619 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1620 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1621 }
1622}
1623
1624impl fmt::Debug for RecoveryErrorDetail {
1625 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1626 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1627 }
1628}
1629
1630impl fmt::Debug for RecoveryFormatMarkerError {
1631 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1632 fmt_compact_diagnostic(
1633 f,
1634 diagnostic_code::DiagnosticCode::RuntimeCorruption,
1635 Some(diagnostic_code::DiagnosticDetail::RuntimeKind {
1636 kind: diagnostic_code::RuntimeErrorKind::Corruption,
1637 }),
1638 )
1639 }
1640}
1641
1642impl fmt::Debug for SchemaDdlAdmissionError {
1643 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1644 fmt_compact_diagnostic(
1645 f,
1646 diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
1647 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1648 reason: self.diagnostic_code(),
1649 }),
1650 )
1651 }
1652}
1653
1654fn fmt_compact_diagnostic(
1655 f: &mut fmt::Formatter<'_>,
1656 code: diagnostic_code::DiagnosticCode,
1657 detail: Option<diagnostic_code::DiagnosticDetail>,
1658) -> fmt::Result {
1659 write!(
1660 f,
1661 "{}",
1662 diagnostic_code::ErrorCode::from_parts(code, detail).raw()
1663 )
1664}
1665
1666impl ErrorDetail {
1667 #[must_use]
1669 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1670 match self {
1671 Self::Store(error) => error.diagnostic_code(),
1672 Self::Query(error) => error.diagnostic_code(),
1673 Self::Recovery(error) => error.diagnostic_code(),
1674 }
1675 }
1676
1677 #[must_use]
1679 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1680 match self {
1681 Self::Store(error) => error.diagnostic_detail(),
1682 Self::Query(error) => error.diagnostic_detail(),
1683 Self::Recovery(error) => error.diagnostic_detail(),
1684 }
1685 }
1686}
1687
1688impl RecoveryErrorDetail {
1689 #[must_use]
1691 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1692 match self {
1693 Self::UnsupportedFormatVersion { .. } => {
1694 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
1695 }
1696 Self::MalformedFormatMarker { .. } => {
1697 diagnostic_code::DiagnosticCode::RuntimeCorruption
1698 }
1699 }
1700 }
1701
1702 #[must_use]
1704 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1705 let kind = match self {
1706 Self::UnsupportedFormatVersion { .. } => {
1707 diagnostic_code::RuntimeErrorKind::IncompatiblePersistedFormat
1708 }
1709 Self::MalformedFormatMarker { .. } => diagnostic_code::RuntimeErrorKind::Corruption,
1710 };
1711
1712 Some(diagnostic_code::DiagnosticDetail::RuntimeKind { kind })
1713 }
1714}
1715
1716impl StoreError {
1717 #[must_use]
1719 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1720 match self {
1721 Self::NotFound => diagnostic_code::DiagnosticCode::StoreNotFound,
1722 Self::Corrupt => diagnostic_code::DiagnosticCode::StoreCorruption,
1723 Self::InvariantViolation => diagnostic_code::DiagnosticCode::StoreInvariantViolation,
1724 Self::SchemaDdlPublicationRaceLost | Self::SchemaDdlSetNotNullValidationFailed => {
1725 diagnostic_code::DiagnosticCode::SchemaDdlAdmission
1726 }
1727 }
1728 }
1729
1730 #[must_use]
1732 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1733 match self {
1734 Self::SchemaDdlPublicationRaceLost => {
1735 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1736 reason: diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost,
1737 })
1738 }
1739 Self::SchemaDdlSetNotNullValidationFailed => {
1740 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1741 reason: diagnostic_code::SchemaDdlAdmissionCode::SetNotNullValidationFailed,
1742 })
1743 }
1744 Self::NotFound | Self::Corrupt | Self::InvariantViolation => None,
1745 }
1746 }
1747}
1748
1749impl QueryErrorDetail {
1750 #[must_use]
1752 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1753 match self {
1754 Self::NumericOverflow => diagnostic_code::DiagnosticCode::QueryNumericOverflow,
1755 Self::NumericNotRepresentable => {
1756 diagnostic_code::DiagnosticCode::QueryNumericNotRepresentable
1757 }
1758 Self::UnsupportedSqlFeature { .. } => {
1759 diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature
1760 }
1761 Self::SqlLowering { .. } => diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature,
1762 Self::UnsupportedProjection { .. } => {
1763 diagnostic_code::DiagnosticCode::QueryUnsupportedProjection
1764 }
1765 Self::UnknownAggregateTargetField => {
1766 diagnostic_code::DiagnosticCode::QueryUnknownAggregateTargetField
1767 }
1768 Self::ResultShapeMismatch { .. } => {
1769 diagnostic_code::DiagnosticCode::QueryResultShapeMismatch
1770 }
1771 Self::QueryReadAdmission { .. } => diagnostic_code::DiagnosticCode::QueryReadAdmission,
1772 Self::SqlSurfaceMismatch { .. } => {
1773 diagnostic_code::DiagnosticCode::QuerySqlSurfaceMismatch
1774 }
1775 Self::SqlWriteBoundary { .. } => diagnostic_code::DiagnosticCode::QuerySqlWriteBoundary,
1776 Self::SchemaDdlAdmission { .. } => diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
1777 Self::StaleSchemaRevision => diagnostic_code::DiagnosticCode::RuntimeConflict,
1778 }
1779 }
1780
1781 #[must_use]
1783 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1784 match self {
1785 Self::UnsupportedSqlFeature { feature } => {
1786 Some(diagnostic_code::DiagnosticDetail::UnsupportedSqlFeature { feature: *feature })
1787 }
1788 Self::SqlLowering { reason } => {
1789 Some(diagnostic_code::DiagnosticDetail::SqlLowering { reason: *reason })
1790 }
1791 Self::UnsupportedProjection { reason } => {
1792 Some(diagnostic_code::DiagnosticDetail::QueryProjection { reason: *reason })
1793 }
1794 Self::ResultShapeMismatch { reason } => {
1795 Some(diagnostic_code::DiagnosticDetail::QueryResultShape { reason: *reason })
1796 }
1797 Self::QueryReadAdmission { reason } => {
1798 Some(diagnostic_code::DiagnosticDetail::QueryReadAdmission { reason: *reason })
1799 }
1800 Self::SqlSurfaceMismatch { mismatch } => {
1801 Some(diagnostic_code::DiagnosticDetail::SqlSurfaceMismatch {
1802 mismatch: *mismatch,
1803 })
1804 }
1805 Self::SqlWriteBoundary { boundary } => {
1806 Some(diagnostic_code::DiagnosticDetail::SqlWriteBoundary {
1807 boundary: *boundary,
1808 })
1809 }
1810 Self::SchemaDdlAdmission { error } => {
1811 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1812 reason: error.diagnostic_code(),
1813 })
1814 }
1815 Self::NumericOverflow
1816 | Self::NumericNotRepresentable
1817 | Self::UnknownAggregateTargetField
1818 | Self::StaleSchemaRevision => None,
1819 }
1820 }
1821}
1822
1823impl SchemaDdlAdmissionError {
1824 #[must_use]
1826 pub const fn diagnostic_code(&self) -> diagnostic_code::SchemaDdlAdmissionCode {
1827 match self {
1828 Self::MissingExpectedSchemaVersion => {
1829 diagnostic_code::SchemaDdlAdmissionCode::MissingExpectedSchemaVersion
1830 }
1831 Self::MissingNextSchemaVersion => {
1832 diagnostic_code::SchemaDdlAdmissionCode::MissingNextSchemaVersion
1833 }
1834 Self::StaleExpectedSchemaVersion => {
1835 diagnostic_code::SchemaDdlAdmissionCode::StaleExpectedSchemaVersion
1836 }
1837 Self::InvalidExpectedSchemaVersion => {
1838 diagnostic_code::SchemaDdlAdmissionCode::InvalidExpectedSchemaVersion
1839 }
1840 Self::InvalidNextSchemaVersion => {
1841 diagnostic_code::SchemaDdlAdmissionCode::InvalidNextSchemaVersion
1842 }
1843 Self::AcceptedSchemaChangeWithoutVersionBump => {
1844 diagnostic_code::SchemaDdlAdmissionCode::AcceptedSchemaChangeWithoutVersionBump
1845 }
1846 Self::EmptyVersionBump => diagnostic_code::SchemaDdlAdmissionCode::EmptyVersionBump,
1847 Self::VersionGap => diagnostic_code::SchemaDdlAdmissionCode::VersionGap,
1848 Self::VersionRollback => diagnostic_code::SchemaDdlAdmissionCode::VersionRollback,
1849 Self::FingerprintMethodMismatch => {
1850 diagnostic_code::SchemaDdlAdmissionCode::FingerprintMethodMismatch
1851 }
1852 Self::UnsupportedTransitionClass => {
1853 diagnostic_code::SchemaDdlAdmissionCode::UnsupportedTransitionClass
1854 }
1855 Self::PhysicalRunnerMissing => {
1856 diagnostic_code::SchemaDdlAdmissionCode::PhysicalRunnerMissing
1857 }
1858 Self::ValidationFailed => diagnostic_code::SchemaDdlAdmissionCode::ValidationFailed,
1859 Self::PublicationRaceLost => {
1860 diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost
1861 }
1862 Self::InvalidAddColumnDefault => {
1863 diagnostic_code::SchemaDdlAdmissionCode::InvalidAddColumnDefault
1864 }
1865 Self::InvalidAlterColumnDefault => {
1866 diagnostic_code::SchemaDdlAdmissionCode::InvalidAlterColumnDefault
1867 }
1868 Self::GeneratedIndexDropRejected => {
1869 diagnostic_code::SchemaDdlAdmissionCode::GeneratedIndexDropRejected
1870 }
1871 Self::RequiredDropDefaultUnsupported => {
1872 diagnostic_code::SchemaDdlAdmissionCode::RequiredDropDefaultUnsupported
1873 }
1874 Self::GeneratedFieldDefaultChangeRejected => {
1875 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldDefaultChangeRejected
1876 }
1877 Self::GeneratedFieldNullabilityChangeRejected => {
1878 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldNullabilityChangeRejected
1879 }
1880 Self::SetNotNullValidationFailed => {
1881 diagnostic_code::SchemaDdlAdmissionCode::SetNotNullValidationFailed
1882 }
1883 }
1884 }
1885}
1886
1887#[repr(u16)]
1894#[derive(Clone, Copy, Eq, PartialEq)]
1895pub enum ErrorClass {
1896 Corruption,
1897 IncompatiblePersistedFormat,
1898 NotFound,
1899 Internal,
1900 Conflict,
1901 Unsupported,
1902 InvariantViolation,
1903}
1904
1905impl ErrorClass {
1906 #[must_use]
1908 pub const fn diagnostic_code(self, origin: ErrorOrigin) -> diagnostic_code::DiagnosticCode {
1909 match self {
1910 Self::Corruption if matches!(origin, ErrorOrigin::Store) => {
1911 diagnostic_code::DiagnosticCode::StoreCorruption
1912 }
1913 Self::Corruption => diagnostic_code::DiagnosticCode::RuntimeCorruption,
1914 Self::IncompatiblePersistedFormat => {
1915 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
1916 }
1917 Self::NotFound if matches!(origin, ErrorOrigin::Store) => {
1918 diagnostic_code::DiagnosticCode::StoreNotFound
1919 }
1920 Self::NotFound => diagnostic_code::DiagnosticCode::RuntimeNotFound,
1921 Self::Internal => diagnostic_code::DiagnosticCode::RuntimeInternal,
1922 Self::Conflict => diagnostic_code::DiagnosticCode::RuntimeConflict,
1923 Self::Unsupported if matches!(origin, ErrorOrigin::Cursor) => {
1924 diagnostic_code::DiagnosticCode::QueryInvalidContinuationCursor
1925 }
1926 Self::Unsupported => diagnostic_code::DiagnosticCode::RuntimeUnsupported,
1927 Self::InvariantViolation if matches!(origin, ErrorOrigin::Store) => {
1928 diagnostic_code::DiagnosticCode::StoreInvariantViolation
1929 }
1930 Self::InvariantViolation => diagnostic_code::DiagnosticCode::RuntimeInvariantViolation,
1931 }
1932 }
1933}
1934
1935impl fmt::Debug for ErrorClass {
1936 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1937 write!(f, "{}", *self as u16)
1938 }
1939}
1940
1941#[repr(u16)]
1948#[derive(Clone, Copy, Eq, PartialEq)]
1949pub enum ErrorOrigin {
1950 Serialize,
1951 Store,
1952 Index,
1953 Identity,
1954 Query,
1955 Planner,
1956 Cursor,
1957 Recovery,
1958 Response,
1959 Executor,
1960 Interface,
1961}
1962
1963impl ErrorOrigin {
1964 #[must_use]
1966 pub const fn diagnostic_origin(self) -> diagnostic_code::ErrorOrigin {
1967 match self {
1968 Self::Serialize => diagnostic_code::ErrorOrigin::Serialize,
1969 Self::Store => diagnostic_code::ErrorOrigin::Store,
1970 Self::Index => diagnostic_code::ErrorOrigin::Index,
1971 Self::Identity => diagnostic_code::ErrorOrigin::Identity,
1972 Self::Query => diagnostic_code::ErrorOrigin::Query,
1973 Self::Planner => diagnostic_code::ErrorOrigin::Planner,
1974 Self::Cursor => diagnostic_code::ErrorOrigin::Cursor,
1975 Self::Recovery => diagnostic_code::ErrorOrigin::Recovery,
1976 Self::Response => diagnostic_code::ErrorOrigin::Response,
1977 Self::Executor => diagnostic_code::ErrorOrigin::Executor,
1978 Self::Interface => diagnostic_code::ErrorOrigin::Interface,
1979 }
1980 }
1981}
1982
1983impl fmt::Debug for ErrorOrigin {
1984 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1985 write!(f, "{}", *self as u16)
1986 }
1987}