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

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
target

1240
Cargo.lock generated Normal file

File diff suppressed because it is too large Load diff

7
Cargo.toml Normal file
View file

@ -0,0 +1,7 @@
[workspace]
resolver = "2"
members = [
#"crates/crawler",
#"crates/http",
"crates/mysql",
]

1
crates/mysql/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
*.bak

17
crates/mysql/Cargo.toml Normal file
View file

@ -0,0 +1,17 @@
[package]
name = "hlstate-mysql"
version = "0.1.0"
edition = "2024"
license = "MIT"
readme = "README.md"
description = "Shared MySQL database library"
keywords = ["hlstate", "database", "mysql", "library", "api"]
# categories = []
repository = "https://github.com/YGGverse/hlstate-rs"
[features]
default = []
transaction = []
[dependencies]
mysql = "26.0.1"

3
crates/mysql/README.md Normal file
View file

@ -0,0 +1,3 @@
# hlstate-mysql
Shared MySQL database library

BIN
crates/mysql/database.mwb Normal file

Binary file not shown.

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),
)
}
}

View file