graphrecords_core/errors/
schema.rs1use crate::graphrecord::{EdgeIndex, GraphRecordAttribute, Group, NodeIndex, datatypes::DataType};
2use std::{
3 error::Error,
4 fmt::{Display, Formatter, Result as FmtResult},
5};
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub enum SchemaError {
9 GroupNotInSchema {
10 group: Group,
11 },
12 GroupAlreadyInSchema {
13 group: Group,
14 },
15 NodeAttributeMissing {
16 node_index: NodeIndex,
17 attribute: GraphRecordAttribute,
18 data_type: DataType,
19 },
20 EdgeAttributeMissing {
21 edge_index: EdgeIndex,
22 attribute: GraphRecordAttribute,
23 data_type: DataType,
24 },
25 NodeAttributeDataTypeMismatch {
26 node_index: NodeIndex,
27 attribute: GraphRecordAttribute,
28 data_type: DataType,
29 expected_data_type: DataType,
30 },
31 EdgeAttributeDataTypeMismatch {
32 edge_index: EdgeIndex,
33 attribute: GraphRecordAttribute,
34 data_type: DataType,
35 expected_data_type: DataType,
36 },
37 NodeAttributesNotInSchema {
38 node_index: NodeIndex,
39 attributes: Vec<GraphRecordAttribute>,
40 },
41 EdgeAttributesNotInSchema {
42 edge_index: EdgeIndex,
43 attributes: Vec<GraphRecordAttribute>,
44 },
45 ContinuousAttributeNotNumeric,
46 TemporalAttributeNotTemporal,
47}
48
49impl Error for SchemaError {}
50
51fn join_attributes(attributes: &[GraphRecordAttribute]) -> String {
52 attributes
53 .iter()
54 .map(ToString::to_string)
55 .collect::<Vec<_>>()
56 .join(", ")
57}
58
59impl Display for SchemaError {
60 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
61 match self {
62 Self::GroupNotInSchema { group } => {
63 write!(f, "Group `{group}` is not defined in the schema")
64 }
65 Self::GroupAlreadyInSchema { group } => {
66 write!(f, "Group `{group}` already exists in the schema")
67 }
68 Self::NodeAttributeMissing {
69 node_index,
70 attribute,
71 data_type,
72 } => write!(
73 f,
74 "Attribute `{attribute}` of type `{data_type}` not found on node with index `{node_index}`"
75 ),
76 Self::EdgeAttributeMissing {
77 edge_index,
78 attribute,
79 data_type,
80 } => write!(
81 f,
82 "Attribute `{attribute}` of type `{data_type}` not found on edge with index `{edge_index}`"
83 ),
84 Self::NodeAttributeDataTypeMismatch {
85 node_index,
86 attribute,
87 data_type,
88 expected_data_type,
89 } => write!(
90 f,
91 "Attribute `{attribute}` of node with index `{node_index}` is of type `{data_type}`. Expected `{expected_data_type}`."
92 ),
93 Self::EdgeAttributeDataTypeMismatch {
94 edge_index,
95 attribute,
96 data_type,
97 expected_data_type,
98 } => write!(
99 f,
100 "Attribute `{attribute}` of edge with index `{edge_index}` is of type `{data_type}`. Expected `{expected_data_type}`."
101 ),
102 Self::NodeAttributesNotInSchema {
103 node_index,
104 attributes,
105 } => write!(
106 f,
107 "Attributes [{}] of node with index `{node_index}` do not exist in schema.",
108 join_attributes(attributes)
109 ),
110 Self::EdgeAttributesNotInSchema {
111 edge_index,
112 attributes,
113 } => write!(
114 f,
115 "Attributes [{}] of edge with index `{edge_index}` do not exist in schema.",
116 join_attributes(attributes)
117 ),
118 Self::ContinuousAttributeNotNumeric => {
119 write!(
120 f,
121 "Continuous attribute must be of (sub-)type `Int` or `Float`."
122 )
123 }
124 Self::TemporalAttributeNotTemporal => {
125 write!(
126 f,
127 "Temporal attribute must be of (sub-)type `DateTime` or `Duration`."
128 )
129 }
130 }
131 }
132}
133
134#[cfg(test)]
135mod test {
136 use super::SchemaError;
137 use crate::graphrecord::datatypes::DataType;
138
139 #[test]
140 fn test_display_groups() {
141 assert_eq!(
142 "Group `\"test\"` is not defined in the schema",
143 SchemaError::GroupNotInSchema {
144 group: "test".into()
145 }
146 .to_string()
147 );
148 assert_eq!(
149 "Group `\"test\"` already exists in the schema",
150 SchemaError::GroupAlreadyInSchema {
151 group: "test".into()
152 }
153 .to_string()
154 );
155 }
156
157 #[test]
158 fn test_display_attributes() {
159 assert_eq!(
160 "Attribute `\"key\"` of type `Int` not found on node with index `\"0\"`",
161 SchemaError::NodeAttributeMissing {
162 node_index: "0".into(),
163 attribute: "key".into(),
164 data_type: DataType::Int,
165 }
166 .to_string()
167 );
168 assert_eq!(
169 "Attribute `\"key\"` of type `Int` not found on edge with index `0`",
170 SchemaError::EdgeAttributeMissing {
171 edge_index: 0,
172 attribute: "key".into(),
173 data_type: DataType::Int,
174 }
175 .to_string()
176 );
177 assert_eq!(
178 "Attribute `\"key\"` of node with index `\"0\"` is of type `Int`. Expected `Float`.",
179 SchemaError::NodeAttributeDataTypeMismatch {
180 node_index: "0".into(),
181 attribute: "key".into(),
182 data_type: DataType::Int,
183 expected_data_type: DataType::Float,
184 }
185 .to_string()
186 );
187 assert_eq!(
188 "Attribute `\"key\"` of edge with index `0` is of type `Int`. Expected `Float`.",
189 SchemaError::EdgeAttributeDataTypeMismatch {
190 edge_index: 0,
191 attribute: "key".into(),
192 data_type: DataType::Int,
193 expected_data_type: DataType::Float,
194 }
195 .to_string()
196 );
197 assert_eq!(
198 "Attributes [\"key1\", \"key2\"] of node with index `\"0\"` do not exist in schema.",
199 SchemaError::NodeAttributesNotInSchema {
200 node_index: "0".into(),
201 attributes: vec!["key1".into(), "key2".into()],
202 }
203 .to_string()
204 );
205 assert_eq!(
206 "Attributes [\"key1\", \"key2\"] of edge with index `0` do not exist in schema.",
207 SchemaError::EdgeAttributesNotInSchema {
208 edge_index: 0,
209 attributes: vec!["key1".into(), "key2".into()],
210 }
211 .to_string()
212 );
213 }
214
215 #[test]
216 fn test_display_attribute_types() {
217 assert_eq!(
218 "Continuous attribute must be of (sub-)type `Int` or `Float`.",
219 SchemaError::ContinuousAttributeNotNumeric.to_string()
220 );
221 assert_eq!(
222 "Temporal attribute must be of (sub-)type `DateTime` or `Duration`.",
223 SchemaError::TemporalAttributeNotTemporal.to_string()
224 );
225 }
226}