qraft-core 0.1.2

Core type system, query model, decoding, and SQL lowering primitives for qraft.
Documentation
//! Temporal extraction expressions for date and time filtering.

use core::marker::PhantomData;

use crate::{
    BigInt, Date, Time, Timestamp,
    expression::{Binary, Expression, op},
    instr::TemporalKind,
    lower::LowerCtx,
};

pub struct DateExtract<E> {
    inner: E,
}

pub struct TimeExtract<E> {
    inner: E,
}

pub struct YearExtract<E, S> {
    inner: E,
    marker: PhantomData<S>,
}

pub struct MonthExtract<E, S> {
    inner: E,
    marker: PhantomData<S>,
}

pub struct DayExtract<E, S> {
    inner: E,
    marker: PhantomData<S>,
}

pub struct TimestampSource;
pub struct DateSource;

pub trait TimestampExt: Sized + Expression<Type = Timestamp> {
    fn date(self) -> DateExtract<Self> {
        DateExtract { inner: self }
    }

    fn time(self) -> TimeExtract<Self> {
        TimeExtract { inner: self }
    }

    fn year(self) -> YearExtract<Self, TimestampSource> {
        YearExtract {
            inner: self,
            marker: PhantomData,
        }
    }

    fn month(self) -> MonthExtract<Self, TimestampSource> {
        MonthExtract {
            inner: self,
            marker: PhantomData,
        }
    }

    fn day(self) -> DayExtract<Self, TimestampSource> {
        DayExtract {
            inner: self,
            marker: PhantomData,
        }
    }
}

impl<E> TimestampExt for E where E: Expression<Type = Timestamp> {}

pub trait TimestampRelativeExt: Sized + Expression<Type = Timestamp> {
    fn past(self) -> Binary<op::Lt, Self, crate::expression::Now> {
        Binary {
            left: self,
            right: crate::expression::now(),
            op: PhantomData,
        }
    }

    fn future(self) -> Binary<op::Gt, Self, crate::expression::Now> {
        Binary {
            left: self,
            right: crate::expression::now(),
            op: PhantomData,
        }
    }

    fn today(self) -> Binary<op::Eq, DateExtract<Self>, crate::expression::CurrentDate> {
        Binary {
            left: self.date(),
            right: crate::expression::current_date(),
            op: PhantomData,
        }
    }

    fn before_today(self) -> Binary<op::Lt, DateExtract<Self>, crate::expression::CurrentDate> {
        Binary {
            left: self.date(),
            right: crate::expression::current_date(),
            op: PhantomData,
        }
    }

    fn after_today(self) -> Binary<op::Gt, DateExtract<Self>, crate::expression::CurrentDate> {
        Binary {
            left: self.date(),
            right: crate::expression::current_date(),
            op: PhantomData,
        }
    }
}

impl<E> TimestampRelativeExt for E where E: Expression<Type = Timestamp> {}

pub trait DateExt: Sized + Expression<Type = Date> {
    fn year(self) -> YearExtract<Self, DateSource> {
        YearExtract {
            inner: self,
            marker: PhantomData,
        }
    }

    fn month(self) -> MonthExtract<Self, DateSource> {
        MonthExtract {
            inner: self,
            marker: PhantomData,
        }
    }

    fn day(self) -> DayExtract<Self, DateSource> {
        DayExtract {
            inner: self,
            marker: PhantomData,
        }
    }
}

impl<E> DateExt for E where E: Expression<Type = Date> {}

pub trait DateRelativeExt: Sized + Expression<Type = Date> {
    fn past(self) -> Binary<op::Lt, Self, crate::expression::CurrentDate> {
        Binary {
            left: self,
            right: crate::expression::current_date(),
            op: PhantomData,
        }
    }

    fn future(self) -> Binary<op::Gt, Self, crate::expression::CurrentDate> {
        Binary {
            left: self,
            right: crate::expression::current_date(),
            op: PhantomData,
        }
    }

    fn today(self) -> Binary<op::Eq, Self, crate::expression::CurrentDate> {
        Binary {
            left: self,
            right: crate::expression::current_date(),
            op: PhantomData,
        }
    }

    fn before_today(self) -> Binary<op::Lt, Self, crate::expression::CurrentDate> {
        Binary {
            left: self,
            right: crate::expression::current_date(),
            op: PhantomData,
        }
    }

    fn after_today(self) -> Binary<op::Gt, Self, crate::expression::CurrentDate> {
        Binary {
            left: self,
            right: crate::expression::current_date(),
            op: PhantomData,
        }
    }
}

impl<E> DateRelativeExt for E where E: Expression<Type = Date> {}

#[qraft_expression_macro::as_expression]
impl<E> Expression for DateExtract<E>
where
    E: Expression<Type = Timestamp>,
{
    type Type = Date;

    fn lower(&self, ctx: &mut LowerCtx) -> usize {
        let inner = self.inner.lower(ctx);
        ctx.lower_temporal(inner, TemporalKind::Date)
    }
}

#[qraft_expression_macro::as_expression]
impl<E> Expression for TimeExtract<E>
where
    E: Expression<Type = Timestamp>,
{
    type Type = Time;

    fn lower(&self, ctx: &mut LowerCtx) -> usize {
        let inner = self.inner.lower(ctx);
        ctx.lower_temporal(inner, TemporalKind::Time)
    }
}

#[qraft_expression_macro::as_expression]
impl<E> Expression for YearExtract<E, TimestampSource>
where
    E: Expression<Type = Timestamp>,
{
    type Type = BigInt;

    fn lower(&self, ctx: &mut LowerCtx) -> usize {
        let inner = self.inner.lower(ctx);
        ctx.lower_temporal(inner, TemporalKind::Year)
    }
}

#[qraft_expression_macro::as_expression]
impl<E> Expression for MonthExtract<E, TimestampSource>
where
    E: Expression<Type = Timestamp>,
{
    type Type = BigInt;

    fn lower(&self, ctx: &mut LowerCtx) -> usize {
        let inner = self.inner.lower(ctx);
        ctx.lower_temporal(inner, TemporalKind::Month)
    }
}

#[qraft_expression_macro::as_expression]
impl<E> Expression for DayExtract<E, TimestampSource>
where
    E: Expression<Type = Timestamp>,
{
    type Type = BigInt;

    fn lower(&self, ctx: &mut LowerCtx) -> usize {
        let inner = self.inner.lower(ctx);
        ctx.lower_temporal(inner, TemporalKind::Day)
    }
}

#[qraft_expression_macro::as_expression]
impl<E> Expression for YearExtract<E, DateSource>
where
    E: Expression<Type = Date>,
{
    type Type = BigInt;

    fn lower(&self, ctx: &mut LowerCtx) -> usize {
        let inner = self.inner.lower(ctx);
        ctx.lower_temporal(inner, TemporalKind::Year)
    }
}

#[qraft_expression_macro::as_expression]
impl<E> Expression for MonthExtract<E, DateSource>
where
    E: Expression<Type = Date>,
{
    type Type = BigInt;

    fn lower(&self, ctx: &mut LowerCtx) -> usize {
        let inner = self.inner.lower(ctx);
        ctx.lower_temporal(inner, TemporalKind::Month)
    }
}

#[qraft_expression_macro::as_expression]
impl<E> Expression for DayExtract<E, DateSource>
where
    E: Expression<Type = Date>,
{
    type Type = BigInt;

    fn lower(&self, ctx: &mut LowerCtx) -> usize {
        let inner = self.inner.lower(ctx);
        ctx.lower_temporal(inner, TemporalKind::Day)
    }
}