use crate::query::QueryBuilder;
use crate::types::{Client, Common, Method, Select};
use serde_json::Value;
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct ChainBuilder {
client: Client,
pub(crate) db: Option<String>,
pub(crate) table: Option<String>,
pub(crate) table_raw: Option<(String, Option<Vec<Value>>)>,
pub(crate) as_name: Option<String>,
pub(crate) select: Vec<Select>,
pub(crate) query: QueryBuilder,
pub(crate) method: Method,
pub(crate) insert_update: Value,
pub(crate) sql_str: String,
pub(crate) is_distinct: bool,
}
impl ChainBuilder {
pub fn new(client: Client) -> ChainBuilder {
let query = QueryBuilder::new(client.clone());
ChainBuilder {
client,
table: None,
table_raw: None,
select: Vec::new(),
as_name: None,
db: None,
query,
method: Method::Select,
insert_update: Value::Null,
sql_str: String::new(),
is_distinct: false,
}
}
#[cfg(feature = "mysql")]
pub fn new_mysql() -> ChainBuilder {
ChainBuilder::new(Client::Mysql)
}
#[cfg(feature = "sqlite")]
pub fn new_sqlite() -> ChainBuilder {
ChainBuilder::new(Client::Sqlite)
}
pub fn db(&mut self, db: &str) -> &mut ChainBuilder {
self.db = Some(db.to_string());
self
}
pub fn table(&mut self, table: &str) -> &mut ChainBuilder {
self.table = Some(table.to_string());
self
}
pub fn table_raw(&mut self, table: &str, val: Option<Vec<Value>>) -> &mut ChainBuilder {
self.table_raw = Some((table.to_string(), val));
self
}
pub fn distinct(&mut self) -> &mut ChainBuilder {
self.is_distinct = true;
self
}
pub fn select(&mut self, select: Select) -> &mut ChainBuilder {
self.method = Method::Select;
self.select.push(select);
self
}
pub fn select_raw(&mut self, sql: &str, binds: Option<Vec<Value>>) -> &mut ChainBuilder {
self.method = Method::Select;
self.select.push(Select::Raw(sql.to_string(), binds));
self
}
pub fn select_distinct(&mut self, columns: Vec<String>) -> &mut ChainBuilder {
self.method = Method::Select;
self.is_distinct = true;
self.select.push(Select::Columns(columns));
self
}
pub fn select_count(&mut self, column: &str) -> &mut ChainBuilder {
self.method = Method::Select;
self.select
.push(Select::Raw(format!("COUNT({})", column), None));
self
}
pub fn select_sum(&mut self, column: &str) -> &mut ChainBuilder {
self.method = Method::Select;
self.select
.push(Select::Raw(format!("SUM({})", column), None));
self
}
pub fn select_avg(&mut self, column: &str) -> &mut ChainBuilder {
self.method = Method::Select;
self.select
.push(Select::Raw(format!("AVG({})", column), None));
self
}
pub fn select_max(&mut self, column: &str) -> &mut ChainBuilder {
self.method = Method::Select;
self.select
.push(Select::Raw(format!("MAX({})", column), None));
self
}
pub fn select_min(&mut self, column: &str) -> &mut ChainBuilder {
self.method = Method::Select;
self.select
.push(Select::Raw(format!("MIN({})", column), None));
self
}
pub fn select_alias(&mut self, column: &str, alias: &str) -> &mut ChainBuilder {
self.method = Method::Select;
self.select
.push(Select::Raw(format!("{} AS {}", column, alias), None));
self
}
pub fn insert(&mut self, data: Value) -> &mut ChainBuilder {
self.method = Method::Insert;
self.insert_update = data;
self
}
pub fn insert_many(&mut self, data: Vec<Value>) -> &mut ChainBuilder {
self.method = Method::InsertMany;
self.insert_update = Value::Array(data);
self
}
pub fn update(&mut self, data: Value) -> &mut ChainBuilder {
self.method = Method::Update;
self.insert_update = data;
self
}
pub fn insert_ignore(&mut self, data: Value) -> &mut ChainBuilder {
self.method = Method::Insert;
self.insert_update = data;
self
}
pub fn insert_or_update(&mut self, data: Value, _update_data: Value) -> &mut ChainBuilder {
self.method = Method::Insert;
self.insert_update = data;
self
}
pub fn update_raw(&mut self, _sql: &str, _binds: Option<Vec<Value>>) -> &mut ChainBuilder {
self.method = Method::Update;
self
}
pub fn increment(&mut self, column: &str, amount: i64) -> &mut ChainBuilder {
self.method = Method::Update;
let update_data = serde_json::json!({
column: format!("{} + {}", column, amount)
});
self.insert_update = update_data;
self
}
pub fn decrement(&mut self, column: &str, amount: i64) -> &mut ChainBuilder {
self.method = Method::Update;
let update_data = serde_json::json!({
column: format!("{} - {}", column, amount)
});
self.insert_update = update_data;
self
}
pub fn delete(&mut self) -> &mut ChainBuilder {
self.method = Method::Delete;
self
}
pub fn as_name(&mut self, name: &str) -> &mut ChainBuilder {
self.as_name = Some(name.to_string());
self
}
pub fn with(&mut self, alias: &str, chain_builder: ChainBuilder) -> &mut ChainBuilder {
self.query
.query_common
.push(Common::With(alias.to_string(), false, chain_builder));
self
}
pub fn with_recursive(
&mut self,
alias: &str,
chain_builder: ChainBuilder,
) -> &mut ChainBuilder {
self.query
.query_common
.push(Common::With(alias.to_string(), true, chain_builder));
self
}
pub fn union(&mut self, chain_builder: ChainBuilder) -> &mut ChainBuilder {
self.query
.query_common
.push(Common::Union(false, chain_builder));
self
}
pub fn union_all(&mut self, chain_builder: ChainBuilder) -> &mut ChainBuilder {
self.query
.query_common
.push(Common::Union(true, chain_builder));
self
}
pub fn query(&mut self, query: impl FnOnce(&mut QueryBuilder)) {
query(&mut self.query);
}
pub fn add_raw(&mut self, sql: &str, val: Option<Vec<Value>>) {
self.query.raw.push((sql.to_string(), val));
}
pub fn to_sql(&mut self) -> (String, Vec<Value>) {
match self.client {
#[cfg(feature = "mysql")]
Client::Mysql => {
let rs = crate::mysql::merge_to_sql(crate::mysql::to_sql(self));
self.sql_str = rs.0.clone();
(self.sql_str.clone(), rs.1)
}
#[cfg(feature = "sqlite")]
Client::Sqlite => {
let rs = crate::sqlite::merge_to_sql(crate::sqlite::to_sql(self));
self.sql_str = rs.0.clone();
(self.sql_str.clone(), rs.1)
}
#[cfg(feature = "postgres")]
Client::Postgres => {
panic!("PostgreSQL support not yet implemented");
}
_ => {
panic!("Unsupported database client");
}
}
}
}