1use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5
6#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
8pub enum ExecutionState {
9 #[serde(rename = "QUERY_STATE_PENDING")]
10 Pending,
11 #[serde(rename = "QUERY_STATE_EXECUTING")]
12 Executing,
13 #[serde(rename = "QUERY_STATE_COMPLETED")]
14 Completed,
15 #[serde(rename = "QUERY_STATE_FAILED")]
16 Failed,
17 #[serde(rename = "QUERY_STATE_CANCELLED")]
18 Cancelled,
19 #[serde(rename = "QUERY_STATE_EXPIRED")]
20 Expired,
21}
22
23impl ExecutionState {
24 pub fn is_finished(&self) -> bool {
26 matches!(
27 self,
28 ExecutionState::Completed
29 | ExecutionState::Failed
30 | ExecutionState::Cancelled
31 | ExecutionState::Expired
32 )
33 }
34
35 pub fn is_success(&self) -> bool {
37 matches!(self, ExecutionState::Completed)
38 }
39}
40
41#[derive(Debug, Clone, Deserialize, Serialize)]
43pub struct ExecuteQueryResponse {
44 pub execution_id: String,
46 pub state: ExecutionState,
48}
49
50#[derive(Debug, Clone, Serialize, Default)]
52pub struct ExecuteQueryRequest {
53 #[serde(skip_serializing_if = "Option::is_none")]
55 pub query_parameters: Option<HashMap<String, String>>,
56 #[serde(skip_serializing_if = "Option::is_none")]
58 pub performance: Option<String>,
59}
60
61impl ExecuteQueryRequest {
62 pub fn new() -> Self {
63 Self::default()
64 }
65
66 pub fn param(mut self, key: &str, value: &str) -> Self {
68 self.query_parameters
69 .get_or_insert_with(HashMap::new)
70 .insert(key.to_string(), value.to_string());
71 self
72 }
73
74 pub fn large(mut self) -> Self {
76 self.performance = Some("large".to_string());
77 self
78 }
79}
80
81#[derive(Debug, Clone, Serialize)]
83pub struct ExecuteSqlRequest {
84 pub query_sql: String,
86 #[serde(skip_serializing_if = "Option::is_none")]
88 pub query_parameters: Option<HashMap<String, String>>,
89 #[serde(skip_serializing_if = "Option::is_none")]
91 pub performance: Option<String>,
92}
93
94impl ExecuteSqlRequest {
95 pub fn new(query_sql: &str) -> Self {
96 Self {
97 query_sql: query_sql.to_string(),
98 query_parameters: None,
99 performance: None,
100 }
101 }
102
103 pub fn param(mut self, key: &str, value: &str) -> Self {
105 self.query_parameters
106 .get_or_insert_with(HashMap::new)
107 .insert(key.to_string(), value.to_string());
108 self
109 }
110
111 pub fn large(mut self) -> Self {
113 self.performance = Some("large".to_string());
114 self
115 }
116}
117
118#[derive(Debug, Clone, Deserialize, Serialize)]
120pub struct SyntaxErrorMetadata {
121 pub line: Option<i64>,
123 pub column: Option<i64>,
125}
126
127#[derive(Debug, Clone, Deserialize, Serialize)]
129pub struct QueryResultError {
130 #[serde(rename = "type")]
132 pub error_type: Option<String>,
133 pub message: Option<String>,
135 pub metadata: Option<SyntaxErrorMetadata>,
137}
138
139#[derive(Debug, Clone, Deserialize, Serialize)]
141pub struct ExecutionResultMetadata {
142 #[serde(default)]
144 pub column_names: Vec<String>,
145 #[serde(default)]
147 pub column_types: Vec<String>,
148 pub row_count: Option<i64>,
150 pub total_row_count: Option<i64>,
152 pub result_set_bytes: Option<i64>,
154 pub total_result_set_bytes: Option<i64>,
156 pub datapoint_count: Option<i64>,
158 pub execution_time_millis: Option<i64>,
160 pub pending_time_millis: Option<i64>,
162}
163
164#[derive(Debug, Clone, Deserialize, Serialize)]
166pub struct ExecutionStatus {
167 pub execution_id: String,
169 pub query_id: Option<i64>,
171 pub state: ExecutionState,
173 pub is_execution_finished: bool,
175 pub submitted_at: Option<String>,
177 pub execution_started_at: Option<String>,
179 pub execution_ended_at: Option<String>,
181 pub cancelled_at: Option<String>,
183 pub expires_at: Option<String>,
185 pub execution_cost_credits: Option<f64>,
187 pub queue_position: Option<i64>,
189 pub result_metadata: Option<ExecutionResultMetadata>,
191 pub error: Option<QueryResultError>,
193}
194
195pub type Row = HashMap<String, serde_json::Value>;
197
198#[derive(Debug, Clone, Deserialize, Serialize)]
200pub struct QueryResultData {
201 pub metadata: Option<ExecutionResultMetadata>,
203 #[serde(default)]
205 pub rows: Vec<Row>,
206}
207
208#[derive(Debug, Clone, Deserialize, Serialize)]
210pub struct ExecutionResult {
211 pub execution_id: String,
213 pub query_id: Option<i64>,
215 pub state: ExecutionState,
217 pub is_execution_finished: bool,
219 pub submitted_at: Option<String>,
221 pub execution_started_at: Option<String>,
223 pub execution_ended_at: Option<String>,
225 pub cancelled_at: Option<String>,
227 pub expires_at: Option<String>,
229 pub error: Option<QueryResultError>,
231 pub result: Option<QueryResultData>,
233 pub next_offset: Option<i64>,
235 pub next_uri: Option<String>,
237}
238
239#[derive(Debug, Clone, Deserialize, Serialize)]
241pub struct CancelExecutionResponse {
242 pub success: bool,
244}
245
246#[derive(Debug, Clone, Default)]
248pub struct GetResultsOptions {
249 pub limit: Option<u32>,
251 pub offset: Option<i64>,
253 pub sort_by: Option<String>,
255 pub order: Option<String>,
257 pub columns: Option<String>,
259 pub sample_count: Option<u32>,
261 pub allow_partial_results: Option<bool>,
263}
264
265impl GetResultsOptions {
266 pub fn to_query_string(&self) -> String {
267 let mut params = Vec::new();
268 if let Some(limit) = self.limit {
269 params.push(format!("limit={}", limit));
270 }
271 if let Some(offset) = self.offset {
272 params.push(format!("offset={}", offset));
273 }
274 if let Some(ref sort_by) = self.sort_by {
275 params.push(format!("sort_by={}", sort_by));
276 }
277 if let Some(ref order) = self.order {
278 params.push(format!("order={}", order));
279 }
280 if let Some(ref columns) = self.columns {
281 params.push(format!("columns={}", columns));
282 }
283 if let Some(sample_count) = self.sample_count {
284 params.push(format!("sample_count={}", sample_count));
285 }
286 if let Some(allow_partial) = self.allow_partial_results {
287 params.push(format!("allow_partial_results={}", allow_partial));
288 }
289 if params.is_empty() {
290 String::new()
291 } else {
292 format!("?{}", params.join("&"))
293 }
294 }
295}