use crate::{
BigInt, Date, LowerCompatible, Numeric, Text, Time, Timestamp,
expression::Expression,
lower::{Instructions, LowerCtx},
};
pub struct Random;
pub struct CurrentDate;
pub struct CurrentTime;
pub struct Now;
pub struct Null<T>(std::marker::PhantomData<T>);
pub struct Lower<E> {
inner: E,
}
pub struct Upper<E> {
inner: E,
}
pub struct Length<E> {
inner: E,
}
pub struct Abs<E> {
inner: E,
}
pub struct Round<E> {
inner: E,
}
pub struct NullIf<L, R> {
left: L,
right: R,
}
pub struct Coalesce<L, R> {
left: L,
right: R,
}
pub fn random() -> Random {
Random
}
pub fn current_date() -> CurrentDate {
CurrentDate
}
pub fn current_time() -> CurrentTime {
CurrentTime
}
pub fn now() -> Now {
Now
}
pub fn null<T>() -> Null<T> {
Null(std::marker::PhantomData)
}
pub fn lower<E>(inner: E) -> Lower<E> {
Lower { inner }
}
pub fn upper<E>(inner: E) -> Upper<E> {
Upper { inner }
}
pub fn length<E>(inner: E) -> Length<E> {
Length { inner }
}
pub fn abs<E>(inner: E) -> Abs<E> {
Abs { inner }
}
pub fn round<E>(inner: E) -> Round<E> {
Round { inner }
}
pub fn null_if<L, R>(left: L, right: R) -> NullIf<L, R> {
NullIf { left, right }
}
pub fn coalesce<L, R>(left: L, right: R) -> Coalesce<L, R> {
Coalesce { left, right }
}
#[qraft_expression_macro::as_expression]
impl Expression for Random {
type Type = crate::Double;
fn lower(&self, ctx: &mut LowerCtx) -> usize {
ctx.lower_fn("random", 0)
}
}
#[qraft_expression_macro::as_expression]
impl Expression for CurrentDate {
type Type = Date;
fn lower(&self, ctx: &mut LowerCtx) -> usize {
ctx.lower_fn("current_date", 0)
}
}
#[qraft_expression_macro::as_expression]
impl Expression for CurrentTime {
type Type = Time;
fn lower(&self, ctx: &mut LowerCtx) -> usize {
ctx.lower_fn("current_time", 0)
}
}
#[qraft_expression_macro::as_expression]
impl Expression for Now {
type Type = Timestamp;
fn lower(&self, ctx: &mut LowerCtx) -> usize {
ctx.lower_fn("current_timestamp", 0)
}
}
#[qraft_expression_macro::as_expression]
impl<T> Expression for Null<T>
where
T: crate::TypeMeta,
{
type Type = crate::Nullable<T>;
fn lower(&self, ctx: &mut LowerCtx) -> usize {
ctx.lower_null()
}
}
#[qraft_expression_macro::as_expression]
impl<E> Expression for Lower<E>
where
E: Expression<Type = Text>,
{
type Type = Text;
fn lower(&self, ctx: &mut LowerCtx) -> usize {
let inner = self.inner.lower(ctx);
ctx.lower_fn("lower", inner)
}
}
#[qraft_expression_macro::as_expression]
impl<E> Expression for Upper<E>
where
E: Expression<Type = Text>,
{
type Type = Text;
fn lower(&self, ctx: &mut LowerCtx) -> usize {
let inner = self.inner.lower(ctx);
ctx.lower_fn("upper", inner)
}
}
#[qraft_expression_macro::as_expression]
impl<E> Expression for Length<E>
where
E: Expression<Type = Text>,
{
type Type = BigInt;
fn lower(&self, ctx: &mut LowerCtx) -> usize {
let inner = self.inner.lower(ctx);
ctx.lower_fn("length", inner)
}
}
#[qraft_expression_macro::as_expression]
impl<E> Expression for Abs<E>
where
E: Expression,
E::Type: Numeric,
{
type Type = E::Type;
fn lower(&self, ctx: &mut LowerCtx) -> usize {
let inner = self.inner.lower(ctx);
ctx.lower_fn("abs", inner)
}
}
#[qraft_expression_macro::as_expression]
impl<E> Expression for Round<E>
where
E: Expression,
E::Type: Numeric,
{
type Type = E::Type;
fn lower(&self, ctx: &mut LowerCtx) -> usize {
let inner = self.inner.lower(ctx);
ctx.lower_fn("round", inner)
}
}
#[qraft_expression_macro::as_expression]
impl<L, R> Expression for NullIf<L, R>
where
L: Expression,
R: LowerCompatible<L::Type>,
{
type Type = L::Type;
fn lower(&self, ctx: &mut LowerCtx) -> usize {
let lhs = self.left.lower(ctx);
let rhs = self.right.lower_compatible(ctx);
ctx.instrs.push_seperated(2);
ctx.lower_fn("nullif", lhs + rhs + 1)
}
}
#[qraft_expression_macro::as_expression]
impl<L, R> Expression for Coalesce<L, R>
where
L: Expression,
R: LowerCompatible<L::Type>,
{
type Type = L::Type;
fn lower(&self, ctx: &mut LowerCtx) -> usize {
let lhs = self.left.lower(ctx);
let rhs = self.right.lower_compatible(ctx);
ctx.instrs.push_seperated(2);
ctx.lower_fn("coalesce", lhs + rhs + 1)
}
}