use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
pub enum ExecutionState {
#[serde(rename = "QUERY_STATE_PENDING")]
Pending,
#[serde(rename = "QUERY_STATE_EXECUTING")]
Executing,
#[serde(rename = "QUERY_STATE_COMPLETED")]
Completed,
#[serde(rename = "QUERY_STATE_FAILED")]
Failed,
#[serde(rename = "QUERY_STATE_CANCELLED")]
Cancelled,
#[serde(rename = "QUERY_STATE_EXPIRED")]
Expired,
}
impl ExecutionState {
pub fn is_finished(&self) -> bool {
matches!(
self,
ExecutionState::Completed
| ExecutionState::Failed
| ExecutionState::Cancelled
| ExecutionState::Expired
)
}
pub fn is_success(&self) -> bool {
matches!(self, ExecutionState::Completed)
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ExecuteQueryResponse {
pub execution_id: String,
pub state: ExecutionState,
}
#[derive(Debug, Clone, Serialize, Default)]
pub struct ExecuteQueryRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub query_parameters: Option<HashMap<String, String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub performance: Option<String>,
}
impl ExecuteQueryRequest {
pub fn new() -> Self {
Self::default()
}
pub fn param(mut self, key: &str, value: &str) -> Self {
self.query_parameters
.get_or_insert_with(HashMap::new)
.insert(key.to_string(), value.to_string());
self
}
pub fn large(mut self) -> Self {
self.performance = Some("large".to_string());
self
}
}
#[derive(Debug, Clone, Serialize)]
pub struct ExecuteSqlRequest {
pub query_sql: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub query_parameters: Option<HashMap<String, String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub performance: Option<String>,
}
impl ExecuteSqlRequest {
pub fn new(query_sql: &str) -> Self {
Self {
query_sql: query_sql.to_string(),
query_parameters: None,
performance: None,
}
}
pub fn param(mut self, key: &str, value: &str) -> Self {
self.query_parameters
.get_or_insert_with(HashMap::new)
.insert(key.to_string(), value.to_string());
self
}
pub fn large(mut self) -> Self {
self.performance = Some("large".to_string());
self
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct SyntaxErrorMetadata {
pub line: Option<i64>,
pub column: Option<i64>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct QueryResultError {
#[serde(rename = "type")]
pub error_type: Option<String>,
pub message: Option<String>,
pub metadata: Option<SyntaxErrorMetadata>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ExecutionResultMetadata {
#[serde(default)]
pub column_names: Vec<String>,
#[serde(default)]
pub column_types: Vec<String>,
pub row_count: Option<i64>,
pub total_row_count: Option<i64>,
pub result_set_bytes: Option<i64>,
pub total_result_set_bytes: Option<i64>,
pub datapoint_count: Option<i64>,
pub execution_time_millis: Option<i64>,
pub pending_time_millis: Option<i64>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ExecutionStatus {
pub execution_id: String,
pub query_id: Option<i64>,
pub state: ExecutionState,
pub is_execution_finished: bool,
pub submitted_at: Option<String>,
pub execution_started_at: Option<String>,
pub execution_ended_at: Option<String>,
pub cancelled_at: Option<String>,
pub expires_at: Option<String>,
pub execution_cost_credits: Option<f64>,
pub queue_position: Option<i64>,
pub result_metadata: Option<ExecutionResultMetadata>,
pub error: Option<QueryResultError>,
}
pub type Row = HashMap<String, serde_json::Value>;
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct QueryResultData {
pub metadata: Option<ExecutionResultMetadata>,
#[serde(default)]
pub rows: Vec<Row>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ExecutionResult {
pub execution_id: String,
pub query_id: Option<i64>,
pub state: ExecutionState,
pub is_execution_finished: bool,
pub submitted_at: Option<String>,
pub execution_started_at: Option<String>,
pub execution_ended_at: Option<String>,
pub cancelled_at: Option<String>,
pub expires_at: Option<String>,
pub error: Option<QueryResultError>,
pub result: Option<QueryResultData>,
pub next_offset: Option<i64>,
pub next_uri: Option<String>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct CancelExecutionResponse {
pub success: bool,
}
#[derive(Debug, Clone, Default)]
pub struct GetResultsOptions {
pub limit: Option<u32>,
pub offset: Option<i64>,
pub sort_by: Option<String>,
pub order: Option<String>,
pub columns: Option<String>,
pub sample_count: Option<u32>,
pub allow_partial_results: Option<bool>,
}
impl GetResultsOptions {
pub fn to_query_string(&self) -> String {
let mut params = Vec::new();
if let Some(limit) = self.limit {
params.push(format!("limit={}", limit));
}
if let Some(offset) = self.offset {
params.push(format!("offset={}", offset));
}
if let Some(ref sort_by) = self.sort_by {
params.push(format!("sort_by={}", sort_by));
}
if let Some(ref order) = self.order {
params.push(format!("order={}", order));
}
if let Some(ref columns) = self.columns {
params.push(format!("columns={}", columns));
}
if let Some(sample_count) = self.sample_count {
params.push(format!("sample_count={}", sample_count));
}
if let Some(allow_partial) = self.allow_partial_results {
params.push(format!("allow_partial_results={}", allow_partial));
}
if params.is_empty() {
String::new()
} else {
format!("?{}", params.join("&"))
}
}
}