add initial mysql crate draft

This commit is contained in:
yggverse 2026-03-05 15:19:36 +02:00
parent 4bd4587565
commit 2bf2148011
12 changed files with 1418 additions and 0 deletions

View file

@ -0,0 +1,54 @@
use crate::table::*;
use mysql::{Error, Pool, PooledConn, prelude::Queryable};
/// Safe, read-only operations
pub struct Connection {
conn: PooledConn,
}
impl Connection {
pub fn create(pool: &Pool) -> Result<Self, Error> {
Ok(Self {
conn: pool.get_conn()?,
})
}
pub fn server(&mut self, id: u64) -> Result<Option<Server>, Error> {
self.conn.exec_first(
"SELECT `id`,
`added`,
`updated`,
`host`,
`port`,
`name`,
`description` FROM `server` WHERE `id` = ?",
(id,),
)
}
pub fn servers(
&mut self,
sort: Option<Sort>,
start: Option<usize>,
limit: Option<usize>,
) -> Result<Vec<Server>, Error> {
self.conn.exec(
format!(
"SELECT `id`,
`added`,
`updated`,
`host`,
`port`,
`name`,
`description` FROM `server`
ORDER BY `id` {} LIMIT {},{}",
sort.unwrap_or_default(),
start.unwrap_or(0),
limit.unwrap_or(DEFAULT_LIMIT)
),
(),
)
}
}
const DEFAULT_LIMIT: usize = 100;

36
crates/mysql/src/lib.rs Normal file
View file

@ -0,0 +1,36 @@
mod connection;
pub mod table;
#[cfg(feature = "transaction")]
mod transaction;
pub use connection::Connection;
#[cfg(feature = "transaction")]
pub use transaction::Transaction;
pub struct Database {
pool: mysql::Pool,
}
impl Database {
pub fn pool(
host: &str,
port: u16,
user: &str,
password: &str,
database: &str,
) -> Result<Self, mysql::Error> {
Ok(Self {
pool: mysql::Pool::new(
format!("mysql://{user}:{password}@{host}:{port}/{database}").as_str(),
)?,
})
}
pub fn connection(&self) -> Result<Connection, mysql::Error> {
Connection::create(&self.pool)
}
#[cfg(feature = "transaction")]
pub fn transaction(&self) -> Result<Transaction, mysql::Error> {
Transaction::create(&self.pool)
}
}

28
crates/mysql/src/table.rs Normal file
View file

@ -0,0 +1,28 @@
use mysql::prelude::FromRow;
#[derive(Debug, PartialEq, Eq, FromRow)]
pub struct Server {
pub id: u64,
pub added: u64,
pub updated: u64,
pub host: String,
pub port: u32,
pub name: String,
pub description: String,
}
#[derive(Default)]
pub enum Sort {
Asc,
#[default]
Desc,
}
impl std::fmt::Display for Sort {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self::Asc => write!(f, "ASC"),
Self::Desc => write!(f, "DESC"),
}
}
}

View file

@ -0,0 +1,31 @@
use crate::table::*;
use mysql::{Error, Pool, TxOpts, prelude::Queryable};
/// Safe, optimized read/write operations
/// * all members implementation requires `commit` action
pub struct Transaction {
tx: mysql::Transaction<'static>,
}
impl Transaction {
pub fn create(pool: &Pool) -> Result<Self, Error> {
Ok(Self {
tx: pool.start_transaction(TxOpts::default())?,
})
}
pub fn commit(self) -> Result<(), Error> {
self.tx.commit()
}
pub fn rollback(self) -> Result<(), Error> {
self.tx.rollback()
}
pub fn server_id_by_host_port(&mut self, host: &str, port: u32) -> Result<Option<u64>, Error> {
self.tx.exec_first(
"SELECT `id` FROM `server` WHERE `host` = ? AND `port` = ? LIMIT 1",
(host, port),
)
}
}