1
use clap::Parser;
2
use futures_util::SinkExt;
3
use prettytable::{Cell, Row, Table};
4
use tokio_stream::StreamExt;
5

            
6
use crate::{
7
    client::commands::erroneous_server_response,
8
    core::{
9
        protocol::{ClientToServerMessageStream, Request, Response},
10
        types::MySQLDatabase,
11
    },
12
};
13

            
14
#[derive(Parser, Debug, Clone)]
15
pub struct ShowDbArgs {
16
    /// The name of the database(s) to show
17
    #[arg(num_args = 0..)]
18
    name: Vec<MySQLDatabase>,
19

            
20
    /// Print the information as JSON
21
    #[arg(short, long)]
22
    json: bool,
23
}
24

            
25
pub async fn show_databases(
26
    args: ShowDbArgs,
27
    mut server_connection: ClientToServerMessageStream,
28
) -> anyhow::Result<()> {
29
    let message = if args.name.is_empty() {
30
        Request::ListDatabases(None)
31
    } else {
32
        Request::ListDatabases(Some(args.name.to_owned()))
33
    };
34

            
35
    server_connection.send(message).await?;
36

            
37
    // TODO: collect errors for json output.
38

            
39
    let database_list = match server_connection.next().await {
40
        Some(Ok(Response::ListDatabases(databases))) => databases
41
            .into_iter()
42
            .filter_map(|(database_name, result)| match result {
43
                Ok(database_row) => Some(database_row),
44
                Err(err) => {
45
                    eprintln!("{}", err.to_error_message(&database_name));
46
                    eprintln!("Skipping...");
47
                    println!();
48
                    None
49
                }
50
            })
51
            .collect::<Vec<_>>(),
52
        Some(Ok(Response::ListAllDatabases(database_list))) => match database_list {
53
            Ok(list) => list,
54
            Err(err) => {
55
                server_connection.send(Request::Exit).await?;
56
                return Err(
57
                    anyhow::anyhow!(err.to_error_message()).context("Failed to list databases")
58
                );
59
            }
60
        },
61
        response => return erroneous_server_response(response),
62
    };
63

            
64
    server_connection.send(Request::Exit).await?;
65

            
66
    if args.json {
67
        println!("{}", serde_json::to_string_pretty(&database_list)?);
68
    } else if database_list.is_empty() {
69
        println!("No databases to show.");
70
    } else {
71
        let mut table = Table::new();
72
        table.add_row(Row::new(vec![Cell::new("Database")]));
73
        for db in database_list {
74
            table.add_row(row![db.database]);
75
        }
76
        table.printstd();
77
    }
78

            
79
    Ok(())
80
}