use std::collections::HashMap;
use std::fmt::{self, Display, Formatter, Result};
use clap::ValueEnum;
use ratatui::style::{Color, Style};
use ratatui::text::Span;
use serde::{Deserialize, Serialize};
use sqlx::{MySqlPool, PgPool, SqlitePool};
#[derive(Debug, Clone, Serialize, Deserialize, ValueEnum)]
pub enum Engine {
Postgres,
Mysql,
Sqlite,
}
impl Engine {
pub fn to_source(&self, url: String) -> ConnectionSource {
match self {
Engine::Postgres => ConnectionSource::Url(DatabaseString::Postgres(url)),
Engine::Mysql => ConnectionSource::Url(DatabaseString::Mysql(url)),
Engine::Sqlite => ConnectionSource::Url(DatabaseString::Sqlite(url)),
}
}
pub fn badge(&self) -> Span<'static> {
match self {
Engine::Postgres => {
Span::styled("[Postgres] ", Style::default().fg(Color::Blue).bold())
}
Engine::Mysql => Span::styled("[MySQL] ", Style::default().fg(Color::Yellow).bold()),
Engine::Sqlite => Span::styled("[SQLite] ", Style::default().fg(Color::Green).bold()),
}
}
}
impl Display for Engine {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
let s = match self {
Engine::Postgres => "postgres",
Engine::Mysql => "mysql",
Engine::Sqlite => "sqlite",
};
write!(f, "{s}")
}
}
#[derive(Deserialize, Serialize, Default)]
pub struct DatabaseStore {
pub databases: HashMap<String, Database>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Database {
pub name: String,
pub engine: Engine,
pub connection: ConnectionSource,
}
impl Display for Database {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.name)
}
}
#[derive(Debug, Clone)]
pub enum DbPool {
Postgres(PgPool),
Mysql(MySqlPool),
Sqlite(SqlitePool),
}
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
pub enum ConnectionSource {
Url(DatabaseString),
Config(DatabaseConnection),
}
impl ConnectionSource {
pub fn host(&self) -> String {
use crate::connection::store::extract_host;
match self {
ConnectionSource::Url(url) => {
let s = match url {
DatabaseString::Postgres(s) => s.as_str(),
DatabaseString::Mysql(s) => s.as_str(),
DatabaseString::Sqlite(s) => s.as_str(),
};
extract_host(s)
}
ConnectionSource::Config(config) => match config {
DatabaseConnection::Postgres(c) => c.hostname.clone(),
DatabaseConnection::Mysql(c) => c.hostname.clone(),
DatabaseConnection::Sqlite(c) => c.path.clone(),
},
}
}
}
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
pub enum DatabaseString {
Postgres(String),
Mysql(String),
Sqlite(String),
}
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
pub enum DatabaseConnection {
Postgres(PostgresConnection),
Mysql(MysqlConnection),
Sqlite(SqliteConnection),
}
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
pub struct PostgresConnection {
pub username: String,
pub password: String,
pub hostname: String,
pub database: String,
pub stack_trace: bool,
pub port: i16,
pub pool_size: i8,
pub ssl: Option<SslOptions>,
}
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
pub struct MysqlConnection {
pub username: String,
pub password: String,
pub hostname: String,
pub database: String,
pub stack_trace: bool,
pub port: i16,
pub pool_size: i8,
pub ssl: Option<SslOptions>,
}
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
pub struct SqliteConnection {
pub path: String,
pub stack_trace: bool,
pub pool_size: i8,
pub create_if_missing: bool,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum SslVerifyMode {
None,
Peer,
}
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
pub struct SslOptions {
pub verify: SslVerifyMode,
pub certfile: Option<String>,
}