use crate::expr::{Column, ColumnKey, ExprKind, Keyed, LabelKey, Labeled, SqlType};
use crate::render::SelectItem;
use std::marker::PhantomData;
use crate::row::{Named, Row, RowCons, RowKey, RowNil};
use crate::scope::{Find, Superset, Table, WrapNullable};
mod private {
pub trait Sealed<Scope, Idx> {}
}
#[doc(hidden)]
pub trait SelectableSealed {}
impl<C, Scope, Idx> private::Sealed<Scope, Idx> for Column<C>
where
C: crate::expr::ColumnKey,
Scope: Find<C::Table, Idx>,
{
}
impl<K, Req, S: SqlType, Scope, Idx> private::Sealed<Scope, Idx> for Keyed<K, Req, S> where
Scope: Superset<Req, Idx>
{
}
impl<K, Inner, Scope, Idx> private::Sealed<Scope, Idx> for Labeled<K, Inner> where
Inner: RowField<Scope, Idx>
{
}
impl<T: AllColumns, Scope, Idx> private::Sealed<Scope, Idx> for All<T> where
T::Columns: ColumnList<Scope, Idx>
{
}
pub trait SingleColumn {}
#[diagnostic::on_unimplemented(
message = "`{Self}` can't be a field of this query's rows",
label = "a column, an aggregate, a window function, a `sql!` fragment, or a labelled one of those can be",
note = "an expression the builder inferred a type for — a comparison, an `is_null`, a `LIKE` — has to state what it decodes to with `.decodes_as::<..>()`, since that inference can contradict the join; a `sql!` fragment already states it"
)]
pub trait RowField<Scope, Idx>: RowKey + private::Sealed<Scope, Idx> {
type Value;
fn item(&self) -> SelectItem;
}
impl<C: ColumnKey, Scope, Idx> RowField<Scope, Idx> for Column<C>
where
Scope: Find<C::Table, Idx>,
C::Sql: WrapNullable<<Scope as Find<C::Table, Idx>>::Nullability>,
<C::Sql as WrapNullable<<Scope as Find<C::Table, Idx>>::Nullability>>::Output: SqlType,
{
type Value = <<C::Sql as WrapNullable<
<Scope as Find<C::Table, Idx>>::Nullability,
>>::Output as SqlType>::Native;
fn item(&self) -> SelectItem {
SelectItem::bare(ExprKind::Column {
table: <C::Table as Table>::NAME,
name: C::NAME,
})
}
}
impl<K, Req, S: SqlType, Scope, Idx> RowField<Scope, Idx> for Keyed<K, Req, S>
where
Scope: Superset<Req, Idx>,
{
type Value = S::Native;
fn item(&self) -> SelectItem {
SelectItem::bare(self.kind.clone())
}
}
impl<K: LabelKey, Inner: RowField<Scope, Idx>, Scope, Idx> RowField<Scope, Idx>
for Labeled<K, Inner>
{
type Value = Inner::Value;
fn item(&self) -> SelectItem {
SelectItem::labeled(self.inner.item().kind, <K as Named>::NAME)
}
}
#[diagnostic::on_unimplemented(
message = "`{Self}` isn't a valid selection list here",
label = "a selection is a column, an aggregate, a window function, a `sql!` fragment, a labelled one of those, `<table>::All`, or a tuple of up to 16 of them",
note = "every element has to be in scope — `.from(..)`/`.join(..)` the tables it names — and an expression the builder inferred a type for has to state its decoded type with `.decodes_as::<..>()`"
)]
pub trait Selection<Scope, Idx>: private::Sealed<Scope, Idx> {
type Output;
fn items(&self) -> Vec<SelectItem>;
}
macro_rules! scalar_selection {
(impl[$($generics:tt)*] $ty:ty) => {
impl<$($generics)*, Scope, Idx> Selection<Scope, Idx> for $ty
where
$ty: RowField<Scope, Idx>,
{
type Output = <$ty as RowField<Scope, Idx>>::Value;
fn items(&self) -> Vec<SelectItem> {
vec![RowField::item(self)]
}
}
};
}
#[diagnostic::on_unimplemented(
message = "`{Self}` can't be part of a selection list",
label = "a column, an aggregate, a window function, a `sql!` fragment, a labelled one of those, or `<table>::All` can be",
note = "an expression the builder inferred a type for — a comparison, an `is_null`, a `LIKE` — has to state what it decodes to with `.decodes_as::<..>()`, since that inference can contradict the join"
)]
pub trait SelectionPart<Scope, Idx>: private::Sealed<Scope, Idx> {
type Fields<Tail>;
fn push_items(&self, out: &mut Vec<SelectItem>);
}
macro_rules! field_part {
(impl[$($generics:tt)*] $ty:ty) => {
impl<$($generics)*, Scope, Idx> SelectionPart<Scope, Idx> for $ty
where
$ty: RowField<Scope, Idx>,
{
type Fields<Tail> = RowCons<
<$ty as RowKey>::Key,
<$ty as RowField<Scope, Idx>>::Value,
Tail,
>;
fn push_items(&self, out: &mut Vec<SelectItem>) {
out.push(RowField::item(self));
}
}
};
}
macro_rules! selectable {
(impl[$($generics:tt)*] $ty:ty) => {
scalar_selection!(impl[$($generics)*] $ty);
field_part!(impl[$($generics)*] $ty);
};
}
selectable!(impl[C: ColumnKey] Column<C>);
selectable!(impl[K, Req, S: SqlType] Keyed<K, Req, S>);
selectable!(impl[K, Inner] Labeled<K, Inner>);
pub struct All<T>(PhantomData<fn() -> T>);
impl<T> All<T> {
pub const fn new() -> Self {
All(PhantomData)
}
}
impl<T> Clone for All<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for All<T> {}
impl<T> Default for All<T> {
fn default() -> Self {
All::new()
}
}
pub trait AllColumns: SelectableSealed {
type Columns;
}
mod column_list {
pub trait Sealed {}
impl Sealed for crate::scope::Nil {}
impl<C: crate::expr::ColumnKey, Tail> Sealed for crate::scope::Cons<crate::expr::Column<C>, Tail> {}
}
pub trait ColumnList<Scope, Idx>: column_list::Sealed {
type Fields<Tail>;
fn push_items(out: &mut Vec<SelectItem>);
}
impl<Scope, Idx> ColumnList<Scope, Idx> for crate::scope::Nil {
type Fields<Tail> = Tail;
fn push_items(_out: &mut Vec<SelectItem>) {}
}
impl<C: ColumnKey, Tail, Scope, Idx> ColumnList<Scope, Idx> for crate::scope::Cons<Column<C>, Tail>
where
Column<C>: RowField<Scope, Idx>,
Tail: ColumnList<Scope, Idx>,
{
type Fields<T> = RowCons<C, <Column<C> as RowField<Scope, Idx>>::Value, Tail::Fields<T>>;
fn push_items(out: &mut Vec<SelectItem>) {
out.push(RowField::item(&Column::<C>::new()));
Tail::push_items(out);
}
}
impl<T: AllColumns, Scope, Idx> SelectionPart<Scope, Idx> for All<T>
where
T::Columns: ColumnList<Scope, Idx>,
{
type Fields<Tail> = <T::Columns as ColumnList<Scope, Idx>>::Fields<Tail>;
fn push_items(&self, out: &mut Vec<SelectItem>) {
<T::Columns as ColumnList<Scope, Idx>>::push_items(out);
}
}
impl<T: AllColumns, Scope, Idx> Selection<Scope, Idx> for All<T>
where
T::Columns: ColumnList<Scope, Idx>,
{
type Output = Row<<T::Columns as ColumnList<Scope, Idx>>::Fields<RowNil>>;
fn items(&self) -> Vec<SelectItem> {
let mut out = Vec::new();
<T::Columns as ColumnList<Scope, Idx>>::push_items(&mut out);
out
}
}
macro_rules! row_chain {
($n:ident $i:ident) => {
<$n as SelectionPart<Scope, $i>>::Fields<RowNil>
};
($n:ident $i:ident, $($rest:tt)*) => {
<$n as SelectionPart<Scope, $i>>::Fields<row_chain!($($rest)*)>
};
}
macro_rules! tuple_selection {
($($n:ident $i:ident),+) => {
impl<Scope, $($n,)+ $($i,)+> private::Sealed<Scope, ($($i,)+)> for ($($n,)+)
where
$($n: SelectionPart<Scope, $i>,)+
{
}
#[allow(non_snake_case)]
impl<Scope, $($n,)+ $($i,)+> Selection<Scope, ($($i,)+)> for ($($n,)+)
where
$($n: SelectionPart<Scope, $i>,)+
{
type Output = Row<row_chain!($($n $i),+)>;
fn items(&self) -> Vec<SelectItem> {
let ($($n,)+) = self;
let mut out = Vec::new();
$(SelectionPart::push_items($n, &mut out);)+
out
}
}
};
}
tuple_selection!(A IA);
tuple_selection!(A IA, B IB);
tuple_selection!(A IA, B IB, C IC);
tuple_selection!(A IA, B IB, C IC, D ID);
tuple_selection!(A IA, B IB, C IC, D ID, E IE);
tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF);
tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG);
tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH);
tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II);
tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ);
tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ, K IK);
tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ, K IK, L IL);
tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ, K IK, L IL, M IM);
tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ, K IK, L IL, M IM, N IN);
tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ, K IK, L IL, M IM, N IN, O IO);
tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ, K IK, L IL, M IM, N IN, O IO, P IP);