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