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_executor_load_plan_required() -> Self {
489 Self::query_executor_invariant()
490 }
491
492 pub(crate) fn delete_executor_grouped_unsupported() -> Self {
494 Self::executor_unsupported()
495 }
496
497 pub(crate) fn delete_executor_delete_plan_required() -> Self {
499 Self::query_executor_invariant()
500 }
501
502 pub(crate) fn aggregate_fold_mode_terminal_contract_required() -> Self {
504 Self::query_executor_invariant()
505 }
506
507 pub(crate) fn fast_stream_route_kind_request_match_required() -> Self {
509 Self::query_executor_invariant()
510 }
511
512 pub(crate) fn secondary_index_prefix_spec_required() -> Self {
514 Self::query_executor_invariant()
515 }
516
517 pub(crate) fn index_range_limit_spec_required() -> Self {
519 Self::query_executor_invariant()
520 }
521
522 pub(crate) fn mutation_atomic_save_duplicate_key(_entity_path: &str, _key: impl Sized) -> Self {
524 Self::executor_conflict()
525 }
526
527 pub(crate) fn mutation_index_store_generation_changed(
529 _expected_generation: u64,
530 _observed_generation: u64,
531 ) -> Self {
532 Self::executor_invariant()
533 }
534
535 #[cold]
537 #[inline(never)]
538 pub(crate) fn planner_invariant() -> Self {
539 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Planner)
540 }
541
542 pub(crate) fn query_invalid_logical_plan() -> Self {
544 Self::planner_invariant()
545 }
546
547 pub(crate) fn store_invariant() -> Self {
549 Self::new(ErrorClass::InvariantViolation, ErrorOrigin::Store)
550 }
551
552 pub(crate) fn duplicate_runtime_hooks_for_entity_tag(
554 _entity_tag: crate::types::EntityTag,
555 ) -> Self {
556 Self::store_invariant()
557 }
558
559 pub(crate) fn duplicate_runtime_hooks_for_entity_path(_entity_path: &str) -> Self {
561 Self::store_invariant()
562 }
563
564 #[cold]
566 #[inline(never)]
567 pub(crate) fn store_internal() -> Self {
568 Self::new(ErrorClass::Internal, ErrorOrigin::Store)
569 }
570
571 pub(crate) fn commit_memory_id_unconfigured() -> Self {
573 Self::store_internal()
574 }
575
576 pub(crate) fn commit_memory_id_mismatch(_cached_id: u8, _configured_id: u8) -> Self {
578 Self::store_internal()
579 }
580
581 pub(crate) fn commit_memory_stable_key_mismatch(
583 _cached_key: &str,
584 _configured_key: &str,
585 ) -> Self {
586 Self::store_internal()
587 }
588
589 pub(crate) fn recovery_unsupported_database_format(found: Option<u16>, required: u16) -> Self {
591 Self {
592 class: ErrorClass::IncompatiblePersistedFormat,
593 origin: ErrorOrigin::Recovery,
594 detail: Some(ErrorDetail::Recovery(
595 RecoveryErrorDetail::UnsupportedFormatVersion { found, required },
596 )),
597 }
598 }
599
600 pub(crate) fn recovery_malformed_database_format_marker(
602 reason: RecoveryFormatMarkerError,
603 ) -> Self {
604 Self {
605 class: ErrorClass::Corruption,
606 origin: ErrorOrigin::Recovery,
607 detail: Some(ErrorDetail::Recovery(
608 RecoveryErrorDetail::MalformedFormatMarker { reason },
609 )),
610 }
611 }
612
613 pub(crate) fn recovery_database_format_control_unavailable() -> Self {
615 Self::new(ErrorClass::Internal, ErrorOrigin::Recovery)
616 }
617
618 pub(crate) fn commit_control_memory_growth_failed() -> Self {
620 Self::store_internal()
621 }
622
623 #[cfg(not(test))]
625 pub(crate) fn database_format_memory_registration_failed(_err: impl Sized) -> Self {
626 Self::store_internal()
627 }
628
629 pub(crate) fn delete_rollback_row_required() -> Self {
631 Self::store_internal()
632 }
633
634 pub(crate) fn recovery_integrity_validation_failed(
636 _missing_index_entries: u64,
637 _divergent_index_entries: u64,
638 _orphan_index_references: u64,
639 ) -> Self {
640 Self::store_corruption()
641 }
642
643 #[cold]
645 #[inline(never)]
646 pub(crate) fn index_internal() -> Self {
647 Self::new(ErrorClass::Internal, ErrorOrigin::Index)
648 }
649
650 pub(crate) fn structural_index_removal_entity_key_required() -> Self {
652 Self::index_internal()
653 }
654
655 pub(crate) fn structural_index_insertion_entity_key_required() -> Self {
657 Self::index_internal()
658 }
659
660 pub(crate) fn index_commit_op_old_entity_key_required() -> Self {
662 Self::index_internal()
663 }
664
665 pub(crate) fn index_commit_op_new_entity_key_required() -> Self {
667 Self::index_internal()
668 }
669
670 #[cfg(test)]
672 pub(crate) fn query_internal() -> Self {
673 Self::new(ErrorClass::Internal, ErrorOrigin::Query)
674 }
675
676 #[cold]
678 #[inline(never)]
679 pub(crate) fn query_unsupported() -> Self {
680 Self::new(ErrorClass::Unsupported, ErrorOrigin::Query)
681 }
682
683 #[cold]
686 #[inline(never)]
687 pub(crate) fn query_stale_accepted_schema_revision(
688 _expected_revision: u64,
689 _current_revision: Option<u64>,
690 ) -> Self {
691 Self {
692 class: ErrorClass::Conflict,
693 origin: ErrorOrigin::Query,
694 detail: Some(ErrorDetail::Query(QueryErrorDetail::StaleSchemaRevision)),
695 }
696 }
697
698 #[cold]
700 #[inline(never)]
701 #[cfg(feature = "sql")]
702 pub(crate) fn query_schema_ddl_admission(error: SchemaDdlAdmissionError) -> Self {
703 Self {
704 class: ErrorClass::Unsupported,
705 origin: ErrorOrigin::Query,
706 detail: Some(ErrorDetail::Query(QueryErrorDetail::SchemaDdlAdmission {
707 error,
708 })),
709 }
710 }
711
712 #[cold]
714 #[inline(never)]
715 pub(crate) fn query_numeric_overflow() -> Self {
716 Self {
717 class: ErrorClass::Unsupported,
718 origin: ErrorOrigin::Query,
719 detail: Some(ErrorDetail::Query(QueryErrorDetail::NumericOverflow)),
720 }
721 }
722
723 #[cold]
726 #[inline(never)]
727 pub(crate) fn query_numeric_not_representable() -> Self {
728 Self {
729 class: ErrorClass::Unsupported,
730 origin: ErrorOrigin::Query,
731 detail: Some(ErrorDetail::Query(
732 QueryErrorDetail::NumericNotRepresentable,
733 )),
734 }
735 }
736
737 #[cold]
739 #[inline(never)]
740 pub(crate) fn serialize_internal() -> Self {
741 Self::new(ErrorClass::Internal, ErrorOrigin::Serialize)
742 }
743
744 pub(crate) fn persisted_row_encode_failed(_detail: impl Sized) -> Self {
746 Self::persisted_row_encode_internal()
747 }
748
749 pub(crate) fn persisted_row_encode_internal() -> Self {
751 Self::serialize_internal()
752 }
753
754 pub(crate) fn persisted_row_field_encode_failed(field_name: &str, _detail: impl Sized) -> Self {
756 Self::persisted_row_field_encode_internal(field_name)
757 }
758
759 pub(crate) fn persisted_row_field_encode_internal(_field_name: &str) -> Self {
761 Self::persisted_row_encode_internal()
762 }
763
764 pub(crate) fn bytes_field_value_encode_failed(_detail: impl Sized) -> Self {
766 Self::serialize_internal()
767 }
768
769 #[cold]
771 #[inline(never)]
772 pub(crate) fn store_corruption() -> Self {
773 Self::new(ErrorClass::Corruption, ErrorOrigin::Store)
774 }
775
776 pub(crate) fn commit_corruption() -> Self {
778 Self::store_corruption()
779 }
780
781 pub(crate) fn commit_component_corruption() -> Self {
783 Self::commit_corruption()
784 }
785
786 pub(crate) fn commit_id_generation_failed() -> Self {
788 Self::store_internal()
789 }
790
791 pub(crate) fn commit_marker_payload_exceeds_u32_length_limit() -> Self {
793 Self::store_unsupported()
794 }
795
796 pub(crate) fn commit_component_length_invalid() -> Self {
798 Self::commit_corruption()
799 }
800
801 pub(crate) fn commit_marker_exceeds_max_size() -> Self {
803 Self::commit_corruption()
804 }
805
806 pub(crate) fn commit_control_slot_exceeds_max_size() -> Self {
808 Self::store_unsupported()
809 }
810
811 pub(crate) fn commit_control_slot_marker_bytes_exceed_u32_length_limit() -> Self {
813 Self::store_unsupported()
814 }
815
816 pub(crate) fn startup_index_rebuild_invalid_data_key() -> Self {
818 Self::store_corruption()
819 }
820
821 #[cold]
823 #[inline(never)]
824 pub(crate) fn index_corruption() -> Self {
825 Self::new(ErrorClass::Corruption, ErrorOrigin::Index)
826 }
827
828 pub(crate) fn index_unique_validation_corruption() -> Self {
830 Self::index_plan_index_corruption()
831 }
832
833 pub(crate) fn structural_index_entry_corruption() -> Self {
835 Self::index_plan_index_corruption()
836 }
837
838 pub(crate) fn index_unique_validation_entity_key_required() -> Self {
840 Self::index_invariant()
841 }
842
843 pub(crate) fn index_unique_validation_row_deserialize_failed() -> Self {
845 Self::index_plan_serialize_corruption()
846 }
847
848 pub(crate) fn index_unique_validation_primary_key_decode_failed() -> Self {
850 Self::index_plan_serialize_corruption()
851 }
852
853 pub(crate) fn index_unique_validation_key_rebuild_failed() -> Self {
855 Self::index_plan_serialize_corruption()
856 }
857
858 pub(crate) fn index_unique_validation_row_required() -> Self {
860 Self::index_plan_store_corruption()
861 }
862
863 pub(crate) fn index_only_predicate_component_required() -> Self {
865 Self::index_invariant()
866 }
867
868 pub(crate) fn index_scan_continuation_anchor_within_envelope_required() -> Self {
870 Self::index_invariant()
871 }
872
873 pub(crate) fn index_scan_continuation_advancement_required() -> Self {
875 Self::index_invariant()
876 }
877
878 pub(crate) fn index_scan_key_corrupted_during(
880 _context: &'static str,
881 _err: impl Sized,
882 ) -> Self {
883 Self::index_corruption()
884 }
885
886 pub(crate) fn index_projection_component_required(
888 _index_name: &str,
889 _component_index: usize,
890 ) -> Self {
891 Self::index_invariant()
892 }
893
894 pub(crate) fn index_entry_decode_failed() -> Self {
896 Self::index_corruption()
897 }
898
899 pub(crate) fn serialize_corruption() -> Self {
901 Self::new(ErrorClass::Corruption, ErrorOrigin::Serialize)
902 }
903
904 pub(crate) fn persisted_row_decode_failed(_detail: impl Sized) -> Self {
906 Self::persisted_row_decode_corruption()
907 }
908
909 pub(crate) fn persisted_row_decode_corruption() -> Self {
911 Self::serialize_corruption()
912 }
913
914 pub(crate) fn persisted_row_field_decode_failed(field_name: &str, _detail: impl Sized) -> Self {
916 Self::persisted_row_field_decode_corruption(field_name)
917 }
918
919 pub(crate) fn persisted_row_field_decode_corruption(_field_name: &str) -> Self {
921 Self::persisted_row_decode_corruption()
922 }
923
924 pub(crate) fn persisted_row_field_kind_decode_failed(
926 field_name: &str,
927 _field_kind: impl fmt::Debug,
928 _detail: impl Sized,
929 ) -> Self {
930 Self::persisted_row_field_decode_corruption(field_name)
931 }
932
933 pub(crate) fn persisted_row_field_payload_exact_len_required(field_name: &str) -> Self {
935 Self::persisted_row_field_decode_corruption(field_name)
936 }
937
938 pub(crate) fn persisted_row_field_payload_must_be_empty(field_name: &str) -> Self {
940 Self::persisted_row_field_decode_corruption(field_name)
941 }
942
943 pub(crate) fn persisted_row_field_payload_invalid_byte(field_name: &str) -> Self {
945 Self::persisted_row_field_decode_corruption(field_name)
946 }
947
948 pub(crate) fn persisted_row_field_payload_non_finite(field_name: &str) -> Self {
950 Self::persisted_row_field_decode_corruption(field_name)
951 }
952
953 pub(crate) fn persisted_row_field_payload_out_of_range(field_name: &str) -> Self {
955 Self::persisted_row_field_decode_corruption(field_name)
956 }
957
958 pub(crate) fn persisted_row_field_text_payload_invalid_utf8(field_name: &str) -> Self {
960 Self::persisted_row_field_decode_corruption(field_name)
961 }
962
963 pub(crate) fn persisted_row_slot_lookup_out_of_bounds(_model_path: &str, _slot: usize) -> Self {
965 Self::index_invariant()
966 }
967
968 pub(crate) fn persisted_row_slot_cache_lookup_out_of_bounds(
970 _model_path: &str,
971 _slot: usize,
972 ) -> Self {
973 Self::index_invariant()
974 }
975
976 pub(crate) fn persisted_row_primary_key_not_primary_key_encodable(
978 _data_key: impl fmt::Debug,
979 _detail: impl Sized,
980 ) -> Self {
981 Self::persisted_row_decode_corruption()
982 }
983
984 pub(crate) fn persisted_row_primary_key_slot_missing(_data_key: impl fmt::Debug) -> Self {
986 Self::persisted_row_decode_corruption()
987 }
988
989 pub(crate) fn persisted_row_key_mismatch() -> Self {
991 Self::store_corruption()
992 }
993
994 pub(crate) fn persisted_row_declared_field_missing(field_name: &str) -> Self {
996 Self::persisted_row_field_decode_corruption(field_name)
997 }
998
999 pub(crate) fn data_key_entity_mismatch() -> Self {
1001 Self::store_corruption()
1002 }
1003
1004 pub(crate) fn reverse_index_ordinal_overflow(
1006 _source_path: &str,
1007 _field_name: &str,
1008 _target_path: &str,
1009 _detail: impl Sized,
1010 ) -> Self {
1011 Self::index_internal()
1012 }
1013
1014 pub(crate) fn reverse_index_entry_corrupted(
1016 _source_path: &str,
1017 _field_name: &str,
1018 _target_path: &str,
1019 _index_key: impl fmt::Debug,
1020 _detail: impl Sized,
1021 ) -> Self {
1022 Self::index_corruption()
1023 }
1024
1025 pub(crate) fn relation_target_store_missing(
1027 _source_path: &str,
1028 _field_name: &str,
1029 _target_path: &str,
1030 _store_path: &str,
1031 _detail: impl Sized,
1032 ) -> Self {
1033 Self::executor_internal()
1034 }
1035
1036 pub(crate) fn relation_target_key_decode_failed(
1038 _context_label: &str,
1039 _source_path: &str,
1040 _field_name: &str,
1041 _target_path: &str,
1042 _detail: impl Sized,
1043 ) -> Self {
1044 Self::identity_corruption()
1045 }
1046
1047 pub(crate) fn relation_target_entity_mismatch(
1049 _context_label: &str,
1050 _source_path: &str,
1051 _field_name: &str,
1052 _target_path: &str,
1053 _target_entity_name: &str,
1054 _expected_tag: impl Sized,
1055 _actual_tag: impl Sized,
1056 ) -> Self {
1057 Self::store_corruption()
1058 }
1059
1060 pub(crate) fn relation_source_row_decode_failed(
1062 _source_path: &str,
1063 _field_name: &str,
1064 _target_path: &str,
1065 _detail: impl Sized,
1066 ) -> Self {
1067 Self::persisted_row_decode_corruption()
1068 }
1069
1070 pub(crate) fn relation_source_row_unsupported_scalar_relation_key(
1072 _source_path: &str,
1073 _field_name: &str,
1074 _target_path: &str,
1075 ) -> Self {
1076 Self::persisted_row_decode_corruption()
1077 }
1078
1079 pub(crate) fn relation_source_row_unsupported_key_kind(_field_kind: impl fmt::Debug) -> Self {
1081 Self::persisted_row_decode_corruption()
1082 }
1083
1084 pub(crate) fn reverse_index_relation_target_decode_invariant_violated(
1086 _source_path: &str,
1087 _field_name: &str,
1088 _target_path: &str,
1089 ) -> Self {
1090 Self::executor_internal()
1091 }
1092
1093 pub(crate) fn bytes_covering_component_payload_empty() -> Self {
1095 Self::index_corruption()
1096 }
1097
1098 pub(crate) fn bytes_covering_bool_payload_truncated() -> Self {
1100 Self::index_corruption()
1101 }
1102
1103 pub(crate) fn bytes_covering_component_payload_invalid_length() -> Self {
1105 Self::index_corruption()
1106 }
1107
1108 pub(crate) fn bytes_covering_bool_payload_invalid_value() -> Self {
1110 Self::index_corruption()
1111 }
1112
1113 pub(crate) fn bytes_covering_text_payload_invalid_terminator() -> Self {
1115 Self::index_corruption()
1116 }
1117
1118 pub(crate) fn bytes_covering_text_payload_trailing_bytes() -> Self {
1120 Self::index_corruption()
1121 }
1122
1123 pub(crate) fn bytes_covering_text_payload_invalid_utf8() -> Self {
1125 Self::index_corruption()
1126 }
1127
1128 pub(crate) fn bytes_covering_text_payload_invalid_escape_byte() -> Self {
1130 Self::index_corruption()
1131 }
1132
1133 pub(crate) fn bytes_covering_text_payload_missing_terminator() -> Self {
1135 Self::index_corruption()
1136 }
1137
1138 #[must_use]
1140 pub fn missing_persisted_slot(field_name: &'static str) -> Self {
1141 Self::persisted_row_field_decode_corruption(field_name)
1142 }
1143
1144 pub(crate) fn identity_corruption() -> Self {
1146 Self::new(ErrorClass::Corruption, ErrorOrigin::Identity)
1147 }
1148
1149 #[cold]
1151 #[inline(never)]
1152 pub(crate) fn store_unsupported() -> Self {
1153 Self::new(ErrorClass::Unsupported, ErrorOrigin::Store)
1154 }
1155
1156 #[cfg(any(test, feature = "sql"))]
1158 pub(crate) fn schema_ddl_publication_race_lost(_entity_path: &'static str) -> Self {
1159 Self {
1160 class: ErrorClass::Unsupported,
1161 origin: ErrorOrigin::Store,
1162 detail: Some(ErrorDetail::Store(StoreError::SchemaDdlPublicationRaceLost)),
1163 }
1164 }
1165
1166 #[cfg(feature = "sql")]
1168 pub(crate) fn schema_ddl_set_not_null_validation_failed(
1169 _entity_path: &'static str,
1170 _column_name: &str,
1171 ) -> Self {
1172 Self {
1173 class: ErrorClass::Unsupported,
1174 origin: ErrorOrigin::Store,
1175 detail: Some(ErrorDetail::Store(
1176 StoreError::SchemaDdlSetNotNullValidationFailed,
1177 )),
1178 }
1179 }
1180
1181 pub(crate) fn unsupported_entity_tag_in_data_store(
1183 _entity_tag: crate::types::EntityTag,
1184 ) -> Self {
1185 Self::store_unsupported()
1186 }
1187
1188 #[cfg(not(test))]
1190 pub(crate) fn commit_memory_id_registration_failed(_err: impl Sized) -> Self {
1191 Self::store_internal()
1192 }
1193
1194 pub(crate) fn index_unsupported() -> Self {
1196 Self::new(ErrorClass::Unsupported, ErrorOrigin::Index)
1197 }
1198
1199 pub(crate) fn index_component_exceeds_max_size() -> Self {
1201 Self::index_unsupported()
1202 }
1203
1204 pub(crate) fn serialize_unsupported() -> Self {
1206 Self::new(ErrorClass::Unsupported, ErrorOrigin::Serialize)
1207 }
1208
1209 pub(crate) fn cursor_invalid_continuation() -> Self {
1211 Self::new(ErrorClass::Unsupported, ErrorOrigin::Cursor)
1212 }
1213
1214 pub(crate) fn serialize_incompatible_persisted_format() -> Self {
1216 Self::new(
1217 ErrorClass::IncompatiblePersistedFormat,
1218 ErrorOrigin::Serialize,
1219 )
1220 }
1221
1222 #[cfg(feature = "sql")]
1225 pub(crate) fn query_unsupported_sql_feature(feature: diagnostic_code::SqlFeatureCode) -> Self {
1226 Self {
1227 class: ErrorClass::Unsupported,
1228 origin: ErrorOrigin::Query,
1229 detail: Some(ErrorDetail::Query(
1230 QueryErrorDetail::UnsupportedSqlFeature { feature },
1231 )),
1232 }
1233 }
1234
1235 #[cfg(feature = "sql")]
1238 pub(crate) fn query_sql_lowering(reason: diagnostic_code::SqlLoweringCode) -> Self {
1239 Self {
1240 class: ErrorClass::Unsupported,
1241 origin: ErrorOrigin::Query,
1242 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlLowering { reason })),
1243 }
1244 }
1245
1246 pub(crate) fn query_unsupported_projection(
1249 reason: diagnostic_code::QueryProjectionCode,
1250 ) -> Self {
1251 Self {
1252 class: ErrorClass::Unsupported,
1253 origin: ErrorOrigin::Query,
1254 detail: Some(ErrorDetail::Query(
1255 QueryErrorDetail::UnsupportedProjection { reason },
1256 )),
1257 }
1258 }
1259
1260 pub(crate) fn query_unknown_aggregate_target_field() -> Self {
1262 Self {
1263 class: ErrorClass::Unsupported,
1264 origin: ErrorOrigin::Query,
1265 detail: Some(ErrorDetail::Query(
1266 QueryErrorDetail::UnknownAggregateTargetField,
1267 )),
1268 }
1269 }
1270
1271 pub(crate) fn query_result_shape_mismatch(
1274 reason: diagnostic_code::QueryResultShapeCode,
1275 ) -> Self {
1276 Self {
1277 class: ErrorClass::Unsupported,
1278 origin: ErrorOrigin::Query,
1279 detail: Some(ErrorDetail::Query(QueryErrorDetail::ResultShapeMismatch {
1280 reason,
1281 })),
1282 }
1283 }
1284
1285 #[cfg(feature = "sql")]
1288 pub(crate) fn query_sql_surface_mismatch(
1289 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1290 ) -> Self {
1291 Self {
1292 class: ErrorClass::Unsupported,
1293 origin: ErrorOrigin::Query,
1294 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlSurfaceMismatch {
1295 mismatch,
1296 })),
1297 }
1298 }
1299
1300 #[cfg(feature = "sql")]
1302 pub(crate) fn query_sql_write_boundary(
1303 boundary: diagnostic_code::SqlWriteBoundaryCode,
1304 ) -> Self {
1305 Self {
1306 class: ErrorClass::Unsupported,
1307 origin: ErrorOrigin::Query,
1308 detail: Some(ErrorDetail::Query(QueryErrorDetail::SqlWriteBoundary {
1309 boundary,
1310 })),
1311 }
1312 }
1313
1314 pub fn store_not_found(_key: impl Sized) -> Self {
1315 Self {
1316 class: ErrorClass::NotFound,
1317 origin: ErrorOrigin::Store,
1318 detail: Some(ErrorDetail::Store(StoreError::NotFound)),
1319 }
1320 }
1321
1322 pub fn unsupported_entity_path(_path: impl Sized) -> Self {
1324 Self::store_unsupported()
1325 }
1326
1327 #[must_use]
1328 pub const fn is_not_found(&self) -> bool {
1329 matches!(self.detail, Some(ErrorDetail::Store(StoreError::NotFound)))
1330 }
1331
1332 #[cold]
1334 #[inline(never)]
1335 pub(crate) fn index_plan_corruption(origin: ErrorOrigin) -> Self {
1336 Self::new(ErrorClass::Corruption, origin)
1337 }
1338
1339 #[cold]
1341 #[inline(never)]
1342 pub(crate) fn index_plan_index_corruption() -> Self {
1343 Self::index_plan_corruption(ErrorOrigin::Index)
1344 }
1345
1346 #[cold]
1348 #[inline(never)]
1349 pub(crate) fn index_plan_store_corruption() -> Self {
1350 Self::index_plan_corruption(ErrorOrigin::Store)
1351 }
1352
1353 #[cold]
1355 #[inline(never)]
1356 pub(crate) fn index_plan_serialize_corruption() -> Self {
1357 Self::index_plan_corruption(ErrorOrigin::Serialize)
1358 }
1359
1360 #[cfg(test)]
1362 pub(crate) fn index_plan_invariant(origin: ErrorOrigin) -> Self {
1363 Self::new(ErrorClass::InvariantViolation, origin)
1364 }
1365
1366 #[cfg(test)]
1368 pub(crate) fn index_plan_store_invariant() -> Self {
1369 Self::index_plan_invariant(ErrorOrigin::Store)
1370 }
1371
1372 pub(crate) fn index_violation(_path: &str, _index_fields: &[&str]) -> Self {
1374 Self::new(ErrorClass::Conflict, ErrorOrigin::Index)
1375 }
1376}
1377
1378impl From<diagnostic_code::QueryReadAdmissionCode> for InternalError {
1379 fn from(reason: diagnostic_code::QueryReadAdmissionCode) -> Self {
1380 Self {
1381 class: ErrorClass::Unsupported,
1382 origin: ErrorOrigin::Query,
1383 detail: Some(ErrorDetail::Query(QueryErrorDetail::QueryReadAdmission {
1384 reason,
1385 })),
1386 }
1387 }
1388}
1389
1390impl fmt::Debug for InternalError {
1391 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1392 fmt_compact_diagnostic(
1393 f,
1394 self.diagnostic_code(),
1395 self.detail
1396 .as_ref()
1397 .and_then(ErrorDetail::diagnostic_detail),
1398 )
1399 }
1400}
1401
1402impl fmt::Display for InternalError {
1403 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1404 f.write_str(self.message())
1405 }
1406}
1407
1408impl std::error::Error for InternalError {}
1409
1410pub enum ErrorDetail {
1418 Store(StoreError),
1419 Query(QueryErrorDetail),
1420 Recovery(RecoveryErrorDetail),
1421 }
1426
1427pub enum RecoveryErrorDetail {
1434 UnsupportedFormatVersion { found: Option<u16>, required: u16 },
1435
1436 MalformedFormatMarker { reason: RecoveryFormatMarkerError },
1437}
1438
1439#[derive(Clone, Copy, Eq, PartialEq)]
1441pub enum RecoveryFormatMarkerError {
1442 Magic,
1443 Checksum,
1444 State,
1445}
1446
1447pub enum StoreError {
1455 NotFound,
1456
1457 Corrupt,
1458
1459 InvariantViolation,
1460
1461 SchemaDdlPublicationRaceLost,
1462
1463 SchemaDdlSetNotNullValidationFailed,
1464}
1465
1466pub enum QueryErrorDetail {
1473 NumericOverflow,
1474
1475 NumericNotRepresentable,
1476
1477 UnsupportedSqlFeature {
1478 feature: diagnostic_code::SqlFeatureCode,
1479 },
1480
1481 SqlLowering {
1482 reason: diagnostic_code::SqlLoweringCode,
1483 },
1484
1485 UnsupportedProjection {
1486 reason: diagnostic_code::QueryProjectionCode,
1487 },
1488
1489 UnknownAggregateTargetField,
1490
1491 ResultShapeMismatch {
1492 reason: diagnostic_code::QueryResultShapeCode,
1493 },
1494
1495 QueryReadAdmission {
1496 reason: diagnostic_code::QueryReadAdmissionCode,
1497 },
1498
1499 SqlSurfaceMismatch {
1500 mismatch: diagnostic_code::SqlSurfaceMismatchCode,
1501 },
1502
1503 SqlWriteBoundary {
1504 boundary: diagnostic_code::SqlWriteBoundaryCode,
1505 },
1506
1507 SchemaDdlAdmission {
1508 error: SchemaDdlAdmissionError,
1509 },
1510
1511 StaleSchemaRevision,
1512}
1513
1514impl fmt::Display for QueryErrorDetail {
1515 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1516 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
1517 }
1518}
1519
1520impl std::error::Error for QueryErrorDetail {}
1521
1522#[derive(Clone, Copy, Eq, PartialEq)]
1531pub enum SchemaDdlAdmissionError {
1532 MissingExpectedSchemaVersion,
1533
1534 MissingNextSchemaVersion,
1535
1536 StaleExpectedSchemaVersion,
1537
1538 InvalidExpectedSchemaVersion,
1539
1540 InvalidNextSchemaVersion,
1541
1542 AcceptedSchemaChangeWithoutVersionBump,
1543
1544 EmptyVersionBump,
1545
1546 VersionGap,
1547
1548 VersionRollback,
1549
1550 FingerprintMethodMismatch,
1551
1552 UnsupportedTransitionClass,
1553
1554 PhysicalRunnerMissing,
1555
1556 ValidationFailed,
1557
1558 PublicationRaceLost,
1559
1560 InvalidAddColumnDefault,
1561
1562 InvalidAlterColumnDefault,
1563
1564 GeneratedIndexDropRejected,
1565
1566 RequiredDropDefaultUnsupported,
1567
1568 GeneratedFieldDefaultChangeRejected,
1569
1570 GeneratedFieldNullabilityChangeRejected,
1571
1572 SetNotNullValidationFailed,
1573}
1574
1575impl fmt::Display for SchemaDdlAdmissionError {
1576 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1577 f.write_str(COMPACT_QUERY_DIAGNOSTIC_MESSAGE)
1578 }
1579}
1580
1581impl std::error::Error for SchemaDdlAdmissionError {}
1582
1583impl fmt::Debug for ErrorDetail {
1584 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1585 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1586 }
1587}
1588
1589impl fmt::Debug for StoreError {
1590 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1591 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1592 }
1593}
1594
1595impl fmt::Debug for QueryErrorDetail {
1596 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1597 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1598 }
1599}
1600
1601impl fmt::Debug for RecoveryErrorDetail {
1602 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1603 fmt_compact_diagnostic(f, self.diagnostic_code(), self.diagnostic_detail())
1604 }
1605}
1606
1607impl fmt::Debug for RecoveryFormatMarkerError {
1608 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1609 fmt_compact_diagnostic(
1610 f,
1611 diagnostic_code::DiagnosticCode::RuntimeCorruption,
1612 Some(diagnostic_code::DiagnosticDetail::RuntimeKind {
1613 kind: diagnostic_code::RuntimeErrorKind::Corruption,
1614 }),
1615 )
1616 }
1617}
1618
1619impl fmt::Debug for SchemaDdlAdmissionError {
1620 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1621 fmt_compact_diagnostic(
1622 f,
1623 diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
1624 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1625 reason: self.diagnostic_code(),
1626 }),
1627 )
1628 }
1629}
1630
1631fn fmt_compact_diagnostic(
1632 f: &mut fmt::Formatter<'_>,
1633 code: diagnostic_code::DiagnosticCode,
1634 detail: Option<diagnostic_code::DiagnosticDetail>,
1635) -> fmt::Result {
1636 write!(
1637 f,
1638 "{}",
1639 diagnostic_code::ErrorCode::from_parts(code, detail).raw()
1640 )
1641}
1642
1643impl ErrorDetail {
1644 #[must_use]
1646 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1647 match self {
1648 Self::Store(error) => error.diagnostic_code(),
1649 Self::Query(error) => error.diagnostic_code(),
1650 Self::Recovery(error) => error.diagnostic_code(),
1651 }
1652 }
1653
1654 #[must_use]
1656 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1657 match self {
1658 Self::Store(error) => error.diagnostic_detail(),
1659 Self::Query(error) => error.diagnostic_detail(),
1660 Self::Recovery(error) => error.diagnostic_detail(),
1661 }
1662 }
1663}
1664
1665impl RecoveryErrorDetail {
1666 #[must_use]
1668 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1669 match self {
1670 Self::UnsupportedFormatVersion { .. } => {
1671 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
1672 }
1673 Self::MalformedFormatMarker { .. } => {
1674 diagnostic_code::DiagnosticCode::RuntimeCorruption
1675 }
1676 }
1677 }
1678
1679 #[must_use]
1681 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1682 let kind = match self {
1683 Self::UnsupportedFormatVersion { .. } => {
1684 diagnostic_code::RuntimeErrorKind::IncompatiblePersistedFormat
1685 }
1686 Self::MalformedFormatMarker { .. } => diagnostic_code::RuntimeErrorKind::Corruption,
1687 };
1688
1689 Some(diagnostic_code::DiagnosticDetail::RuntimeKind { kind })
1690 }
1691}
1692
1693impl StoreError {
1694 #[must_use]
1696 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1697 match self {
1698 Self::NotFound => diagnostic_code::DiagnosticCode::StoreNotFound,
1699 Self::Corrupt => diagnostic_code::DiagnosticCode::StoreCorruption,
1700 Self::InvariantViolation => diagnostic_code::DiagnosticCode::StoreInvariantViolation,
1701 Self::SchemaDdlPublicationRaceLost | Self::SchemaDdlSetNotNullValidationFailed => {
1702 diagnostic_code::DiagnosticCode::SchemaDdlAdmission
1703 }
1704 }
1705 }
1706
1707 #[must_use]
1709 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1710 match self {
1711 Self::SchemaDdlPublicationRaceLost => {
1712 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1713 reason: diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost,
1714 })
1715 }
1716 Self::SchemaDdlSetNotNullValidationFailed => {
1717 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1718 reason: diagnostic_code::SchemaDdlAdmissionCode::SetNotNullValidationFailed,
1719 })
1720 }
1721 Self::NotFound | Self::Corrupt | Self::InvariantViolation => None,
1722 }
1723 }
1724}
1725
1726impl QueryErrorDetail {
1727 #[must_use]
1729 pub const fn diagnostic_code(&self) -> diagnostic_code::DiagnosticCode {
1730 match self {
1731 Self::NumericOverflow => diagnostic_code::DiagnosticCode::QueryNumericOverflow,
1732 Self::NumericNotRepresentable => {
1733 diagnostic_code::DiagnosticCode::QueryNumericNotRepresentable
1734 }
1735 Self::UnsupportedSqlFeature { .. } => {
1736 diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature
1737 }
1738 Self::SqlLowering { .. } => diagnostic_code::DiagnosticCode::QueryUnsupportedSqlFeature,
1739 Self::UnsupportedProjection { .. } => {
1740 diagnostic_code::DiagnosticCode::QueryUnsupportedProjection
1741 }
1742 Self::UnknownAggregateTargetField => {
1743 diagnostic_code::DiagnosticCode::QueryUnknownAggregateTargetField
1744 }
1745 Self::ResultShapeMismatch { .. } => {
1746 diagnostic_code::DiagnosticCode::QueryResultShapeMismatch
1747 }
1748 Self::QueryReadAdmission { .. } => diagnostic_code::DiagnosticCode::QueryReadAdmission,
1749 Self::SqlSurfaceMismatch { .. } => {
1750 diagnostic_code::DiagnosticCode::QuerySqlSurfaceMismatch
1751 }
1752 Self::SqlWriteBoundary { .. } => diagnostic_code::DiagnosticCode::QuerySqlWriteBoundary,
1753 Self::SchemaDdlAdmission { .. } => diagnostic_code::DiagnosticCode::SchemaDdlAdmission,
1754 Self::StaleSchemaRevision => diagnostic_code::DiagnosticCode::RuntimeConflict,
1755 }
1756 }
1757
1758 #[must_use]
1760 pub const fn diagnostic_detail(&self) -> Option<diagnostic_code::DiagnosticDetail> {
1761 match self {
1762 Self::UnsupportedSqlFeature { feature } => {
1763 Some(diagnostic_code::DiagnosticDetail::UnsupportedSqlFeature { feature: *feature })
1764 }
1765 Self::SqlLowering { reason } => {
1766 Some(diagnostic_code::DiagnosticDetail::SqlLowering { reason: *reason })
1767 }
1768 Self::UnsupportedProjection { reason } => {
1769 Some(diagnostic_code::DiagnosticDetail::QueryProjection { reason: *reason })
1770 }
1771 Self::ResultShapeMismatch { reason } => {
1772 Some(diagnostic_code::DiagnosticDetail::QueryResultShape { reason: *reason })
1773 }
1774 Self::QueryReadAdmission { reason } => {
1775 Some(diagnostic_code::DiagnosticDetail::QueryReadAdmission { reason: *reason })
1776 }
1777 Self::SqlSurfaceMismatch { mismatch } => {
1778 Some(diagnostic_code::DiagnosticDetail::SqlSurfaceMismatch {
1779 mismatch: *mismatch,
1780 })
1781 }
1782 Self::SqlWriteBoundary { boundary } => {
1783 Some(diagnostic_code::DiagnosticDetail::SqlWriteBoundary {
1784 boundary: *boundary,
1785 })
1786 }
1787 Self::SchemaDdlAdmission { error } => {
1788 Some(diagnostic_code::DiagnosticDetail::SchemaDdlAdmission {
1789 reason: error.diagnostic_code(),
1790 })
1791 }
1792 Self::NumericOverflow
1793 | Self::NumericNotRepresentable
1794 | Self::UnknownAggregateTargetField
1795 | Self::StaleSchemaRevision => None,
1796 }
1797 }
1798}
1799
1800impl SchemaDdlAdmissionError {
1801 #[must_use]
1803 pub const fn diagnostic_code(&self) -> diagnostic_code::SchemaDdlAdmissionCode {
1804 match self {
1805 Self::MissingExpectedSchemaVersion => {
1806 diagnostic_code::SchemaDdlAdmissionCode::MissingExpectedSchemaVersion
1807 }
1808 Self::MissingNextSchemaVersion => {
1809 diagnostic_code::SchemaDdlAdmissionCode::MissingNextSchemaVersion
1810 }
1811 Self::StaleExpectedSchemaVersion => {
1812 diagnostic_code::SchemaDdlAdmissionCode::StaleExpectedSchemaVersion
1813 }
1814 Self::InvalidExpectedSchemaVersion => {
1815 diagnostic_code::SchemaDdlAdmissionCode::InvalidExpectedSchemaVersion
1816 }
1817 Self::InvalidNextSchemaVersion => {
1818 diagnostic_code::SchemaDdlAdmissionCode::InvalidNextSchemaVersion
1819 }
1820 Self::AcceptedSchemaChangeWithoutVersionBump => {
1821 diagnostic_code::SchemaDdlAdmissionCode::AcceptedSchemaChangeWithoutVersionBump
1822 }
1823 Self::EmptyVersionBump => diagnostic_code::SchemaDdlAdmissionCode::EmptyVersionBump,
1824 Self::VersionGap => diagnostic_code::SchemaDdlAdmissionCode::VersionGap,
1825 Self::VersionRollback => diagnostic_code::SchemaDdlAdmissionCode::VersionRollback,
1826 Self::FingerprintMethodMismatch => {
1827 diagnostic_code::SchemaDdlAdmissionCode::FingerprintMethodMismatch
1828 }
1829 Self::UnsupportedTransitionClass => {
1830 diagnostic_code::SchemaDdlAdmissionCode::UnsupportedTransitionClass
1831 }
1832 Self::PhysicalRunnerMissing => {
1833 diagnostic_code::SchemaDdlAdmissionCode::PhysicalRunnerMissing
1834 }
1835 Self::ValidationFailed => diagnostic_code::SchemaDdlAdmissionCode::ValidationFailed,
1836 Self::PublicationRaceLost => {
1837 diagnostic_code::SchemaDdlAdmissionCode::PublicationRaceLost
1838 }
1839 Self::InvalidAddColumnDefault => {
1840 diagnostic_code::SchemaDdlAdmissionCode::InvalidAddColumnDefault
1841 }
1842 Self::InvalidAlterColumnDefault => {
1843 diagnostic_code::SchemaDdlAdmissionCode::InvalidAlterColumnDefault
1844 }
1845 Self::GeneratedIndexDropRejected => {
1846 diagnostic_code::SchemaDdlAdmissionCode::GeneratedIndexDropRejected
1847 }
1848 Self::RequiredDropDefaultUnsupported => {
1849 diagnostic_code::SchemaDdlAdmissionCode::RequiredDropDefaultUnsupported
1850 }
1851 Self::GeneratedFieldDefaultChangeRejected => {
1852 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldDefaultChangeRejected
1853 }
1854 Self::GeneratedFieldNullabilityChangeRejected => {
1855 diagnostic_code::SchemaDdlAdmissionCode::GeneratedFieldNullabilityChangeRejected
1856 }
1857 Self::SetNotNullValidationFailed => {
1858 diagnostic_code::SchemaDdlAdmissionCode::SetNotNullValidationFailed
1859 }
1860 }
1861 }
1862}
1863
1864#[repr(u16)]
1871#[derive(Clone, Copy, Eq, PartialEq)]
1872pub enum ErrorClass {
1873 Corruption,
1874 IncompatiblePersistedFormat,
1875 NotFound,
1876 Internal,
1877 Conflict,
1878 Unsupported,
1879 InvariantViolation,
1880}
1881
1882impl ErrorClass {
1883 #[must_use]
1885 pub const fn diagnostic_code(self, origin: ErrorOrigin) -> diagnostic_code::DiagnosticCode {
1886 match self {
1887 Self::Corruption if matches!(origin, ErrorOrigin::Store) => {
1888 diagnostic_code::DiagnosticCode::StoreCorruption
1889 }
1890 Self::Corruption => diagnostic_code::DiagnosticCode::RuntimeCorruption,
1891 Self::IncompatiblePersistedFormat => {
1892 diagnostic_code::DiagnosticCode::RuntimeIncompatiblePersistedFormat
1893 }
1894 Self::NotFound if matches!(origin, ErrorOrigin::Store) => {
1895 diagnostic_code::DiagnosticCode::StoreNotFound
1896 }
1897 Self::NotFound => diagnostic_code::DiagnosticCode::RuntimeNotFound,
1898 Self::Internal => diagnostic_code::DiagnosticCode::RuntimeInternal,
1899 Self::Conflict => diagnostic_code::DiagnosticCode::RuntimeConflict,
1900 Self::Unsupported if matches!(origin, ErrorOrigin::Cursor) => {
1901 diagnostic_code::DiagnosticCode::QueryInvalidContinuationCursor
1902 }
1903 Self::Unsupported => diagnostic_code::DiagnosticCode::RuntimeUnsupported,
1904 Self::InvariantViolation if matches!(origin, ErrorOrigin::Store) => {
1905 diagnostic_code::DiagnosticCode::StoreInvariantViolation
1906 }
1907 Self::InvariantViolation => diagnostic_code::DiagnosticCode::RuntimeInvariantViolation,
1908 }
1909 }
1910}
1911
1912impl fmt::Debug for ErrorClass {
1913 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1914 write!(f, "{}", *self as u16)
1915 }
1916}
1917
1918#[repr(u16)]
1925#[derive(Clone, Copy, Eq, PartialEq)]
1926pub enum ErrorOrigin {
1927 Serialize,
1928 Store,
1929 Index,
1930 Identity,
1931 Query,
1932 Planner,
1933 Cursor,
1934 Recovery,
1935 Response,
1936 Executor,
1937 Interface,
1938}
1939
1940impl ErrorOrigin {
1941 #[must_use]
1943 pub const fn diagnostic_origin(self) -> diagnostic_code::ErrorOrigin {
1944 match self {
1945 Self::Serialize => diagnostic_code::ErrorOrigin::Serialize,
1946 Self::Store => diagnostic_code::ErrorOrigin::Store,
1947 Self::Index => diagnostic_code::ErrorOrigin::Index,
1948 Self::Identity => diagnostic_code::ErrorOrigin::Identity,
1949 Self::Query => diagnostic_code::ErrorOrigin::Query,
1950 Self::Planner => diagnostic_code::ErrorOrigin::Planner,
1951 Self::Cursor => diagnostic_code::ErrorOrigin::Cursor,
1952 Self::Recovery => diagnostic_code::ErrorOrigin::Recovery,
1953 Self::Response => diagnostic_code::ErrorOrigin::Response,
1954 Self::Executor => diagnostic_code::ErrorOrigin::Executor,
1955 Self::Interface => diagnostic_code::ErrorOrigin::Interface,
1956 }
1957 }
1958}
1959
1960impl fmt::Debug for ErrorOrigin {
1961 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1962 write!(f, "{}", *self as u16)
1963 }
1964}