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_conflict() -> Self {
313 Self::new(ErrorClass::Conflict, ErrorOrigin::Executor)
314 }
315
316 #[cold]
318 #[inline(never)]
319 pub(crate) fn executor_internal() -> Self {
320 Self::new(ErrorClass::Internal, ErrorOrigin::Executor)
321 }
322
323 #[cold]
325 #[inline(never)]
326 pub(crate) fn executor_unsupported() -> Self {
327 Self::new(ErrorClass::Unsupported, ErrorOrigin::Executor)
328 }
329
330 pub(crate) fn mutation_entity_primary_key_missing(
332 _entity_path: &str,
333 _field_name: &str,
334 ) -> Self {
335 Self::executor_invariant()
336 }
337
338 pub(crate) fn mutation_entity_primary_key_invalid_value(
340 _entity_path: &str,
341 _field_name: &str,
342 _value: &crate::value::Value,
343 ) -> Self {
344 Self::executor_invariant()
345 }
346
347 pub(crate) fn mutation_entity_primary_key_type_mismatch(
349 _entity_path: &str,
350 _field_name: &str,
351 _value: &crate::value::Value,
352 ) -> Self {
353 Self::executor_invariant()
354 }
355
356 pub(crate) fn mutation_entity_primary_key_mismatch(
358 _entity_path: &str,
359 _field_name: &str,
360 _field_value: &crate::value::Value,
361 _identity_key: &crate::value::Value,
362 ) -> Self {
363 Self::executor_invariant()
364 }
365
366 pub(crate) fn mutation_entity_field_missing(
368 _entity_path: &str,
369 _field_name: &str,
370 _indexed: bool,
371 ) -> Self {
372 Self::executor_invariant()
373 }
374
375 pub(crate) fn mutation_structural_patch_required_field_missing(
377 _entity_path: &str,
378 _field_name: &str,
379 ) -> Self {
380 Self::executor_invariant()
381 }
382
383 pub(crate) fn mutation_entity_field_type_mismatch(
385 _entity_path: &str,
386 _field_name: &str,
387 _value: &crate::value::Value,
388 ) -> Self {
389 Self::executor_invariant()
390 }
391
392 pub(crate) fn mutation_generated_field_explicit(_entity_path: &str, _field_name: &str) -> Self {
394 Self::executor_unsupported()
395 }
396
397 #[must_use]
399 pub fn mutation_create_missing_authored_fields(_entity_path: &str, _field_names: &str) -> Self {
400 Self::executor_unsupported()
401 }
402
403 pub(crate) fn mutation_structural_after_image_invalid(
408 _entity_path: &str,
409 _data_key: impl Sized,
410 _detail: impl Sized,
411 ) -> Self {
412 Self::executor_invariant()
413 }
414
415 pub(crate) fn mutation_structural_field_unknown(_entity_path: &str, _field_name: &str) -> Self {
417 Self::executor_invariant()
418 }
419
420 pub(crate) fn mutation_decimal_scale_mismatch(
422 _entity_path: &str,
423 _field_name: &str,
424 _expected_scale: impl Sized,
425 _actual_scale: impl Sized,
426 ) -> Self {
427 Self::executor_unsupported()
428 }
429
430 pub(crate) fn mutation_text_max_len_exceeded(
432 _entity_path: &str,
433 _field_name: &str,
434 _max_len: impl Sized,
435 _actual_len: impl Sized,
436 ) -> Self {
437 Self::executor_unsupported()
438 }
439
440 pub(crate) fn mutation_set_field_list_required(_entity_path: &str, _field_name: &str) -> Self {
442 Self::executor_invariant()
443 }
444
445 pub(crate) fn mutation_set_field_not_canonical(_entity_path: &str, _field_name: &str) -> Self {
447 Self::executor_invariant()
448 }
449
450 pub(crate) fn mutation_map_field_map_required(_entity_path: &str, _field_name: &str) -> Self {
452 Self::executor_invariant()
453 }
454
455 pub(crate) fn mutation_map_field_entries_invalid(
457 _entity_path: &str,
458 _field_name: &str,
459 _detail: impl Sized,
460 ) -> Self {
461 Self::executor_invariant()
462 }
463
464 pub(crate) fn mutation_map_field_entries_not_canonical(
466 _entity_path: &str,
467 _field_name: &str,
468 ) -> Self {
469 Self::executor_invariant()
470 }
471
472 pub(crate) fn scalar_page_cursor_boundary_order_required() -> Self {
474 Self::query_executor_invariant()
475 }
476
477 pub(crate) fn scalar_page_cursor_boundary_after_ordering_required() -> Self {
479 Self::query_executor_invariant()
480 }
481
482 pub(crate) fn scalar_page_pagination_after_ordering_required() -> Self {
484 Self::query_executor_invariant()
485 }
486
487 pub(crate) fn load_runtime_scalar_payload_required() -> Self {
489 Self::query_executor_invariant()
490 }
491
492 pub(crate) fn load_runtime_grouped_payload_required() -> Self {
494 Self::query_executor_invariant()
495 }
496
497 pub(crate) fn load_runtime_scalar_surface_payload_required() -> Self {
499 Self::query_executor_invariant()
500 }
501
502 pub(crate) fn load_runtime_grouped_surface_payload_required() -> Self {
504 Self::query_executor_invariant()
505 }
506
507 pub(crate) fn load_executor_load_plan_required() -> Self {
509 Self::query_executor_invariant()
510 }
511
512 pub(crate) fn delete_executor_grouped_unsupported() -> Self {
514 Self::executor_unsupported()
515 }
516
517 pub(crate) fn delete_executor_delete_plan_required() -> Self {
519 Self::query_executor_invariant()
520 }
521
522 pub(crate) fn aggregate_fold_mode_terminal_contract_required() -> Self {
524 Self::query_executor_invariant()
525 }
526
527 pub(crate) fn fast_stream_route_kind_request_match_required() -> Self {
529 Self::query_executor_invariant()
530 }
531
532 pub(crate) fn secondary_index_prefix_spec_required() -> Self {
534 Self::query_executor_invariant()
535 }
536
537 pub(crate) fn index_range_limit_spec_required() -> Self {
539 Self::query_executor_invariant()
540 }
541
542 pub(crate) fn mutation_atomic_save_duplicate_key(_entity_path: &str, _key: impl Sized) -> Self {
544 Self::executor_conflict()
545 }
546
547 pub(crate) fn mutation_index_store_generation_changed(
549 _expected_generation: u64,
550 _observed_generation: u64,
551 ) -> Self {
552 Self::executor_invariant()
553 }
554
555 #[cold]
557 #[inline(never)]
558 pub(crate) fn planner_invariant() -> Self {
559 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Planner)
560 }
561
562 pub(crate) fn query_invalid_logical_plan() -> Self {
564 Self::planner_invariant()
565 }
566
567 pub(crate) fn store_invariant() -> Self {
569 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Store)
570 }
571
572 pub(crate) fn duplicate_runtime_hooks_for_entity_tag(
574 _entity_tag: crate::types::EntityTag,
575 ) -> Self {
576 Self::store_invariant()
577 }
578
579 pub(crate) fn duplicate_runtime_hooks_for_entity_path(_entity_path: &str) -> Self {
581 Self::store_invariant()
582 }
583
584 #[cold]
586 #[inline(never)]
587 pub(crate) fn store_internal() -> Self {
588 Self::new(ErrorClass::Internal, ErrorOrigin::Store)
589 }
590
591 pub(crate) fn commit_memory_id_unconfigured() -> Self {
593 Self::store_internal()
594 }
595
596 pub(crate) fn commit_memory_id_mismatch(_cached_id: u8, _configured_id: u8) -> Self {
598 Self::store_internal()
599 }
600
601 pub(crate) fn commit_memory_stable_key_mismatch(
603 _cached_key: &str,
604 _configured_key: &str,
605 ) -> Self {
606 Self::store_internal()
607 }
608
609 pub(crate) fn recovery_unsupported_database_format(found: Option<u16>, required: u16) -> Self {
611 Self {
612 class: ErrorClass::IncompatiblePersistedFormat,
613 origin: ErrorOrigin::Recovery,
614 detail: Some(ErrorDetail::Recovery(
615 RecoveryErrorDetail::UnsupportedFormatVersion { found, required },
616 )),
617 }
618 }
619
620 pub(crate) fn recovery_malformed_database_format_marker(
622 reason: RecoveryFormatMarkerError,
623 ) -> Self {
624 Self {
625 class: ErrorClass::Corruption,
626 origin: ErrorOrigin::Recovery,
627 detail: Some(ErrorDetail::Recovery(
628 RecoveryErrorDetail::MalformedFormatMarker { reason },
629 )),
630 }
631 }
632
633 pub(crate) fn recovery_database_format_control_unavailable() -> Self {
635 Self::new(ErrorClass::Internal, ErrorOrigin::Recovery)
636 }
637
638 pub(crate) fn commit_control_memory_growth_failed() -> Self {
640 Self::store_internal()
641 }
642
643 #[cfg(not(test))]
645 pub(crate) fn database_format_memory_registration_failed(_err: impl Sized) -> Self {
646 Self::store_internal()
647 }
648
649 pub(crate) fn delete_rollback_row_required() -> Self {
651 Self::store_internal()
652 }
653
654 pub(crate) fn recovery_integrity_validation_failed(
656 _missing_index_entries: u64,
657 _divergent_index_entries: u64,
658 _orphan_index_references: u64,
659 ) -> Self {
660 Self::store_corruption()
661 }
662
663 #[cold]
665 #[inline(never)]
666 pub(crate) fn index_internal() -> Self {
667 Self::new(ErrorClass::Internal, ErrorOrigin::Index)
668 }
669
670 pub(crate) fn structural_index_removal_entity_key_required() -> Self {
672 Self::index_internal()
673 }
674
675 pub(crate) fn structural_index_insertion_entity_key_required() -> Self {
677 Self::index_internal()
678 }
679
680 pub(crate) fn index_commit_op_old_entity_key_required() -> Self {
682 Self::index_internal()
683 }
684
685 pub(crate) fn index_commit_op_new_entity_key_required() -> Self {
687 Self::index_internal()
688 }
689
690 #[cfg(test)]
692 pub(crate) fn query_internal() -> Self {
693 Self::new(ErrorClass::Internal, ErrorOrigin::Query)
694 }
695
696 #[cold]
698 #[inline(never)]
699 pub(crate) fn query_unsupported() -> Self {
700 Self::new(ErrorClass::Unsupported, ErrorOrigin::Query)
701 }
702
703 #[cold]
706 #[inline(never)]
707 pub(crate) fn query_stale_accepted_schema_revision(
708 _expected_revision: u64,
709 _current_revision: Option<u64>,
710 ) -> Self {
711 Self {
712 class: ErrorClass::Conflict,
713 origin: ErrorOrigin::Query,
714 detail: Some(ErrorDetail::Query(QueryErrorDetail::StaleSchemaRevision)),
715 }
716 }
717
718 #[cold]
720 #[inline(never)]
721 #[cfg(feature = "sql")]
722 pub(crate) fn query_schema_ddl_admission(error: SchemaDdlAdmissionError) -> Self {
723 Self {
724 class: ErrorClass::Unsupported,
725 origin: ErrorOrigin::Query,
726 detail: Some(ErrorDetail::Query(QueryErrorDetail::SchemaDdlAdmission {
727 error,
728 })),
729 }
730 }
731
732 #[cold]
734 #[inline(never)]
735 pub(crate) fn query_numeric_overflow() -> Self {
736 Self {
737 class: ErrorClass::Unsupported,
738 origin: ErrorOrigin::Query,
739 detail: Some(ErrorDetail::Query(QueryErrorDetail::NumericOverflow)),
740 }
741 }
742
743 #[cold]
746 #[inline(never)]
747 pub(crate) fn query_numeric_not_representable() -> Self {
748 Self {
749 class: ErrorClass::Unsupported,
750 origin: ErrorOrigin::Query,
751 detail: Some(ErrorDetail::Query(
752 QueryErrorDetail::NumericNotRepresentable,
753 )),
754 }
755 }
756
757 #[cold]
759 #[inline(never)]
760 pub(crate) fn serialize_internal() -> Self {
761 Self::new(ErrorClass::Internal, ErrorOrigin::Serialize)
762 }
763
764 pub(crate) fn persisted_row_encode_failed(_detail: impl Sized) -> Self {
766 Self::persisted_row_encode_internal()
767 }
768
769 pub(crate) fn persisted_row_encode_internal() -> Self {
771 Self::serialize_internal()
772 }
773
774 pub(crate) fn persisted_row_field_encode_failed(field_name: &str, _detail: impl Sized) -> Self {
776 Self::persisted_row_field_encode_internal(field_name)
777 }
778
779 pub(crate) fn persisted_row_field_encode_internal(_field_name: &str) -> Self {
781 Self::persisted_row_encode_internal()
782 }
783
784 pub(crate) fn bytes_field_value_encode_failed(_detail: impl Sized) -> Self {
786 Self::serialize_internal()
787 }
788
789 #[cold]
791 #[inline(never)]
792 pub(crate) fn store_corruption() -> Self {
793 Self::new(ErrorClass::Corruption, ErrorOrigin::Store)
794 }
795
796 pub(crate) fn commit_corruption() -> Self {
798 Self::store_corruption()
799 }
800
801 pub(crate) fn commit_component_corruption() -> Self {
803 Self::commit_corruption()
804 }
805
806 pub(crate) fn commit_id_generation_failed() -> Self {
808 Self::store_internal()
809 }
810
811 pub(crate) fn commit_marker_payload_exceeds_u32_length_limit() -> Self {
813 Self::store_unsupported()
814 }
815
816 pub(crate) fn commit_component_length_invalid() -> Self {
818 Self::commit_corruption()
819 }
820
821 pub(crate) fn commit_marker_exceeds_max_size() -> Self {
823 Self::commit_corruption()
824 }
825
826 pub(crate) fn commit_control_slot_exceeds_max_size() -> Self {
828 Self::store_unsupported()
829 }
830
831 pub(crate) fn commit_control_slot_marker_bytes_exceed_u32_length_limit() -> Self {
833 Self::store_unsupported()
834 }
835
836 pub(crate) fn startup_index_rebuild_invalid_data_key() -> Self {
838 Self::store_corruption()
839 }
840
841 #[cold]
843 #[inline(never)]
844 pub(crate) fn index_corruption() -> Self {
845 Self::new(ErrorClass::Corruption, ErrorOrigin::Index)
846 }
847
848 pub(crate) fn index_unique_validation_corruption() -> Self {
850 Self::index_plan_index_corruption()
851 }
852
853 pub(crate) fn structural_index_entry_corruption() -> Self {
855 Self::index_plan_index_corruption()
856 }
857
858 pub(crate) fn index_unique_validation_entity_key_required() -> Self {
860 Self::index_invariant()
861 }
862
863 pub(crate) fn index_unique_validation_row_deserialize_failed() -> Self {
865 Self::index_plan_serialize_corruption()
866 }
867
868 pub(crate) fn index_unique_validation_primary_key_decode_failed() -> Self {
870 Self::index_plan_serialize_corruption()
871 }
872
873 pub(crate) fn index_unique_validation_key_rebuild_failed() -> Self {
875 Self::index_plan_serialize_corruption()
876 }
877
878 pub(crate) fn index_unique_validation_row_required() -> Self {
880 Self::index_plan_store_corruption()
881 }
882
883 pub(crate) fn index_only_predicate_component_required() -> Self {
885 Self::index_invariant()
886 }
887
888 pub(crate) fn index_scan_continuation_anchor_within_envelope_required() -> Self {
890 Self::index_invariant()
891 }
892
893 pub(crate) fn index_scan_continuation_advancement_required() -> Self {
895 Self::index_invariant()
896 }
897
898 pub(crate) fn index_scan_key_corrupted_during(
900 _context: &'static str,
901 _err: impl Sized,
902 ) -> Self {
903 Self::index_corruption()
904 }
905
906 pub(crate) fn index_projection_component_required(
908 _index_name: &str,
909 _component_index: usize,
910 ) -> Self {
911 Self::index_invariant()
912 }
913
914 pub(crate) fn index_entry_decode_failed() -> Self {
916 Self::index_corruption()
917 }
918
919 pub(crate) fn serialize_corruption() -> Self {
921 Self::new(ErrorClass::Corruption, ErrorOrigin::Serialize)
922 }
923
924 pub(crate) fn persisted_row_decode_failed(_detail: impl Sized) -> Self {
926 Self::persisted_row_decode_corruption()
927 }
928
929 pub(crate) fn persisted_row_decode_corruption() -> Self {
931 Self::serialize_corruption()
932 }
933
934 pub(crate) fn persisted_row_field_decode_failed(field_name: &str, _detail: impl Sized) -> Self {
936 Self::persisted_row_field_decode_corruption(field_name)
937 }
938
939 pub(crate) fn persisted_row_field_decode_corruption(_field_name: &str) -> Self {
941 Self::persisted_row_decode_corruption()
942 }
943
944 pub(crate) fn persisted_row_field_kind_decode_failed(
946 field_name: &str,
947 _field_kind: impl fmt::Debug,
948 _detail: impl Sized,
949 ) -> Self {
950 Self::persisted_row_field_decode_corruption(field_name)
951 }
952
953 pub(crate) fn persisted_row_field_payload_exact_len_required(field_name: &str) -> Self {
955 Self::persisted_row_field_decode_corruption(field_name)
956 }
957
958 pub(crate) fn persisted_row_field_payload_must_be_empty(field_name: &str) -> Self {
960 Self::persisted_row_field_decode_corruption(field_name)
961 }
962
963 pub(crate) fn persisted_row_field_payload_invalid_byte(field_name: &str) -> Self {
965 Self::persisted_row_field_decode_corruption(field_name)
966 }
967
968 pub(crate) fn persisted_row_field_payload_non_finite(field_name: &str) -> Self {
970 Self::persisted_row_field_decode_corruption(field_name)
971 }
972
973 pub(crate) fn persisted_row_field_payload_out_of_range(field_name: &str) -> Self {
975 Self::persisted_row_field_decode_corruption(field_name)
976 }
977
978 pub(crate) fn persisted_row_field_text_payload_invalid_utf8(field_name: &str) -> Self {
980 Self::persisted_row_field_decode_corruption(field_name)
981 }
982
983 pub(crate) fn persisted_row_slot_lookup_out_of_bounds(_model_path: &str, _slot: usize) -> Self {
985 Self::index_invariant()
986 }
987
988 pub(crate) fn persisted_row_slot_cache_lookup_out_of_bounds(
990 _model_path: &str,
991 _slot: usize,
992 ) -> Self {
993 Self::index_invariant()
994 }
995
996 pub(crate) fn persisted_row_primary_key_not_primary_key_encodable(
998 _data_key: impl fmt::Debug,
999 _detail: impl Sized,
1000 ) -> Self {
1001 Self::persisted_row_decode_corruption()
1002 }
1003
1004 pub(crate) fn persisted_row_primary_key_slot_missing(_data_key: impl fmt::Debug) -> Self {
1006 Self::persisted_row_decode_corruption()
1007 }
1008
1009 pub(crate) fn persisted_row_key_mismatch() -> Self {
1011 Self::store_corruption()
1012 }
1013
1014 pub(crate) fn persisted_row_declared_field_missing(field_name: &str) -> Self {
1016 Self::persisted_row_field_decode_corruption(field_name)
1017 }
1018
1019 pub(crate) fn data_key_entity_mismatch() -> Self {
1021 Self::store_corruption()
1022 }
1023
1024 pub(crate) fn reverse_index_ordinal_overflow(
1026 _source_path: &str,
1027 _field_name: &str,
1028 _target_path: &str,
1029 _detail: impl Sized,
1030 ) -> Self {
1031 Self::index_internal()
1032 }
1033
1034 pub(crate) fn reverse_index_entry_corrupted(
1036 _source_path: &str,
1037 _field_name: &str,
1038 _target_path: &str,
1039 _index_key: impl fmt::Debug,
1040 _detail: impl Sized,
1041 ) -> Self {
1042 Self::index_corruption()
1043 }
1044
1045 pub(crate) fn relation_target_store_missing(
1047 _source_path: &str,
1048 _field_name: &str,
1049 _target_path: &str,
1050 _store_path: &str,
1051 _detail: impl Sized,
1052 ) -> Self {
1053 Self::executor_internal()
1054 }
1055
1056 pub(crate) fn relation_target_key_decode_failed(
1058 _context_label: &str,
1059 _source_path: &str,
1060 _field_name: &str,
1061 _target_path: &str,
1062 _detail: impl Sized,
1063 ) -> Self {
1064 Self::identity_corruption()
1065 }
1066
1067 pub(crate) fn relation_target_entity_mismatch(
1069 _context_label: &str,
1070 _source_path: &str,
1071 _field_name: &str,
1072 _target_path: &str,
1073 _target_entity_name: &str,
1074 _expected_tag: impl Sized,
1075 _actual_tag: impl Sized,
1076 ) -> Self {
1077 Self::store_corruption()
1078 }
1079
1080 pub(crate) fn relation_source_row_decode_failed(
1082 _source_path: &str,
1083 _field_name: &str,
1084 _target_path: &str,
1085 _detail: impl Sized,
1086 ) -> Self {
1087 Self::persisted_row_decode_corruption()
1088 }
1089
1090 pub(crate) fn relation_source_row_unsupported_scalar_relation_key(
1092 _source_path: &str,
1093 _field_name: &str,
1094 _target_path: &str,
1095 ) -> Self {
1096 Self::persisted_row_decode_corruption()
1097 }
1098
1099 pub(crate) fn relation_source_row_unsupported_key_kind(_field_kind: impl fmt::Debug) -> Self {
1101 Self::persisted_row_decode_corruption()
1102 }
1103
1104 pub(crate) fn reverse_index_relation_target_decode_invariant_violated(
1106 _source_path: &str,
1107 _field_name: &str,
1108 _target_path: &str,
1109 ) -> Self {
1110 Self::executor_internal()
1111 }
1112
1113 pub(crate) fn bytes_covering_component_payload_empty() -> Self {
1115 Self::index_corruption()
1116 }
1117
1118 pub(crate) fn bytes_covering_bool_payload_truncated() -> Self {
1120 Self::index_corruption()
1121 }
1122
1123 pub(crate) fn bytes_covering_component_payload_invalid_length() -> Self {
1125 Self::index_corruption()
1126 }
1127
1128 pub(crate) fn bytes_covering_bool_payload_invalid_value() -> Self {
1130 Self::index_corruption()
1131 }
1132
1133 pub(crate) fn bytes_covering_text_payload_invalid_terminator() -> Self {
1135 Self::index_corruption()
1136 }
1137
1138 pub(crate) fn bytes_covering_text_payload_trailing_bytes() -> Self {
1140 Self::index_corruption()
1141 }
1142
1143 pub(crate) fn bytes_covering_text_payload_invalid_utf8() -> Self {
1145 Self::index_corruption()
1146 }
1147
1148 pub(crate) fn bytes_covering_text_payload_invalid_escape_byte() -> Self {
1150 Self::index_corruption()
1151 }
1152
1153 pub(crate) fn bytes_covering_text_payload_missing_terminator() -> Self {
1155 Self::index_corruption()
1156 }
1157
1158 #[must_use]
1160 pub fn missing_persisted_slot(field_name: &'static str) -> Self {
1161 Self::persisted_row_field_decode_corruption(field_name)
1162 }
1163
1164 pub(crate) fn identity_corruption() -> Self {
1166 Self::new(ErrorClass::Corruption, ErrorOrigin::Identity)
1167 }
1168
1169 #[cold]
1171 #[inline(never)]
1172 pub(crate) fn store_unsupported() -> Self {
1173 Self::new(ErrorClass::Unsupported, ErrorOrigin::Store)
1174 }
1175
1176 #[cfg(any(test, feature = "sql"))]
1178 pub(crate) fn schema_ddl_publication_race_lost(_entity_path: &'static str) -> Self {
1179 Self {
1180 class: ErrorClass::Unsupported,
1181 origin: ErrorOrigin::Store,
1182 detail: Some(ErrorDetail::Store(StoreError::SchemaDdlPublicationRaceLost)),
1183 }
1184 }
1185
1186 #[cfg(feature = "sql")]
1188 pub(crate) fn schema_ddl_set_not_null_validation_failed(
1189 _entity_path: &'static str,
1190 _column_name: &str,
1191 ) -> Self {
1192 Self {
1193 class: ErrorClass::Unsupported,
1194 origin: ErrorOrigin::Store,
1195 detail: Some(ErrorDetail::Store(
1196 StoreError::SchemaDdlSetNotNullValidationFailed,
1197 )),
1198 }
1199 }
1200
1201 pub(crate) fn unsupported_entity_tag_in_data_store(
1203 _entity_tag: crate::types::EntityTag,
1204 ) -> Self {
1205 Self::store_unsupported()
1206 }
1207
1208 #[cfg(not(test))]
1210 pub(crate) fn commit_memory_id_registration_failed(_err: impl Sized) -> Self {
1211 Self::store_internal()
1212 }
1213
1214 pub(crate) fn index_unsupported() -> Self {
1216 Self::new(ErrorClass::Unsupported, ErrorOrigin::Index)
1217 }
1218
1219 pub(crate) fn index_component_exceeds_max_size() -> Self {
1221 Self::index_unsupported()
1222 }
1223
1224 pub(crate) fn serialize_unsupported() -> Self {
1226 Self::new(ErrorClass::Unsupported, ErrorOrigin::Serialize)
1227 }
1228
1229 pub(crate) fn cursor_invalid_continuation() -> Self {
1231 Self::new(ErrorClass::Unsupported, ErrorOrigin::Cursor)
1232 }
1233
1234 pub(crate) fn serialize_incompatible_persisted_format() -> Self {
1236 Self::new(
1237 ErrorClass::IncompatiblePersistedFormat,
1238 ErrorOrigin::Serialize,
1239 )
1240 }
1241
1242 #[cfg(feature = "sql")]
1245 pub(crate) fn query_unsupported_sql_feature(feature: diagnostic_code::SqlFeatureCode) -> Self {
1246 Self {
1247 class: ErrorClass::Unsupported,
1248 origin: ErrorOrigin::Query,
1249 detail: Some(ErrorDetail::Query(
1250 QueryErrorDetail::UnsupportedSqlFeature { feature },
1251 )),
1252 }
1253 }
1254
1255 #[cfg(feature = "sql")]
1258 pub(crate) fn query_sql_lowering(reason: diagnostic_code::SqlLoweringCode) -> Self {
1259 Self {
1260 class: ErrorClass::Unsupported,
1261 origin: ErrorOrigin::Query,
1262 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlLowering { reason })),
1263 }
1264 }
1265
1266 pub(crate) fn query_unsupported_projection(
1269 reason: diagnostic_code::QueryProjectionCode,
1270 ) -> Self {
1271 Self {
1272 class: ErrorClass::Unsupported,
1273 origin: ErrorOrigin::Query,
1274 detail: Some(ErrorDetail::Query(
1275 QueryErrorDetail::UnsupportedProjection { reason },
1276 )),
1277 }
1278 }
1279
1280 pub(crate) fn query_unknown_aggregate_target_field() -> Self {
1282 Self {
1283 class: ErrorClass::Unsupported,
1284 origin: ErrorOrigin::Query,
1285 detail: Some(ErrorDetail::Query(
1286 QueryErrorDetail::UnknownAggregateTargetField,
1287 )),
1288 }
1289 }
1290
1291 pub(crate) fn query_result_shape_mismatch(
1294 reason: diagnostic_code::QueryResultShapeCode,
1295 ) -> Self {
1296 Self {
1297 class: ErrorClass::Unsupported,
1298 origin: ErrorOrigin::Query,
1299 detail: Some(ErrorDetail::Query(QueryErrorDetail::ResultShapeMismatch {
1300 reason,
1301 })),
1302 }
1303 }
1304
1305 #[cfg(feature = "sql")]
1308 pub(crate) fn query_sql_surface_mismatch(
1309 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1310 ) -> Self {
1311 Self {
1312 class: ErrorClass::Unsupported,
1313 origin: ErrorOrigin::Query,
1314 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlSurfaceMismatch {
1315 mismatch,
1316 })),
1317 }
1318 }
1319
1320 #[cfg(feature = "sql")]
1322 pub(crate) fn query_sql_write_boundary(
1323 boundary: diagnostic_code::SqlWriteBoundaryCode,
1324 ) -> Self {
1325 Self {
1326 class: ErrorClass::Unsupported,
1327 origin: ErrorOrigin::Query,
1328 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlWriteBoundary {
1329 boundary,
1330 })),
1331 }
1332 }
1333
1334 pub fn store_not_found(_key: impl Sized) -> Self {
1335 Self {
1336 class: ErrorClass::NotFound,
1337 origin: ErrorOrigin::Store,
1338 detail: Some(ErrorDetail::Store(StoreError::NotFound)),
1339 }
1340 }
1341
1342 pub fn unsupported_entity_path(_path: impl Sized) -> Self {
1344 Self::store_unsupported()
1345 }
1346
1347 #[must_use]
1348 pub const fn is_not_found(&self) -> bool {
1349 matches!(self.detail, Some(ErrorDetail::Store(StoreError::NotFound)))
1350 }
1351
1352 #[cold]
1354 #[inline(never)]
1355 pub(crate) fn index_plan_corruption(origin: ErrorOrigin) -> Self {
1356 Self::new(ErrorClass::Corruption, origin)
1357 }
1358
1359 #[cold]
1361 #[inline(never)]
1362 pub(crate) fn index_plan_index_corruption() -> Self {
1363 Self::index_plan_corruption(ErrorOrigin::Index)
1364 }
1365
1366 #[cold]
1368 #[inline(never)]
1369 pub(crate) fn index_plan_store_corruption() -> Self {
1370 Self::index_plan_corruption(ErrorOrigin::Store)
1371 }
1372
1373 #[cold]
1375 #[inline(never)]
1376 pub(crate) fn index_plan_serialize_corruption() -> Self {
1377 Self::index_plan_corruption(ErrorOrigin::Serialize)
1378 }
1379
1380 #[cfg(test)]
1382 pub(crate) fn index_plan_invariant(origin: ErrorOrigin) -> Self {
1383 Self::new(ErrorClass::InvariantViolation, origin)
1384 }
1385
1386 #[cfg(test)]
1388 pub(crate) fn index_plan_store_invariant() -> Self {
1389 Self::index_plan_invariant(ErrorOrigin::Store)
1390 }
1391
1392 pub(crate) fn index_violation(_path: &str, _index_fields: &[&str]) -> Self {
1394 Self::new(ErrorClass::Conflict, ErrorOrigin::Index)
1395 }
1396}
1397
1398impl From<diagnostic_code::QueryReadAdmissionCode> for InternalError {
1399 fn from(reason: diagnostic_code::QueryReadAdmissionCode) -> Self {
1400 Self {
1401 class: ErrorClass::Unsupported,
1402 origin: ErrorOrigin::Query,
1403 detail: Some(ErrorDetail::Query(QueryErrorDetail::QueryReadAdmission {
1404 reason,
1405 })),
1406 }
1407 }
1408}
1409
1410impl fmt::Debug for InternalError {
1411 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1412 fmt_compact_diagnostic(
1413 f,
1414 self.diagnostic_code(),
1415 self.detail
1416 .as_ref()
1417 .and_then(ErrorDetail::diagnostic_detail),
1418 )
1419 }
1420}
1421
1422impl fmt::Display for InternalError {
1423 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1424 f.write_str(self.message())
1425 }
1426}
1427
1428impl std::error::Error for InternalError {}
1429
1430pub enum ErrorDetail {
1438 Store(StoreError),
1439 Query(QueryErrorDetail),
1440 Recovery(RecoveryErrorDetail),
1441 }
1446
1447pub enum RecoveryErrorDetail {
1454 UnsupportedFormatVersion { found: Option<u16>, required: u16 },
1455
1456 MalformedFormatMarker { reason: RecoveryFormatMarkerError },
1457}
1458
1459#[derive(Clone, Copy, Eq, PartialEq)]
1461pub enum RecoveryFormatMarkerError {
1462 Magic,
1463 Checksum,
1464 State,
1465}
1466
1467pub enum StoreError {
1475 NotFound,
1476
1477 Corrupt,
1478
1479 InvariantViolation,
1480
1481 SchemaDdlPublicationRaceLost,
1482
1483 SchemaDdlSetNotNullValidationFailed,
1484}
1485
1486pub enum QueryErrorDetail {
1493 NumericOverflow,
1494
1495 NumericNotRepresentable,
1496
1497 UnsupportedSqlFeature {
1498 feature: diagnostic_code::SqlFeatureCode,
1499 },
1500
1501 SqlLowering {
1502 reason: diagnostic_code::SqlLoweringCode,
1503 },
1504
1505 UnsupportedProjection {
1506 reason: diagnostic_code::QueryProjectionCode,
1507 },
1508
1509 UnknownAggregateTargetField,
1510
1511 ResultShapeMismatch {
1512 reason: diagnostic_code::QueryResultShapeCode,
1513 },
1514
1515 QueryReadAdmission {
1516 reason: diagnostic_code::QueryReadAdmissionCode,
1517 },
1518
1519 SqlSurfaceMismatch {
1520 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1521 },
1522
1523 SqlWriteBoundary {
1524 boundary: diagnostic_code::SqlWriteBoundaryCode,
1525 },
1526
1527 SchemaDdlAdmission {
1528 error: SchemaDdlAdmissionError,
1529 },
1530
1531 StaleSchemaRevision,
1532}
1533
1534impl fmt::Display for QueryErrorDetail {
1535 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1536 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
1537 }
1538}
1539
1540impl std::error::Error for QueryErrorDetail {}
1541
1542#[derive(Clone, Copy, Eq, PartialEq)]
1551pub enum SchemaDdlAdmissionError {
1552 MissingExpectedSchemaVersion,
1553
1554 MissingNextSchemaVersion,
1555
1556 StaleExpectedSchemaVersion,
1557
1558 InvalidExpectedSchemaVersion,
1559
1560 InvalidNextSchemaVersion,
1561
1562 AcceptedSchemaChangeWithoutVersionBump,
1563
1564 EmptyVersionBump,
1565
1566 VersionGap,
1567
1568 VersionRollback,
1569
1570 FingerprintMethodMismatch,
1571
1572 UnsupportedTransitionClass,
1573
1574 PhysicalRunnerMissing,
1575
1576 ValidationFailed,
1577
1578 PublicationRaceLost,
1579
1580 InvalidAddColumnDefault,
1581
1582 InvalidAlterColumnDefault,
1583
1584 GeneratedIndexDropRejected,
1585
1586 RequiredDropDefaultUnsupported,
1587
1588 GeneratedFieldDefaultChangeRejected,
1589
1590 GeneratedFieldNullabilityChangeRejected,
1591
1592 SetNotNullValidationFailed,
1593}
1594
1595impl fmt::Display for SchemaDdlAdmissionError {
1596 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1597 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
1598 }
1599}
1600
1601impl std::error::Error for SchemaDdlAdmissionError {}
1602
1603impl fmt::Debug for ErrorDetail {
1604 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1605 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1606 }
1607}
1608
1609impl fmt::Debug for StoreError {
1610 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1611 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1612 }
1613}
1614
1615impl fmt::Debug for QueryErrorDetail {
1616 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1617 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1618 }
1619}
1620
1621impl fmt::Debug for RecoveryErrorDetail {
1622 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1623 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1624 }
1625}
1626
1627impl fmt::Debug for RecoveryFormatMarkerError {
1628 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1629 fmt_compact_diagnostic(
1630 f,
1631 diagnostic_code::DiagnosticCode::RuntimeCorruption,
1632 Some(diagnostic_code::DiagnosticDetail::RuntimeKind {
1633 kind: diagnostic_code::RuntimeErrorKind::Corruption,
1634 }),
1635 )
1636 }
1637}
1638
1639impl fmt::Debug for SchemaDdlAdmissionError {
1640 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1641 fmt_compact_diagnostic(
1642 f,
1643 diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
1644 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1645 reason: self.diagnostic_code(),
1646 }),
1647 )
1648 }
1649}
1650
1651fn fmt_compact_diagnostic(
1652 f: &mut fmt::Formatter<'_>,
1653 code: diagnostic_code::DiagnosticCode,
1654 detail: Option<diagnostic_code::DiagnosticDetail>,
1655) -> fmt::Result {
1656 write!(
1657 f,
1658 "{}",
1659 diagnostic_code::ErrorCode::from_parts(code, detail).raw()
1660 )
1661}
1662
1663impl ErrorDetail {
1664 #[must_use]
1666 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1667 match self {
1668 Self::Store(error) => error.diagnostic_code(),
1669 Self::Query(error) => error.diagnostic_code(),
1670 Self::Recovery(error) => error.diagnostic_code(),
1671 }
1672 }
1673
1674 #[must_use]
1676 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1677 match self {
1678 Self::Store(error) => error.diagnostic_detail(),
1679 Self::Query(error) => error.diagnostic_detail(),
1680 Self::Recovery(error) => error.diagnostic_detail(),
1681 }
1682 }
1683}
1684
1685impl RecoveryErrorDetail {
1686 #[must_use]
1688 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1689 match self {
1690 Self::UnsupportedFormatVersion { .. } => {
1691 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
1692 }
1693 Self::MalformedFormatMarker { .. } => {
1694 diagnostic_code::DiagnosticCode::RuntimeCorruption
1695 }
1696 }
1697 }
1698
1699 #[must_use]
1701 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1702 let kind = match self {
1703 Self::UnsupportedFormatVersion { .. } => {
1704 diagnostic_code::RuntimeErrorKind::IncompatiblePersistedFormat
1705 }
1706 Self::MalformedFormatMarker { .. } => diagnostic_code::RuntimeErrorKind::Corruption,
1707 };
1708
1709 Some(diagnostic_code::DiagnosticDetail::RuntimeKind { kind })
1710 }
1711}
1712
1713impl StoreError {
1714 #[must_use]
1716 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1717 match self {
1718 Self::NotFound => diagnostic_code::DiagnosticCode::StoreNotFound,
1719 Self::Corrupt => diagnostic_code::DiagnosticCode::StoreCorruption,
1720 Self::InvariantViolation => diagnostic_code::DiagnosticCode::StoreInvariantViolation,
1721 Self::SchemaDdlPublicationRaceLost | Self::SchemaDdlSetNotNullValidationFailed => {
1722 diagnostic_code::DiagnosticCode::SchemaDdlAdmission
1723 }
1724 }
1725 }
1726
1727 #[must_use]
1729 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1730 match self {
1731 Self::SchemaDdlPublicationRaceLost => {
1732 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1733 reason: diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost,
1734 })
1735 }
1736 Self::SchemaDdlSetNotNullValidationFailed => {
1737 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1738 reason: diagnostic_code::SchemaDdlAdmissionCode::SetNotNullValidationFailed,
1739 })
1740 }
1741 Self::NotFound | Self::Corrupt | Self::InvariantViolation => None,
1742 }
1743 }
1744}
1745
1746impl QueryErrorDetail {
1747 #[must_use]
1749 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1750 match self {
1751 Self::NumericOverflow => diagnostic_code::DiagnosticCode::QueryNumericOverflow,
1752 Self::NumericNotRepresentable => {
1753 diagnostic_code::DiagnosticCode::QueryNumericNotRepresentable
1754 }
1755 Self::UnsupportedSqlFeature { .. } => {
1756 diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature
1757 }
1758 Self::SqlLowering { .. } => diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature,
1759 Self::UnsupportedProjection { .. } => {
1760 diagnostic_code::DiagnosticCode::QueryUnsupportedProjection
1761 }
1762 Self::UnknownAggregateTargetField => {
1763 diagnostic_code::DiagnosticCode::QueryUnknownAggregateTargetField
1764 }
1765 Self::ResultShapeMismatch { .. } => {
1766 diagnostic_code::DiagnosticCode::QueryResultShapeMismatch
1767 }
1768 Self::QueryReadAdmission { .. } => diagnostic_code::DiagnosticCode::QueryReadAdmission,
1769 Self::SqlSurfaceMismatch { .. } => {
1770 diagnostic_code::DiagnosticCode::QuerySqlSurfaceMismatch
1771 }
1772 Self::SqlWriteBoundary { .. } => diagnostic_code::DiagnosticCode::QuerySqlWriteBoundary,
1773 Self::SchemaDdlAdmission { .. } => diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
1774 Self::StaleSchemaRevision => diagnostic_code::DiagnosticCode::RuntimeConflict,
1775 }
1776 }
1777
1778 #[must_use]
1780 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1781 match self {
1782 Self::UnsupportedSqlFeature { feature } => {
1783 Some(diagnostic_code::DiagnosticDetail::UnsupportedSqlFeature { feature: *feature })
1784 }
1785 Self::SqlLowering { reason } => {
1786 Some(diagnostic_code::DiagnosticDetail::SqlLowering { reason: *reason })
1787 }
1788 Self::UnsupportedProjection { reason } => {
1789 Some(diagnostic_code::DiagnosticDetail::QueryProjection { reason: *reason })
1790 }
1791 Self::ResultShapeMismatch { reason } => {
1792 Some(diagnostic_code::DiagnosticDetail::QueryResultShape { reason: *reason })
1793 }
1794 Self::QueryReadAdmission { reason } => {
1795 Some(diagnostic_code::DiagnosticDetail::QueryReadAdmission { reason: *reason })
1796 }
1797 Self::SqlSurfaceMismatch { mismatch } => {
1798 Some(diagnostic_code::DiagnosticDetail::SqlSurfaceMismatch {
1799 mismatch: *mismatch,
1800 })
1801 }
1802 Self::SqlWriteBoundary { boundary } => {
1803 Some(diagnostic_code::DiagnosticDetail::SqlWriteBoundary {
1804 boundary: *boundary,
1805 })
1806 }
1807 Self::SchemaDdlAdmission { error } => {
1808 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1809 reason: error.diagnostic_code(),
1810 })
1811 }
1812 Self::NumericOverflow
1813 | Self::NumericNotRepresentable
1814 | Self::UnknownAggregateTargetField
1815 | Self::StaleSchemaRevision => None,
1816 }
1817 }
1818}
1819
1820impl SchemaDdlAdmissionError {
1821 #[must_use]
1823 pub const fn diagnostic_code(&self) -> diagnostic_code::SchemaDdlAdmissionCode {
1824 match self {
1825 Self::MissingExpectedSchemaVersion => {
1826 diagnostic_code::SchemaDdlAdmissionCode::MissingExpectedSchemaVersion
1827 }
1828 Self::MissingNextSchemaVersion => {
1829 diagnostic_code::SchemaDdlAdmissionCode::MissingNextSchemaVersion
1830 }
1831 Self::StaleExpectedSchemaVersion => {
1832 diagnostic_code::SchemaDdlAdmissionCode::StaleExpectedSchemaVersion
1833 }
1834 Self::InvalidExpectedSchemaVersion => {
1835 diagnostic_code::SchemaDdlAdmissionCode::InvalidExpectedSchemaVersion
1836 }
1837 Self::InvalidNextSchemaVersion => {
1838 diagnostic_code::SchemaDdlAdmissionCode::InvalidNextSchemaVersion
1839 }
1840 Self::AcceptedSchemaChangeWithoutVersionBump => {
1841 diagnostic_code::SchemaDdlAdmissionCode::AcceptedSchemaChangeWithoutVersionBump
1842 }
1843 Self::EmptyVersionBump => diagnostic_code::SchemaDdlAdmissionCode::EmptyVersionBump,
1844 Self::VersionGap => diagnostic_code::SchemaDdlAdmissionCode::VersionGap,
1845 Self::VersionRollback => diagnostic_code::SchemaDdlAdmissionCode::VersionRollback,
1846 Self::FingerprintMethodMismatch => {
1847 diagnostic_code::SchemaDdlAdmissionCode::FingerprintMethodMismatch
1848 }
1849 Self::UnsupportedTransitionClass => {
1850 diagnostic_code::SchemaDdlAdmissionCode::UnsupportedTransitionClass
1851 }
1852 Self::PhysicalRunnerMissing => {
1853 diagnostic_code::SchemaDdlAdmissionCode::PhysicalRunnerMissing
1854 }
1855 Self::ValidationFailed => diagnostic_code::SchemaDdlAdmissionCode::ValidationFailed,
1856 Self::PublicationRaceLost => {
1857 diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost
1858 }
1859 Self::InvalidAddColumnDefault => {
1860 diagnostic_code::SchemaDdlAdmissionCode::InvalidAddColumnDefault
1861 }
1862 Self::InvalidAlterColumnDefault => {
1863 diagnostic_code::SchemaDdlAdmissionCode::InvalidAlterColumnDefault
1864 }
1865 Self::GeneratedIndexDropRejected => {
1866 diagnostic_code::SchemaDdlAdmissionCode::GeneratedIndexDropRejected
1867 }
1868 Self::RequiredDropDefaultUnsupported => {
1869 diagnostic_code::SchemaDdlAdmissionCode::RequiredDropDefaultUnsupported
1870 }
1871 Self::GeneratedFieldDefaultChangeRejected => {
1872 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldDefaultChangeRejected
1873 }
1874 Self::GeneratedFieldNullabilityChangeRejected => {
1875 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldNullabilityChangeRejected
1876 }
1877 Self::SetNotNullValidationFailed => {
1878 diagnostic_code::SchemaDdlAdmissionCode::SetNotNullValidationFailed
1879 }
1880 }
1881 }
1882}
1883
1884#[repr(u16)]
1891#[derive(Clone, Copy, Eq, PartialEq)]
1892pub enum ErrorClass {
1893 Corruption,
1894 IncompatiblePersistedFormat,
1895 NotFound,
1896 Internal,
1897 Conflict,
1898 Unsupported,
1899 InvariantViolation,
1900}
1901
1902impl ErrorClass {
1903 #[must_use]
1905 pub const fn diagnostic_code(self, origin: ErrorOrigin) -> diagnostic_code::DiagnosticCode {
1906 match self {
1907 Self::Corruption if matches!(origin, ErrorOrigin::Store) => {
1908 diagnostic_code::DiagnosticCode::StoreCorruption
1909 }
1910 Self::Corruption => diagnostic_code::DiagnosticCode::RuntimeCorruption,
1911 Self::IncompatiblePersistedFormat => {
1912 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
1913 }
1914 Self::NotFound if matches!(origin, ErrorOrigin::Store) => {
1915 diagnostic_code::DiagnosticCode::StoreNotFound
1916 }
1917 Self::NotFound => diagnostic_code::DiagnosticCode::RuntimeNotFound,
1918 Self::Internal => diagnostic_code::DiagnosticCode::RuntimeInternal,
1919 Self::Conflict => diagnostic_code::DiagnosticCode::RuntimeConflict,
1920 Self::Unsupported if matches!(origin, ErrorOrigin::Cursor) => {
1921 diagnostic_code::DiagnosticCode::QueryInvalidContinuationCursor
1922 }
1923 Self::Unsupported => diagnostic_code::DiagnosticCode::RuntimeUnsupported,
1924 Self::InvariantViolation if matches!(origin, ErrorOrigin::Store) => {
1925 diagnostic_code::DiagnosticCode::StoreInvariantViolation
1926 }
1927 Self::InvariantViolation => diagnostic_code::DiagnosticCode::RuntimeInvariantViolation,
1928 }
1929 }
1930}
1931
1932impl fmt::Debug for ErrorClass {
1933 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1934 write!(f, "{}", *self as u16)
1935 }
1936}
1937
1938#[repr(u16)]
1945#[derive(Clone, Copy, Eq, PartialEq)]
1946pub enum ErrorOrigin {
1947 Serialize,
1948 Store,
1949 Index,
1950 Identity,
1951 Query,
1952 Planner,
1953 Cursor,
1954 Recovery,
1955 Response,
1956 Executor,
1957 Interface,
1958}
1959
1960impl ErrorOrigin {
1961 #[must_use]
1963 pub const fn diagnostic_origin(self) -> diagnostic_code::ErrorOrigin {
1964 match self {
1965 Self::Serialize => diagnostic_code::ErrorOrigin::Serialize,
1966 Self::Store => diagnostic_code::ErrorOrigin::Store,
1967 Self::Index => diagnostic_code::ErrorOrigin::Index,
1968 Self::Identity => diagnostic_code::ErrorOrigin::Identity,
1969 Self::Query => diagnostic_code::ErrorOrigin::Query,
1970 Self::Planner => diagnostic_code::ErrorOrigin::Planner,
1971 Self::Cursor => diagnostic_code::ErrorOrigin::Cursor,
1972 Self::Recovery => diagnostic_code::ErrorOrigin::Recovery,
1973 Self::Response => diagnostic_code::ErrorOrigin::Response,
1974 Self::Executor => diagnostic_code::ErrorOrigin::Executor,
1975 Self::Interface => diagnostic_code::ErrorOrigin::Interface,
1976 }
1977 }
1978}
1979
1980impl fmt::Debug for ErrorOrigin {
1981 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1982 write!(f, "{}", *self as u16)
1983 }
1984}