athena_cli/commands/database/
describe.rs

1use super::utils::{ColumnDisplay, ParameterDisplay};
2use crate::cli::DescribeTableArgs;
3use crate::context::Context;
4use anyhow::{Context as _, Result};
5
6pub async fn describe_table(ctx: &Context, args: &DescribeTableArgs) -> Result<()> {
7    let client = ctx.create_athena_client();
8
9    // Parse database and table names
10    let (database_name, table_name) = if args.table.contains('.') {
11        let parts: Vec<&str> = args.table.splitn(2, '.').collect();
12        (parts[0].to_string(), parts[1].to_string())
13    } else if let Some(db) = args.db.as_ref() {
14        (db.clone(), args.table.clone())
15    } else if let Some(db) = ctx.database().as_ref() {
16        (db.clone(), args.table.clone())
17    } else {
18        anyhow::bail!("No database specified. Use --db or 'database.table' format")
19    };
20
21    // Get table metadata
22    let result = client
23        .get_table_metadata()
24        .catalog_name(ctx.catalog())
25        .database_name(&database_name)
26        .table_name(&table_name)
27        .send()
28        .await
29        .with_context(|| {
30            format!(
31                "Failed to get metadata for table {}.{}",
32                database_name, table_name
33            )
34        })?;
35
36    let table_metadata = result.table_metadata().ok_or_else(|| {
37        anyhow::anyhow!(
38            "No metadata found for table {}.{}",
39            database_name,
40            table_name
41        )
42    })?;
43
44    // Display table info
45    println!("Table: {}.{}", database_name, table_name);
46    println!();
47
48    // Display table properties
49    if let Some(table_type) = table_metadata.table_type() {
50        println!("Type: {}", table_type);
51    }
52
53    if let Some(create_time) = table_metadata.create_time() {
54        println!("Created: {}", create_time);
55    }
56
57    if let Some(description) = table_metadata.parameters().and_then(|p| p.get("comment")) {
58        println!("Description: {}", description);
59    }
60
61    // Display columns
62    let columns = table_metadata.columns();
63    println!("\nColumns: (found {})", columns.len());
64    if !columns.is_empty() {
65        let table = ColumnDisplay::create_columns_table(columns);
66        table.printstd();
67    } else {
68        println!("No columns found in table metadata");
69    }
70
71    // Display partitions
72    let partitions = table_metadata.partition_keys();
73
74    // Always show partition information
75    println!("\nPartition Details:");
76    if partitions.is_empty() {
77        println!("Table is not partitioned");
78    } else {
79        println!("Table has {} partition keys", partitions.len());
80
81        // Display partition keys in a table
82        let table = ColumnDisplay::create_columns_table(partitions);
83        table.printstd();
84
85        println!("\nDetailed partition information is available through SQL with:");
86        println!("SHOW PARTITIONS {}.{}", database_name, table_name);
87    }
88
89    // Display storage parameters
90    if let Some(parameters) = table_metadata.parameters() {
91        println!("\nStorage Parameters:");
92        let table = ParameterDisplay::create_parameters_table(parameters, &["comment"]);
93        table.printstd();
94    }
95
96    Ok(())
97}