Added distinct_on to query builder
This commit is contained in:
@@ -1,21 +1,24 @@
|
|||||||
|
use std::fmt::Write;
|
||||||
use crate::data::condition::Condition;
|
use crate::data::condition::Condition;
|
||||||
use crate::data::executable_query::ExecutableQuery;
|
use crate::data::executable_query::ExecutableQuery;
|
||||||
use crate::data::Value;
|
use crate::data::Value;
|
||||||
|
|
||||||
pub struct QueryBuilder {
|
pub struct QueryBuilder<'a> {
|
||||||
table: String,
|
table: &'a str,
|
||||||
columns: Vec<String>,
|
columns: Vec<&'a str>,
|
||||||
|
distinct_on: Option<Vec<String>>,
|
||||||
condition: Option<Condition>,
|
condition: Option<Condition>,
|
||||||
order_by: Vec<String>,
|
order_by: Vec<String>,
|
||||||
limit: Option<usize>,
|
limit: Option<usize>,
|
||||||
offset: Option<usize>,
|
offset: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl QueryBuilder {
|
impl<'a> QueryBuilder<'a> {
|
||||||
pub fn new(table: &str) -> Self {
|
pub fn new(table: &'a str) -> Self {
|
||||||
QueryBuilder {
|
QueryBuilder {
|
||||||
table: table.to_string(),
|
table,
|
||||||
columns: Vec::new(),
|
columns: Vec::new(),
|
||||||
|
distinct_on: None,
|
||||||
condition: None,
|
condition: None,
|
||||||
order_by: Vec::new(),
|
order_by: Vec::new(),
|
||||||
limit: None,
|
limit: None,
|
||||||
@@ -23,8 +26,13 @@ impl QueryBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select(mut self, columns: &[&str]) -> Self {
|
pub fn select(mut self, columns: &[&'a str]) -> Self {
|
||||||
self.columns = columns.iter().map(|s| s.to_string()).collect();
|
self.columns.extend(columns);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn distinct_on(mut self, columns: &[&str]) -> Self {
|
||||||
|
self.distinct_on = Some(columns.iter().map(|s| s.to_string()).collect());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,8 +41,11 @@ impl QueryBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn order_by(mut self, column: &str, direction: &str) -> Self {
|
pub fn order_by(mut self, column: &str, direction: Option<OrderDirection>) -> Self {
|
||||||
self.order_by.push(format!("{} {}", column, direction));
|
match direction {
|
||||||
|
Some(order) => self.order_by.push(format!("{} {}", column, order.to_string())),
|
||||||
|
None => self.order_by.push(column.to_string()),
|
||||||
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +55,22 @@ impl QueryBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExecutableQuery for QueryBuilder {
|
pub enum OrderDirection {
|
||||||
|
Asc,
|
||||||
|
Desc
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for OrderDirection {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
let direction_str = match self {
|
||||||
|
OrderDirection::Asc => "ASC",
|
||||||
|
OrderDirection::Desc => "DESC",
|
||||||
|
};
|
||||||
|
write!(f, "{}", direction_str)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ExecutableQuery for QueryBuilder<'a> {
|
||||||
fn build(&self) -> (String, Vec<Value>) {
|
fn build(&self) -> (String, Vec<Value>) {
|
||||||
let columns = if self.columns.is_empty() {
|
let columns = if self.columns.is_empty() {
|
||||||
"*".to_string()
|
"*".to_string()
|
||||||
@@ -52,7 +78,16 @@ impl ExecutableQuery for QueryBuilder {
|
|||||||
self.columns.join(",")
|
self.columns.join(",")
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut query = format!("SELECT {} FROM {}", columns, self.table);
|
let mut query = String::new();
|
||||||
|
|
||||||
|
if let Some(distinct_columns) = &self.distinct_on {
|
||||||
|
let distinct_on_clause = distinct_columns.join(",");
|
||||||
|
query = format!("SELECT DISTINCT ON ({}) {}", distinct_on_clause, columns);
|
||||||
|
} else {
|
||||||
|
query = format!("SELECT {}", columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
query.push_str(format!(" FROM {}", self.table).as_str());
|
||||||
|
|
||||||
let mut values: Vec<Value> = Vec::new();
|
let mut values: Vec<Value> = Vec::new();
|
||||||
if let Some(condition) = &self.condition {
|
if let Some(condition) = &self.condition {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use axum::http::StatusCode;
|
use axum::http::StatusCode;
|
||||||
use axum::{http, Json};
|
use axum::Json;
|
||||||
use axum::response::{IntoResponse, Response};
|
use axum::response::{IntoResponse, Response};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use dotenv::{dotenv, from_filename};
|
use dotenv::from_filename;
|
||||||
use serenity::http::Http;
|
use serenity::http::Http;
|
||||||
use serenity::prelude::*;
|
use serenity::prelude::*;
|
||||||
use songbird::{SerenityInit, Songbird};
|
use songbird::{SerenityInit, Songbird};
|
||||||
|
|||||||
Reference in New Issue
Block a user