use crate::{
alias::Aliased,
count_idents,
expression::Expression,
impl_for_all_tuples,
lower::{Instructions, LowerCtx},
span::TextSpan,
};
pub trait LowerProject {
fn lower_project(self, ctx: &mut LowerCtx);
}
#[derive(Debug, Clone, Copy)]
pub struct Star {
_priv: (),
}
pub fn star() -> Star {
Star { _priv: () }
}
impl LowerProject for Star {
fn lower_project(self, ctx: &mut LowerCtx) {
let _ = ctx.lower_star();
}
}
impl<E> LowerProject for E
where
E: Expression,
{
fn lower_project(self, ctx: &mut LowerCtx) {
let _ = self.lower(ctx);
}
}
impl<E> LowerProject for Aliased<E>
where
E: Expression,
{
fn lower_project(self, ctx: &mut LowerCtx) {
let inner = self.inner.lower(ctx);
let _ = ctx.lower_alias(self.alias, inner);
}
}
impl LowerProject for &'static str {
fn lower_project(self, ctx: &mut LowerCtx) {
let span = TextSpan::new_static(self);
ctx.instrs.push_column(None, span);
}
}
impl LowerProject for Aliased<&'static str> {
fn lower_project(self, ctx: &mut LowerCtx) {
self.inner.lower_project(ctx);
let _ = ctx.lower_alias(self.alias, 1);
}
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ColumnOf {
pub table: &'static str,
pub name: &'static str,
}
impl ColumnOf {
pub const fn new(table: &'static str, name: &'static str) -> Self {
Self { table, name }
}
}
impl LowerProject for ColumnOf {
fn lower_project(self, ctx: &mut LowerCtx) {
let _ = ctx.lower_column(Some(self.table), self.name);
}
}
impl LowerProject for Aliased<ColumnOf> {
fn lower_project(self, ctx: &mut LowerCtx) {
self.inner.lower_project(ctx);
let _ = ctx.lower_alias(self.alias, 1);
}
}
impl<T: LowerProject, const N: usize> LowerProject for [T; N] {
fn lower_project(self, ctx: &mut LowerCtx) {
let len = self.len();
for item in self {
item.lower_project(ctx);
}
ctx.instrs.push_seperated(len);
}
}
impl<T: LowerProject> LowerProject for Vec<T> {
fn lower_project(self, ctx: &mut LowerCtx) {
let len = self.len();
for item in self {
item.lower_project(ctx);
}
ctx.instrs.push_seperated(len);
}
}
macro_rules! impl_project_macro {
($($T:ident),+) => {
impl<$($T,)+> LowerProject for ($($T,)+)
where
$($T: LowerProject,)+
{
fn lower_project(self, ctx: &mut LowerCtx) {
#[allow(non_snake_case)]
let ($($T,)+) = self;
$(
$T.lower_project(ctx);
)+
let count = count_idents!($($T,)+);
ctx.instrs.push_seperated(count);
}
}
};
}
impl_for_all_tuples!(impl_project_macro);