use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
#[non_exhaustive]
pub enum DbType {
MySQL,
#[default]
PostgreSQL,
Sqlite,
Redis,
MongoDB,
ClickHouse,
Oracle,
OceanBase,
SqlServer,
VectorDb,
PureJsDb,
Dameng,
Kingbase,
Db2,
MariaDB,
TiDB,
PolarDB,
GaussDB,
GBase,
Sybase,
}
impl DbType {
pub fn as_str(&self) -> &'static str {
match self {
DbType::MySQL => "mysql",
DbType::PostgreSQL => "postgres",
DbType::Sqlite => "sqlite",
DbType::Redis => "redis",
DbType::MongoDB => "mongodb",
DbType::ClickHouse => "clickhouse",
DbType::Oracle => "oracle",
DbType::OceanBase => "oceanbase",
DbType::SqlServer => "mssql",
DbType::VectorDb => "vectordb",
DbType::PureJsDb => "purejsdb",
DbType::Dameng => "dameng",
DbType::Kingbase => "kingbase",
DbType::Db2 => "db2",
DbType::MariaDB => "mariadb",
DbType::TiDB => "tidb",
DbType::PolarDB => "polardb",
DbType::GaussDB => "gaussdb",
DbType::GBase => "gbase",
DbType::Sybase => "sybase",
}
}
#[allow(clippy::should_implement_trait)]
pub fn from_str(s: &str) -> Option<Self> {
match s.to_lowercase().as_str() {
"mysql" => Some(DbType::MySQL),
"postgres" | "postgresql" => Some(DbType::PostgreSQL),
"sqlite" | "sqlite3" => Some(DbType::Sqlite),
"redis" => Some(DbType::Redis),
"mongodb" | "mongo" => Some(DbType::MongoDB),
"clickhouse" => Some(DbType::ClickHouse),
"oracle" => Some(DbType::Oracle),
"oceanbase" => Some(DbType::OceanBase),
"mssql" | "sqlserver" => Some(DbType::SqlServer),
"vectordb" | "vector" => Some(DbType::VectorDb),
"purejsdb" | "purejs" => Some(DbType::PureJsDb),
"dameng" | "dm" | "dm7" | "dm8" => Some(DbType::Dameng),
"kingbase" | "kingbasees" | "es" => Some(DbType::Kingbase),
"db2" => Some(DbType::Db2),
"mariadb" => Some(DbType::MariaDB),
"tidb" => Some(DbType::TiDB),
"polardb" => Some(DbType::PolarDB),
"gaussdb" => Some(DbType::GaussDB),
"gbase" | "gbase8s" => Some(DbType::GBase),
"sybase" | "ase" => Some(DbType::Sybase),
_ => None,
}
}
pub fn supports_schema(&self) -> bool {
!matches!(self, DbType::Redis | DbType::VectorDb)
}
pub fn supports_transaction(&self) -> bool {
!matches!(self, DbType::Redis | DbType::VectorDb | DbType::MongoDB)
}
pub fn supports_foreign_key(&self) -> bool {
!matches!(
self,
DbType::Redis | DbType::VectorDb | DbType::MongoDB | DbType::Sqlite
)
}
pub fn supports_stored_procedure(&self) -> bool {
matches!(
self,
DbType::MySQL
| DbType::PostgreSQL
| DbType::Oracle
| DbType::OceanBase
| DbType::SqlServer
| DbType::Dameng
| DbType::Kingbase
| DbType::Db2
| DbType::MariaDB
| DbType::TiDB
| DbType::PolarDB
| DbType::GaussDB
| DbType::GBase
| DbType::Sybase
)
}
pub fn default_port(&self) -> u16 {
match self {
DbType::MySQL => 3306,
DbType::PostgreSQL => 5432,
DbType::Sqlite => 0,
DbType::Redis => 6379,
DbType::MongoDB => 27017,
DbType::ClickHouse => 8123,
DbType::Oracle => 1521,
DbType::OceanBase => 2881,
DbType::SqlServer => 1433,
DbType::VectorDb => 19530,
DbType::PureJsDb => 0,
DbType::Dameng => 5236,
DbType::Kingbase => 54321,
DbType::Db2 => 50000,
DbType::MariaDB => 3306,
DbType::TiDB => 4000,
DbType::PolarDB => 5432,
DbType::GaussDB => 25308,
DbType::GBase => 9088,
DbType::Sybase => 5000,
}
}
pub fn is_mysql_family(&self) -> bool {
matches!(
self,
DbType::MySQL | DbType::MariaDB | DbType::TiDB | DbType::OceanBase
)
}
pub fn is_postgres_family(&self) -> bool {
matches!(
self,
DbType::PostgreSQL | DbType::Kingbase | DbType::GaussDB
)
}
pub fn is_oracle_family(&self) -> bool {
matches!(self, DbType::Oracle | DbType::Dameng)
}
}
impl fmt::Display for DbType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.as_str())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_db_type_as_str() {
assert_eq!(DbType::MySQL.as_str(), "mysql");
assert_eq!(DbType::PostgreSQL.as_str(), "postgres");
}
#[test]
fn test_db_type_from_str() {
assert_eq!(DbType::from_str("mysql"), Some(DbType::MySQL));
assert_eq!(DbType::from_str("postgres"), Some(DbType::PostgreSQL));
assert_eq!(DbType::from_str("unknown"), None);
}
#[test]
fn test_db_type_supports_schema() {
assert!(DbType::MySQL.supports_schema());
assert!(!DbType::Redis.supports_schema());
}
#[test]
fn test_db_type_default_port() {
assert_eq!(DbType::MySQL.default_port(), 3306);
assert_eq!(DbType::PostgreSQL.default_port(), 5432);
assert_eq!(DbType::Sqlite.default_port(), 0);
}
}