athena_cli/commands/inspect/
fields.rs

1use crate::commands::common::{OptionByteDisplay, OptionDisplayValue, OptionDurationFormat};
2use crate::config;
3use aws_sdk_athena::types::QueryExecution;
4use std::fmt;
5use std::str::FromStr;
6
7// Define all possible fields that can be displayed in the inspect command
8#[derive(Debug, Clone, Copy, PartialEq)]
9pub enum InspectField {
10    Id,
11    Status,
12    StatusReason,
13    Query,
14    SubmissionTime,
15    CompletionTime,
16    Database,
17    Catalog,
18    Workgroup,
19    DataScanned,
20    CacheStatus,
21    EngineExecutionTime,
22    TotalExecutionTime,
23    QueryPlanningTime,
24    QueryQueueTime,
25    ServiceProcessingTime,
26    OutputLocation,
27    TotalRows,
28}
29
30// Add FromStr implementation for parsing from config
31impl FromStr for InspectField {
32    type Err = String;
33
34    fn from_str(s: &str) -> Result<Self, Self::Err> {
35        match s {
36            "Id" => Ok(InspectField::Id),
37            "Status" => Ok(InspectField::Status),
38            "StatusReason" => Ok(InspectField::StatusReason),
39            "Query" => Ok(InspectField::Query),
40            "SubmissionTime" => Ok(InspectField::SubmissionTime),
41            "CompletionTime" => Ok(InspectField::CompletionTime),
42            "Database" => Ok(InspectField::Database),
43            "Catalog" => Ok(InspectField::Catalog),
44            "Workgroup" => Ok(InspectField::Workgroup),
45            "DataScanned" => Ok(InspectField::DataScanned),
46            "CacheStatus" => Ok(InspectField::CacheStatus),
47            "EngineExecutionTime" => Ok(InspectField::EngineExecutionTime),
48            "TotalExecutionTime" => Ok(InspectField::TotalExecutionTime),
49            "QueryPlanningTime" => Ok(InspectField::QueryPlanningTime),
50            "QueryQueueTime" => Ok(InspectField::QueryQueueTime),
51            "ServiceProcessingTime" => Ok(InspectField::ServiceProcessingTime),
52            "OutputLocation" => Ok(InspectField::OutputLocation),
53            "TotalRows" => Ok(InspectField::TotalRows),
54            _ => Err(format!("Unknown inspect field: {}", s)),
55        }
56    }
57}
58
59impl fmt::Display for InspectField {
60    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61        match self {
62            InspectField::Id => write!(f, "Query ID"),
63            InspectField::Status => write!(f, "Status"),
64            InspectField::StatusReason => write!(f, "Status Reason"),
65            InspectField::Query => write!(f, "Query"),
66            InspectField::SubmissionTime => write!(f, "Submission Time"),
67            InspectField::CompletionTime => write!(f, "Completion Time"),
68            InspectField::Database => write!(f, "Database"),
69            InspectField::Catalog => write!(f, "Catalog"),
70            InspectField::Workgroup => write!(f, "Workgroup"),
71            InspectField::DataScanned => write!(f, "Data Scanned"),
72            InspectField::CacheStatus => write!(f, "Cache Status"),
73            InspectField::EngineExecutionTime => write!(f, "Engine Execution Time"),
74            InspectField::TotalExecutionTime => write!(f, "Total Execution Time"),
75            InspectField::QueryPlanningTime => write!(f, "Query Planning Time"),
76            InspectField::QueryQueueTime => write!(f, "Query Queue Time"),
77            InspectField::ServiceProcessingTime => write!(f, "Service Processing Time"),
78            InspectField::OutputLocation => write!(f, "Output Location"),
79            InspectField::TotalRows => write!(f, "Total Rows"),
80        }
81    }
82}
83
84// Default set of fields to display
85pub fn default_inspect_fields() -> Vec<InspectField> {
86    vec![
87        InspectField::Id,
88        InspectField::Status,
89        InspectField::StatusReason,
90        InspectField::Query,
91        InspectField::SubmissionTime,
92        InspectField::CompletionTime,
93        InspectField::Database,
94        InspectField::Catalog,
95        InspectField::Workgroup,
96        InspectField::DataScanned,
97        InspectField::TotalRows,
98        InspectField::CacheStatus,
99        InspectField::EngineExecutionTime,
100        InspectField::TotalExecutionTime,
101        InspectField::QueryPlanningTime,
102        InspectField::QueryQueueTime,
103        InspectField::ServiceProcessingTime,
104        InspectField::OutputLocation,
105    ]
106}
107
108// Get fields from config or use defaults
109pub fn get_inspect_fields() -> Vec<InspectField> {
110    if let Ok(config) = config::Config::load() {
111        if let Some(field_names) = config.app.inspect_fields {
112            let fields: Vec<InspectField> = field_names
113                .iter()
114                .filter_map(|name| InspectField::from_str(name).ok())
115                .collect();
116
117            if !fields.is_empty() {
118                return fields;
119            }
120        }
121    }
122
123    // Fall back to defaults if config loading fails or fields are empty
124    default_inspect_fields()
125}
126
127// Extract a field value from a query execution
128pub fn get_field_value(execution: &QueryExecution, field: InspectField) -> String {
129    match field {
130        InspectField::Id => execution.query_execution_id().to_display_value_or_default(),
131
132        InspectField::Status => execution
133            .status()
134            .and_then(|s| s.state())
135            .map(|s| s.as_str())
136            .to_display_value_or_default(),
137
138        InspectField::StatusReason => execution
139            .status()
140            .and_then(|s| s.state_change_reason())
141            .to_display_value_or_default(),
142
143        InspectField::Query => execution.query().to_display_value_or_default(),
144
145        InspectField::SubmissionTime => execution
146            .status()
147            .and_then(|s| s.submission_date_time())
148            .to_display_value_or_default(),
149
150        InspectField::CompletionTime => execution
151            .status()
152            .and_then(|s| s.completion_date_time())
153            .to_display_value_or_default(),
154
155        InspectField::Database => execution
156            .query_execution_context()
157            .and_then(|c| c.database())
158            .to_display_value_or_default(),
159
160        InspectField::Catalog => execution
161            .query_execution_context()
162            .and_then(|c| c.catalog())
163            .to_display_value_or_default(),
164
165        InspectField::Workgroup => execution.work_group().to_display_value_or_default(),
166
167        InspectField::DataScanned => execution
168            .statistics()
169            .and_then(|s| s.data_scanned_in_bytes())
170            .format_bytes_or_default(),
171
172        InspectField::CacheStatus => {
173            let data_scanned = execution
174                .statistics()
175                .and_then(|s| s.data_scanned_in_bytes())
176                .unwrap_or(1);
177
178            if data_scanned == 0 {
179                "Used cache".to_string()
180            } else {
181                "Fresh execution".to_string()
182            }
183        }
184
185        InspectField::EngineExecutionTime => execution
186            .statistics()
187            .and_then(|s| s.engine_execution_time_in_millis())
188            .format_duration_ms_or_default(),
189
190        InspectField::TotalExecutionTime => execution
191            .statistics()
192            .and_then(|s| s.total_execution_time_in_millis())
193            .format_duration_ms_or_default(),
194
195        InspectField::QueryPlanningTime => execution
196            .statistics()
197            .and_then(|s| s.query_planning_time_in_millis())
198            .format_duration_ms_or_default(),
199
200        InspectField::QueryQueueTime => execution
201            .statistics()
202            .and_then(|s| s.query_queue_time_in_millis())
203            .format_duration_ms_or_default(),
204
205        InspectField::ServiceProcessingTime => execution
206            .statistics()
207            .and_then(|s| s.service_processing_time_in_millis())
208            .format_duration_ms_or_default(),
209
210        InspectField::OutputLocation => execution
211            .result_configuration()
212            .and_then(|c| c.output_location())
213            .to_display_value_or_default(),
214        InspectField::TotalRows => "".to_string(),
215    }
216}