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 #[cfg(feature = "sql")]
709 pub(crate) fn query_stale_accepted_schema_revision(
710 _expected_revision: u64,
711 _current_revision: Option<u64>,
712 ) -> Self {
713 Self {
714 class: ErrorClass::Conflict,
715 origin: ErrorOrigin::Query,
716 detail: Some(ErrorDetail::Query(QueryErrorDetail::StaleSchemaRevision)),
717 }
718 }
719
720 #[cold]
722 #[inline(never)]
723 #[cfg(feature = "sql")]
724 pub(crate) fn query_schema_ddl_admission(error: SchemaDdlAdmissionError) -> Self {
725 Self {
726 class: ErrorClass::Unsupported,
727 origin: ErrorOrigin::Query,
728 detail: Some(ErrorDetail::Query(QueryErrorDetail::SchemaDdlAdmission {
729 error,
730 })),
731 }
732 }
733
734 #[cold]
736 #[inline(never)]
737 pub(crate) fn query_numeric_overflow() -> Self {
738 Self {
739 class: ErrorClass::Unsupported,
740 origin: ErrorOrigin::Query,
741 detail: Some(ErrorDetail::Query(QueryErrorDetail::NumericOverflow)),
742 }
743 }
744
745 #[cold]
748 #[inline(never)]
749 pub(crate) fn query_numeric_not_representable() -> Self {
750 Self {
751 class: ErrorClass::Unsupported,
752 origin: ErrorOrigin::Query,
753 detail: Some(ErrorDetail::Query(
754 QueryErrorDetail::NumericNotRepresentable,
755 )),
756 }
757 }
758
759 #[cold]
761 #[inline(never)]
762 pub(crate) fn serialize_internal() -> Self {
763 Self::new(ErrorClass::Internal, ErrorOrigin::Serialize)
764 }
765
766 pub(crate) fn persisted_row_encode_failed(_detail: impl Sized) -> Self {
768 Self::persisted_row_encode_internal()
769 }
770
771 pub(crate) fn persisted_row_encode_internal() -> Self {
773 Self::serialize_internal()
774 }
775
776 pub(crate) fn persisted_row_field_encode_failed(field_name: &str, _detail: impl Sized) -> Self {
778 Self::persisted_row_field_encode_internal(field_name)
779 }
780
781 pub(crate) fn persisted_row_field_encode_internal(_field_name: &str) -> Self {
783 Self::persisted_row_encode_internal()
784 }
785
786 pub(crate) fn bytes_field_value_encode_failed(_detail: impl Sized) -> Self {
788 Self::serialize_internal()
789 }
790
791 #[cold]
793 #[inline(never)]
794 pub(crate) fn store_corruption() -> Self {
795 Self::new(ErrorClass::Corruption, ErrorOrigin::Store)
796 }
797
798 pub(crate) fn commit_corruption() -> Self {
800 Self::store_corruption()
801 }
802
803 pub(crate) fn commit_component_corruption() -> Self {
805 Self::commit_corruption()
806 }
807
808 pub(crate) fn commit_id_generation_failed() -> Self {
810 Self::store_internal()
811 }
812
813 pub(crate) fn commit_marker_payload_exceeds_u32_length_limit() -> Self {
815 Self::store_unsupported()
816 }
817
818 pub(crate) fn commit_component_length_invalid() -> Self {
820 Self::commit_corruption()
821 }
822
823 pub(crate) fn commit_marker_exceeds_max_size() -> Self {
825 Self::commit_corruption()
826 }
827
828 pub(crate) fn commit_control_slot_exceeds_max_size() -> Self {
830 Self::store_unsupported()
831 }
832
833 pub(crate) fn commit_control_slot_marker_bytes_exceed_u32_length_limit() -> Self {
835 Self::store_unsupported()
836 }
837
838 pub(crate) fn startup_index_rebuild_invalid_data_key() -> Self {
840 Self::store_corruption()
841 }
842
843 #[cold]
845 #[inline(never)]
846 pub(crate) fn index_corruption() -> Self {
847 Self::new(ErrorClass::Corruption, ErrorOrigin::Index)
848 }
849
850 pub(crate) fn index_unique_validation_corruption() -> Self {
852 Self::index_plan_index_corruption()
853 }
854
855 pub(crate) fn structural_index_entry_corruption() -> Self {
857 Self::index_plan_index_corruption()
858 }
859
860 pub(crate) fn index_unique_validation_entity_key_required() -> Self {
862 Self::index_invariant()
863 }
864
865 pub(crate) fn index_unique_validation_row_deserialize_failed() -> Self {
867 Self::index_plan_serialize_corruption()
868 }
869
870 pub(crate) fn index_unique_validation_primary_key_decode_failed() -> Self {
872 Self::index_plan_serialize_corruption()
873 }
874
875 pub(crate) fn index_unique_validation_key_rebuild_failed() -> Self {
877 Self::index_plan_serialize_corruption()
878 }
879
880 pub(crate) fn index_unique_validation_row_required() -> Self {
882 Self::index_plan_store_corruption()
883 }
884
885 pub(crate) fn index_only_predicate_component_required() -> Self {
887 Self::index_invariant()
888 }
889
890 pub(crate) fn index_scan_continuation_anchor_within_envelope_required() -> Self {
892 Self::index_invariant()
893 }
894
895 pub(crate) fn index_scan_continuation_advancement_required() -> Self {
897 Self::index_invariant()
898 }
899
900 pub(crate) fn index_scan_key_corrupted_during(
902 _context: &'static str,
903 _err: impl Sized,
904 ) -> Self {
905 Self::index_corruption()
906 }
907
908 pub(crate) fn index_projection_component_required(
910 _index_name: &str,
911 _component_index: usize,
912 ) -> Self {
913 Self::index_invariant()
914 }
915
916 pub(crate) fn index_entry_decode_failed() -> Self {
918 Self::index_corruption()
919 }
920
921 pub(crate) fn serialize_corruption() -> Self {
923 Self::new(ErrorClass::Corruption, ErrorOrigin::Serialize)
924 }
925
926 pub(crate) fn persisted_row_decode_failed(_detail: impl Sized) -> Self {
928 Self::persisted_row_decode_corruption()
929 }
930
931 pub(crate) fn persisted_row_decode_corruption() -> Self {
933 Self::serialize_corruption()
934 }
935
936 pub(crate) fn persisted_row_field_decode_failed(field_name: &str, _detail: impl Sized) -> Self {
938 Self::persisted_row_field_decode_corruption(field_name)
939 }
940
941 pub(crate) fn persisted_row_field_decode_corruption(_field_name: &str) -> Self {
943 Self::persisted_row_decode_corruption()
944 }
945
946 pub(crate) fn persisted_row_field_kind_decode_failed(
948 field_name: &str,
949 _field_kind: impl fmt::Debug,
950 _detail: impl Sized,
951 ) -> Self {
952 Self::persisted_row_field_decode_corruption(field_name)
953 }
954
955 pub(crate) fn persisted_row_field_payload_exact_len_required(field_name: &str) -> Self {
957 Self::persisted_row_field_decode_corruption(field_name)
958 }
959
960 pub(crate) fn persisted_row_field_payload_must_be_empty(field_name: &str) -> Self {
962 Self::persisted_row_field_decode_corruption(field_name)
963 }
964
965 pub(crate) fn persisted_row_field_payload_invalid_byte(field_name: &str) -> Self {
967 Self::persisted_row_field_decode_corruption(field_name)
968 }
969
970 pub(crate) fn persisted_row_field_payload_non_finite(field_name: &str) -> Self {
972 Self::persisted_row_field_decode_corruption(field_name)
973 }
974
975 pub(crate) fn persisted_row_field_payload_out_of_range(field_name: &str) -> Self {
977 Self::persisted_row_field_decode_corruption(field_name)
978 }
979
980 pub(crate) fn persisted_row_field_text_payload_invalid_utf8(field_name: &str) -> Self {
982 Self::persisted_row_field_decode_corruption(field_name)
983 }
984
985 pub(crate) fn persisted_row_slot_lookup_out_of_bounds(_model_path: &str, _slot: usize) -> Self {
987 Self::index_invariant()
988 }
989
990 pub(crate) fn persisted_row_slot_cache_lookup_out_of_bounds(
992 _model_path: &str,
993 _slot: usize,
994 ) -> Self {
995 Self::index_invariant()
996 }
997
998 pub(crate) fn persisted_row_primary_key_not_primary_key_encodable(
1000 _data_key: impl fmt::Debug,
1001 _detail: impl Sized,
1002 ) -> Self {
1003 Self::persisted_row_decode_corruption()
1004 }
1005
1006 pub(crate) fn persisted_row_primary_key_slot_missing(_data_key: impl fmt::Debug) -> Self {
1008 Self::persisted_row_decode_corruption()
1009 }
1010
1011 pub(crate) fn persisted_row_key_mismatch() -> Self {
1013 Self::store_corruption()
1014 }
1015
1016 pub(crate) fn persisted_row_declared_field_missing(field_name: &str) -> Self {
1018 Self::persisted_row_field_decode_corruption(field_name)
1019 }
1020
1021 pub(crate) fn data_key_entity_mismatch() -> Self {
1023 Self::store_corruption()
1024 }
1025
1026 pub(crate) fn reverse_index_ordinal_overflow(
1028 _source_path: &str,
1029 _field_name: &str,
1030 _target_path: &str,
1031 _detail: impl Sized,
1032 ) -> Self {
1033 Self::index_internal()
1034 }
1035
1036 pub(crate) fn reverse_index_entry_corrupted(
1038 _source_path: &str,
1039 _field_name: &str,
1040 _target_path: &str,
1041 _index_key: impl fmt::Debug,
1042 _detail: impl Sized,
1043 ) -> Self {
1044 Self::index_corruption()
1045 }
1046
1047 pub(crate) fn relation_target_store_missing(
1049 _source_path: &str,
1050 _field_name: &str,
1051 _target_path: &str,
1052 _store_path: &str,
1053 _detail: impl Sized,
1054 ) -> Self {
1055 Self::executor_internal()
1056 }
1057
1058 pub(crate) fn relation_target_key_decode_failed(
1060 _context_label: &str,
1061 _source_path: &str,
1062 _field_name: &str,
1063 _target_path: &str,
1064 _detail: impl Sized,
1065 ) -> Self {
1066 Self::identity_corruption()
1067 }
1068
1069 pub(crate) fn relation_target_entity_mismatch(
1071 _context_label: &str,
1072 _source_path: &str,
1073 _field_name: &str,
1074 _target_path: &str,
1075 _target_entity_name: &str,
1076 _expected_tag: impl Sized,
1077 _actual_tag: impl Sized,
1078 ) -> Self {
1079 Self::store_corruption()
1080 }
1081
1082 pub(crate) fn relation_source_row_decode_failed(
1084 _source_path: &str,
1085 _field_name: &str,
1086 _target_path: &str,
1087 _detail: impl Sized,
1088 ) -> Self {
1089 Self::persisted_row_decode_corruption()
1090 }
1091
1092 pub(crate) fn relation_source_row_unsupported_scalar_relation_key(
1094 _source_path: &str,
1095 _field_name: &str,
1096 _target_path: &str,
1097 ) -> Self {
1098 Self::persisted_row_decode_corruption()
1099 }
1100
1101 pub(crate) fn relation_source_row_unsupported_key_kind(_field_kind: impl fmt::Debug) -> Self {
1103 Self::persisted_row_decode_corruption()
1104 }
1105
1106 pub(crate) fn reverse_index_relation_target_decode_invariant_violated(
1108 _source_path: &str,
1109 _field_name: &str,
1110 _target_path: &str,
1111 ) -> Self {
1112 Self::executor_internal()
1113 }
1114
1115 pub(crate) fn bytes_covering_component_payload_empty() -> Self {
1117 Self::index_corruption()
1118 }
1119
1120 pub(crate) fn bytes_covering_bool_payload_truncated() -> Self {
1122 Self::index_corruption()
1123 }
1124
1125 pub(crate) fn bytes_covering_component_payload_invalid_length() -> Self {
1127 Self::index_corruption()
1128 }
1129
1130 pub(crate) fn bytes_covering_bool_payload_invalid_value() -> Self {
1132 Self::index_corruption()
1133 }
1134
1135 pub(crate) fn bytes_covering_text_payload_invalid_terminator() -> Self {
1137 Self::index_corruption()
1138 }
1139
1140 pub(crate) fn bytes_covering_text_payload_trailing_bytes() -> Self {
1142 Self::index_corruption()
1143 }
1144
1145 pub(crate) fn bytes_covering_text_payload_invalid_utf8() -> Self {
1147 Self::index_corruption()
1148 }
1149
1150 pub(crate) fn bytes_covering_text_payload_invalid_escape_byte() -> Self {
1152 Self::index_corruption()
1153 }
1154
1155 pub(crate) fn bytes_covering_text_payload_missing_terminator() -> Self {
1157 Self::index_corruption()
1158 }
1159
1160 #[must_use]
1162 pub fn missing_persisted_slot(field_name: &'static str) -> Self {
1163 Self::persisted_row_field_decode_corruption(field_name)
1164 }
1165
1166 pub(crate) fn identity_corruption() -> Self {
1168 Self::new(ErrorClass::Corruption, ErrorOrigin::Identity)
1169 }
1170
1171 #[cold]
1173 #[inline(never)]
1174 pub(crate) fn store_unsupported() -> Self {
1175 Self::new(ErrorClass::Unsupported, ErrorOrigin::Store)
1176 }
1177
1178 #[cfg(any(test, feature = "sql"))]
1180 pub(crate) fn schema_ddl_publication_race_lost(_entity_path: &'static str) -> Self {
1181 Self {
1182 class: ErrorClass::Unsupported,
1183 origin: ErrorOrigin::Store,
1184 detail: Some(ErrorDetail::Store(StoreError::SchemaDdlPublicationRaceLost)),
1185 }
1186 }
1187
1188 #[cfg(feature = "sql")]
1190 pub(crate) fn schema_ddl_set_not_null_validation_failed(
1191 _entity_path: &'static str,
1192 _column_name: &str,
1193 ) -> Self {
1194 Self {
1195 class: ErrorClass::Unsupported,
1196 origin: ErrorOrigin::Store,
1197 detail: Some(ErrorDetail::Store(
1198 StoreError::SchemaDdlSetNotNullValidationFailed,
1199 )),
1200 }
1201 }
1202
1203 pub(crate) fn unsupported_entity_tag_in_data_store(
1205 _entity_tag: crate::types::EntityTag,
1206 ) -> Self {
1207 Self::store_unsupported()
1208 }
1209
1210 #[cfg(not(test))]
1212 pub(crate) fn commit_memory_id_registration_failed(_err: impl Sized) -> Self {
1213 Self::store_internal()
1214 }
1215
1216 pub(crate) fn index_unsupported() -> Self {
1218 Self::new(ErrorClass::Unsupported, ErrorOrigin::Index)
1219 }
1220
1221 pub(crate) fn index_component_exceeds_max_size() -> Self {
1223 Self::index_unsupported()
1224 }
1225
1226 pub(crate) fn serialize_unsupported() -> Self {
1228 Self::new(ErrorClass::Unsupported, ErrorOrigin::Serialize)
1229 }
1230
1231 pub(crate) fn cursor_unsupported() -> Self {
1233 Self::new(ErrorClass::Unsupported, ErrorOrigin::Cursor)
1234 }
1235
1236 pub(crate) fn serialize_incompatible_persisted_format() -> Self {
1238 Self::new(
1239 ErrorClass::IncompatiblePersistedFormat,
1240 ErrorOrigin::Serialize,
1241 )
1242 }
1243
1244 #[cfg(feature = "sql")]
1247 pub(crate) fn query_unsupported_sql_feature(feature: diagnostic_code::SqlFeatureCode) -> Self {
1248 Self {
1249 class: ErrorClass::Unsupported,
1250 origin: ErrorOrigin::Query,
1251 detail: Some(ErrorDetail::Query(
1252 QueryErrorDetail::UnsupportedSqlFeature { feature },
1253 )),
1254 }
1255 }
1256
1257 #[cfg(feature = "sql")]
1260 pub(crate) fn query_sql_lowering(reason: diagnostic_code::SqlLoweringCode) -> Self {
1261 Self {
1262 class: ErrorClass::Unsupported,
1263 origin: ErrorOrigin::Query,
1264 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlLowering { reason })),
1265 }
1266 }
1267
1268 pub(crate) fn query_unsupported_projection(
1271 reason: diagnostic_code::QueryProjectionCode,
1272 ) -> Self {
1273 Self {
1274 class: ErrorClass::Unsupported,
1275 origin: ErrorOrigin::Query,
1276 detail: Some(ErrorDetail::Query(
1277 QueryErrorDetail::UnsupportedProjection { reason },
1278 )),
1279 }
1280 }
1281
1282 pub(crate) fn query_unknown_aggregate_target_field() -> Self {
1284 Self {
1285 class: ErrorClass::Unsupported,
1286 origin: ErrorOrigin::Query,
1287 detail: Some(ErrorDetail::Query(
1288 QueryErrorDetail::UnknownAggregateTargetField,
1289 )),
1290 }
1291 }
1292
1293 pub(crate) fn query_result_shape_mismatch(
1296 reason: diagnostic_code::QueryResultShapeCode,
1297 ) -> Self {
1298 Self {
1299 class: ErrorClass::Unsupported,
1300 origin: ErrorOrigin::Query,
1301 detail: Some(ErrorDetail::Query(QueryErrorDetail::ResultShapeMismatch {
1302 reason,
1303 })),
1304 }
1305 }
1306
1307 #[cfg(feature = "sql")]
1310 pub(crate) fn query_sql_surface_mismatch(
1311 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1312 ) -> Self {
1313 Self {
1314 class: ErrorClass::Unsupported,
1315 origin: ErrorOrigin::Query,
1316 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlSurfaceMismatch {
1317 mismatch,
1318 })),
1319 }
1320 }
1321
1322 #[cfg(feature = "sql")]
1324 pub(crate) fn query_sql_write_boundary(
1325 boundary: diagnostic_code::SqlWriteBoundaryCode,
1326 ) -> Self {
1327 Self {
1328 class: ErrorClass::Unsupported,
1329 origin: ErrorOrigin::Query,
1330 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlWriteBoundary {
1331 boundary,
1332 })),
1333 }
1334 }
1335
1336 pub fn store_not_found(_key: impl Sized) -> Self {
1337 Self {
1338 class: ErrorClass::NotFound,
1339 origin: ErrorOrigin::Store,
1340 detail: Some(ErrorDetail::Store(StoreError::NotFound)),
1341 }
1342 }
1343
1344 pub fn unsupported_entity_path(_path: impl Sized) -> Self {
1346 Self::store_unsupported()
1347 }
1348
1349 #[must_use]
1350 pub const fn is_not_found(&self) -> bool {
1351 matches!(self.detail, Some(ErrorDetail::Store(StoreError::NotFound)))
1352 }
1353
1354 #[cold]
1356 #[inline(never)]
1357 pub(crate) fn index_plan_corruption(origin: ErrorOrigin) -> Self {
1358 Self::new(ErrorClass::Corruption, origin)
1359 }
1360
1361 #[cold]
1363 #[inline(never)]
1364 pub(crate) fn index_plan_index_corruption() -> Self {
1365 Self::index_plan_corruption(ErrorOrigin::Index)
1366 }
1367
1368 #[cold]
1370 #[inline(never)]
1371 pub(crate) fn index_plan_store_corruption() -> Self {
1372 Self::index_plan_corruption(ErrorOrigin::Store)
1373 }
1374
1375 #[cold]
1377 #[inline(never)]
1378 pub(crate) fn index_plan_serialize_corruption() -> Self {
1379 Self::index_plan_corruption(ErrorOrigin::Serialize)
1380 }
1381
1382 #[cfg(test)]
1384 pub(crate) fn index_plan_invariant(origin: ErrorOrigin) -> Self {
1385 Self::new(ErrorClass::InvariantViolation, origin)
1386 }
1387
1388 #[cfg(test)]
1390 pub(crate) fn index_plan_store_invariant() -> Self {
1391 Self::index_plan_invariant(ErrorOrigin::Store)
1392 }
1393
1394 pub(crate) fn index_violation(_path: &str, _index_fields: &[&str]) -> Self {
1396 Self::new(ErrorClass::Conflict, ErrorOrigin::Index)
1397 }
1398}
1399
1400impl From<diagnostic_code::QueryReadAdmissionCode> for InternalError {
1401 fn from(reason: diagnostic_code::QueryReadAdmissionCode) -> Self {
1402 Self {
1403 class: ErrorClass::Unsupported,
1404 origin: ErrorOrigin::Query,
1405 detail: Some(ErrorDetail::Query(QueryErrorDetail::QueryReadAdmission {
1406 reason,
1407 })),
1408 }
1409 }
1410}
1411
1412impl fmt::Debug for InternalError {
1413 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1414 fmt_compact_diagnostic(
1415 f,
1416 self.diagnostic_code(),
1417 self.detail
1418 .as_ref()
1419 .and_then(ErrorDetail::diagnostic_detail),
1420 )
1421 }
1422}
1423
1424impl fmt::Display for InternalError {
1425 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1426 f.write_str(self.message())
1427 }
1428}
1429
1430impl std::error::Error for InternalError {}
1431
1432pub enum ErrorDetail {
1440 Store(StoreError),
1441 Query(QueryErrorDetail),
1442 Recovery(RecoveryErrorDetail),
1443 }
1448
1449pub enum RecoveryErrorDetail {
1456 UnsupportedFormatVersion { found: Option<u16>, required: u16 },
1457
1458 MalformedFormatMarker { reason: RecoveryFormatMarkerError },
1459}
1460
1461#[derive(Clone, Copy, Eq, PartialEq)]
1463pub enum RecoveryFormatMarkerError {
1464 Magic,
1465 Checksum,
1466 State,
1467}
1468
1469pub enum StoreError {
1477 NotFound,
1478
1479 Corrupt,
1480
1481 InvariantViolation,
1482
1483 SchemaDdlPublicationRaceLost,
1484
1485 SchemaDdlSetNotNullValidationFailed,
1486}
1487
1488pub enum QueryErrorDetail {
1495 NumericOverflow,
1496
1497 NumericNotRepresentable,
1498
1499 UnsupportedSqlFeature {
1500 feature: diagnostic_code::SqlFeatureCode,
1501 },
1502
1503 SqlLowering {
1504 reason: diagnostic_code::SqlLoweringCode,
1505 },
1506
1507 UnsupportedProjection {
1508 reason: diagnostic_code::QueryProjectionCode,
1509 },
1510
1511 UnknownAggregateTargetField,
1512
1513 ResultShapeMismatch {
1514 reason: diagnostic_code::QueryResultShapeCode,
1515 },
1516
1517 QueryReadAdmission {
1518 reason: diagnostic_code::QueryReadAdmissionCode,
1519 },
1520
1521 SqlSurfaceMismatch {
1522 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1523 },
1524
1525 SqlWriteBoundary {
1526 boundary: diagnostic_code::SqlWriteBoundaryCode,
1527 },
1528
1529 SchemaDdlAdmission {
1530 error: SchemaDdlAdmissionError,
1531 },
1532
1533 StaleSchemaRevision,
1534}
1535
1536impl fmt::Display for QueryErrorDetail {
1537 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1538 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
1539 }
1540}
1541
1542impl std::error::Error for QueryErrorDetail {}
1543
1544#[derive(Clone, Copy, Eq, PartialEq)]
1553pub enum SchemaDdlAdmissionError {
1554 MissingExpectedSchemaVersion,
1555
1556 MissingNextSchemaVersion,
1557
1558 StaleExpectedSchemaVersion,
1559
1560 InvalidExpectedSchemaVersion,
1561
1562 InvalidNextSchemaVersion,
1563
1564 AcceptedSchemaChangeWithoutVersionBump,
1565
1566 EmptyVersionBump,
1567
1568 VersionGap,
1569
1570 VersionRollback,
1571
1572 FingerprintMethodMismatch,
1573
1574 UnsupportedTransitionClass,
1575
1576 PhysicalRunnerMissing,
1577
1578 ValidationFailed,
1579
1580 PublicationRaceLost,
1581
1582 InvalidAddColumnDefault,
1583
1584 InvalidAlterColumnDefault,
1585
1586 GeneratedIndexDropRejected,
1587
1588 RequiredDropDefaultUnsupported,
1589
1590 GeneratedFieldDefaultChangeRejected,
1591
1592 GeneratedFieldNullabilityChangeRejected,
1593
1594 SetNotNullValidationFailed,
1595}
1596
1597impl fmt::Display for SchemaDdlAdmissionError {
1598 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1599 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
1600 }
1601}
1602
1603impl std::error::Error for SchemaDdlAdmissionError {}
1604
1605impl fmt::Debug for ErrorDetail {
1606 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1607 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1608 }
1609}
1610
1611impl fmt::Debug for StoreError {
1612 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1613 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1614 }
1615}
1616
1617impl fmt::Debug for QueryErrorDetail {
1618 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1619 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1620 }
1621}
1622
1623impl fmt::Debug for RecoveryErrorDetail {
1624 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1625 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1626 }
1627}
1628
1629impl fmt::Debug for RecoveryFormatMarkerError {
1630 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1631 fmt_compact_diagnostic(
1632 f,
1633 diagnostic_code::DiagnosticCode::RuntimeCorruption,
1634 Some(diagnostic_code::DiagnosticDetail::RuntimeKind {
1635 kind: diagnostic_code::RuntimeErrorKind::Corruption,
1636 }),
1637 )
1638 }
1639}
1640
1641impl fmt::Debug for SchemaDdlAdmissionError {
1642 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1643 fmt_compact_diagnostic(
1644 f,
1645 diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
1646 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1647 reason: self.diagnostic_code(),
1648 }),
1649 )
1650 }
1651}
1652
1653fn fmt_compact_diagnostic(
1654 f: &mut fmt::Formatter<'_>,
1655 code: diagnostic_code::DiagnosticCode,
1656 detail: Option<diagnostic_code::DiagnosticDetail>,
1657) -> fmt::Result {
1658 write!(
1659 f,
1660 "{}",
1661 diagnostic_code::ErrorCode::from_parts(code, detail).raw()
1662 )
1663}
1664
1665impl ErrorDetail {
1666 #[must_use]
1668 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1669 match self {
1670 Self::Store(error) => error.diagnostic_code(),
1671 Self::Query(error) => error.diagnostic_code(),
1672 Self::Recovery(error) => error.diagnostic_code(),
1673 }
1674 }
1675
1676 #[must_use]
1678 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1679 match self {
1680 Self::Store(error) => error.diagnostic_detail(),
1681 Self::Query(error) => error.diagnostic_detail(),
1682 Self::Recovery(error) => error.diagnostic_detail(),
1683 }
1684 }
1685}
1686
1687impl RecoveryErrorDetail {
1688 #[must_use]
1690 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1691 match self {
1692 Self::UnsupportedFormatVersion { .. } => {
1693 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
1694 }
1695 Self::MalformedFormatMarker { .. } => {
1696 diagnostic_code::DiagnosticCode::RuntimeCorruption
1697 }
1698 }
1699 }
1700
1701 #[must_use]
1703 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1704 let kind = match self {
1705 Self::UnsupportedFormatVersion { .. } => {
1706 diagnostic_code::RuntimeErrorKind::IncompatiblePersistedFormat
1707 }
1708 Self::MalformedFormatMarker { .. } => diagnostic_code::RuntimeErrorKind::Corruption,
1709 };
1710
1711 Some(diagnostic_code::DiagnosticDetail::RuntimeKind { kind })
1712 }
1713}
1714
1715impl StoreError {
1716 #[must_use]
1718 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1719 match self {
1720 Self::NotFound => diagnostic_code::DiagnosticCode::StoreNotFound,
1721 Self::Corrupt => diagnostic_code::DiagnosticCode::StoreCorruption,
1722 Self::InvariantViolation => diagnostic_code::DiagnosticCode::StoreInvariantViolation,
1723 Self::SchemaDdlPublicationRaceLost | Self::SchemaDdlSetNotNullValidationFailed => {
1724 diagnostic_code::DiagnosticCode::SchemaDdlAdmission
1725 }
1726 }
1727 }
1728
1729 #[must_use]
1731 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1732 match self {
1733 Self::SchemaDdlPublicationRaceLost => {
1734 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1735 reason: diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost,
1736 })
1737 }
1738 Self::SchemaDdlSetNotNullValidationFailed => {
1739 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1740 reason: diagnostic_code::SchemaDdlAdmissionCode::SetNotNullValidationFailed,
1741 })
1742 }
1743 Self::NotFound | Self::Corrupt | Self::InvariantViolation => None,
1744 }
1745 }
1746}
1747
1748impl QueryErrorDetail {
1749 #[must_use]
1751 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1752 match self {
1753 Self::NumericOverflow => diagnostic_code::DiagnosticCode::QueryNumericOverflow,
1754 Self::NumericNotRepresentable => {
1755 diagnostic_code::DiagnosticCode::QueryNumericNotRepresentable
1756 }
1757 Self::UnsupportedSqlFeature { .. } => {
1758 diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature
1759 }
1760 Self::SqlLowering { .. } => diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature,
1761 Self::UnsupportedProjection { .. } => {
1762 diagnostic_code::DiagnosticCode::QueryUnsupportedProjection
1763 }
1764 Self::UnknownAggregateTargetField => {
1765 diagnostic_code::DiagnosticCode::QueryUnknownAggregateTargetField
1766 }
1767 Self::ResultShapeMismatch { .. } => {
1768 diagnostic_code::DiagnosticCode::QueryResultShapeMismatch
1769 }
1770 Self::QueryReadAdmission { .. } => diagnostic_code::DiagnosticCode::QueryReadAdmission,
1771 Self::SqlSurfaceMismatch { .. } => {
1772 diagnostic_code::DiagnosticCode::QuerySqlSurfaceMismatch
1773 }
1774 Self::SqlWriteBoundary { .. } => diagnostic_code::DiagnosticCode::QuerySqlWriteBoundary,
1775 Self::SchemaDdlAdmission { .. } => diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
1776 Self::StaleSchemaRevision => diagnostic_code::DiagnosticCode::RuntimeConflict,
1777 }
1778 }
1779
1780 #[must_use]
1782 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1783 match self {
1784 Self::UnsupportedSqlFeature { feature } => {
1785 Some(diagnostic_code::DiagnosticDetail::UnsupportedSqlFeature { feature: *feature })
1786 }
1787 Self::SqlLowering { reason } => {
1788 Some(diagnostic_code::DiagnosticDetail::SqlLowering { reason: *reason })
1789 }
1790 Self::UnsupportedProjection { reason } => {
1791 Some(diagnostic_code::DiagnosticDetail::QueryProjection { reason: *reason })
1792 }
1793 Self::ResultShapeMismatch { reason } => {
1794 Some(diagnostic_code::DiagnosticDetail::QueryResultShape { reason: *reason })
1795 }
1796 Self::QueryReadAdmission { reason } => {
1797 Some(diagnostic_code::DiagnosticDetail::QueryReadAdmission { reason: *reason })
1798 }
1799 Self::SqlSurfaceMismatch { mismatch } => {
1800 Some(diagnostic_code::DiagnosticDetail::SqlSurfaceMismatch {
1801 mismatch: *mismatch,
1802 })
1803 }
1804 Self::SqlWriteBoundary { boundary } => {
1805 Some(diagnostic_code::DiagnosticDetail::SqlWriteBoundary {
1806 boundary: *boundary,
1807 })
1808 }
1809 Self::SchemaDdlAdmission { error } => {
1810 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1811 reason: error.diagnostic_code(),
1812 })
1813 }
1814 Self::NumericOverflow
1815 | Self::NumericNotRepresentable
1816 | Self::UnknownAggregateTargetField
1817 | Self::StaleSchemaRevision => None,
1818 }
1819 }
1820}
1821
1822impl SchemaDdlAdmissionError {
1823 #[must_use]
1825 pub const fn diagnostic_code(&self) -> diagnostic_code::SchemaDdlAdmissionCode {
1826 match self {
1827 Self::MissingExpectedSchemaVersion => {
1828 diagnostic_code::SchemaDdlAdmissionCode::MissingExpectedSchemaVersion
1829 }
1830 Self::MissingNextSchemaVersion => {
1831 diagnostic_code::SchemaDdlAdmissionCode::MissingNextSchemaVersion
1832 }
1833 Self::StaleExpectedSchemaVersion => {
1834 diagnostic_code::SchemaDdlAdmissionCode::StaleExpectedSchemaVersion
1835 }
1836 Self::InvalidExpectedSchemaVersion => {
1837 diagnostic_code::SchemaDdlAdmissionCode::InvalidExpectedSchemaVersion
1838 }
1839 Self::InvalidNextSchemaVersion => {
1840 diagnostic_code::SchemaDdlAdmissionCode::InvalidNextSchemaVersion
1841 }
1842 Self::AcceptedSchemaChangeWithoutVersionBump => {
1843 diagnostic_code::SchemaDdlAdmissionCode::AcceptedSchemaChangeWithoutVersionBump
1844 }
1845 Self::EmptyVersionBump => diagnostic_code::SchemaDdlAdmissionCode::EmptyVersionBump,
1846 Self::VersionGap => diagnostic_code::SchemaDdlAdmissionCode::VersionGap,
1847 Self::VersionRollback => diagnostic_code::SchemaDdlAdmissionCode::VersionRollback,
1848 Self::FingerprintMethodMismatch => {
1849 diagnostic_code::SchemaDdlAdmissionCode::FingerprintMethodMismatch
1850 }
1851 Self::UnsupportedTransitionClass => {
1852 diagnostic_code::SchemaDdlAdmissionCode::UnsupportedTransitionClass
1853 }
1854 Self::PhysicalRunnerMissing => {
1855 diagnostic_code::SchemaDdlAdmissionCode::PhysicalRunnerMissing
1856 }
1857 Self::ValidationFailed => diagnostic_code::SchemaDdlAdmissionCode::ValidationFailed,
1858 Self::PublicationRaceLost => {
1859 diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost
1860 }
1861 Self::InvalidAddColumnDefault => {
1862 diagnostic_code::SchemaDdlAdmissionCode::InvalidAddColumnDefault
1863 }
1864 Self::InvalidAlterColumnDefault => {
1865 diagnostic_code::SchemaDdlAdmissionCode::InvalidAlterColumnDefault
1866 }
1867 Self::GeneratedIndexDropRejected => {
1868 diagnostic_code::SchemaDdlAdmissionCode::GeneratedIndexDropRejected
1869 }
1870 Self::RequiredDropDefaultUnsupported => {
1871 diagnostic_code::SchemaDdlAdmissionCode::RequiredDropDefaultUnsupported
1872 }
1873 Self::GeneratedFieldDefaultChangeRejected => {
1874 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldDefaultChangeRejected
1875 }
1876 Self::GeneratedFieldNullabilityChangeRejected => {
1877 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldNullabilityChangeRejected
1878 }
1879 Self::SetNotNullValidationFailed => {
1880 diagnostic_code::SchemaDdlAdmissionCode::SetNotNullValidationFailed
1881 }
1882 }
1883 }
1884}
1885
1886#[repr(u16)]
1893#[derive(Clone, Copy, Eq, PartialEq)]
1894pub enum ErrorClass {
1895 Corruption,
1896 IncompatiblePersistedFormat,
1897 NotFound,
1898 Internal,
1899 Conflict,
1900 Unsupported,
1901 InvariantViolation,
1902}
1903
1904impl ErrorClass {
1905 #[must_use]
1907 pub const fn diagnostic_code(self, origin: ErrorOrigin) -> diagnostic_code::DiagnosticCode {
1908 match self {
1909 Self::Corruption if matches!(origin, ErrorOrigin::Store) => {
1910 diagnostic_code::DiagnosticCode::StoreCorruption
1911 }
1912 Self::Corruption => diagnostic_code::DiagnosticCode::RuntimeCorruption,
1913 Self::IncompatiblePersistedFormat => {
1914 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
1915 }
1916 Self::NotFound if matches!(origin, ErrorOrigin::Store) => {
1917 diagnostic_code::DiagnosticCode::StoreNotFound
1918 }
1919 Self::NotFound => diagnostic_code::DiagnosticCode::RuntimeNotFound,
1920 Self::Internal => diagnostic_code::DiagnosticCode::RuntimeInternal,
1921 Self::Conflict => diagnostic_code::DiagnosticCode::RuntimeConflict,
1922 Self::Unsupported => diagnostic_code::DiagnosticCode::RuntimeUnsupported,
1923 Self::InvariantViolation if matches!(origin, ErrorOrigin::Store) => {
1924 diagnostic_code::DiagnosticCode::StoreInvariantViolation
1925 }
1926 Self::InvariantViolation => diagnostic_code::DiagnosticCode::RuntimeInvariantViolation,
1927 }
1928 }
1929}
1930
1931impl fmt::Debug for ErrorClass {
1932 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1933 write!(f, "{}", *self as u16)
1934 }
1935}
1936
1937#[repr(u16)]
1944#[derive(Clone, Copy, Eq, PartialEq)]
1945pub enum ErrorOrigin {
1946 Serialize,
1947 Store,
1948 Index,
1949 Identity,
1950 Query,
1951 Planner,
1952 Cursor,
1953 Recovery,
1954 Response,
1955 Executor,
1956 Interface,
1957}
1958
1959impl ErrorOrigin {
1960 #[must_use]
1962 pub const fn diagnostic_origin(self) -> diagnostic_code::ErrorOrigin {
1963 match self {
1964 Self::Serialize => diagnostic_code::ErrorOrigin::Serialize,
1965 Self::Store => diagnostic_code::ErrorOrigin::Store,
1966 Self::Index => diagnostic_code::ErrorOrigin::Index,
1967 Self::Identity => diagnostic_code::ErrorOrigin::Identity,
1968 Self::Query => diagnostic_code::ErrorOrigin::Query,
1969 Self::Planner => diagnostic_code::ErrorOrigin::Planner,
1970 Self::Cursor => diagnostic_code::ErrorOrigin::Cursor,
1971 Self::Recovery => diagnostic_code::ErrorOrigin::Recovery,
1972 Self::Response => diagnostic_code::ErrorOrigin::Response,
1973 Self::Executor => diagnostic_code::ErrorOrigin::Executor,
1974 Self::Interface => diagnostic_code::ErrorOrigin::Interface,
1975 }
1976 }
1977}
1978
1979impl fmt::Debug for ErrorOrigin {
1980 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1981 write!(f, "{}", *self as u16)
1982 }
1983}