use crate::{AkitaValue, GetFields, IntoAkitaValue, SqlOperator, Wrapper};
use std::marker::PhantomData;
pub struct LambdaWrapper<T: GetFields> {
wrapper: Wrapper,
_phantom: PhantomData<T>,
}
impl<T: GetFields> LambdaWrapper<T> {
pub fn new() -> Self {
Self {
wrapper: Wrapper::new(),
_phantom: PhantomData,
}
}
pub fn from_wrapper(wrapper: Wrapper) -> Self {
Self {
wrapper,
_phantom: PhantomData,
}
}
pub fn into_wrapper(self) -> Wrapper {
self.wrapper
}
pub fn wrapper(&self) -> &Wrapper {
&self.wrapper
}
pub fn eq<V: IntoAkitaValue>(mut self, field: fn(&T) -> String, value: V) -> Self {
let column = get_column_name::<T>(field);
self.wrapper = self.wrapper.eq(column, value);
self
}
pub fn ne<V: IntoAkitaValue>(mut self, field: fn(&T) -> String, value: V) -> Self {
let column = get_column_name::<T>(field);
self.wrapper = self.wrapper.ne(column, value);
self
}
pub fn gt<V: IntoAkitaValue>(mut self, field: fn(&T) -> String, value: V) -> Self {
let column = get_column_name::<T>(field);
self.wrapper = self.wrapper.gt(column, value);
self
}
pub fn ge<V: IntoAkitaValue>(mut self, field: fn(&T) -> String, value: V) -> Self {
let column = get_column_name::<T>(field);
self.wrapper = self.wrapper.ge(column, value);
self
}
pub fn lt<V: IntoAkitaValue>(mut self, field: fn(&T) -> String, value: V) -> Self {
let column = get_column_name::<T>(field);
self.wrapper = self.wrapper.lt(column, value);
self
}
pub fn le<V: IntoAkitaValue>(mut self, field: fn(&T) -> String, value: V) -> Self {
let column = get_column_name::<T>(field);
self.wrapper = self.wrapper.le(column, value);
self
}
pub fn like<V: IntoAkitaValue>(mut self, field: fn(&T) -> String, value: V) -> Self {
let column = get_column_name::<T>(field);
self.wrapper = self.wrapper.like(column, value);
self
}
pub fn not_like<V: IntoAkitaValue>(mut self, field: fn(&T) -> String, value: V) -> Self {
let column = get_column_name::<T>(field);
self.wrapper = self.wrapper.not_like(column, value);
self
}
pub fn is_null(mut self, field: fn(&T) -> String) -> Self {
let column = get_column_name::<T>(field);
self.wrapper = self.wrapper.is_null(column);
self
}
pub fn is_not_null(mut self, field: fn(&T) -> String) -> Self {
let column = get_column_name::<T>(field);
self.wrapper = self.wrapper.is_not_null(column);
self
}
pub fn r#in<V: IntoAkitaValue, I: IntoIterator<Item = V>>(
mut self,
field: fn(&T) -> String,
values: I,
) -> Self {
let column = get_column_name::<T>(field);
self.wrapper = self.wrapper.r#in(column, values);
self
}
pub fn not_in<V: IntoAkitaValue, I: IntoIterator<Item = V>>(
mut self,
field: fn(&T) -> String,
values: I,
) -> Self {
let column = get_column_name::<T>(field);
self.wrapper = self.wrapper.not_in(column, values);
self
}
pub fn between<V: IntoAkitaValue>(mut self, field: fn(&T) -> String, start: V, end: V) -> Self {
let column = get_column_name::<T>(field);
self.wrapper = self.wrapper.between(column, start, end);
self
}
pub fn not_between<V: IntoAkitaValue>(
mut self,
field: fn(&T) -> String,
start: V,
end: V,
) -> Self {
let column = get_column_name::<T>(field);
self.wrapper = self.wrapper.not_between(column, start, end);
self
}
pub fn and<F>(mut self, func: F) -> Self
where
F: FnOnce(LambdaWrapper<T>) -> LambdaWrapper<T>,
{
let inner = func(LambdaWrapper::new());
self.wrapper = self.wrapper.and(|_| inner.into_wrapper());
self
}
pub fn or<F>(mut self, func: F) -> Self
where
F: FnOnce(LambdaWrapper<T>) -> LambdaWrapper<T>,
{
let inner = func(LambdaWrapper::new());
self.wrapper = self.wrapper.or(|_| inner.into_wrapper());
self
}
pub fn or_direct(mut self) -> Self {
self.wrapper = self.wrapper.or_direct();
self
}
pub fn order_by_asc(mut self, field: fn(&T) -> String) -> Self {
let column = get_column_name::<T>(field);
self.wrapper = self.wrapper.order_by_asc(vec![column]);
self
}
pub fn order_by_desc(mut self, field: fn(&T) -> String) -> Self {
let column = get_column_name::<T>(field);
self.wrapper = self.wrapper.order_by_desc(vec![column]);
self
}
pub fn limit(mut self, limit: u64) -> Self {
self.wrapper = self.wrapper.limit(limit);
self
}
pub fn offset(mut self, offset: u64) -> Self {
self.wrapper = self.wrapper.offset(offset);
self
}
pub fn page(mut self, page: u64, size: u64) -> Self {
self.wrapper = self.wrapper.page(page, size);
self
}
pub fn when(mut self, condition: bool) -> Self {
self.wrapper = self.wrapper.when(condition);
self
}
pub fn unless(mut self, condition: bool) -> Self {
self.wrapper = self.wrapper.unless(condition);
self
}
}
fn get_column_name<T: GetFields>(field: fn(&T) -> String) -> String {
let fields = T::fields();
for f in &fields {
return f.name.clone();
}
"unknown".to_string()
}
#[cfg(test)]
mod tests {
use super::*;
struct MockEntity;
impl GetFields for MockEntity {
fn fields() -> Vec<crate::FieldName> {
vec![
crate::FieldName {
name: "id".to_string(),
column: "id".to_string(),
..Default::default()
},
crate::FieldName {
name: "name".to_string(),
column: "user_name".to_string(),
..Default::default()
},
]
}
}
#[test]
fn test_lambda_wrapper_new() {
let wrapper = LambdaWrapper::<MockEntity>::new();
assert!(wrapper.wrapper().get_where_conditions().is_empty());
}
#[test]
fn test_lambda_wrapper_into() {
let wrapper = LambdaWrapper::<MockEntity>::new();
let inner = wrapper.into_wrapper();
assert!(inner.get_where_conditions().is_empty());
}
}