athena_cli/commands/inspect/
detail.rs

1use super::download::download_from_s3;
2use super::fields::{get_field_value, get_inspect_fields};
3use crate::cli::InspectArgs;
4use crate::context::Context;
5use anyhow::Result;
6use aws_sdk_s3;
7use owo_colors::OwoColorize;
8use prettytable::{format, Cell, Row, Table};
9
10pub async fn detail(ctx: &Context, args: &InspectArgs) -> Result<()> {
11    let client = ctx.create_athena_client();
12    let query_id = args.query_id.clone();
13
14    // Command-specific quiet overrides global setting
15    let quiet_mode = args.quiet || ctx.quiet();
16
17    if !quiet_mode {
18        println!("\n{}", "Query Execution Details".bold());
19        println!("ID: {}\n", query_id.bright_green());
20    }
21
22    // Get query execution details
23    let result = client
24        .get_query_execution()
25        .query_execution_id(&query_id)
26        .send()
27        .await?;
28
29    let execution = result
30        .query_execution()
31        .ok_or_else(|| anyhow::anyhow!("No query execution found with ID: {}", query_id))?;
32
33    if !quiet_mode {
34        // Create a table for the query information
35        let mut table = Table::new();
36
37        // Configure table style
38        table.set_format(*format::consts::FORMAT_CLEAN); // Clean borders
39
40        // Get fields to display
41        let fields = get_inspect_fields();
42
43        // Add header
44        table.add_row(Row::new(vec![
45            Cell::new("Field").style_spec("Fb"), // Bold
46            Cell::new("Value").style_spec("Fb"), // Bold
47        ]));
48
49        // Add rows for each field
50        for field in fields {
51            let value = get_field_value(execution, field);
52            let formatted_value = match field.to_string().as_str() {
53                "Status" => match value.as_str() {
54                    "SUCCEEDED" => value.bright_green().to_string(),
55                    "FAILED" => value.bright_red().to_string(),
56                    _ => value.yellow().to_string(),
57                },
58                "Data Scanned" => value.bright_cyan().to_string(),
59                _ => value,
60            };
61
62            table.add_row(Row::new(vec![
63                Cell::new(&field.to_string()).style_spec("Fb"), // Bold field names
64                Cell::new(&formatted_value),
65            ]));
66        }
67
68        // Print the table
69        table.printstd();
70    }
71
72    // Check if query was successful before trying to get results
73    if let Some(status) = execution.status() {
74        if let Some(state) = status.state() {
75            if state.as_str() == "SUCCEEDED" {
76                // If output option is provided, download results from S3
77                if let Some(output_dir) = &args.output {
78                    let s3_output_location = execution
79                        .result_configuration()
80                        .and_then(|c| c.output_location())
81                        .ok_or_else(|| {
82                            anyhow::anyhow!("No output location found for query: {}", query_id)
83                        })?;
84
85                    if !quiet_mode {
86                        println!("\n{}", "S3 Output Location:".bold());
87                        println!("📂 {}", s3_output_location.bright_blue());
88                        println!("\n{}", "Downloading Results...".bold());
89                    }
90
91                    let s3_client = aws_sdk_s3::Client::new(ctx.aws_config());
92
93                    match download_from_s3(&s3_client, s3_output_location, output_dir, &query_id)
94                        .await
95                    {
96                        Ok(file_path) => {
97                            if quiet_mode {
98                                println!("{}", file_path.display());
99                            } else {
100                                println!(
101                                    "✅ Downloaded to: {}",
102                                    file_path.display().to_string().bright_green()
103                                )
104                            }
105                        }
106                        Err(e) => {
107                            if quiet_mode {
108                                return Err(e);
109                            } else {
110                                println!("❌ Error: {}", e.to_string().bright_red())
111                            }
112                        }
113                    }
114                }
115            } else if !quiet_mode {
116                println!("\n{}", "Cannot display results:".bold());
117                println!("❌ Query status is {}", state.as_str().bright_red());
118            }
119        }
120    }
121
122    if !quiet_mode {
123        println!(); // Add final newline
124    }
125    Ok(())
126}