use tylisp::{sexpr,sexpr_val,defun, marker_traits::List, ops::Ret};
use crate::{
relation::RelationImpl,
query::filter::QueryFilter,
query::order::SortKey,
};
use std::{
marker::PhantomData,
};
pub trait QueryRequestImpl {
type Filters;
type OrderBy;
fn into_filters(self)->Self::Filters;
}
#[derive(Copy,Clone,Debug)]
pub struct GenericQueryRequest<Filters,Order> {
filters: Filters,
phantom: PhantomData<Order>,
}
#[derive(Copy,Clone,Debug,Default)]
pub struct NewRequest;
defun! { NewRequest {
(Filters: List + QueryFilter, Order: List + SortKey)
{ filters: Filters, _: PhantomData<Order> } =>
{Ret, @GenericQueryRequest<Filters,Order> = GenericQueryRequest { filters, phantom: PhantomData }};
}}
#[test]
fn test_new_request() {
col!{A:u32}
col!{B:u32}
use tylisp::{calc,HCons,HNil, ops::Phantom, ops::list::BuildList};
use super::filter::Exact;
let _: GenericQueryRequest<HNil, HNil> = calc!{NewRequest, @HNil = HNil, {Phantom, @HNil}};
let _: GenericQueryRequest<HCons<Exact<B>,HNil>, HNil>
= calc!{NewRequest, {BuildList, @Exact<B> = Exact(B(42))}, {Phantom, @HNil}};
}
impl<F,O> GenericQueryRequest<F,O> {
pub fn new(filters:F) -> Self {
GenericQueryRequest { filters, phantom: PhantomData }
}
}
impl<F,O> QueryRequestImpl for GenericQueryRequest<F,O> {
type Filters = F;
type OrderBy = O;
fn into_filters(self)->Self::Filters { self.filters }
}
#[derive(Debug)]
pub struct AllRows<R>(PhantomData<R>);
impl<R> Default for AllRows<R> where Self:QueryRequest {
fn default()->Self { AllRows(PhantomData) }
}
impl<R> Clone for AllRows<R> {
fn clone(&self)->Self { AllRows(PhantomData) }
}
impl<R> Copy for AllRows<R> {}
impl<R:RelationImpl> QueryRequestImpl for AllRows<R> {
type Filters = sexpr!{};
type OrderBy = sexpr!{};
fn into_filters(self)->Self::Filters { sexpr_val!{} }
}
pub trait QueryRequest: Clone {
type Filters: List + QueryFilter;
type OrderBy: List + SortKey;
fn into_filters(self)->Self::Filters;
fn add_filter<F>(self, filter:F)->AddFilter<Self, F>
where AddFilter<Self, F>: QueryRequest {
AddFilter { req: self, filter }
}
fn set_filters<F>(self, filters:F)->ReplaceFilters<Self, F>
where ReplaceFilters<Self, F>: QueryRequest {
ReplaceFilters::new(self, filters)
}
fn set_order<K>(self)->ReplaceOrder<Self, K>
where ReplaceOrder<Self, K>: QueryRequest {
ReplaceOrder { req: self, key: PhantomData }
}
}
impl<QR, Filt, Order> QueryRequest for QR
where QR: Clone + QueryRequestImpl<Filters = Filt, OrderBy = Order>,
Filt: List + QueryFilter,
Order: List + SortKey,
{
type Filters = <QR as QueryRequestImpl>::Filters;
type OrderBy = <QR as QueryRequestImpl>::OrderBy;
#[inline(always)]
fn into_filters(self)-><Self as QueryRequestImpl>::Filters {
QueryRequestImpl::into_filters(self)
}
}
#[derive(Debug, Clone, Copy)]
pub struct BlankRequest;
impl QueryRequestImpl for BlankRequest {
type Filters = sexpr!{};
type OrderBy = sexpr!{};
#[inline(always)]
fn into_filters(self)->Self::Filters { sexpr_val!{} }
}
#[derive(Clone,Debug)]
pub struct ReplaceOrder<Req, Key> {
req: Req,
key: PhantomData<Key>,
}
impl<Req:QueryRequest,Key> QueryRequestImpl for ReplaceOrder<Req, Key> {
type Filters = Req::Filters;
type OrderBy = Key;
#[inline(always)]
fn into_filters(self)->Self::Filters { self.req.into_filters() }
}
#[derive(Debug,Clone)]
pub struct AddFilter<Req, F> {
req: Req,
filter: F
}
impl<Req:QueryRequest, F> QueryRequestImpl for AddFilter<Req,F> {
type Filters = sexpr!{F; Req::Filters};
type OrderBy = Req::OrderBy;
#[inline(always)]
fn into_filters(self)->Self::Filters
{
sexpr_val!{self.filter; self.req.into_filters() }
}
}
#[derive(Debug,Clone)]
pub struct ReplaceFilters<Req, F> {
req: PhantomData<Req>,
filters: F
}
impl<Req,F> ReplaceFilters<Req,F> where Self: QueryRequest {
pub fn new(_:Req, filters:F) -> Self {
ReplaceFilters { req: PhantomData, filters }
}
}
impl<Req:QueryRequest, F> QueryRequestImpl for ReplaceFilters<Req, F> {
type Filters = F;
type OrderBy = Req::OrderBy;
#[inline(always)]
fn into_filters(self)->Self::Filters { self.filters }
}