mem-query 0.0.1

Relational algebra interface for Rust collections
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!{} }
}

/// A description of requested records
///
/// Types that implement `QueryRequest` describe the columns, row, and order
/// of records that should be returned from a query.  This is then passed
/// to a `Relation`'s `plan` or `query` methods to obtain an iterator.
///
/// This is not implemented directly.  Instead, implement `QueryRequestImpl`,
/// and this will be automatically provided when the required conditions are
/// met.
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: Clone + QueryRequestImpl> QueryRequest for QR
where <QR as QueryRequestImpl>::OutputCols: Header,
      <QR as QueryRequestImpl>::Filters: List,
*/
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 }
}