use crate::query::QueryBuilder;
use crate::types::Common;
use serde_json::Value;
fn build_placeholders(len: usize) -> String {
if len == 0 {
return String::new();
}
let mut s = String::with_capacity(len * 3 - 2);
s.push('?');
for _ in 1..len {
s.push_str(", ?");
}
s
}
pub trait QueryCommon {
fn with(&mut self, alias: &str, chain_builder: crate::builder::ChainBuilder);
fn with_recursive(&mut self, alias: &str, chain_builder: crate::builder::ChainBuilder);
fn union(&mut self, chain_builder: crate::builder::ChainBuilder);
fn union_all(&mut self, chain_builder: crate::builder::ChainBuilder);
fn limit(&mut self, limit: usize);
fn offset(&mut self, offset: usize);
fn group_by(&mut self, columns: Vec<String>);
fn group_by_raw(&mut self, sql: &str, binds: Option<Vec<Value>>);
fn order_by(&mut self, column: &str, order: &str);
fn order_by_raw(&mut self, sql: &str, binds: Option<Vec<Value>>);
}
impl QueryCommon for QueryBuilder {
fn with(&mut self, alias: &str, chain_builder: crate::builder::ChainBuilder) {
self.query_common
.push(Common::With(alias.to_string(), false, chain_builder));
}
fn with_recursive(&mut self, alias: &str, chain_builder: crate::builder::ChainBuilder) {
self.query_common
.push(Common::With(alias.to_string(), true, chain_builder));
}
fn union(&mut self, chain_builder: crate::builder::ChainBuilder) {
self.query_common.push(Common::Union(false, chain_builder));
}
fn union_all(&mut self, chain_builder: crate::builder::ChainBuilder) {
self.query_common.push(Common::Union(true, chain_builder));
}
fn limit(&mut self, limit: usize) {
self.query_common.push(Common::Limit(limit));
}
fn offset(&mut self, offset: usize) {
self.query_common.push(Common::Offset(offset));
}
fn group_by(&mut self, columns: Vec<String>) {
self.query_common.push(Common::GroupBy(columns));
}
fn group_by_raw(&mut self, sql: &str, binds: Option<Vec<Value>>) {
self.query_common
.push(Common::GroupByRaw(sql.to_string(), binds));
}
fn order_by(&mut self, column: &str, order: &str) {
self.query_common
.push(Common::OrderBy(column.to_string(), order.to_string()));
}
fn order_by_raw(&mut self, sql: &str, binds: Option<Vec<Value>>) {
self.query_common
.push(Common::OrderByRaw(sql.to_string(), binds));
}
}
pub trait HavingClauses {
fn having(&mut self, column: &str, operator: &str, value: Value);
fn having_raw(&mut self, sql: &str, binds: Option<Vec<Value>>);
fn having_between(&mut self, column: &str, values: [Value; 2]);
fn having_in(&mut self, column: &str, values: Vec<Value>);
fn having_not_in(&mut self, column: &str, values: Vec<Value>);
}
impl HavingClauses for QueryBuilder {
fn having(&mut self, column: &str, operator: &str, value: Value) {
let sql = format!("{} {} ?", column, operator);
self.query_common
.push(Common::Having(sql, Some(vec![value])));
}
fn having_raw(&mut self, sql: &str, binds: Option<Vec<Value>>) {
self.query_common
.push(Common::Having(sql.to_string(), binds));
}
fn having_between(&mut self, column: &str, values: [Value; 2]) {
let sql = format!("{} BETWEEN ? AND ?", column);
self.query_common
.push(Common::Having(sql, Some(values.to_vec())));
}
fn having_in(&mut self, column: &str, values: Vec<Value>) {
if values.is_empty() {
self.query_common
.push(Common::Having("1 = 0".to_string(), None));
return;
}
let placeholders = build_placeholders(values.len());
let sql = format!("{} IN ({})", column, placeholders);
self.query_common.push(Common::Having(sql, Some(values)));
}
fn having_not_in(&mut self, column: &str, values: Vec<Value>) {
if values.is_empty() {
self.query_common
.push(Common::Having("1 = 1".to_string(), None));
return;
}
let placeholders = build_placeholders(values.len());
let sql = format!("{} NOT IN ({})", column, placeholders);
self.query_common.push(Common::Having(sql, Some(values)));
}
}
pub trait WhereClauses {
fn where_eq(&mut self, column: &str, value: Value);
fn where_ne(&mut self, column: &str, value: Value);
fn where_in(&mut self, column: &str, values: Vec<Value>);
fn where_not_in(&mut self, column: &str, values: Vec<Value>);
fn where_null(&mut self, column: &str);
fn where_not_null(&mut self, column: &str);
fn where_between(&mut self, column: &str, values: [Value; 2]);
fn where_not_between(&mut self, column: &str, values: [Value; 2]);
fn where_like(&mut self, column: &str, value: Value);
fn where_not_like(&mut self, column: &str, value: Value);
fn where_ilike(&mut self, column: &str, value: Value);
fn where_gt(&mut self, column: &str, value: Value);
fn where_gte(&mut self, column: &str, value: Value);
fn where_lt(&mut self, column: &str, value: Value);
fn where_lte(&mut self, column: &str, value: Value);
fn where_column(&mut self, lhs: &str, operator: &str, rhs: &str);
fn where_exists(&mut self, query: impl FnOnce(&mut crate::builder::ChainBuilder));
fn where_not_exists(&mut self, query: impl FnOnce(&mut crate::builder::ChainBuilder));
fn where_json_contains(&mut self, column: &str, value: Value);
fn where_subquery(&mut self, query: impl FnOnce(&mut QueryBuilder));
fn or(&mut self) -> &mut QueryBuilder;
fn where_raw(&mut self, sql: &str, binds: Option<Vec<Value>>);
}
impl WhereClauses for QueryBuilder {
fn where_eq(&mut self, column: &str, value: Value) {
self.statement.push(crate::types::Statement::Value(
column.to_string(),
crate::query::Operator::Equal,
value,
));
}
fn where_ne(&mut self, column: &str, value: Value) {
self.statement.push(crate::types::Statement::Value(
column.to_string(),
crate::query::Operator::NotEqual,
value,
));
}
fn where_in(&mut self, column: &str, values: Vec<Value>) {
self.statement.push(crate::types::Statement::Value(
column.to_string(),
crate::query::Operator::In,
Value::Array(values),
));
}
fn where_not_in(&mut self, column: &str, values: Vec<Value>) {
self.statement.push(crate::types::Statement::Value(
column.to_string(),
crate::query::Operator::NotIn,
Value::Array(values),
));
}
fn where_null(&mut self, column: &str) {
self.statement.push(crate::types::Statement::Value(
column.to_string(),
crate::query::Operator::IsNull,
Value::Null,
));
}
fn where_not_null(&mut self, column: &str) {
self.statement.push(crate::types::Statement::Value(
column.to_string(),
crate::query::Operator::IsNotNull,
Value::Null,
));
}
fn where_between(&mut self, column: &str, values: [Value; 2]) {
self.statement.push(crate::types::Statement::Value(
column.to_string(),
crate::query::Operator::Between,
Value::Array(values.to_vec()),
));
}
fn where_not_between(&mut self, column: &str, values: [Value; 2]) {
self.statement.push(crate::types::Statement::Value(
column.to_string(),
crate::query::Operator::NotBetween,
Value::Array(values.to_vec()),
));
}
fn where_like(&mut self, column: &str, value: Value) {
self.statement.push(crate::types::Statement::Value(
column.to_string(),
crate::query::Operator::Like,
value,
));
}
fn where_not_like(&mut self, column: &str, value: Value) {
self.statement.push(crate::types::Statement::Value(
column.to_string(),
crate::query::Operator::NotLike,
value,
));
}
fn where_gt(&mut self, column: &str, value: Value) {
self.statement.push(crate::types::Statement::Value(
column.to_string(),
crate::query::Operator::GreaterThan,
value,
));
}
fn where_gte(&mut self, column: &str, value: Value) {
self.statement.push(crate::types::Statement::Value(
column.to_string(),
crate::query::Operator::GreaterThanOrEqual,
value,
));
}
fn where_lt(&mut self, column: &str, value: Value) {
self.statement.push(crate::types::Statement::Value(
column.to_string(),
crate::query::Operator::LessThan,
value,
));
}
fn where_lte(&mut self, column: &str, value: Value) {
self.statement.push(crate::types::Statement::Value(
column.to_string(),
crate::query::Operator::LessThanOrEqual,
value,
));
}
fn where_subquery(&mut self, query: impl FnOnce(&mut QueryBuilder)) {
let mut sub_query = QueryBuilder::new(self.client.clone());
query(&mut sub_query);
self.statement
.push(crate::types::Statement::SubChain(Box::new(sub_query)));
}
fn or(&mut self) -> &mut QueryBuilder {
let or_query = QueryBuilder::new(self.client.clone());
self.statement
.push(crate::types::Statement::OrChain(Box::new(or_query)));
self.statement.last_mut().unwrap().to_query_builder()
}
fn where_raw(&mut self, sql: &str, binds: Option<Vec<Value>>) {
self.statement
.push(crate::types::Statement::Raw((sql.to_string(), binds)));
}
fn where_ilike(&mut self, column: &str, value: Value) {
let sql = format!("LOWER({}) LIKE LOWER(?)", column);
self.statement
.push(crate::types::Statement::Raw((sql, Some(vec![value]))));
}
fn where_column(&mut self, lhs: &str, operator: &str, rhs: &str) {
let sql = format!("{} {} {}", lhs, operator, rhs);
self.statement
.push(crate::types::Statement::Raw((sql, None)));
}
fn where_exists(&mut self, query: impl FnOnce(&mut crate::builder::ChainBuilder)) {
let mut sub_builder = crate::builder::ChainBuilder::new(self.client.clone());
query(&mut sub_builder);
let (sub_sql, sub_binds) = sub_builder.to_sql();
let sql = format!("EXISTS ({})", sub_sql);
self.statement
.push(crate::types::Statement::Raw((sql, Some(sub_binds))));
}
fn where_not_exists(&mut self, query: impl FnOnce(&mut crate::builder::ChainBuilder)) {
let mut sub_builder = crate::builder::ChainBuilder::new(self.client.clone());
query(&mut sub_builder);
let (sub_sql, sub_binds) = sub_builder.to_sql();
let sql = format!("NOT EXISTS ({})", sub_sql);
self.statement
.push(crate::types::Statement::Raw((sql, Some(sub_binds))));
}
fn where_json_contains(&mut self, column: &str, value: Value) {
let sql = format!("JSON_CONTAINS({}, ?)", column);
self.statement
.push(crate::types::Statement::Raw((sql, Some(vec![value]))));
}
}