Added querybuilder
This commit is contained in:
@@ -30,3 +30,4 @@ axum = "0.7.7"
|
|||||||
lazy_static = "1.5.0"
|
lazy_static = "1.5.0"
|
||||||
futures = "0.3.31"
|
futures = "0.3.31"
|
||||||
axum-login = "0.16.0"
|
axum-login = "0.16.0"
|
||||||
|
sqlx-postgres = "0.8.2"
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
|
use crate::data::query::{Condition, QueryBuilder};
|
||||||
use crate::error::SirenResult;
|
use crate::error::SirenResult;
|
||||||
|
|
||||||
const TABLE_NAME: &str = "guilds";
|
const TABLE_NAME: &str = "guilds";
|
||||||
@@ -36,7 +37,10 @@ impl GuildCache {
|
|||||||
|
|
||||||
pub async fn get_by_id(id: i64) -> SirenResult<Option<Self>> {
|
pub async fn get_by_id(id: i64) -> SirenResult<Option<Self>> {
|
||||||
let pool = crate::data::pool();
|
let pool = crate::data::pool();
|
||||||
let item = sqlx::query_as::<_, Self>(&format!("SELECT * FROM {} WHERE id = $1", TABLE_NAME))
|
let query = QueryBuilder::new(TABLE_NAME)
|
||||||
|
.where_condition(Condition::is_equal("id", "$1")) // Use a placeholder
|
||||||
|
.build();
|
||||||
|
let item = sqlx::query_as(&query)
|
||||||
.bind(id)
|
.bind(id)
|
||||||
.fetch_optional(pool)
|
.fetch_optional(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use crate::error::SirenResult;
|
|||||||
pub mod events;
|
pub mod events;
|
||||||
pub mod guilds;
|
pub mod guilds;
|
||||||
pub mod messages;
|
pub mod messages;
|
||||||
|
mod query;
|
||||||
|
|
||||||
static POOL: OnceLock<Pool<Postgres>> = OnceLock::new();
|
static POOL: OnceLock<Pool<Postgres>> = OnceLock::new();
|
||||||
static REDIS: OnceLock<RedisClient> = OnceLock::new();
|
static REDIS: OnceLock<RedisClient> = OnceLock::new();
|
||||||
|
|||||||
163
src/data/query.rs
Normal file
163
src/data/query.rs
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
pub struct QueryBuilder {
|
||||||
|
table: String,
|
||||||
|
columns: Vec<String>,
|
||||||
|
condition: Option<Condition>,
|
||||||
|
order_by: Vec<String>,
|
||||||
|
limit: Option<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl QueryBuilder {
|
||||||
|
pub fn new(table: &str) -> Self {
|
||||||
|
QueryBuilder {
|
||||||
|
table: table.to_string(),
|
||||||
|
columns: Vec::new(),
|
||||||
|
condition: None,
|
||||||
|
order_by: Vec::new(),
|
||||||
|
limit: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn select(mut self, columns: &[&str]) -> Self {
|
||||||
|
self.columns = columns.iter().map(|s| s.to_string()).collect();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn where_condition(mut self, condition: Condition) -> Self {
|
||||||
|
self.condition = Some(condition);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn order_by(mut self, column: &str, direction: &str) -> Self {
|
||||||
|
self.order_by.push(format!("{} {}", column, direction));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn limit(mut self, limit: usize) -> Self {
|
||||||
|
self.limit = Some(limit);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> String {
|
||||||
|
let columns = if self.columns.is_empty() {
|
||||||
|
"*".to_string()
|
||||||
|
} else {
|
||||||
|
self.columns.join(",")
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut query = format!("SELECT {} FROM {}", columns, self.table);
|
||||||
|
|
||||||
|
if let Some(condition) = self.condition {
|
||||||
|
query.push_str(&format!(" WHERE {}", condition.to_sql()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.order_by.is_empty() {
|
||||||
|
query.push_str(&format!(" ORDER BY {}", self.order_by.join(" ORDER BY")));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(limit) = self.limit {
|
||||||
|
query.push_str(&format!(" LIMIT {}", limit));
|
||||||
|
}
|
||||||
|
|
||||||
|
query
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Condition {
|
||||||
|
Simple(String),
|
||||||
|
And(Box<Condition>, Box<Condition>),
|
||||||
|
Or(Box<Condition>, Box<Condition>),
|
||||||
|
Group(Box<Condition>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Condition {
|
||||||
|
pub fn new(condition: &str) -> Self {
|
||||||
|
Condition::Simple(condition.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn and(self, other: Self) -> Self {
|
||||||
|
Condition::And(Box::new(self), Box::new(other))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn or(self, other: Self) -> Self {
|
||||||
|
Condition::Or(Box::new(self), Box::new(other))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn group(self) -> Self {
|
||||||
|
Condition::Group(Box::new(self))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_equal(left: &str, right: &str) -> Self {
|
||||||
|
Condition::Simple(format!("{} = {}", left, right))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn not_equal(left: &str, right: &str) -> Self {
|
||||||
|
Condition::Simple(format!("{} != {}", left, right))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_null(value: &str) -> Self {
|
||||||
|
Condition::Simple(format!("{} IS NULL", value))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn not_null(value: &str) -> Self {
|
||||||
|
Condition::Simple(format!("{} IS NOT NULL", value))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_in(left: &str, right: &[&str]) -> Self {
|
||||||
|
let right_list = right
|
||||||
|
.iter()
|
||||||
|
.map(|v| format!("'{}'", v))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ");
|
||||||
|
Condition::Simple(format!("{} IN ({})", left, right_list))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn not_in(left: &str, right: &[&str]) -> Self {
|
||||||
|
let right_list = right
|
||||||
|
.iter()
|
||||||
|
.map(|v| format!("'{}'", v))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ");
|
||||||
|
Condition::Simple(format!("{} NOT IN ({})", left, right_list))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn like(left: &str, right: &str) -> Self {
|
||||||
|
Condition::Simple(format!("{} LIKE '{}'", left, right))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn not_like(left: &str, right: &str) -> Self {
|
||||||
|
Condition::Simple(format!("{} NOT LIKE '{}'", left, right))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn i_like(left: &str, right: &str) -> Self {
|
||||||
|
Condition::Simple(format!("{} ILIKE '{}'", left, right))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn not_i_like(left: &str, right: &str) -> Self {
|
||||||
|
Condition::Simple(format!("{} NOT ILIKE '{}'", left, right))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gt(left: &str, right: &str) -> Self {
|
||||||
|
Condition::Simple(format!("{} > {}", left, right))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gte(left: &str, right: &str) -> Self {
|
||||||
|
Condition::Simple(format!("{} >= {}", left, right))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lt(left: &str, right: &str) -> Self {
|
||||||
|
Condition::Simple(format!("{} < {}", left, right))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lte(left: &str, right: &str) -> Self {
|
||||||
|
Condition::Simple(format!("{} <= {}", left, right))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_sql(&self) -> String {
|
||||||
|
match self {
|
||||||
|
Condition::Simple(s) => s.to_string(),
|
||||||
|
Condition::And(a, b) => format!("{} AND {}", a.to_sql(), b.to_sql()),
|
||||||
|
Condition::Or(a, b) => format!("{} OR {}", a.to_sql(), b.to_sql()),
|
||||||
|
Condition::Group(a) => format!("({})", a.to_sql()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user