icydb_core/db/schema/
errors.rs1use crate::db::predicate::{CoercionId, CompareOp};
7use std::fmt;
8
9#[derive(Clone, Debug, Eq, PartialEq)]
11pub enum SchemaValidationOperator {
12 Compare(CompareOp),
13 CompareField { op: CompareOp, right_field: String },
14 IsEmpty,
15 IsNotEmpty,
16 TextContains,
17 TextContainsCi,
18}
19
20impl SchemaValidationOperator {
21 pub(crate) const fn compare(op: CompareOp) -> Self {
22 Self::Compare(op)
23 }
24
25 pub(crate) fn compare_field(op: CompareOp, right_field: &str) -> Self {
26 Self::CompareField {
27 op,
28 right_field: right_field.to_string(),
29 }
30 }
31}
32
33impl fmt::Display for SchemaValidationOperator {
34 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35 match self {
36 Self::Compare(op) => write!(f, "{op:?}"),
37 Self::CompareField { op, right_field } => {
38 write!(f, "{op:?} against field '{right_field}'")
39 }
40 Self::IsEmpty => f.write_str("is_empty"),
41 Self::IsNotEmpty => f.write_str("is_not_empty"),
42 Self::TextContains => f.write_str("text_contains"),
43 Self::TextContainsCi => f.write_str("text_contains_ci"),
44 }
45 }
46}
47
48#[derive(Clone, Copy, Debug, Eq, PartialEq)]
50pub enum SchemaLiteralValidationReason {
51 ExpectedList,
52 ExpectedText,
53 ExpectedScalar,
54 LiteralTypeMismatch,
55 ListElementTypeMismatch,
56 EnumPathMismatch,
57 UnknownEnumVariant,
58 EnumBodyMismatch,
59}
60
61impl fmt::Display for SchemaLiteralValidationReason {
62 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63 match self {
64 Self::ExpectedList => f.write_str("expected list literal"),
65 Self::ExpectedText => f.write_str("expected text literal"),
66 Self::ExpectedScalar => f.write_str("expected scalar literal"),
67 Self::LiteralTypeMismatch => f.write_str("literal type does not match field type"),
68 Self::ListElementTypeMismatch => {
69 f.write_str("list literal does not match field element type")
70 }
71 Self::EnumPathMismatch => f.write_str("enum path does not match field enum type"),
72 Self::UnknownEnumVariant => f.write_str("enum variant is not accepted for field type"),
73 Self::EnumBodyMismatch => {
74 f.write_str("enum payload does not match the accepted variant contract")
75 }
76 }
77 }
78}
79
80#[derive(Debug, thiserror::Error)]
82pub enum ValidateError {
83 #[error("unknown field '{field}'")]
84 UnknownField { field: String },
85
86 #[error("field '{field}' is not queryable")]
87 NonQueryableFieldType { field: String },
88
89 #[error("duplicate field '{field}'")]
90 DuplicateField { field: String },
91
92 #[error("map predicates are unsupported for field '{field}'")]
93 MapPredicateUnsupported { field: String },
94
95 #[error("primary key '{field}' not present in entity fields")]
96 InvalidPrimaryKey { field: String },
97
98 #[error("primary key '{field}' has a non-keyable type")]
99 InvalidPrimaryKeyType { field: String },
100
101 #[error("duplicate index name '{name}'")]
102 DuplicateIndexName { name: String },
103
104 #[error("operator {operator} is not valid for field '{field}'")]
105 InvalidOperator {
106 field: String,
107 operator: SchemaValidationOperator,
108 },
109
110 #[error("coercion {coercion:?} is not valid for field '{field}'")]
111 InvalidCoercion { field: String, coercion: CoercionId },
112
113 #[error("invalid literal for field '{field}': {reason}")]
114 InvalidLiteral {
115 field: String,
116 reason: SchemaLiteralValidationReason,
117 },
118}
119
120impl ValidateError {
121 pub(crate) fn invalid_operator(field: &str, operator: SchemaValidationOperator) -> Self {
122 Self::InvalidOperator {
123 field: field.to_string(),
124 operator,
125 }
126 }
127
128 pub(crate) fn invalid_literal(field: &str, reason: SchemaLiteralValidationReason) -> Self {
129 Self::InvalidLiteral {
130 field: field.to_string(),
131 reason,
132 }
133 }
134}