1use crate::parse_utils::{datetime_from_str, optional_datetime_from_str};
2use chrono::{DateTime, Utc};
3use serde::Deserialize;
4use serde_with::DeserializeFromStr;
5use std::str::FromStr;
6
7#[derive(Deserialize, Debug)]
9pub struct ExecutionResponse {
10 pub execution_id: String,
11 pub state: ExecutionStatus,
12}
13
14#[derive(DeserializeFromStr, Debug, PartialEq)]
19pub enum ExecutionStatus {
20 Complete,
21 Executing,
22 Pending,
23 Cancelled,
24 Failed,
25}
26
27impl FromStr for ExecutionStatus {
28 type Err = String;
29
30 fn from_str(input: &str) -> Result<ExecutionStatus, Self::Err> {
31 match input {
32 "QUERY_STATE_COMPLETED" => Ok(ExecutionStatus::Complete),
33 "QUERY_STATE_EXECUTING" => Ok(ExecutionStatus::Executing),
34 "QUERY_STATE_PENDING" => Ok(ExecutionStatus::Pending),
35 "QUERY_STATE_CANCELLED" => Ok(ExecutionStatus::Cancelled),
36 "QUERY_STATE_FAILED" => Ok(ExecutionStatus::Failed),
37 other => Err(format!("Parse Error {other}")),
38 }
39 }
40}
41
42impl ExecutionStatus {
43 pub fn is_terminal(&self) -> bool {
46 match self {
47 ExecutionStatus::Complete => true,
48 ExecutionStatus::Cancelled => true,
49 ExecutionStatus::Failed => true,
50 ExecutionStatus::Executing => false,
51 ExecutionStatus::Pending => false,
52 }
53 }
54}
55
56#[derive(Deserialize, Debug)]
58pub struct CancellationResponse {
59 pub success: bool,
61}
62
63#[derive(Deserialize, Debug)]
67pub struct ResultMetaData {
68 pub column_names: Vec<String>,
69 pub result_set_bytes: u64,
70 pub total_row_count: u32,
71 pub datapoint_count: u32,
72 pub pending_time_millis: Option<u32>,
73 pub execution_time_millis: u32,
74}
75
76#[derive(Deserialize, Debug)]
80pub struct ExecutionTimes {
81 #[serde(deserialize_with = "datetime_from_str")]
83 pub submitted_at: DateTime<Utc>,
84 #[serde(deserialize_with = "optional_datetime_from_str", default)]
87 pub expires_at: Option<DateTime<Utc>>,
88 #[serde(deserialize_with = "optional_datetime_from_str", default)]
91 pub execution_started_at: Option<DateTime<Utc>>,
92 #[serde(deserialize_with = "optional_datetime_from_str", default)]
94 pub execution_ended_at: Option<DateTime<Utc>>,
95 #[serde(deserialize_with = "optional_datetime_from_str", default)]
97 pub cancelled_at: Option<DateTime<Utc>>,
98}
99
100#[derive(Deserialize, Debug)]
103pub struct GetStatusResponse {
104 pub execution_id: String,
105 pub query_id: u32,
106 pub state: ExecutionStatus,
107 #[serde(flatten)]
108 pub times: ExecutionTimes,
109 pub queue_position: Option<u32>,
112 pub result_metadata: Option<ResultMetaData>,
114}
115
116#[derive(Deserialize, Debug)]
120pub struct ExecutionResult<T> {
121 pub rows: Vec<T>,
122 pub metadata: ResultMetaData,
123}
124
125#[derive(Deserialize, Debug)]
129pub struct GetResultResponse<T> {
130 pub execution_id: String,
131 pub query_id: u32,
132 pub state: ExecutionStatus,
133 #[serde(flatten)]
137 pub times: ExecutionTimes,
138 pub result: ExecutionResult<T>,
139}
140
141impl<T> GetResultResponse<T> {
142 pub fn get_rows(self) -> Vec<T> {
144 self.result.rows
145 }
146}
147
148#[cfg(test)]
149mod tests {
150 use super::*;
151
152 #[test]
153 fn status_from_str() {
154 assert_eq!(
155 ExecutionStatus::from_str("invalid"),
156 Err(String::from("Parse Error invalid"))
157 );
158 assert_eq!(
159 ExecutionStatus::from_str("QUERY_STATE_COMPLETED"),
160 Ok(ExecutionStatus::Complete)
161 );
162 assert_eq!(
163 ExecutionStatus::from_str("QUERY_STATE_EXECUTING"),
164 Ok(ExecutionStatus::Executing)
165 );
166 assert_eq!(
167 ExecutionStatus::from_str("QUERY_STATE_PENDING"),
168 Ok(ExecutionStatus::Pending)
169 );
170 assert_eq!(
171 ExecutionStatus::from_str("QUERY_STATE_CANCELLED"),
172 Ok(ExecutionStatus::Cancelled)
173 );
174 assert_eq!(
175 ExecutionStatus::from_str("QUERY_STATE_FAILED"),
176 Ok(ExecutionStatus::Failed)
177 );
178 }
179
180 #[test]
181 fn terminal_statuses() {
182 assert!(ExecutionStatus::Complete.is_terminal());
183 assert!(ExecutionStatus::Cancelled.is_terminal());
184 assert!(ExecutionStatus::Failed.is_terminal());
185
186 assert!(!ExecutionStatus::Pending.is_terminal());
187 assert!(!ExecutionStatus::Executing.is_terminal());
188 }
189 #[test]
190 fn derive_debug() {
191 assert_eq!(
192 format!(
193 "{:?}",
194 ExecutionResponse {
195 execution_id: "jerb".to_string(),
196 state: ExecutionStatus::Failed
197 }
198 ),
199 "ExecutionResponse { execution_id: \"jerb\", state: Failed }"
200 );
201 assert_eq!(
202 format!("{:?}", CancellationResponse { success: false }),
203 "CancellationResponse { success: false }"
204 );
205 let query_id = 71;
206 let execution_id = "jerb ID";
207
208 assert_eq!(
209 format!(
210 "{:?}",
211 GetStatusResponse {
212 execution_id: execution_id.to_string(),
213 query_id,
214 state: ExecutionStatus::Pending,
215 times: ExecutionTimes {
216 submitted_at: Default::default(),
217 expires_at: Default::default(),
218 execution_started_at: Default::default(),
219 execution_ended_at: Default::default(),
220 cancelled_at: Default::default(),
221 },
222 queue_position: Some(10),
223 result_metadata: Some(ResultMetaData {
224 column_names: vec![],
225 result_set_bytes: 0,
226 total_row_count: 0,
227 datapoint_count: 0,
228 pending_time_millis: None,
229 execution_time_millis: 0,
230 }),
231 }
232 ),
233 "GetStatusResponse { \
234 execution_id: \"jerb ID\", \
235 query_id: 71, \
236 state: Pending, \
237 times: ExecutionTimes { \
238 submitted_at: 1970-01-01T00:00:00Z, \
239 expires_at: None, \
240 execution_started_at: None, \
241 execution_ended_at: None, \
242 cancelled_at: None \
243 }, \
244 queue_position: Some(10), \
245 result_metadata: Some(ResultMetaData { \
246 column_names: [], \
247 result_set_bytes: 0, \
248 total_row_count: 0, \
249 datapoint_count: 0, \
250 pending_time_millis: None, \
251 execution_time_millis: 0 \
252 }\
253 ) }",
254 );
255 assert_eq!(
256 format!(
257 "{:?}",
258 GetResultResponse {
259 execution_id: execution_id.to_string(),
260 query_id,
261 state: ExecutionStatus::Complete,
262 times: ExecutionTimes {
263 submitted_at: Default::default(),
264 expires_at: Default::default(),
265 execution_started_at: Default::default(),
266 execution_ended_at: Default::default(),
267 cancelled_at: Default::default(),
268 },
269 result: ExecutionResult::<u8> {
270 rows: vec![],
271 metadata: ResultMetaData {
272 column_names: vec![],
273 result_set_bytes: 0,
274 total_row_count: 0,
275 datapoint_count: 0,
276 pending_time_millis: None,
277 execution_time_millis: 0,
278 }
279 },
280 }
281 ),
282 "GetResultResponse { \
283 execution_id: \"jerb ID\", \
284 query_id: 71, \
285 state: Complete, \
286 times: ExecutionTimes { \
287 submitted_at: 1970-01-01T00:00:00Z, \
288 expires_at: None, \
289 execution_started_at: None, \
290 execution_ended_at: None, \
291 cancelled_at: None \
292 }, \
293 result: ExecutionResult { \
294 rows: [], \
295 metadata: ResultMetaData { \
296 column_names: [], \
297 result_set_bytes: 0, \
298 total_row_count: 0, \
299 datapoint_count: 0, \
300 pending_time_millis: None, \
301 execution_time_millis: 0 \
302 } \
303 } \
304 }",
305 );
306 }
307}