dune_api/executions/
types.rs

1//! Types for the Executions API
2
3use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5
6/// Query execution state
7#[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    /// Check if the execution is finished
25    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    /// Check if the execution succeeded
36    pub fn is_success(&self) -> bool {
37        matches!(self, ExecutionState::Completed)
38    }
39}
40
41/// Response from executing a query
42#[derive(Debug, Clone, Deserialize, Serialize)]
43pub struct ExecuteQueryResponse {
44    /// Execution ID
45    pub execution_id: String,
46    /// Current state
47    pub state: ExecutionState,
48}
49
50/// Request to execute a query
51#[derive(Debug, Clone, Serialize, Default)]
52pub struct ExecuteQueryRequest {
53    /// Query parameters (key-value pairs)
54    #[serde(skip_serializing_if = "Option::is_none")]
55    pub query_parameters: Option<HashMap<String, String>>,
56    /// Performance tier (medium or large)
57    #[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    /// Set a query parameter
67    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    /// Set performance tier to large
75    pub fn large(mut self) -> Self {
76        self.performance = Some("large".to_string());
77        self
78    }
79}
80
81/// Request to execute raw SQL
82#[derive(Debug, Clone, Serialize)]
83pub struct ExecuteSqlRequest {
84    /// SQL query to execute
85    pub query_sql: String,
86    /// Query parameters
87    #[serde(skip_serializing_if = "Option::is_none")]
88    pub query_parameters: Option<HashMap<String, String>>,
89    /// Performance tier
90    #[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    /// Set a query parameter
104    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    /// Set performance tier to large
112    pub fn large(mut self) -> Self {
113        self.performance = Some("large".to_string());
114        self
115    }
116}
117
118/// Syntax error metadata
119#[derive(Debug, Clone, Deserialize, Serialize)]
120pub struct SyntaxErrorMetadata {
121    /// Line number
122    pub line: Option<i64>,
123    /// Column number
124    pub column: Option<i64>,
125}
126
127/// Query execution error
128#[derive(Debug, Clone, Deserialize, Serialize)]
129pub struct QueryResultError {
130    /// Error type
131    #[serde(rename = "type")]
132    pub error_type: Option<String>,
133    /// Error message
134    pub message: Option<String>,
135    /// Syntax error metadata
136    pub metadata: Option<SyntaxErrorMetadata>,
137}
138
139/// Execution result metadata
140#[derive(Debug, Clone, Deserialize, Serialize)]
141pub struct ExecutionResultMetadata {
142    /// Column names
143    #[serde(default)]
144    pub column_names: Vec<String>,
145    /// Column types
146    #[serde(default)]
147    pub column_types: Vec<String>,
148    /// Row count in current page
149    pub row_count: Option<i64>,
150    /// Total row count across all pages
151    pub total_row_count: Option<i64>,
152    /// Result set bytes
153    pub result_set_bytes: Option<i64>,
154    /// Total result set bytes
155    pub total_result_set_bytes: Option<i64>,
156    /// Datapoint count (for billing)
157    pub datapoint_count: Option<i64>,
158    /// Execution time in milliseconds
159    pub execution_time_millis: Option<i64>,
160    /// Pending time in milliseconds
161    pub pending_time_millis: Option<i64>,
162}
163
164/// Execution status response
165#[derive(Debug, Clone, Deserialize, Serialize)]
166pub struct ExecutionStatus {
167    /// Execution ID
168    pub execution_id: String,
169    /// Query ID
170    pub query_id: Option<i64>,
171    /// Current state
172    pub state: ExecutionState,
173    /// Whether execution is finished
174    pub is_execution_finished: bool,
175    /// Timestamp when submitted
176    pub submitted_at: Option<String>,
177    /// Timestamp when execution started
178    pub execution_started_at: Option<String>,
179    /// Timestamp when execution ended
180    pub execution_ended_at: Option<String>,
181    /// Timestamp when cancelled
182    pub cancelled_at: Option<String>,
183    /// Timestamp when results expire
184    pub expires_at: Option<String>,
185    /// Execution cost in credits
186    pub execution_cost_credits: Option<f64>,
187    /// Queue position
188    pub queue_position: Option<i64>,
189    /// Result metadata
190    pub result_metadata: Option<ExecutionResultMetadata>,
191    /// Error information
192    pub error: Option<QueryResultError>,
193}
194
195/// A single row of query results
196pub type Row = HashMap<String, serde_json::Value>;
197
198/// Query result data
199#[derive(Debug, Clone, Deserialize, Serialize)]
200pub struct QueryResultData {
201    /// Result metadata
202    pub metadata: Option<ExecutionResultMetadata>,
203    /// Result rows
204    #[serde(default)]
205    pub rows: Vec<Row>,
206}
207
208/// Execution result response
209#[derive(Debug, Clone, Deserialize, Serialize)]
210pub struct ExecutionResult {
211    /// Execution ID
212    pub execution_id: String,
213    /// Query ID
214    pub query_id: Option<i64>,
215    /// Current state
216    pub state: ExecutionState,
217    /// Whether execution is finished
218    pub is_execution_finished: bool,
219    /// Timestamp when submitted
220    pub submitted_at: Option<String>,
221    /// Timestamp when execution started
222    pub execution_started_at: Option<String>,
223    /// Timestamp when execution ended
224    pub execution_ended_at: Option<String>,
225    /// Timestamp when cancelled
226    pub cancelled_at: Option<String>,
227    /// Timestamp when results expire
228    pub expires_at: Option<String>,
229    /// Error information
230    pub error: Option<QueryResultError>,
231    /// Query result data
232    pub result: Option<QueryResultData>,
233    /// Next page offset
234    pub next_offset: Option<i64>,
235    /// Next page URI
236    pub next_uri: Option<String>,
237}
238
239/// Response from cancelling an execution
240#[derive(Debug, Clone, Deserialize, Serialize)]
241pub struct CancelExecutionResponse {
242    /// Whether cancellation was successful
243    pub success: bool,
244}
245
246/// Options for getting execution results
247#[derive(Debug, Clone, Default)]
248pub struct GetResultsOptions {
249    /// Maximum number of rows
250    pub limit: Option<u32>,
251    /// Pagination offset
252    pub offset: Option<i64>,
253    /// Column to sort by
254    pub sort_by: Option<String>,
255    /// Sort direction (asc, desc)
256    pub order: Option<String>,
257    /// Filter columns (comma-separated)
258    pub columns: Option<String>,
259    /// Sample count (for sampling)
260    pub sample_count: Option<u32>,
261    /// Allow partial results for large datasets
262    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}