datafusion_odata/
error.rs1use datafusion::arrow::datatypes::DataType;
2use std::string::FromUtf8Error;
3
4#[derive(thiserror::Error, Debug)]
7pub enum ODataError {
8 #[error(transparent)]
9 BadRequest(#[from] BadRequest),
10 #[error(transparent)]
11 UnsupportedDataType(#[from] UnsupportedDataType),
12 #[error(transparent)]
13 FromUtf8Error(#[from] FromUtf8Error),
14 #[error(transparent)]
15 UnsupportedFeature(#[from] UnsupportedFeature),
16 #[error(transparent)]
17 UnsupportedNetProtocol(#[from] UnsupportedNetProtocol),
18 #[error(transparent)]
19 CollectionNotFound(#[from] CollectionNotFound),
20 #[error(transparent)]
21 CollectionAddressNotAssigned(#[from] CollectionAddressNotAssigned),
22 #[error(transparent)]
23 KeyColumnNotAssigned(#[from] KeyColumnNotAssigned),
24 #[error(transparent)]
25 Internal(InternalError),
26}
27
28impl ODataError {
29 pub fn internal(error: impl Into<Box<dyn std::error::Error + Send + Sync + 'static>>) -> Self {
30 Self::Internal(InternalError::new(error))
31 }
32
33 pub fn bad_request(
34 error: impl Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
35 ) -> Self {
36 Self::BadRequest(BadRequest::new(error))
37 }
38
39 pub fn handle_no_table_as_collection_not_found(
40 collection: impl Into<String>,
41 err: datafusion::error::DataFusionError,
42 ) -> Self {
43 match err {
44 datafusion::error::DataFusionError::Plan(e) if e.contains("No table named") => {
45 Self::CollectionNotFound(CollectionNotFound::new(collection))
46 }
47 _ => Self::internal(err),
48 }
49 }
50}
51
52impl axum::response::IntoResponse for ODataError {
53 fn into_response(self) -> axum::response::Response {
54 match self {
55 Self::Internal(_) | Self::FromUtf8Error(_) => {
56 (http::StatusCode::INTERNAL_SERVER_ERROR, "Internal error").into_response()
57 }
58 Self::BadRequest(e) => e.into_response(),
59 Self::CollectionNotFound(e) => e.into_response(),
60 Self::UnsupportedDataType(e) => e.into_response(),
61 Self::UnsupportedFeature(e) => e.into_response(),
62 Self::CollectionAddressNotAssigned(e) => e.into_response(),
63 Self::KeyColumnNotAssigned(e) => e.into_response(),
64 Self::UnsupportedNetProtocol(e) => e.into_response(),
65 }
66 }
67}
68
69#[derive(thiserror::Error, Debug)]
72#[error("Internal error")]
73pub struct InternalError {
74 #[source]
75 pub source: Box<dyn std::error::Error + Send + Sync + 'static>,
76}
77
78impl InternalError {
79 pub fn new(error: impl Into<Box<dyn std::error::Error + Send + Sync + 'static>>) -> Self {
80 Self {
81 source: error.into(),
82 }
83 }
84}
85
86#[derive(thiserror::Error, Debug)]
89#[error("{source}")]
90pub struct BadRequest {
91 #[source]
92 pub source: Box<dyn std::error::Error + Send + Sync + 'static>,
93}
94
95impl BadRequest {
96 pub fn new(error: impl Into<Box<dyn std::error::Error + Send + Sync + 'static>>) -> Self {
97 Self {
98 source: error.into(),
99 }
100 }
101}
102
103impl axum::response::IntoResponse for BadRequest {
104 fn into_response(self) -> axum::response::Response {
105 (http::StatusCode::BAD_REQUEST, self.to_string()).into_response()
106 }
107}
108
109#[derive(thiserror::Error, Debug)]
112#[error("Collection {collection} not found")]
113pub struct CollectionNotFound {
114 pub collection: String,
115}
116
117impl CollectionNotFound {
118 pub fn new(collection: impl Into<String>) -> Self {
119 Self {
120 collection: collection.into(),
121 }
122 }
123}
124
125impl axum::response::IntoResponse for CollectionNotFound {
126 fn into_response(self) -> axum::response::Response {
127 (http::StatusCode::NOT_FOUND, self.to_string()).into_response()
128 }
129}
130
131#[derive(thiserror::Error, Debug)]
134#[error("Key column not assigned")]
135pub struct KeyColumnNotAssigned;
136
137impl axum::response::IntoResponse for KeyColumnNotAssigned {
138 fn into_response(self) -> axum::response::Response {
139 (http::StatusCode::NOT_IMPLEMENTED, self.to_string()).into_response()
140 }
141}
142
143#[derive(thiserror::Error, Debug)]
146#[error("Collection address not assigned")]
147pub struct CollectionAddressNotAssigned;
148
149impl axum::response::IntoResponse for CollectionAddressNotAssigned {
150 fn into_response(self) -> axum::response::Response {
151 (http::StatusCode::NOT_IMPLEMENTED, self.to_string()).into_response()
152 }
153}
154
155#[derive(thiserror::Error, Debug)]
158#[error("Unsupported data type: {data_type}")]
159pub struct UnsupportedDataType {
160 pub data_type: DataType,
161}
162
163impl UnsupportedDataType {
164 pub fn new(data_type: DataType) -> Self {
165 Self { data_type }
166 }
167}
168
169impl axum::response::IntoResponse for UnsupportedDataType {
170 fn into_response(self) -> axum::response::Response {
171 (http::StatusCode::NOT_IMPLEMENTED, self.to_string()).into_response()
172 }
173}
174
175#[derive(thiserror::Error, Debug)]
178#[error("Unsupported net protocol: {url}")]
179pub struct UnsupportedNetProtocol {
180 pub url: String,
181}
182
183impl UnsupportedNetProtocol {
184 pub fn new(url: String) -> Self {
185 Self { url }
186 }
187}
188
189impl axum::response::IntoResponse for UnsupportedNetProtocol {
190 fn into_response(self) -> axum::response::Response {
191 (http::StatusCode::NOT_IMPLEMENTED, self.to_string()).into_response()
192 }
193}
194
195#[derive(thiserror::Error, Debug)]
198#[error("Unsupported feature: {feature}")]
199pub struct UnsupportedFeature {
200 pub feature: String,
201}
202
203impl UnsupportedFeature {
204 pub fn new(feature: impl Into<String>) -> Self {
205 Self {
206 feature: feature.into(),
207 }
208 }
209}
210
211impl axum::response::IntoResponse for UnsupportedFeature {
212 fn into_response(self) -> axum::response::Response {
213 (http::StatusCode::NOT_IMPLEMENTED, self.to_string()).into_response()
214 }
215}
216
217impl From<quick_xml::Error> for ODataError {
220 fn from(error: quick_xml::Error) -> Self {
221 ODataError::Internal(InternalError::new(error))
222 }
223}
224
225impl From<quick_xml::encoding::EncodingError> for ODataError {
226 fn from(error: quick_xml::encoding::EncodingError) -> Self {
227 ODataError::Internal(InternalError::new(error))
228 }
229}
230
231impl From<std::io::Error> for ODataError {
232 fn from(error: std::io::Error) -> Self {
233 ODataError::Internal(InternalError::new(error))
234 }
235}