#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
pub enum Dialect {
#[default]
SQLite,
PostgreSQL,
MySQL,
}
impl Dialect {
#[inline]
#[must_use]
pub const fn uses_numbered_placeholders(&self) -> bool {
matches!(self, Self::PostgreSQL)
}
#[must_use]
pub const fn parse(s: &str) -> Option<Self> {
if s.eq_ignore_ascii_case("sqlite")
|| s.eq_ignore_ascii_case("turso")
|| s.eq_ignore_ascii_case("libsql")
{
Some(Self::SQLite)
} else if s.eq_ignore_ascii_case("postgresql")
|| s.eq_ignore_ascii_case("postgres")
|| s.eq_ignore_ascii_case("pg")
{
Some(Self::PostgreSQL)
} else if s.eq_ignore_ascii_case("mysql") {
Some(Self::MySQL)
} else {
None
}
}
#[must_use]
pub const fn table_prefix(&self) -> &'static str {
match self {
Self::SQLite => "#[SQLiteTable",
Self::PostgreSQL => "#[PostgresTable",
Self::MySQL => "#[MySQLTable",
}
}
#[must_use]
pub const fn index_prefix(&self) -> &'static str {
match self {
Self::SQLite => "#[SQLiteIndex",
Self::PostgreSQL => "#[PostgresIndex",
Self::MySQL => "#[MySQLIndex",
}
}
#[must_use]
pub const fn schema_derive(&self) -> &'static str {
match self {
Self::SQLite => "#[derive(SQLiteSchema)]",
Self::PostgreSQL => "#[derive(PostgresSchema)]",
Self::MySQL => "#[derive(MySQLSchema)]",
}
}
#[must_use]
pub const fn as_str(&self) -> &'static str {
match self {
Self::SQLite => "sqlite",
Self::PostgreSQL => "postgresql",
Self::MySQL => "mysql",
}
}
}
impl core::fmt::Display for Dialect {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str(self.as_str())
}
}
impl core::str::FromStr for Dialect {
type Err = DialectParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::parse(s).ok_or(DialectParseError)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DialectParseError;
impl core::fmt::Display for DialectParseError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("unknown dialect")
}
}
#[cfg(feature = "std")]
impl std::error::Error for DialectParseError {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_dialect_parse() {
assert_eq!(Dialect::parse("sqlite"), Some(Dialect::SQLite));
assert_eq!(Dialect::parse("SQLite"), Some(Dialect::SQLite));
assert_eq!(Dialect::parse("turso"), Some(Dialect::SQLite));
assert_eq!(Dialect::parse("libsql"), Some(Dialect::SQLite));
assert_eq!(Dialect::parse("postgresql"), Some(Dialect::PostgreSQL));
assert_eq!(Dialect::parse("postgres"), Some(Dialect::PostgreSQL));
assert_eq!(Dialect::parse("pg"), Some(Dialect::PostgreSQL));
assert_eq!(Dialect::parse("PG"), Some(Dialect::PostgreSQL));
assert_eq!(Dialect::parse("mysql"), Some(Dialect::MySQL));
assert_eq!(Dialect::parse("MySQL"), Some(Dialect::MySQL));
assert_eq!(Dialect::parse("unknown"), None);
assert_eq!(Dialect::parse(""), None);
}
#[test]
fn test_dialect_placeholders() {
assert!(!Dialect::SQLite.uses_numbered_placeholders());
assert!(Dialect::PostgreSQL.uses_numbered_placeholders());
assert!(!Dialect::MySQL.uses_numbered_placeholders());
}
#[test]
fn test_dialect_display() {
assert_eq!(format!("{}", Dialect::SQLite), "sqlite");
assert_eq!(format!("{}", Dialect::PostgreSQL), "postgresql");
assert_eq!(format!("{}", Dialect::MySQL), "mysql");
}
}