use std::marker::PhantomData;
use crate::{
Qrafting, Query,
alias::{Alias, Aliased},
builder::{FormatContext, FormatWriter},
count_idents, impl_for_all_tuples,
lower::{Instructions, LowerCtx},
};
pub trait LowerFrom {
fn lower_from(self, ctx: &mut LowerCtx);
}
pub trait LowerFromItem {
fn lower_from_item(self, ctx: &mut LowerCtx);
}
impl<T> LowerFrom for T
where
T: LowerFromItem,
{
fn lower_from(self, ctx: &mut LowerCtx) {
self.lower_from_item(ctx);
}
}
impl<T> LowerFromItem for Aliased<T>
where
T: Alias + LowerFromItem,
{
fn lower_from_item(self, ctx: &mut LowerCtx) {
self.inner.lower_from_item(ctx);
let _ = ctx.lower_alias(self.alias, 1);
}
}
impl LowerFromItem for Aliased<Query> {
fn lower_from_item(self, ctx: &mut LowerCtx) {
let alias = self.alias;
let inner_query = self.inner;
let inner = ctx.lower_subquery_ref(&inner_query);
let _ = ctx.lower_alias(alias, inner);
}
}
impl LowerFromItem for &'static str {
fn lower_from_item(self, ctx: &mut LowerCtx) {
let _ = ctx.lower_table(self);
}
}
impl<M> Alias for Table<M> {}
impl<M> LowerFromItem for Table<M> {
fn lower_from_item(self, ctx: &mut LowerCtx) {
let _ = ctx.lower_table(self.table);
}
}
#[derive(Debug)]
pub struct Table<M> {
pub table: &'static str,
marker: PhantomData<M>,
}
impl<M> FormatWriter for Table<M>
where
M: Qrafting,
{
fn format_writer<'w, W: std::fmt::Write>(
&self,
context: &mut FormatContext<'w, W>,
) -> std::fmt::Result {
context.write_table(M::TABLE)
}
}
impl<M> Copy for Table<M> {}
impl<M> Clone for Table<M> {
fn clone(&self) -> Self {
*self
}
}
impl<M> Table<M> {
pub const fn new(table: &'static str) -> Self {
Self {
table,
marker: PhantomData,
}
}
pub const fn name(self) -> &'static str {
self.table
}
}
macro_rules! impl_from_macro {
($($T:ident),+) => {
impl<$($T,)+> LowerFrom for ($($T,)+)
where
$($T: LowerFrom,)+
{
fn lower_from(self, ctx: &mut LowerCtx) {
#[allow(non_snake_case)]
let ($($T,)+) = self;
$(
$T.lower_from(ctx);
)+
let count = count_idents!($($T,)+);
ctx.instrs.push_cross_join(count);
}
}
};
}
impl_for_all_tuples!(impl_from_macro);